11import React from 'react' ;
22import { useLocation } from '@reach/router' ;
3- import { render , screen , waitFor } from '@testing-library/react' ;
4- import userEvent from '@testing-library/user-event' ;
3+ import { render , screen } from '@testing-library/react' ;
54import LeftSidebar from './LeftSidebar' ;
65import { useLayoutContext } from 'src/contexts/layout-context' ;
76
@@ -14,6 +13,7 @@ jest.mock('src/contexts/layout-context', () => ({
1413 language : 'javascript' ,
1514 product : null ,
1615 template : null ,
16+ hasProductBar : false ,
1717 } ,
1818 } ) ,
1919} ) ) ;
@@ -37,10 +37,14 @@ jest.mock('gatsby', () => ({
3737} ) ) ;
3838
3939jest . mock ( '../Link' , ( ) => {
40- const MockLink : React . FC < { children : React . ReactNode ; to : string } > = ( { children, to, ...props } ) => (
41- < a href = { to } { ...props } >
42- { children }
43- </ a >
40+ // eslint-disable-next-line @typescript-eslint/no-var-requires
41+ const { forwardRef } = require ( 'react' ) ;
42+ const MockLink = forwardRef (
43+ ( { children, to, ...props } : { children : React . ReactNode ; to : string } , ref : React . Ref < HTMLAnchorElement > ) => (
44+ < a href = { to } ref = { ref } { ...props } >
45+ { children }
46+ </ a >
47+ ) ,
4448 ) ;
4549 MockLink . displayName = 'MockLink' ;
4650 return MockLink ;
@@ -53,20 +57,22 @@ describe('LeftSidebar', () => {
5357 beforeEach ( ( ) => {
5458 mockUseLayoutContext . mockReturnValue ( {
5559 activePage : {
56- page : { name : 'Introduction ' , link : '/platform/intro ' } ,
60+ page : { name : 'About Ably ' , link : '/docs/platform ' } ,
5761 tree : [
5862 { index : 0 , page : { name : 'Platform' , link : '/platform' } } ,
59- { index : 0 , page : { name : 'Introduction ' , link : '/platform/intro ' } } ,
63+ { index : 0 , page : { name : 'About Ably ' , link : '/docs/platform ' } } ,
6064 ] ,
6165 languages : [ ] ,
6266 language : 'javascript' ,
6367 product : 'platform' ,
6468 template : null ,
69+ hasProductBar : false ,
6570 } ,
6671 } ) ;
6772
6873 mockUseLocation . mockReturnValue ( {
69- pathname : '/platform/intro' ,
74+ pathname : '/docs/platform' ,
75+ search : '' ,
7076 } ) ;
7177
7278 const mockIntersectionObserver = jest . fn ( ) ;
@@ -84,98 +90,40 @@ describe('LeftSidebar', () => {
8490 jest . clearAllMocks ( ) ;
8591 } ) ;
8692
87- it ( 'renders the sidebar with products ' , ( ) => {
93+ it ( 'renders nav content for the active product only ' , ( ) => {
8894 render ( < LeftSidebar /> ) ;
89- expect ( screen . getByRole ( 'button' , { name : 'Platform' } ) ) . toBeInTheDocument ( ) ;
90- expect ( screen . getByRole ( 'button' , { name : 'Ably Pub/Sub' } ) ) . toBeInTheDocument ( ) ;
91- } ) ;
92-
93- it ( 'shows Platform accordion expanded with first three child items when active page is under Platform' , async ( ) => {
94- render ( < LeftSidebar /> ) ;
95-
96- // Platform should be auto-expanded since active page is under Platform (index 0)
97- await waitFor ( ( ) => {
98- expect ( screen . getByText ( 'About Ably' ) ) . toBeInTheDocument ( ) ;
99- expect ( screen . getByText ( 'Architecture' ) ) . toBeInTheDocument ( ) ;
100- expect ( screen . getByText ( 'Products and SDKs' ) ) . toBeInTheDocument ( ) ;
101- } ) ;
102-
103- // Verify these are clickable accordion triggers
104- const aboutAblyButton = screen . getByText ( 'About Ably' ) . closest ( 'button' ) ;
105- const archButton = screen . getByText ( 'Architecture' ) . closest ( 'button' ) ;
106- const productsButton = screen . getByText ( 'Products and SDKs' ) . closest ( 'button' ) ;
95+ // Platform nav sections should be present
96+ expect ( screen . getByText ( 'About Ably' ) ) . toBeInTheDocument ( ) ;
97+ expect ( screen . getByText ( 'Architecture' ) ) . toBeInTheDocument ( ) ;
10798
108- expect ( aboutAblyButton ) . toBeInTheDocument ( ) ;
109- expect ( archButton ) . toBeInTheDocument ( ) ;
110- expect ( productsButton ) . toBeInTheDocument ( ) ;
99+ // Other products should NOT appear
100+ expect ( screen . queryByText ( 'Ably Pub/Sub' ) ) . not . toBeInTheDocument ( ) ;
101+ expect ( screen . queryByText ( 'Ably Chat' ) ) . not . toBeInTheDocument ( ) ;
111102 } ) ;
112103
113- it ( 'expands Platform/Architecture accordion and shows first three child items' , async ( ) => {
114- const user = userEvent . setup ( ) ;
115- render ( < LeftSidebar /> ) ;
116-
117- // Platform should be auto-expanded since active page is under Platform (index 0)
118- await waitFor ( ( ) => {
119- expect ( screen . getByText ( 'Architecture' ) ) . toBeInTheDocument ( ) ;
120- } ) ;
121-
122- // Architecture children should not be visible yet
123- expect ( screen . queryByText ( 'Overview' ) ) . not . toBeInTheDocument ( ) ;
124- expect ( screen . queryByText ( 'Edge network' ) ) . not . toBeInTheDocument ( ) ;
125- expect ( screen . queryByText ( 'Infrastructure operations' ) ) . not . toBeInTheDocument ( ) ;
126-
127- // Find and click Architecture button to expand it
128- const architectureButton = screen . getByText ( 'Architecture' ) . closest ( 'button' ) ;
129- if ( ! architectureButton ) {
130- throw new Error ( 'Architecture button not found' ) ;
131- }
132- await user . click ( architectureButton ) ;
133-
134- // After clicking, verify the first three child items are visible
135- await waitFor ( ( ) => {
136- expect ( screen . getByText ( 'Overview' ) ) . toBeInTheDocument ( ) ;
137- expect ( screen . getByText ( 'Edge network' ) ) . toBeInTheDocument ( ) ;
138- expect ( screen . getByText ( 'Infrastructure operations' ) ) . toBeInTheDocument ( ) ;
104+ it ( 'shows placeholder when no product is active' , ( ) => {
105+ mockUseLayoutContext . mockReturnValue ( {
106+ activePage : {
107+ page : { name : '' , link : '' } ,
108+ tree : [ ] ,
109+ languages : [ ] ,
110+ language : 'javascript' ,
111+ product : null ,
112+ template : null ,
113+ hasProductBar : false ,
114+ } ,
139115 } ) ;
140116
141- // Verify these are links (leaf nodes) not accordion triggers
142- const overviewLink = screen . getByText ( 'Overview' ) . closest ( 'a' ) ;
143- const edgeNetworkLink = screen . getByText ( 'Edge network' ) . closest ( 'a' ) ;
144- const infrastructureLink = screen . getByText ( 'Infrastructure operations' ) . closest ( 'a' ) ;
145-
146- expect ( overviewLink ) . toBeInTheDocument ( ) ;
147- expect ( edgeNetworkLink ) . toBeInTheDocument ( ) ;
148- expect ( infrastructureLink ) . toBeInTheDocument ( ) ;
117+ render ( < LeftSidebar /> ) ;
118+ expect ( screen . getByText ( 'Select a product above to browse documentation.' ) ) . toBeInTheDocument ( ) ;
149119 } ) ;
150120
151- it ( 'clicks Ably Pub/Sub to expand Pub/Sub showing first three child items' , async ( ) => {
152- const user = userEvent . setup ( ) ;
121+ it ( 'renders top-level sections as static headings' , ( ) => {
153122 render ( < LeftSidebar /> ) ;
154-
155- // Platform should be auto-expanded since active page is under Platform (index 0)
156- await waitFor ( ( ) => {
157- expect ( screen . getByText ( 'Architecture' ) ) . toBeInTheDocument ( ) ;
158- } ) ;
159-
160- // Pub/Sub children should not be visible initially
161- expect ( screen . queryByText ( 'About Pub/Sub' ) ) . not . toBeInTheDocument ( ) ;
162- expect ( screen . queryByText ( 'Getting started' ) ) . not . toBeInTheDocument ( ) ;
163-
164- // Click on Ably Pub/Sub button to expand it (type="multiple" so Platform stays open)
165- const pubsubButton = screen . getByRole ( 'button' , { name : 'Ably Pub/Sub' } ) ;
166- await user . click ( pubsubButton ) ;
167-
168- // After clicking, verify the Pub/Sub child accordion items appear
169- await waitFor ( ( ) => {
170- expect ( screen . getByText ( 'About Pub/Sub' ) ) . toBeInTheDocument ( ) ;
171- expect ( screen . getByText ( 'Getting started' ) ) . toBeInTheDocument ( ) ;
172- } ) ;
173-
174- // Verify both product sections are visible (Platform has "About Ably", Pub/Sub has "About Pub/Sub")
175- expect ( screen . getByText ( 'About Ably' ) ) . toBeInTheDocument ( ) ;
176- expect ( screen . getByText ( 'About Pub/Sub' ) ) . toBeInTheDocument ( ) ;
177-
178- // Platform's Architecture should still be visible since accordion type is "multiple"
179- expect ( screen . getByText ( 'Architecture' ) ) . toBeInTheDocument ( ) ;
123+ // Top-level sections render as plain headings, not accordion triggers
124+ const sectionHeading = screen . getByText ( 'Getting started' ) ;
125+ expect ( sectionHeading ) . toBeInTheDocument ( ) ;
126+ // Should not be inside an accordion trigger button
127+ expect ( sectionHeading . closest ( 'button' ) ) . toBeNull ( ) ;
180128 } ) ;
181129} ) ;
0 commit comments