@@ -78,6 +78,60 @@ test("documentation examples are tracked source files with recorded successful v
7878 }
7979} ) ;
8080
81+ test ( "documentation sidebar expands only the current route path" , async ( ) => {
82+ run ( "node" , [ "scripts/build-blog.mjs" ] ) ;
83+ run ( "node" , [ "scripts/build-docs.mjs" ] ) ;
84+
85+ const cases = [
86+ {
87+ route : "../public/docs/index.html" ,
88+ openGroup : null ,
89+ openBranches : [ ] ,
90+ active : "RustScript Documentation" ,
91+ } ,
92+ {
93+ route : "../public/docs/learn/embed-pd-vm/index.html" ,
94+ openGroup : "Getting Started" ,
95+ openBranches : [ ] ,
96+ active : "Use in Rust projects" ,
97+ } ,
98+ {
99+ route : "../public/docs/reference/rss/builtins/global/index.html" ,
100+ openGroup : "Reference" ,
101+ openBranches : [ "Syntax Cheatsheet" , "Builtins" ] ,
102+ active : "Global functions" ,
103+ } ,
104+ {
105+ route : "../public/docs/reference/ironrust/internals/index.html" ,
106+ openGroup : "Ecosystem" ,
107+ openBranches : [ "IronRust" ] ,
108+ active : "Internals" ,
109+ } ,
110+ ] ;
111+
112+ for ( const expected of cases ) {
113+ const html = await readFile ( new URL ( expected . route , import . meta. url ) , "utf8" ) ;
114+ const window = new Window ( ) ;
115+ window . document . write ( html ) ;
116+
117+ const groups = [ ...window . document . querySelectorAll ( "details.docs-nav-section" ) ] ;
118+ assert . deepEqual ( groups . map ( ( group ) => group . firstElementChild . textContent . trim ( ) ) , [
119+ "Getting Started" , "Reference" , "Ecosystem" , "Contribute" , "About" ,
120+ ] ) ;
121+ assert . deepEqual (
122+ groups . filter ( ( group ) => group . hasAttribute ( "open" ) ) . map ( ( group ) => group . firstElementChild . textContent . trim ( ) ) ,
123+ expected . openGroup ? [ expected . openGroup ] : [ ] ,
124+ ) ;
125+ assert . deepEqual (
126+ [ ...window . document . querySelectorAll ( "details.docs-nav-branch[open] > summary > a" ) ]
127+ . map ( ( link ) => link . textContent . trim ( ) ) ,
128+ expected . openBranches ,
129+ ) ;
130+ assert . equal ( window . document . querySelector ( '[aria-current="page"]' ) ?. textContent . trim ( ) , expected . active ) ;
131+ window . close ( ) ;
132+ }
133+ } ) ;
134+
81135test ( "Use in Rust projects renders verified Rust and highlighted TOML" , async ( ) => {
82136 run ( "node" , [ "scripts/build-blog.mjs" ] ) ;
83137 run ( "node" , [ "scripts/build-docs.mjs" ] ) ;
@@ -159,9 +213,10 @@ test("API reference covers every catalog entry and renders nested module navigat
159213 const globalHtml = await readFile ( new URL ( "../public/docs/reference/rss/builtins/global/index.html" , import . meta. url ) , "utf8" ) ;
160214 const window = new Window ( ) ;
161215 window . document . write ( globalHtml ) ;
162- const syntaxLink = [ ...window . document . querySelectorAll ( ".docs-nav-item > a" ) ] . find ( ( link ) => link . textContent === "Syntax Cheatsheet" ) ;
216+ const syntaxLink = [ ...window . document . querySelectorAll ( ".docs-nav-item a" ) ] . find ( ( link ) => link . textContent === "Syntax Cheatsheet" ) ;
163217 assert . ok ( syntaxLink ) ;
164- const syntaxChildren = [ ...syntaxLink . parentElement . children ] . find ( ( element ) => element . classList . contains ( "docs-nav-children" ) ) ;
218+ const syntaxBranch = syntaxLink . closest ( "details.docs-nav-branch" ) ;
219+ const syntaxChildren = [ ...syntaxBranch . children ] . find ( ( element ) => element . classList . contains ( "docs-nav-children" ) ) ;
165220 const sectionItems = [ ...syntaxChildren . children ] ;
166221 assert . deepEqual ( sectionItems . map ( ( item ) => item . firstElementChild . textContent ) , [ "Builtins" , "Stdlibs" ] ) ;
167222 const builtinsChildren = [ ...sectionItems [ 0 ] . children ] . find ( ( element ) => element . classList . contains ( "docs-nav-children" ) ) ;
@@ -214,10 +269,11 @@ test("IronRust documents the checked-in WinForms example and its implementation
214269 assert . ok ( internalsText . includes ( expected ) , `IronRust internals missing ${ expected } ` ) ;
215270 }
216271
217- const ironRustLink = [ ...window . document . querySelectorAll ( ".docs-nav-item > a" ) ]
272+ const ironRustLink = [ ...window . document . querySelectorAll ( ".docs-nav-item a" ) ]
218273 . find ( ( link ) => link . textContent === "IronRust" ) ;
219274 assert . ok ( ironRustLink ) ;
220- const children = [ ...ironRustLink . parentElement . children ]
275+ const ironRustBranch = ironRustLink . closest ( "details.docs-nav-branch" ) ;
276+ const children = [ ...ironRustBranch . children ]
221277 . find ( ( element ) => element . classList . contains ( "docs-nav-children" ) ) ;
222278 assert . deepEqual (
223279 [ ...children . children ] . map ( ( item ) => item . firstElementChild . textContent ) ,
@@ -263,11 +319,11 @@ test("documentation generator emits the main routes", async () => {
263319 assert . match ( rssHtml , / a r i a - l a b e l = " D o c u m e n t a t i o n n a v i g a t i o n " / ) ;
264320 assert . match ( rssHtml , / h r e f = " \/ d o c s \/ r e f e r e n c e \/ r s s \/ " a r i a - c u r r e n t = " p a g e " > S y n t a x C h e a t s h e e t < \/ a > / ) ;
265321 assert . match ( rssHtml , / < h 1 i d = " s y n t a x - c h e a t s h e e t " > S y n t a x C h e a t s h e e t < \/ h 1 > / ) ;
266- assert . match ( rssHtml , / < h 2 > G e t t i n g S t a r t e d < \/ h 2 > / ) ;
267- assert . doesNotMatch ( rssHtml , / < h 2 > L e a r n < \/ h 2 > / ) ;
268- assert . match ( rssHtml , / < h 2 > E c o s y s t e m < \/ h 2 > / ) ;
269- assert . match ( rssHtml , / < d i v c l a s s = " d o c s - n a v - i t e m " > < a h r e f = " \/ d o c s \/ r e f e r e n c e \/ p d - e d g e \/ " > p d - e d g e < \/ a > < d i v c l a s s = " d o c s - n a v - c h i l d r e n " > [ \s \S ] * h r e f = " \/ d o c s \/ r e f e r e n c e \/ p d - e d g e \/ f u l l - d a g \/ " > F u l l D A G G r a p h s < \/ a > / ) ;
270- assert . match ( rssHtml , / < d i v c l a s s = " d o c s - n a v - i t e m " > < a h r e f = " \/ d o c s \/ r e f e r e n c e \/ r u s t s c r i p t \/ " > R u s t S c r i p t < \/ a > < d i v c l a s s = " d o c s - n a v - c h i l d r e n " > [ \s \S ] * h r e f = " \/ d o c s \/ r e f e r e n c e \/ r u s t s c r i p t \/ d e v e l o p m e n t \/ " > D e v e l o p m e n t a n d t o o l i n g < \/ a > / ) ;
322+ assert . match ( rssHtml , / < d e t a i l s c l a s s = " d o c s - n a v - s e c t i o n " > < s u m m a r y > G e t t i n g S t a r t e d < \/ s u m m a r y > / ) ;
323+ assert . doesNotMatch ( rssHtml , / < s u m m a r y > L e a r n < \/ s u m m a r y > / ) ;
324+ assert . match ( rssHtml , / < d e t a i l s c l a s s = " d o c s - n a v - s e c t i o n " > < s u m m a r y > E c o s y s t e m < \/ s u m m a r y > / ) ;
325+ assert . match ( rssHtml , / < d e t a i l s c l a s s = " d o c s - n a v - i t e m d o c s - n a v - b r a n c h " > < s u m m a r y > < a h r e f = " \/ d o c s \/ r e f e r e n c e \/ p d - e d g e \/ " > p d - e d g e < \/ a > < \/ s u m m a r y > < d i v c l a s s = " d o c s - n a v - c h i l d r e n " > [ \s \S ] * h r e f = " \/ d o c s \/ r e f e r e n c e \/ p d - e d g e \/ f u l l - d a g \/ " > F u l l D A G G r a p h s < \/ a > / ) ;
326+ assert . match ( rssHtml , / < d e t a i l s c l a s s = " d o c s - n a v - i t e m d o c s - n a v - b r a n c h " > < s u m m a r y > < a h r e f = " \/ d o c s \/ r e f e r e n c e \/ r u s t s c r i p t \/ " > R u s t S c r i p t < \/ a > < \/ s u m m a r y > < d i v c l a s s = " d o c s - n a v - c h i l d r e n " > [ \s \S ] * h r e f = " \/ d o c s \/ r e f e r e n c e \/ r u s t s c r i p t \/ d e v e l o p m e n t \/ " > D e v e l o p m e n t a n d t o o l i n g < \/ a > / ) ;
271327 assert . doesNotMatch ( rssHtml , / > [ ^ < ] * r e f e r e n c e < \/ h 1 > / i) ;
272328 assert . match ( rssHtml , / < t a b l e c l a s s = " d o c s - t a b l e " > / ) ;
273329 assert . match ( rssHtml , / < s p a n c l a s s = " t o k - k w " > u s e < \/ s p a n > / ) ;
0 commit comments