33 */
44
55import { describe , expect , it , vi } from 'vitest' ;
6- import { createTicker , isNoColor } from './ticker.js' ;
6+ import { createTicker , isNoColor , type Ticker } from './ticker.js' ;
7+
8+ /** TTY tests that expect ANSI in-place updates. CI sets NO_COLOR=1, so opt out explicitly. */
9+ function createTtyTicker (
10+ stderrWrite : ( line : string ) => void = ( ) => { } ,
11+ stderrRaw ?: ( text : string ) => void ,
12+ ) : Ticker {
13+ return createTicker ( stderrWrite , true , stderrRaw , false ) ;
14+ }
715
816describe ( 'createTicker — non-TTY (CI mode)' , ( ) => {
917 it ( 'update is a no-op (no writes)' , ( ) => {
@@ -58,11 +66,7 @@ function stripTickerTimestamp(raw: string): string {
5866describe ( 'createTicker — TTY mode' , ( ) => {
5967 it ( 'update writes ANSI clear-line + carriage-return + content via rawWrite' , ( ) => {
6068 const raw : string [ ] = [ ] ;
61- const ticker = createTicker (
62- ( ) => { } ,
63- true , // isTTY = true
64- text => raw . push ( text ) ,
65- ) ;
69+ const ticker = createTtyTicker ( ( ) => { } , text => raw . push ( text ) ) ;
6670 ticker . update ( 'Run run_abc — running (3/8 steps elapsed=12s)' ) ;
6771 expect ( raw ) . toHaveLength ( 1 ) ;
6872 expect ( stripTickerTimestamp ( raw [ 0 ] ! ) ) . toBe (
@@ -72,11 +76,7 @@ describe('createTicker — TTY mode', () => {
7276
7377 it ( 'update rewrites the line on each call (in-place update)' , ( ) => {
7478 const raw : string [ ] = [ ] ;
75- const ticker = createTicker (
76- ( ) => { } ,
77- true ,
78- text => raw . push ( text ) ,
79- ) ;
79+ const ticker = createTtyTicker ( ( ) => { } , text => raw . push ( text ) ) ;
8080 ticker . update ( 'first tick' ) ;
8181 ticker . update ( 'second tick' ) ;
8282 ticker . update ( 'third tick' ) ;
@@ -88,11 +88,7 @@ describe('createTicker — TTY mode', () => {
8888
8989 it ( 'finalize with a final line emits the line then a newline' , ( ) => {
9090 const raw : string [ ] = [ ] ;
91- const ticker = createTicker (
92- ( ) => { } ,
93- true ,
94- text => raw . push ( text ) ,
95- ) ;
91+ const ticker = createTtyTicker ( ( ) => { } , text => raw . push ( text ) ) ;
9692 ticker . update ( 'working' ) ;
9793 ticker . finalize ( 'done — passed' ) ;
9894 // Expect: clear+carriage-return+line, then \n
@@ -103,11 +99,7 @@ describe('createTicker — TTY mode', () => {
10399
104100 it ( 'finalize without args emits just a newline when something was written' , ( ) => {
105101 const raw : string [ ] = [ ] ;
106- const ticker = createTicker (
107- ( ) => { } ,
108- true ,
109- text => raw . push ( text ) ,
110- ) ;
102+ const ticker = createTtyTicker ( ( ) => { } , text => raw . push ( text ) ) ;
111103 ticker . update ( 'progress' ) ;
112104 ticker . finalize ( ) ;
113105 // Last call should be '\n' to flush the line
@@ -116,11 +108,7 @@ describe('createTicker — TTY mode', () => {
116108
117109 it ( 'finalize without args emits nothing when nothing was written' , ( ) => {
118110 const raw : string [ ] = [ ] ;
119- const ticker = createTicker (
120- ( ) => { } ,
121- true ,
122- text => raw . push ( text ) ,
123- ) ;
111+ const ticker = createTtyTicker ( ( ) => { } , text => raw . push ( text ) ) ;
124112 // No update calls
125113 ticker . finalize ( ) ;
126114 // Nothing should have been written (lastLength is 0)
@@ -129,11 +117,7 @@ describe('createTicker — TTY mode', () => {
129117
130118 it ( 'finalize without args but with prior update — emits newline only' , ( ) => {
131119 const raw : string [ ] = [ ] ;
132- const ticker = createTicker (
133- ( ) => { } ,
134- true ,
135- text => raw . push ( text ) ,
136- ) ;
120+ const ticker = createTtyTicker ( ( ) => { } , text => raw . push ( text ) ) ;
137121 ticker . update ( 'x' ) ;
138122 const lengthAfterUpdate = raw . length ;
139123 ticker . finalize ( ) ;
@@ -144,11 +128,7 @@ describe('createTicker — TTY mode', () => {
144128
145129 it ( 'multiple finalize calls only move to fresh line once (idempotent-ish)' , ( ) => {
146130 const raw : string [ ] = [ ] ;
147- const ticker = createTicker (
148- ( ) => { } ,
149- true ,
150- text => raw . push ( text ) ,
151- ) ;
131+ const ticker = createTtyTicker ( ( ) => { } , text => raw . push ( text ) ) ;
152132 ticker . update ( 'something' ) ;
153133 ticker . finalize ( ) ;
154134 const lenAfterFirst = raw . length ;
@@ -178,11 +158,7 @@ describe('createTicker — stderrWrite dependency injection', () => {
178158 it ( 'does not call stderrWrite during update on TTY (rawWrite used instead)' , ( ) => {
179159 const stderrLines : string [ ] = [ ] ;
180160 const raw : string [ ] = [ ] ;
181- const ticker = createTicker (
182- line => stderrLines . push ( line ) ,
183- true ,
184- text => raw . push ( text ) ,
185- ) ;
161+ const ticker = createTtyTicker ( line => stderrLines . push ( line ) , text => raw . push ( text ) ) ;
186162 ticker . update ( 'progress' ) ;
187163 // stderrWrite should not be called (rawWrite handles TTY in-place updates)
188164 expect ( stderrLines ) . toHaveLength ( 0 ) ;
@@ -192,11 +168,7 @@ describe('createTicker — stderrWrite dependency injection', () => {
192168 it ( 'stderrWrite is referenced in finalize (no unused-var warning)' , ( ) => {
193169 // This is purely a compilation concern but we verify no throws.
194170 const stderrLines : string [ ] = [ ] ;
195- const ticker = createTicker (
196- line => stderrLines . push ( line ) ,
197- true ,
198- ( ) => { } ,
199- ) ;
171+ const ticker = createTtyTicker ( line => stderrLines . push ( line ) , ( ) => { } ) ;
200172 expect ( ( ) => ticker . finalize ( 'line' ) ) . not . toThrow ( ) ;
201173 } ) ;
202174} ) ;
@@ -209,7 +181,8 @@ describe('createTicker — spy on process.stderr', () => {
209181 const ticker = createTicker (
210182 ( ) => { } ,
211183 true , // force TTY
212- // No stderrRaw — should default to process.stderr.write
184+ undefined , // stderrRaw — should default to process.stderr.write
185+ false , // CI sets NO_COLOR=1; this test asserts ANSI rawWrite path
213186 ) ;
214187 ticker . update ( 'test line' ) ;
215188 // The ticker prepends an ISO timestamp; verify the call happened and
0 commit comments