Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
159 changes: 158 additions & 1 deletion test/common/watch.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
'use strict';
const common = require('./index.js');
const tmpdir = require('./tmpdir.js');
const fixtures = require('./fixtures.js');
const { writeFileSync, readdirSync, readFileSync, renameSync, unlinkSync } = require('node:fs');
const { spawn } = require('node:child_process');
const { once } = require('node:events');
const assert = require('node:assert');
const { setTimeout } = require('node:timers/promises');

exports.skipIfNoWatchModeSignals = function() {
function skipIfNoWatch() {
if (common.isIBMi) {
common.skip('IBMi does not support `fs.watch()`');
}

if (common.isAIX) {
common.skip('folder watch capability is limited in AIX.');
}
}

function skipIfNoWatchModeSignals() {
if (common.isWindows) {
common.skip('no signals on Windows');
}
Expand All @@ -13,4 +30,144 @@ exports.skipIfNoWatchModeSignals = function() {
if (common.isAIX) {
common.skip('folder watch capability is limited in AIX.');
}
}

const fixturePaths = {};
const fixtureContent = {};

function refreshForTestRunnerWatch() {
tmpdir.refresh();
const files = readdirSync(fixtures.path('test-runner-watch'));
for (const file of files) {
const src = fixtures.path('test-runner-watch', file);
const dest = tmpdir.resolve(file);
fixturePaths[file] = dest;
fixtureContent[file] = readFileSync(src, 'utf8');
writeFileSync(dest, fixtureContent[file]);
}
}

async function testRunnerWatch({
fileToUpdate,
file,
action = 'update',
fileToCreate,
isolation,
}) {
const ran1 = Promise.withResolvers();
const ran2 = Promise.withResolvers();
const child = spawn(process.execPath,
['--watch', '--test', '--test-reporter=spec',
isolation ? `--test-isolation=${isolation}` : '',
file ? fixturePaths[file] : undefined].filter(Boolean),
{ encoding: 'utf8', stdio: 'pipe', cwd: tmpdir.path });
let stdout = '';
let currentRun = '';
const runs = [];

child.stdout.on('data', (data) => {
stdout += data.toString();
currentRun += data.toString();
const testRuns = stdout.match(/duration_ms\s\d+/g);
if (testRuns?.length >= 1) ran1.resolve();
if (testRuns?.length >= 2) ran2.resolve();
});

const testUpdate = async () => {
await ran1.promise;
runs.push(currentRun);
currentRun = '';
const content = fixtureContent[fileToUpdate];
const path = fixturePaths[fileToUpdate];
writeFileSync(path, content);
await setTimeout(common.platformTimeout(1000));
await ran2.promise;
runs.push(currentRun);
child.kill();
await once(child, 'exit');

assert.strictEqual(runs.length, 2);

for (const run of runs) {
assert.match(run, /tests 1/);
assert.match(run, /pass 1/);
assert.match(run, /fail 0/);
assert.match(run, /cancelled 0/);
}
};

const testRename = async () => {
await ran1.promise;
runs.push(currentRun);
currentRun = '';
const fileToRenamePath = tmpdir.resolve(fileToUpdate);
const newFileNamePath = tmpdir.resolve(`test-renamed-${fileToUpdate}`);
renameSync(fileToRenamePath, newFileNamePath);
await setTimeout(common.platformTimeout(1000));
await ran2.promise;
runs.push(currentRun);
child.kill();
await once(child, 'exit');

assert.strictEqual(runs.length, 2);

for (const run of runs) {
assert.match(run, /tests 1/);
assert.match(run, /pass 1/);
assert.match(run, /fail 0/);
assert.match(run, /cancelled 0/);
}
};

const testDelete = async () => {
await ran1.promise;
runs.push(currentRun);
currentRun = '';
const fileToDeletePath = tmpdir.resolve(fileToUpdate);
unlinkSync(fileToDeletePath);
await setTimeout(common.platformTimeout(2000));
ran2.resolve();
runs.push(currentRun);
child.kill();
await once(child, 'exit');

assert.strictEqual(runs.length, 2);

for (const run of runs) {
assert.doesNotMatch(run, /MODULE_NOT_FOUND/);
}
};

const testCreate = async () => {
await ran1.promise;
runs.push(currentRun);
currentRun = '';
const newFilePath = tmpdir.resolve(fileToCreate);
writeFileSync(newFilePath, 'module.exports = {};');
await setTimeout(common.platformTimeout(1000));
await ran2.promise;
runs.push(currentRun);
child.kill();
await once(child, 'exit');

for (const run of runs) {
assert.match(run, /tests 1/);
assert.match(run, /pass 1/);
assert.match(run, /fail 0/);
assert.match(run, /cancelled 0/);
}
};

action === 'update' && await testUpdate();
action === 'rename' && await testRename();
action === 'delete' && await testDelete();
action === 'create' && await testCreate();
}


module.exports = {
skipIfNoWatch,
skipIfNoWatchModeSignals,
testRunnerWatch,
refreshForTestRunnerWatch,
};
1 change: 1 addition & 0 deletions test/fixtures/test-runner-watch/dependency.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = {};
1 change: 1 addition & 0 deletions test/fixtures/test-runner-watch/dependency.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const a = 1;
5 changes: 5 additions & 0 deletions test/fixtures/test-runner-watch/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const test = require('node:test');
require('./dependency.js');
import('./dependency.mjs');
import('data:text/javascript,');
test('test has ran');
4 changes: 0 additions & 4 deletions test/parallel/parallel.status
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ test-runner-run-watch: PASS, FLAKY
# https://github.com/nodejs/node/issues/58353
test-http2-debug: PASS, FLAKY

[$system==linux || $system==win32]
# https://github.com/nodejs/node/issues/49605
test-runner-watch-mode: PASS,FLAKY

[$system==macos]
# https://github.com/nodejs/node/issues/42741
test-http-server-headers-timeout-keepalive: PASS,FLAKY
Expand Down
193 changes: 0 additions & 193 deletions test/parallel/test-runner-watch-mode.mjs

This file was deleted.

4 changes: 4 additions & 0 deletions test/test-runner/test-runner.status
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,7 @@ prefix test-runner
# sample-test : PASS,FLAKY

[true] # This section applies to all platforms

# https://github.com/nodejs/node/pull/54888#issuecomment-2351128116
# TODO(pmarchini): This test is failing when isolation is set to none and must be fixed.
test-watch-create-isolation-none: SKIP
Loading
Loading