Skip to content

Commit

Permalink
Switch from node:test to micro-should, run in bun
Browse files Browse the repository at this point in the history
  • Loading branch information
paulmillr committed Jan 13, 2025
1 parent d4d5b7e commit 32d4a93
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 76 deletions.
66 changes: 46 additions & 20 deletions .github/workflows/test-js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,6 @@ on:
- push
- pull_request
jobs:
bun:
name: Bun
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4
- uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1
- run: bun install
- run: bun run build
- run: bun index.test.js
deno:
name: Deno
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4
- uses: denoland/setup-deno@909cc5acb0fdd60627fb858598759246509fa755 # v2.0.2
- run: deno install
- run: deno run build
- run: deno --allow-env --allow-write --allow-read index.test.js
lint:
name: Lint
runs-on: ubuntu-latest
Expand All @@ -34,13 +16,47 @@ jobs:
- run: npm install
- run: npm run build --if-present
- run: npm run lint --if-present
node:
node_18:
name: Node v${{ matrix.version }} @ ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
version: [18]
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4
- name: Use Node.js ${{ matrix.version }}
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4
with:
node-version: ${{ matrix.version }}
- run: npm install
- run: npm run build --if-present
- run: npm test
node_20:
name: Node v${{ matrix.version }} @ ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
version: [20]
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4
- name: Use Node.js ${{ matrix.version }}
uses: actions/setup-node@8f152de45cc393bb48ce5d89d36b731f54556e65 # v4
with:
node-version: ${{ matrix.version }}
- run: npm install
- run: npm run build --if-present
- run: npm test
node_22:
name: Node v${{ matrix.version }} @ ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
version: [18, 20, 22]
version: [22]
os: [ubuntu-latest, windows-latest, macOS-latest]
steps:
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4
Expand All @@ -51,3 +67,13 @@ jobs:
- run: npm install
- run: npm run build --if-present
- run: npm test
bun:
needs: node_22
name: Bun
runs-on: macOS-latest
steps:
- uses: actions/checkout@1e31de5234b9f8995739874a8ce0492dc87873e2 # v4
- uses: oven-sh/setup-bun@4bc047ad259df6fc24a6c9b0f9a0cb08cf17fbe5 # v2.0.1
- run: bun install
- run: bun run build
- run: bun test.mjs
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
"@paulmillr/jsbt": "0.2.1",
"@types/node": "20.14.8",
"chai": "4.3.4",
"micro-should": "github:paulmillr/micro-should",
"prettier": "3.1.1",
"sinon": "12.0.1",
"sinon-chai": "3.7.0",
Expand All @@ -53,7 +54,7 @@
"build": "tsc && tsc -p tsconfig.esm.json",
"lint": "prettier --check src",
"format": "prettier --write src",
"test": "node --test"
"test": "node test.mjs"
},
"keywords": [
"fs",
Expand Down
110 changes: 55 additions & 55 deletions test.mjs
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
import fs from 'node:fs';
import fs, { writeFileSync } from 'node:fs'; // fs.stat is mocked below, so can't import INDIVIDUAL methods
import sysPath from 'node:path';
import {describe, it, before, after, beforeEach, afterEach} from 'node:test';
// import {describe, it, before, after, beforeEach, afterEach} from 'node:test';
import {describe, it, beforeEach, afterEach} from 'micro-should';
import {fileURLToPath, pathToFileURL, URL} from 'node:url';
import {promisify} from 'node:util';
import childProcess from 'node:child_process';
import { exec as cexec } from 'node:child_process';
import { tmpdir } from 'node:os';
import chai from 'chai';
import sinon from 'sinon';
import sinonChai from 'sinon-chai';
import upath from 'upath';

import chokidar from './esm/index.js';
import { EVENTS as EV, isWindows, isMacos, isIBMi } from './esm/handler.js';
import { tmpdir } from 'node:os';

const imetaurl = import.meta.url;
const __filename = fileURLToPath(new URL('', imetaurl));
const __dirname = fileURLToPath(new URL('.', imetaurl)); // Will contain trailing slash
const TEST_TIMEOUT = 32000; // ms

const {expect} = chai;
chai.use(sinonChai);
chai.should();

const exec = promisify(childProcess.exec);
const exec = promisify(cexec);
const rm = promisify(fs.rm);
const read = promisify(fs.readFile);
const write = promisify(fs.writeFile);
Expand All @@ -30,11 +29,15 @@ const fs_rename = promisify(fs.rename);
const fs_mkdir = promisify(fs.mkdir);
const fs_rmdir = promisify(fs.rmdir);
const fs_unlink = promisify(fs.unlink);

const imetaurl = import.meta.url;
const __filename = fileURLToPath(new URL('', imetaurl));
const __dirname = fileURLToPath(new URL('.', imetaurl)); // Will contain trailing slash
const initialPath = process.cwd();
const FIXTURES_PATH = sysPath.join(tmpdir(), 'chokidar-' + Date.now())
const allWatchers = [];

const WATCHERS = [];
const PERM = 0o755; // rwe, r+e, r+e
const TEST_TIMEOUT = 8000;
let testId = 0;
let currentDir;
let slowerDelay;
Expand Down Expand Up @@ -103,17 +106,17 @@ currentDir = dpath('');

const cwatch = (path = currentDir, opts) => {
const wt = chokidar.watch(path, opts);
allWatchers.push(wt);
WATCHERS.push(wt);
return wt;
};

const waitFor = (spies) => {
if (spies.length === 0) throw new TypeError('SPies zero');
if (spies.length === 0) throw new Error('need at least 1 spy');
return new Promise((resolve, reject) => {
let checkTimer;
const timeout = setTimeout(() => {
clearTimeout(checkTimer);
reject(new Error('timeout'));
reject(new Error('timeout waitFor, passed ms: ' + TEST_TIMEOUT));
}, TEST_TIMEOUT);
const isSpyReady = (spy) => {
if (Array.isArray(spy)) {
Expand All @@ -123,7 +126,6 @@ const waitFor = (spies) => {
};
const checkSpiesReady = () => {
clearTimeout(checkTimer);

if (spies.every(isSpyReady)) {
clearTimeout(timeout);
resolve();
Expand All @@ -138,7 +140,7 @@ const waitFor = (spies) => {
const waitForEvents = (watcher, count) => {
return new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error('timeout'));
reject(new Error('timeout waitForEvents, passed ms: ' + TEST_TIMEOUT));
}, TEST_TIMEOUT);
const events = [];
const handler = (event, path) => {
Expand All @@ -158,19 +160,12 @@ const waitForEvents = (watcher, count) => {
const dateNow = () => Date.now().toString();

const runTests = (baseopts) => {
let macosFswatch;
let win32Polling;
let macosFswatch = isMacos && !baseopts.usePolling;
let win32Polling = isWindows && baseopts.usePolling;
let options;

slowerDelay = macosFswatch ? 100 : undefined;
baseopts.persistent = true;

before(() => {
// flags for bypassing special-case test failures on CI
macosFswatch = isMacos && !baseopts.usePolling;
win32Polling = isWindows && baseopts.usePolling;
slowerDelay = macosFswatch ? 100 : undefined;
});

beforeEach(function clean() {
options = {};
Object.keys(baseopts).forEach((key) => {
Expand Down Expand Up @@ -1794,21 +1789,22 @@ const runTests = (baseopts) => {
spy.should.not.have.been.calledWith(EV.ADD);
if (!macosFswatch) spy.should.have.been.calledOnce;
});
it('should watch paths that were unwatched and added again', async () => {
it.skip('should watch paths that were unwatched and added again', async () => {
const spy = sinon.spy();
const watchPaths = [dpath('change.txt')];
const watcher = cwatch(watchPaths, options);
console.log('watching', watchPaths)
const watcher = cwatch(watchPaths, options).on(EV.ALL, console.log.bind(console));
await waitForWatcher(watcher);

await delay();
watcher.unwatch(dpath('change.txt'));

await delay();
watcher.on(EV.ALL, spy).add(dpath('change.txt'));

await delay();
await write(dpath('change.txt'), dateNow());
console.log('a')
await waitFor([spy]);
console.log('b');
spy.should.have.been.calledWith(EV.CHANGE, dpath('change.txt'));
if (!macosFswatch) spy.should.have.been.calledOnce;
});
Expand Down Expand Up @@ -2092,38 +2088,15 @@ const runTests = (baseopts) => {
};

describe('chokidar', async () => {
before(async () => {
try {
await rm(FIXTURES_PATH, {recursive: true, force: true});
await fs_mkdir(FIXTURES_PATH, { recursive: true, mode: PERM });
} catch (error) {}
process.chdir(FIXTURES_PATH);
const _content = await read(__filename, 'utf-8');
const _only = _content.match(/\sit\.only\(/g);
const itCount = _only && _only.length || _content.match(/\sit\(/g).length;
const testCount = itCount * 3;
while (testId++ < testCount) {
await fs_mkdir(dpath(''), PERM);
await write(dpath('change.txt'), 'b');
await write(dpath('unlink.txt'), 'b');
}
testId = 0;
});

after(async () => {
try {
await rm(FIXTURES_PATH, {recursive: true, force: true});
} catch (error) {}
process.chdir(initialPath);
});

beforeEach(() => {
testId++;
currentDir = dpath('');
});

afterEach(async () => {
await Promise.allSettled(allWatchers.map(w => w.close()));
const promises = WATCHERS.map(w => w.close());
await Promise.all(promises);
await rm(currentDir, { recursive: true});
});

it('should expose public API methods', () => {
Expand All @@ -2136,3 +2109,30 @@ describe('chokidar', async () => {
}
describe('fs.watchFile (polling)', runTests.bind(this, {usePolling: true, interval: 10}));
});
async function main() {
try {
await rm(FIXTURES_PATH, {recursive: true, force: true});
await fs_mkdir(FIXTURES_PATH, { recursive: true, mode: PERM });
} catch (error) {}
process.chdir(FIXTURES_PATH);
// Create many directories before tests.
// Creating them in `beforeEach` increases chance of random failures.
const _content = await read(__filename, 'utf-8');
const _only = _content.match(/\sit\.only\(/g);
const itCount = _only && _only.length || _content.match(/\sit\(/g).length;
const testCount = itCount * 3;
while (testId++ < testCount) {
await fs_mkdir(dpath(''), PERM);
await write(dpath('change.txt'), 'b');
await write(dpath('unlink.txt'), 'b');
}
testId = 0;

await it.run(true);

try {
await rm(FIXTURES_PATH, {recursive: true, force: true});
} catch (error) {}
process.chdir(initialPath);
}
main();

0 comments on commit 32d4a93

Please sign in to comment.