@@ -35,8 +35,8 @@ jest.mock('chokidar', () => {
3535
3636import * as fs from 'fs' ;
3737import * as path from 'path' ;
38- import * as os from 'os' ;
3938import * as cliProgram from '../src/cli/program' ;
39+ import { canonicalTmpDir } from './helpers/paths' ;
4040
4141const { createProgram, compileFile } = cliProgram ;
4242
@@ -47,9 +47,7 @@ const { createProgram, compileFile } = cliProgram;
4747 * We stub process.exit and console to keep the test runner alive and to assert outputs.
4848 */
4949
50- // TODO(windows-ci): this suite uses Windows 8.3 short paths and npm init in a temp
51- // directory; it needs explicit long-path handling before it can pass on win32.
52- ( process . platform === 'win32' ? describe . skip : describe ) ( 'CLI Program (in-process)' , ( ) => {
50+ describe ( 'CLI Program (in-process)' , ( ) => {
5351 let tempDir : string ;
5452 let originalCwd : string ;
5553 let originalExitCode : number | undefined ;
@@ -59,7 +57,7 @@ const { createProgram, compileFile } = cliProgram;
5957 let skipCleanup = false ;
6058
6159 beforeEach ( ( ) => {
62- tempDir = fs . mkdtempSync ( path . join ( os . tmpdir ( ) , 'somon-cli-program-' ) ) ;
60+ tempDir = canonicalTmpDir ( 'somon-cli-program-' ) ;
6361 originalCwd = process . cwd ( ) ;
6462 originalExitCode = process . exitCode ;
6563 consoleLogSpy = jest . spyOn ( console , 'log' ) . mockImplementation ( ( ) => { } ) ;
@@ -72,13 +70,27 @@ const { createProgram, compileFile } = cliProgram;
7270 // Config loader behavior is covered in tests/config.test.ts.
7371
7472 afterEach ( ( ) => {
73+ // Restore cwd FIRST — on Windows, rmSync on the current working
74+ // directory raises EBUSY, which would throw and leave the next suite
75+ // with a stale cwd pointing at a deleted temp dir.
76+ try {
77+ process . chdir ( originalCwd ) ;
78+ } catch {
79+ // originalCwd may itself be gone in pathological cases; swallow and
80+ // keep going so we still restore spies and exit code.
81+ }
82+
7583 // Cleanup temp dir
7684 if ( ! skipCleanup && fs . existsSync ( tempDir ) ) {
77- fs . rmSync ( tempDir , { recursive : true , force : true } ) ;
85+ try {
86+ fs . rmSync ( tempDir , { recursive : true , force : true } ) ;
87+ } catch {
88+ // Windows occasionally keeps file handles open briefly after a
89+ // subprocess exits; the OS will reclaim the temp dir, and a failed
90+ // cleanup here must not break subsequent suites.
91+ }
7892 }
7993
80- // Restore cwd
81- process . chdir ( originalCwd ) ;
8294 // Reset any exit code left by CLI handlers during tests
8395 process . exitCode = originalExitCode ?? 0 ;
8496 consoleLogSpy . mockRestore ( ) ;
0 commit comments