@@ -17,6 +17,22 @@ const fs = require("fs") as typeof import("fs");
1717const path = require ( "path" ) as typeof import ( "path" ) ;
1818const ts = require ( "typescript" ) as typeof import ( "typescript" ) ;
1919
20+ // Minimal ANSI coloring. Honors FORCE_COLOR / NO_COLOR and falls back to plain text when
21+ // stdout isn't a TTY (e.g. CI logs, pipes), so the output degrades gracefully.
22+ const useColor =
23+ ( process . env . FORCE_COLOR ?? "" ) !== "" || ( ! ! process . stdout . isTTY && ( process . env . NO_COLOR ?? "" ) === "" ) ;
24+ const paint =
25+ ( code : string ) =>
26+ ( s : string ) : string =>
27+ useColor ? `\x1b[${ code } m${ s } \x1b[0m` : s ;
28+ const green = paint ( "32" ) ;
29+ const red = paint ( "31" ) ;
30+ const cyan = paint ( "36" ) ;
31+ const bold = paint ( "1" ) ;
32+ const dim = paint ( "2" ) ;
33+ const tick = green ( "✓" ) ;
34+ const cross = red ( "✗" ) ;
35+
2036const TEST_DIR = __dirname ;
2137const ROOT = path . resolve ( TEST_DIR , ".." ) ;
2238
@@ -74,8 +90,11 @@ interface Result {
7490}
7591
7692const results : Array < Result > = [ ] ;
93+ let total = 0 ;
7794let failures = 0 ;
7895
96+ console . log ( bold ( `Type-level tests · ${ caseFiles . length } suite${ caseFiles . length === 1 ? "" : "s" } ` ) ) ;
97+
7998for ( const caseFile of caseFiles ) {
8099 const source = program . getSourceFile ( caseFile ) ;
81100 if ( ! source ) {
@@ -132,28 +151,31 @@ for (const caseFile of caseFiles) {
132151
133152 // ----- report for this file -----
134153
135- console . log ( `\n${ relName } ` ) ;
154+ console . log ( `\n${ bold ( cyan ( relName ) ) } ` ) ;
136155 for ( const r of results . filter ( r => r . file === relName ) ) {
137- console . log ( ` [${ r . ok ? "PASS" : "FAIL" } ] ${ r . name } (line ${ r . line } )` ) ;
156+ total ++ ;
157+ console . log ( ` ${ r . ok ? tick : cross } ${ r . name } ${ dim ( `(line ${ r . line } )` ) } ` ) ;
138158 if ( ! r . ok ) {
139- console . log ( ` expected: ${ r . expected } ` ) ;
140- console . log ( ` actual: ${ r . actual } ` ) ;
159+ console . log ( ` ${ dim ( " expected:" ) } ${ green ( r . expected ) } ` ) ;
160+ console . log ( ` ${ dim ( " actual: " ) } ${ red ( r . actual ) } ` ) ;
141161 }
142162 }
143163 for ( const line of errorLines ) {
164+ total ++ ;
144165 const expected = expectedErrorLines . has ( line ) ;
145166 const actual = actualErrors . has ( line ) ;
146167 const ok = expected && actual ;
147168 if ( ! ok ) failures ++ ;
148169 const stmt = ( rawLines [ line ] ?? "" ) . trim ( ) ;
149- console . log ( ` [ ${ ok ? "PASS" : "FAIL" } ] expect-error: ${ stmt } ( line ${ line + 1 } )` ) ;
150- if ( expected && ! actual ) console . log ( ` expected a type error here, but none was reported` ) ;
151- if ( ! expected && actual ) console . log ( ` unexpected type error: ${ actualErrors . get ( line ) } ` ) ;
170+ console . log ( ` ${ ok ? tick : cross } ${ dim ( " expect-error:" ) } ${ stmt } ${ dim ( `( line ${ line + 1 } )` ) } ` ) ;
171+ if ( expected && ! actual ) console . log ( ` ${ red ( " expected a type error here, but none was reported" ) } ` ) ;
172+ if ( ! expected && actual ) console . log ( ` ${ red ( ` unexpected type error: ${ actualErrors . get ( line ) } ` ) } ` ) ;
152173 }
153174}
154175
176+ const passed = total - failures ;
155177if ( failures > 0 ) {
156- console . error ( `\n${ failures } check(s) failed. ` ) ;
178+ console . error ( `\n${ cross } ${ bold ( red ( ` ${ failures } of ${ total } checks failed` ) ) } ${ dim ( `( ${ passed } passed)` ) } ` ) ;
157179 process . exit ( 1 ) ;
158180}
159- console . log ( "\nAll checks passed." ) ;
181+ console . log ( `\n ${ tick } ${ bold ( green ( `All ${ total } checks passed` ) ) } ` ) ;
0 commit comments