1212import { create } from '@bufbuild/protobuf' ;
1313import { ConnectError , createRouterTransport } from '@connectrpc/connect' ;
1414import userEvent from '@testing-library/user-event' ;
15- import { CreateTopicResponseSchema } from 'protogen/redpanda/api/dataplane/v1/topic_pb' ;
16- import { createTopic } from 'protogen/redpanda/api/dataplane/v1/topic-TopicService_connectquery' ;
15+ import { CreateTopicResponseSchema , ListTopicsResponseSchema } from 'protogen/redpanda/api/dataplane/v1/topic_pb' ;
16+ import { createTopic , listTopics } from 'protogen/redpanda/api/dataplane/v1/topic-TopicService_connectquery' ;
1717import type { ComponentProps } from 'react' ;
1818import { useRef } from 'react' ;
1919import { render , screen , waitFor } from 'test-utils' ;
@@ -60,21 +60,7 @@ import { AddTopicStep } from './add-topic-step';
6060
6161// ── Helpers ────────────────────────────────────────────────────────────
6262
63- /** gRPC ListTopicsResponse (proto JSON shape) for useListTopicsQuery */
64- function createTopicsResponse ( topicNames : string [ ] ) {
65- return {
66- topics : topicNames . map ( ( name ) => ( {
67- name,
68- internal : false ,
69- partitionCount : 1 ,
70- replicationFactor : 3 ,
71- cleanupPolicy : 'delete' ,
72- logDirSummary : { totalSizeBytes : 0 , replicaErrors : [ ] , hint : '' } ,
73- } ) ) ,
74- } ;
75- }
76-
77- function createTransport ( overrides ?: { createTopicMock ?: ReturnType < typeof vi . fn > } ) {
63+ function createTransport ( overrides ?: { createTopicMock ?: ReturnType < typeof vi . fn > ; topicNames ?: string [ ] } ) {
7864 return createRouterTransport ( ( { rpc } ) => {
7965 rpc (
8066 createTopic ,
@@ -87,6 +73,20 @@ function createTransport(overrides?: { createTopicMock?: ReturnType<typeof vi.fn
8773 } )
8874 )
8975 ) ;
76+ // useListTopicsQuery resolves topics over the gRPC transport, so seed them here.
77+ rpc ( listTopics , ( ) =>
78+ create ( ListTopicsResponseSchema , {
79+ topics : ( overrides ?. topicNames ?? [ ] ) . map ( ( name ) => ( {
80+ name,
81+ internal : false ,
82+ partitionCount : 1 ,
83+ replicationFactor : 3 ,
84+ cleanupPolicy : 'delete' ,
85+ logDirSummary : { totalSizeBytes : 0n , replicaErrors : [ ] , hint : '' } ,
86+ } ) ) ,
87+ nextPageToken : '' ,
88+ } )
89+ ) ;
9090 } ) ;
9191}
9292
@@ -111,22 +111,13 @@ function TestHarness({ onResult, ...props }: HarnessProps) {
111111describe ( 'AddTopicStep' , ( ) => {
112112 beforeEach ( ( ) => {
113113 mockFetch . mockReset ( ) ;
114- // Default: return empty topic list
115- mockFetch . mockResolvedValue ( {
116- ok : true ,
117- json : ( ) => Promise . resolve ( createTopicsResponse ( [ ] ) ) ,
118- } ) ;
119114 } ) ;
120115
121116 it ( 'existing topic returns name via triggerSubmit' , async ( ) => {
122117 const user = userEvent . setup ( ) ;
123- mockFetch . mockResolvedValue ( {
124- ok : true ,
125- json : ( ) => Promise . resolve ( createTopicsResponse ( [ 'my-topic' , 'other-topic' ] ) ) ,
126- } ) ;
127118
128119 let result : unknown ;
129- const transport = createTransport ( ) ;
120+ const transport = createTransport ( { topicNames : [ 'my-topic' , 'other-topic' ] } ) ;
130121
131122 render (
132123 < TestHarness
@@ -138,11 +129,6 @@ describe('AddTopicStep', () => {
138129 { transport }
139130 ) ;
140131
141- // Wait for topics to load so the combobox has options
142- await waitFor ( ( ) => {
143- expect ( mockFetch ) . toHaveBeenCalled ( ) ;
144- } ) ;
145-
146132 // The component starts in "Existing" mode when topics exist.
147133 // Open the combobox, type to filter, then click the matching option.
148134 // (Pressing Enter races cmdk's highlighted-value bookkeeping in CI under
@@ -283,11 +269,7 @@ describe('AddTopicStep', () => {
283269 } ) ;
284270
285271 it ( 'selectionMode=existing shows combobox' , async ( ) => {
286- mockFetch . mockResolvedValue ( {
287- ok : true ,
288- json : ( ) => Promise . resolve ( createTopicsResponse ( [ 'topic-a' ] ) ) ,
289- } ) ;
290- const transport = createTransport ( ) ;
272+ const transport = createTransport ( { topicNames : [ 'topic-a' ] } ) ;
291273
292274 render ( < TestHarness onResult = { ( ) => { } } selectionMode = "existing" /> , { transport } ) ;
293275
@@ -297,19 +279,10 @@ describe('AddTopicStep', () => {
297279
298280 it ( 'existing topic alert shown in create mode when name matches' , async ( ) => {
299281 const user = userEvent . setup ( ) ;
300- mockFetch . mockResolvedValue ( {
301- ok : true ,
302- json : ( ) => Promise . resolve ( createTopicsResponse ( [ 'existing-topic' ] ) ) ,
303- } ) ;
304- const transport = createTransport ( ) ;
282+ const transport = createTransport ( { topicNames : [ 'existing-topic' ] } ) ;
305283
306284 render ( < TestHarness onResult = { ( ) => { } } selectionMode = "both" /> , { transport } ) ;
307285
308- // Wait for topics to load
309- await waitFor ( ( ) => {
310- expect ( mockFetch ) . toHaveBeenCalled ( ) ;
311- } ) ;
312-
313286 // Switch to "New" tab (single-select ToggleGroupItem renders as role="radio")
314287 const newButton = await screen . findByRole ( 'radio' , { name : 'New' } ) ;
315288 await user . click ( newButton ) ;
@@ -357,11 +330,7 @@ describe('AddTopicStep', () => {
357330 } ) ;
358331
359332 it ( 'selectionMode=both renders toggle group' , async ( ) => {
360- mockFetch . mockResolvedValue ( {
361- ok : true ,
362- json : ( ) => Promise . resolve ( createTopicsResponse ( [ 't1' ] ) ) ,
363- } ) ;
364- const transport = createTransport ( ) ;
333+ const transport = createTransport ( { topicNames : [ 't1' ] } ) ;
365334
366335 render ( < TestHarness onResult = { ( ) => { } } selectionMode = "both" /> , { transport } ) ;
367336
0 commit comments