@@ -3,7 +3,7 @@ import * as common from '../common/index.mjs';
33import { describe , it } from 'node:test' ;
44import assert from 'node:assert' ;
55import { spawn } from 'node:child_process' ;
6- import { writeFileSync } from 'node:fs' ;
6+ import { writeFileSync , renameSync , unlinkSync , existsSync } from 'node:fs' ;
77import util from 'internal/util' ;
88import tmpdir from '../common/tmpdir.js' ;
99
@@ -30,7 +30,7 @@ const fixturePaths = Object.keys(fixtureContent)
3030Object . entries ( fixtureContent )
3131 . forEach ( ( [ file , content ] ) => writeFileSync ( fixturePaths [ file ] , content ) ) ;
3232
33- async function testWatch ( { fileToUpdate, file } ) {
33+ async function testWatch ( { fileToUpdate, file, action = 'update' } ) {
3434 const ran1 = util . createDeferredPromise ( ) ;
3535 const ran2 = util . createDeferredPromise ( ) ;
3636 const child = spawn ( process . execPath ,
@@ -48,6 +48,7 @@ async function testWatch({ fileToUpdate, file }) {
4848 if ( testRuns ?. length >= 2 ) ran2 . resolve ( ) ;
4949 } ) ;
5050
51+ if ( action === 'update' ) {
5152 await ran1 . promise ;
5253 runs . push ( currentRun ) ;
5354 currentRun = '' ;
@@ -58,11 +59,51 @@ async function testWatch({ fileToUpdate, file }) {
5859 runs . push ( currentRun ) ;
5960 clearInterval ( interval ) ;
6061 child . kill ( ) ;
62+ for ( const run of runs ) {
63+ assert . match ( run , / # t e s t s 1 / ) ;
64+ assert . match ( run , / # p a s s 1 / ) ;
65+ assert . match ( run , / # f a i l 0 / ) ;
66+ assert . match ( run , / # c a n c e l l e d 0 / ) ;
67+ }
68+ } else if ( action === 'rename' ) {
69+ await ran1 . promise ;
70+ runs . push ( currentRun ) ;
71+ currentRun = '' ;
72+ const fileToRenamePath = tmpdir . resolve ( fileToUpdate ) ;
73+ const newFileNamePath = tmpdir . resolve ( `test-renamed-${ fileToUpdate } ` ) ;
74+ const interval = setInterval ( ( ) => renameSync ( fileToRenamePath , newFileNamePath ) , common . platformTimeout ( 1000 ) ) ;
75+ await ran2 . promise ;
76+ runs . push ( currentRun ) ;
77+ clearInterval ( interval ) ;
78+ child . kill ( ) ;
79+
6180 for ( const run of runs ) {
6281 assert . match ( run , / # t e s t s 1 / ) ;
6382 assert . match ( run , / # p a s s 1 / ) ;
6483 assert . match ( run , / # f a i l 0 / ) ;
6584 assert . match ( run , / # c a n c e l l e d 0 / ) ;
85+ }
86+ } else if ( action === 'delete' ) {
87+ await ran1 . promise ;
88+ runs . push ( currentRun ) ;
89+ currentRun = '' ;
90+ const fileToDeletePath = tmpdir . resolve ( fileToUpdate ) ;
91+ const interval = setInterval ( ( ) => {
92+ if ( existsSync ( fileToDeletePath ) ) {
93+ unlinkSync ( fileToDeletePath )
94+ } else {
95+ ran2 . resolve ( ) ;
96+ }
97+ } , common . platformTimeout ( 1000 ) ) ;
98+ await ran2 . promise ;
99+
100+ runs . push ( currentRun ) ;
101+ clearInterval ( interval ) ;
102+ child . kill ( ) ;
103+
104+ for ( const run of runs ) {
105+ assert . doesNotMatch ( run , / M O D U L E _ N O T _ F O U N D / )
106+ }
66107 }
67108}
68109
@@ -82,4 +123,12 @@ describe('test runner watch mode', () => {
82123 it ( 'should support running tests without a file' , async ( ) => {
83124 await testWatch ( { fileToUpdate : 'test.js' } ) ;
84125 } ) ;
126+
127+ it ( 'should support a watched test file rename' , async ( ) => {
128+ await testWatch ( { fileToUpdate : 'test.js' , action : 'rename' } ) ;
129+ } ) ;
130+
131+ it ( 'should not throw when delete a watched test file' , async ( ) => {
132+ await testWatch ( { fileToUpdate : 'test.js' , action : 'delete' } ) ;
133+ } ) ;
85134} ) ;
0 commit comments