mirror of
https://github.com/nodejs/node.git
synced 2025-05-17 04:03:52 +00:00

Change the contents of the file every 100 milliseconds until the watcher notices the change. This is already done in the callback based version of the test (`test-fs-watch.js`). Fixes: https://github.com/nodejs/node/issues/37637 PR-URL: https://github.com/nodejs/node/pull/40863 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com> Reviewed-By: Nitzan Uziely <linkgoron@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Yongsheng Zhang <zyszys98@gmail.com>
118 lines
3.4 KiB
JavaScript
118 lines
3.4 KiB
JavaScript
'use strict';
|
|
const common = require('../common');
|
|
|
|
if (common.isIBMi)
|
|
common.skip('IBMi does not support `fs.watch()`');
|
|
|
|
const { watch } = require('fs/promises');
|
|
const fs = require('fs');
|
|
const assert = require('assert');
|
|
const { join } = require('path');
|
|
const tmpdir = require('../common/tmpdir');
|
|
|
|
class WatchTestCase {
|
|
constructor(shouldInclude, dirName, fileName, field) {
|
|
this.dirName = dirName;
|
|
this.fileName = fileName;
|
|
this.field = field;
|
|
this.shouldSkip = !shouldInclude;
|
|
}
|
|
get dirPath() { return join(tmpdir.path, this.dirName); }
|
|
get filePath() { return join(this.dirPath, this.fileName); }
|
|
}
|
|
|
|
const kCases = [
|
|
// Watch on a directory should callback with a filename on supported systems
|
|
new WatchTestCase(
|
|
common.isLinux || common.isOSX || common.isWindows || common.isAIX,
|
|
'watch1',
|
|
'foo',
|
|
'filePath'
|
|
),
|
|
// Watch on a file should callback with a filename on supported systems
|
|
new WatchTestCase(
|
|
common.isLinux || common.isOSX || common.isWindows,
|
|
'watch2',
|
|
'bar',
|
|
'dirPath'
|
|
),
|
|
];
|
|
|
|
tmpdir.refresh();
|
|
|
|
for (const testCase of kCases) {
|
|
if (testCase.shouldSkip) continue;
|
|
fs.mkdirSync(testCase.dirPath);
|
|
// Long content so it's actually flushed.
|
|
const content1 = Date.now() + testCase.fileName.toLowerCase().repeat(1e4);
|
|
fs.writeFileSync(testCase.filePath, content1);
|
|
|
|
let interval;
|
|
async function test() {
|
|
const watcher = watch(testCase[testCase.field]);
|
|
for await (const { eventType, filename } of watcher) {
|
|
clearInterval(interval);
|
|
assert.strictEqual(['rename', 'change'].includes(eventType), true);
|
|
assert.strictEqual(filename, testCase.fileName);
|
|
break;
|
|
}
|
|
|
|
// Waiting on it again is a non-op
|
|
// eslint-disable-next-line no-unused-vars
|
|
for await (const p of watcher) {
|
|
assert.fail('should not run');
|
|
}
|
|
}
|
|
|
|
// Long content so it's actually flushed. toUpperCase so there's real change.
|
|
const content2 = Date.now() + testCase.fileName.toUpperCase().repeat(1e4);
|
|
interval = setInterval(() => {
|
|
fs.writeFileSync(testCase.filePath, '');
|
|
fs.writeFileSync(testCase.filePath, content2);
|
|
}, 100);
|
|
|
|
test().then(common.mustCall());
|
|
}
|
|
|
|
assert.rejects(
|
|
// eslint-disable-next-line no-unused-vars
|
|
async () => { for await (const _ of watch(1)) {} },
|
|
{ code: 'ERR_INVALID_ARG_TYPE' });
|
|
|
|
assert.rejects(
|
|
// eslint-disable-next-line no-unused-vars
|
|
async () => { for await (const _ of watch(__filename, 1)) {} },
|
|
{ code: 'ERR_INVALID_ARG_TYPE' });
|
|
|
|
assert.rejects(
|
|
// eslint-disable-next-line no-unused-vars
|
|
async () => { for await (const _ of watch('', { persistent: 1 })) {} },
|
|
{ code: 'ERR_INVALID_ARG_TYPE' });
|
|
|
|
assert.rejects(
|
|
// eslint-disable-next-line no-unused-vars
|
|
async () => { for await (const _ of watch('', { recursive: 1 })) {} },
|
|
{ code: 'ERR_INVALID_ARG_TYPE' });
|
|
|
|
assert.rejects(
|
|
// eslint-disable-next-line no-unused-vars
|
|
async () => { for await (const _ of watch('', { encoding: 1 })) {} },
|
|
{ code: 'ERR_INVALID_ARG_VALUE' });
|
|
|
|
assert.rejects(
|
|
// eslint-disable-next-line no-unused-vars
|
|
async () => { for await (const _ of watch('', { signal: 1 })) {} },
|
|
{ code: 'ERR_INVALID_ARG_TYPE' });
|
|
|
|
(async () => {
|
|
const ac = new AbortController();
|
|
const { signal } = ac;
|
|
setImmediate(() => ac.abort());
|
|
try {
|
|
// eslint-disable-next-line no-unused-vars
|
|
for await (const _ of watch(__filename, { signal })) {}
|
|
} catch (err) {
|
|
assert.strictEqual(err.name, 'AbortError');
|
|
}
|
|
})().then(common.mustCall());
|