@@ -591,12 +591,12 @@ describe("renderInfo", () => {
591591describe ( "parseEnvinfoSections" , ( ) => {
592592 it ( "returns one section per heading" , ( ) => {
593593 const sections = parseEnvinfoSections ( ENVINFO_FIXTURE ) ;
594- expect ( sections . map ( ( s ) => s . title ) ) . toEqual ( [ "System" , "Binaries" , "Packages" ] ) ;
594+ expect ( sections . map ( ( section ) => section . title ) ) . toEqual ( [ "System" , "Binaries" , "Packages" ] ) ;
595595 } ) ;
596596
597597 it ( "parses key/value rows correctly" , ( ) => {
598598 const sections = parseEnvinfoSections ( ENVINFO_FIXTURE ) ;
599- const system = sections . find ( ( s ) => s . title === "System" ) ;
599+ const system = sections . find ( ( section ) => section . title === "System" ) ;
600600 expect ( system . rows ) . toEqual (
601601 expect . arrayContaining ( [ expect . objectContaining ( { label : "OS" , value : "macOS 14.0" } ) ] ) ,
602602 ) ;
@@ -608,17 +608,86 @@ describe("parseEnvinfoSections", () => {
608608
609609 it ( "skips sections with no parseable rows" , ( ) => {
610610 const sections = parseEnvinfoSections ( "\n Empty:\n\n Real:\n Key: value\n" ) ;
611- const titles = sections . map ( ( s ) => s . title ) ;
611+ const titles = sections . map ( ( section ) => section . title ) ;
612612 expect ( titles ) . not . toContain ( "Empty" ) ;
613613 expect ( titles ) . toContain ( "Real" ) ;
614614 } ) ;
615615
616+ it ( "sets value to 'N/A' for a row with no value" , ( ) => {
617+ const sections = parseEnvinfoSections ( "\n Browsers:\n Chrome:\n Node: 20.0.0\n" ) ;
618+ const chrome = sections [ 0 ] . rows . find ( ( row ) => row . label === "Chrome" ) ;
619+ expect ( chrome . value ) . toBe ( "N/A" ) ;
620+ } ) ;
621+
622+ it ( "attaches a passthrough color function to an N/A row" , ( ) => {
623+ const sections = parseEnvinfoSections ( "\n Browsers:\n Chrome:\n" ) ;
624+ const chrome = sections [ 0 ] . rows . find ( ( row ) => row . label === "Chrome" ) ;
625+ expect ( chrome . color ) . toBeDefined ( ) ;
626+ expect ( chrome . color ( "test" ) ) . toBe ( "test" ) ;
627+ } ) ;
628+
629+ it ( "does not apply N/A or a color function to a row that has a value" , ( ) => {
630+ const sections = parseEnvinfoSections ( "\n Browsers:\n Node: 20.0.0\n" ) ;
631+ const node = sections [ 0 ] . rows . find ( ( row ) => row . label === "Node" ) ;
632+ expect ( node . value ) . toBe ( "20.0.0" ) ;
633+ expect ( node . color ) . toBeUndefined ( ) ;
634+ } ) ;
635+
636+ it ( "handles a section where every row is empty" , ( ) => {
637+ const sections = parseEnvinfoSections (
638+ "\n Browsers:\n Chrome:\n Firefox:\n Safari:\n" ,
639+ ) ;
640+ expect ( sections [ 0 ] . rows ) . toHaveLength ( 3 ) ;
641+ for ( const row of sections [ 0 ] . rows ) {
642+ expect ( row . value ) . toBe ( "N/A" ) ;
643+ expect ( row . color ( "x" ) ) . toBe ( "x" ) ;
644+ }
645+ } ) ;
646+
647+ it ( "handles mixed empty and valued rows in the same section" , ( ) => {
648+ const sections = parseEnvinfoSections (
649+ "\n Binaries:\n Node: 20.0.0\n Yarn:\n npm: 10.0.0\n pnpm:\n" ,
650+ ) ;
651+ // eslint-disable-next-line prefer-destructuring
652+ const rows = sections [ 0 ] . rows ;
653+ expect ( rows . find ( ( row ) => row . label === "Node" ) . value ) . toBe ( "20.0.0" ) ;
654+ expect ( rows . find ( ( row ) => row . label === "Yarn" ) . value ) . toBe ( "N/A" ) ;
655+ expect ( rows . find ( ( row ) => row . label === "npm" ) . value ) . toBe ( "10.0.0" ) ;
656+ expect ( rows . find ( ( row ) => row . label === "pnpm" ) . value ) . toBe ( "N/A" ) ;
657+ } ) ;
658+
659+ it ( "handles complex output with parentheses, paths, and multiple spaces" , ( ) => {
660+ const COMPLEX_FIXTURE = `
661+ System:
662+ OS: macOS 14.0 (23A344)
663+ CPU: (10) arm64 Apple M2 Pro
664+ Memory: 10.23 GB / 32.00 GB
665+ Binaries:
666+ Node: 20.9.0 - /usr/local/bin/node
667+ Yarn: 1.22.19 - ~/.yarn/bin/yarn
668+ npm:
669+ Utilities:
670+ Git: 2.39.3 (Apple Git-145)
671+ ` ;
672+
673+ const sections = parseEnvinfoSections ( COMPLEX_FIXTURE ) ;
674+ const system = sections . find ( ( str ) => str . title === "System" ) ;
675+ const binaries = sections . find ( ( str ) => str . title === "Binaries" ) ;
676+ const utilities = sections . find ( ( str ) => str . title === "Utilities" ) ;
677+ expect ( system . rows . find ( ( row ) => row . label === "OS" ) . value ) . toBe ( "macOS 14.0 (23A344)" ) ;
678+ expect ( system . rows . find ( ( row ) => row . label === "CPU" ) . value ) . toBe ( "(10) arm64 Apple M2 Pro" ) ;
679+ expect ( binaries . rows . find ( ( row ) => row . label === "Node" ) . value ) . toBe (
680+ "20.9.0 - /usr/local/bin/node" ,
681+ ) ;
682+ expect ( binaries . rows . find ( ( row ) => row . label === "npm" ) . value ) . toBe ( "N/A" ) ;
683+ expect ( utilities . rows . find ( ( row ) => row . label === "Git" ) . value ) . toBe ( "2.39.3 (Apple Git-145)" ) ;
684+ } ) ;
685+
616686 it ( "should match snapshot" , ( ) => {
617687 const sections = parseEnvinfoSections ( ENVINFO_FIXTURE ) ;
618- // strip color functions — not serialisable in snapshots
619- const serialisable = sections . map ( ( s ) => ( {
620- title : s . title ,
621- rows : s . rows . map ( ( { label, value } ) => ( { label, value } ) ) ,
688+ const serialisable = sections . map ( ( section ) => ( {
689+ title : section . title ,
690+ rows : section . rows . map ( ( { label, value } ) => ( { label, value } ) ) ,
622691 } ) ) ;
623692 expect ( serialisable ) . toMatchSnapshot ( ) ;
624693 } ) ;
0 commit comments