@@ -99,11 +99,11 @@ describe('AddComponentsPopover', () => {
9999 fireEvent . click ( trigger ) ;
100100
101101 await waitFor ( ( ) => {
102- expect ( screen . getByPlaceholderText ( 'Add component ' ) ) . toBeInTheDocument ( ) ;
102+ expect ( screen . getByPlaceholderText ( 'Find components ' ) ) . toBeInTheDocument ( ) ;
103103 } ) ;
104104 } ) ;
105105
106- it ( 'should render component search input' , async ( ) => {
106+ it ( 'should render component search input with search icon ' , async ( ) => {
107107 render (
108108 < AddComponentsPopover parentLayerId = "parent-1" >
109109 < button > Add Component</ button >
@@ -114,13 +114,13 @@ describe('AddComponentsPopover', () => {
114114 fireEvent . click ( trigger ) ;
115115
116116 await waitFor ( ( ) => {
117- expect ( screen . getByPlaceholderText ( 'Add component ' ) ) . toBeInTheDocument ( ) ;
117+ expect ( screen . getByPlaceholderText ( 'Find components ' ) ) . toBeInTheDocument ( ) ;
118118 } ) ;
119119 } ) ;
120120 } ) ;
121121
122- describe ( 'Component Grouping' , ( ) => {
123- it ( 'should group components by their path ' , async ( ) => {
122+ describe ( 'Tab-based Component Grouping' , ( ) => {
123+ it ( 'should render tabs for each component group ' , async ( ) => {
124124 render (
125125 < AddComponentsPopover parentLayerId = "parent-1" >
126126 < button > Add Component</ button >
@@ -131,14 +131,14 @@ describe('AddComponentsPopover', () => {
131131 fireEvent . click ( trigger ) ;
132132
133133 await waitFor ( ( ) => {
134- // Should show groups
135- expect ( screen . getByText ( '@/components/ui ' ) ) . toBeInTheDocument ( ) ;
136- expect ( screen . getByText ( '@/custom/components ' ) ) . toBeInTheDocument ( ) ;
137- expect ( screen . getByText ( 'other ' ) ) . toBeInTheDocument ( ) ;
134+ // Should show tabs for different groups - check by the formatted names
135+ expect ( screen . getByText ( 'Ui ' ) ) . toBeInTheDocument ( ) ;
136+ expect ( screen . getByText ( 'Components ' ) ) . toBeInTheDocument ( ) ;
137+ expect ( screen . getByText ( 'Other ' ) ) . toBeInTheDocument ( ) ;
138138 } ) ;
139139 } ) ;
140140
141- it ( 'should render components in their respective groups ' , async ( ) => {
141+ it ( 'should render components with grey box previews in active tab ' , async ( ) => {
142142 render (
143143 < AddComponentsPopover parentLayerId = "parent-1" >
144144 < button > Add Component</ button >
@@ -149,16 +149,56 @@ describe('AddComponentsPopover', () => {
149149 fireEvent . click ( trigger ) ;
150150
151151 await waitFor ( ( ) => {
152- // UI components group
152+ // Components in the first tab should be visible by default
153153 expect ( screen . getByText ( 'Button' ) ) . toBeInTheDocument ( ) ;
154154 expect ( screen . getByText ( 'Input' ) ) . toBeInTheDocument ( ) ;
155155 expect ( screen . getByText ( 'Card' ) ) . toBeInTheDocument ( ) ;
156-
157- // Custom components group
158- expect ( screen . getByText ( 'CustomComponent' ) ) . toBeInTheDocument ( ) ;
159-
160- // Other group (no from path)
161- expect ( screen . getByText ( 'UnGroupedComponent' ) ) . toBeInTheDocument ( ) ;
156+ } ) ;
157+
158+ // Check for grey box previews (muted background divs) - but they might be lazy loaded
159+ await waitFor ( ( ) => {
160+ const greyBoxes = screen . getAllByRole ( 'generic' ) . filter ( el =>
161+ el . className . includes ( 'bg-muted' ) || el . className . includes ( 'rounded border' )
162+ ) ;
163+ expect ( greyBoxes . length ) . toBeGreaterThan ( 0 ) ;
164+ } ) ;
165+ } ) ;
166+
167+ it ( 'should limit tabs to maximum of 3' , async ( ) => {
168+ // Mock registry with more than 3 groups
169+ const registryWithManyGroups = {
170+ ...mockRegistry ,
171+ ExtraComponent1 : {
172+ component : ( ) => null ,
173+ name : 'ExtraComponent1' ,
174+ from : '@/group1/component'
175+ } ,
176+ ExtraComponent2 : {
177+ component : ( ) => null ,
178+ name : 'ExtraComponent2' ,
179+ from : '@/group2/component'
180+ }
181+ } ;
182+
183+ mockUseEditorStore . mockImplementation ( ( selector ) => {
184+ const state = {
185+ registry : registryWithManyGroups ,
186+ } ;
187+ return selector ( state as any ) ;
188+ } ) ;
189+
190+ render (
191+ < AddComponentsPopover parentLayerId = "parent-1" >
192+ < button > Add Component</ button >
193+ </ AddComponentsPopover >
194+ ) ;
195+
196+ const trigger = screen . getByText ( 'Add Component' ) ;
197+ fireEvent . click ( trigger ) ;
198+
199+ await waitFor ( ( ) => {
200+ const tabs = screen . getAllByRole ( 'tab' ) ;
201+ expect ( tabs . length ) . toBeLessThanOrEqual ( 3 ) ;
162202 } ) ;
163203 } ) ;
164204 } ) ;
@@ -251,7 +291,7 @@ describe('AddComponentsPopover', () => {
251291 fireEvent . click ( buttonOption ) ;
252292
253293 await waitFor ( ( ) => {
254- expect ( screen . queryByPlaceholderText ( 'Add component ' ) ) . not . toBeInTheDocument ( ) ;
294+ expect ( screen . queryByPlaceholderText ( 'Find components ' ) ) . not . toBeInTheDocument ( ) ;
255295 } ) ;
256296 } ) ;
257297
@@ -282,7 +322,7 @@ describe('AddComponentsPopover', () => {
282322 } ) ;
283323
284324 describe ( 'Search Functionality' , ( ) => {
285- it ( 'should filter components based on search input' , async ( ) => {
325+ it ( 'should filter components based on search input across tabs ' , async ( ) => {
286326 render (
287327 < AddComponentsPopover parentLayerId = "parent-1" >
288328 < button > Add Component</ button >
@@ -293,13 +333,13 @@ describe('AddComponentsPopover', () => {
293333 fireEvent . click ( trigger ) ;
294334
295335 await waitFor ( ( ) => {
296- expect ( screen . getByPlaceholderText ( 'Add component ' ) ) . toBeInTheDocument ( ) ;
336+ expect ( screen . getByPlaceholderText ( 'Find components ' ) ) . toBeInTheDocument ( ) ;
297337 } ) ;
298338
299- const searchInput = screen . getByPlaceholderText ( 'Add component ' ) ;
339+ const searchInput = screen . getByPlaceholderText ( 'Find components ' ) ;
300340 fireEvent . change ( searchInput , { target : { value : 'Button' } } ) ;
301341
302- // Should still show Button but might filter others based on search implementation
342+ // Should still show Button
303343 expect ( screen . getByText ( 'Button' ) ) . toBeInTheDocument ( ) ;
304344 } ) ;
305345
@@ -314,10 +354,10 @@ describe('AddComponentsPopover', () => {
314354 fireEvent . click ( trigger ) ;
315355
316356 await waitFor ( ( ) => {
317- expect ( screen . getByPlaceholderText ( 'Add component ' ) ) . toBeInTheDocument ( ) ;
357+ expect ( screen . getByPlaceholderText ( 'Find components ' ) ) . toBeInTheDocument ( ) ;
318358 } ) ;
319359
320- const searchInput = screen . getByPlaceholderText ( 'Add component ' ) ;
360+ const searchInput = screen . getByPlaceholderText ( 'Find components ' ) ;
321361 fireEvent . change ( searchInput , { target : { value : 'NonExistentComponent' } } ) ;
322362
323363 await waitFor ( ( ) => {
@@ -338,7 +378,7 @@ describe('AddComponentsPopover', () => {
338378 expect ( popoverWrapper ) . toBeInTheDocument ( ) ;
339379 } ) ;
340380
341- it ( 'should handle empty registry' , async ( ) => {
381+ it ( 'should handle empty registry gracefully ' , async ( ) => {
342382 // Mock empty registry
343383 mockUseEditorStore . mockImplementation ( ( selector ) => {
344384 const state = {
@@ -359,11 +399,28 @@ describe('AddComponentsPopover', () => {
359399 await waitFor ( ( ) => {
360400 expect ( screen . getByText ( 'No components found' ) ) . toBeInTheDocument ( ) ;
361401 } ) ;
402+
403+ // Should not render tabs when no components
404+ expect ( screen . queryByRole ( 'tablist' ) ) . not . toBeInTheDocument ( ) ;
362405 } ) ;
363- } ) ;
364406
365- describe ( 'Component Item Functionality' , ( ) => {
366- it ( 'should handle component selection via GroupedComponentItem' , async ( ) => {
407+ it ( 'should handle single group with single tab' , async ( ) => {
408+ // Mock registry with only one group
409+ const singleGroupRegistry = {
410+ Button : {
411+ component : ( ) => null ,
412+ name : 'Button' ,
413+ from : '@/components/ui/button'
414+ } ,
415+ } ;
416+
417+ mockUseEditorStore . mockImplementation ( ( selector ) => {
418+ const state = {
419+ registry : singleGroupRegistry ,
420+ } ;
421+ return selector ( state as any ) ;
422+ } ) ;
423+
367424 render (
368425 < AddComponentsPopover parentLayerId = "parent-1" >
369426 < button > Add Component</ button >
@@ -374,31 +431,16 @@ describe('AddComponentsPopover', () => {
374431 fireEvent . click ( trigger ) ;
375432
376433 await waitFor ( ( ) => {
377- expect ( screen . getByText ( 'Input' ) ) . toBeInTheDocument ( ) ;
434+ expect ( screen . getByText ( 'Ui' ) ) . toBeInTheDocument ( ) ;
435+ expect ( screen . getByText ( 'Button' ) ) . toBeInTheDocument ( ) ;
378436 } ) ;
379-
380- const inputOption = screen . getByText ( 'Input' ) ;
381- fireEvent . click ( inputOption ) ;
382-
383- expect ( mockAddComponentLayer ) . toHaveBeenCalledWith ( 'Input' , 'parent-1' , undefined ) ;
384437 } ) ;
438+ } ) ;
385439
386- it ( 'should handle component with missing registry entry gracefully' , async ( ) => {
387- // Test selecting a component that might not be in registry
388- mockUseEditorStore . mockImplementation ( ( selector ) => {
389- const state = {
390- registry : {
391- // Missing some components that might be referenced
392- } ,
393- } ;
394- return selector ( state as any ) ;
395- } ) ;
396-
440+ describe ( 'Component Preview Boxes' , ( ) => {
441+ it ( 'should render grey preview boxes for each component' , async ( ) => {
397442 render (
398- < AddComponentsPopover
399- parentLayerId = "parent-1"
400- onChange = { mockOnChange }
401- >
443+ < AddComponentsPopover parentLayerId = "parent-1" >
402444 < button > Add Component</ button >
403445 </ AddComponentsPopover >
404446 ) ;
@@ -407,8 +449,18 @@ describe('AddComponentsPopover', () => {
407449 fireEvent . click ( trigger ) ;
408450
409451 await waitFor ( ( ) => {
410- expect ( screen . getByText ( 'No components found ' ) ) . toBeInTheDocument ( ) ;
452+ expect ( screen . getByText ( 'Button ' ) ) . toBeInTheDocument ( ) ;
411453 } ) ;
454+
455+ // Check for preview containers - these should exist even if lazy loading is happening
456+ const previewContainers = screen . getAllByRole ( 'generic' ) . filter ( el =>
457+ el . className . includes ( 'flex-shrink-0' ) &&
458+ el . className . includes ( 'w-10' ) &&
459+ el . className . includes ( 'h-8' )
460+ ) ;
461+
462+ // Should have at least one preview container for components in the active tab
463+ expect ( previewContainers . length ) . toBeGreaterThan ( 0 ) ;
412464 } ) ;
413465 } ) ;
414466
0 commit comments