mirror of
https://github.com/withastro/astro.git
synced 2024-12-16 21:46:22 -05:00
Use node:test and node:assert/strict (#9649)
This commit is contained in:
parent
d02a3c48a3
commit
71db79e62a
9 changed files with 119 additions and 55 deletions
|
@ -88,13 +88,25 @@ DEBUG=vite:[name] astro dev # debug specific process, e.g. "vite:deps" or "vit
|
|||
# run this in the top-level project root to run all tests
|
||||
pnpm run test
|
||||
# run only a few tests in the `astro` package, great for working on a single feature
|
||||
# (example - `pnpm run test:match "cli"` runs `cli.test.js`)
|
||||
# (example - `pnpm run test:match "cli"` runs tests with "cli" in the name)
|
||||
pnpm run test:match "$STRING_MATCH"
|
||||
# run tests on another package
|
||||
# (example - `pnpm --filter @astrojs/rss run test` runs `packages/astro-rss/test/rss.test.js`)
|
||||
pnpm --filter $STRING_MATCH run test
|
||||
```
|
||||
|
||||
Most tests use [`mocha`](https://mochajs.org) as the test runner. We're slowly migrating to use [`node:test`](https://nodejs.org/api/test.html) instead through the custom [`astro-scripts test`](./scripts/cmd/test.js) command. For packages that use `node:test`, you can run these commands in their directories:
|
||||
|
||||
```shell
|
||||
# run all of the package's tests
|
||||
pnpm run test
|
||||
# run only a few tests in the package
|
||||
# (example - `pnpm run test -m "cli"` runs tests with "cli" in the name)
|
||||
pnpm run test -m "$STRING_MATCH"
|
||||
# run a single test file, you can use `node --test` directly
|
||||
node --test ./test/foo.test.js
|
||||
```
|
||||
|
||||
#### E2E tests
|
||||
|
||||
Certain features, like HMR and client hydration, need end-to-end tests to verify functionality in the dev server. [Playwright](https://playwright.dev/) is used to test against the dev server.
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
"build": "astro-scripts build \"src/index.ts\" --bundle && tsc",
|
||||
"build:ci": "astro-scripts build \"src/index.ts\" --bundle",
|
||||
"dev": "astro-scripts dev \"src/**/*.ts\"",
|
||||
"test": "mocha --exit --timeout 20000 --parallel"
|
||||
"test": "astro-scripts test \"test/**/*.test.js\""
|
||||
},
|
||||
"files": [
|
||||
"dist",
|
||||
|
@ -39,8 +39,6 @@
|
|||
"@types/which-pm-runs": "^1.0.0",
|
||||
"arg": "^5.0.2",
|
||||
"astro-scripts": "workspace:*",
|
||||
"chai": "^4.3.7",
|
||||
"mocha": "^10.2.0",
|
||||
"strip-ansi": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
|
|
|
@ -1,19 +1,20 @@
|
|||
import { expect } from 'chai';
|
||||
import { describe, it } from 'node:test';
|
||||
import * as assert from 'node:assert/strict';
|
||||
import { getContext } from '../dist/index.js';
|
||||
|
||||
describe('context', () => {
|
||||
it('no arguments', async () => {
|
||||
const ctx = await getContext([]);
|
||||
expect(ctx.version).to.eq('latest');
|
||||
expect(ctx.dryRun).to.be.undefined;
|
||||
assert.equal(ctx.version, 'latest');
|
||||
assert.equal(ctx.dryRun, undefined);
|
||||
});
|
||||
it('tag', async () => {
|
||||
const ctx = await getContext(['beta']);
|
||||
expect(ctx.version).to.eq('beta');
|
||||
expect(ctx.dryRun).to.be.undefined;
|
||||
assert.equal(ctx.version, 'beta');
|
||||
assert.equal(ctx.dryRun, undefined);
|
||||
});
|
||||
it('dry run', async () => {
|
||||
const ctx = await getContext(['--dry-run']);
|
||||
expect(ctx.dryRun).to.eq(true);
|
||||
assert.equal(ctx.dryRun, true);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { expect } from 'chai';
|
||||
import { describe, it } from 'node:test';
|
||||
import * as assert from 'node:assert/strict';
|
||||
import { setup } from './utils.js';
|
||||
import { install } from '../dist/index.js';
|
||||
|
||||
|
@ -23,7 +24,7 @@ describe('install', () => {
|
|||
],
|
||||
};
|
||||
await install(context);
|
||||
expect(fixture.hasMessage('◼ astro is up to date on v1.0.0')).to.be.true;
|
||||
assert.equal(fixture.hasMessage('◼ astro is up to date on v1.0.0'), true);
|
||||
});
|
||||
|
||||
it('patch', async () => {
|
||||
|
@ -38,7 +39,7 @@ describe('install', () => {
|
|||
],
|
||||
};
|
||||
await install(context);
|
||||
expect(fixture.hasMessage('● astro can be updated to v1.0.1')).to.be.true;
|
||||
assert.equal(fixture.hasMessage('● astro can be updated to v1.0.1'), true);
|
||||
});
|
||||
|
||||
it('minor', async () => {
|
||||
|
@ -53,7 +54,7 @@ describe('install', () => {
|
|||
],
|
||||
};
|
||||
await install(context);
|
||||
expect(fixture.hasMessage('● astro can be updated to v1.2.0')).to.be.true;
|
||||
assert.equal(fixture.hasMessage('● astro can be updated to v1.2.0'), true);
|
||||
});
|
||||
|
||||
it('major (reject)', async () => {
|
||||
|
@ -80,10 +81,10 @@ describe('install', () => {
|
|||
],
|
||||
};
|
||||
await install(context);
|
||||
expect(fixture.hasMessage('▲ astro can be updated to v2.0.0')).to.be.true;
|
||||
expect(prompted).to.be.true;
|
||||
expect(exitCode).to.eq(0);
|
||||
expect(fixture.hasMessage('check Be sure to follow the CHANGELOG.')).to.be.false;
|
||||
assert.equal(fixture.hasMessage('▲ astro can be updated to v2.0.0'), true);
|
||||
assert.equal(prompted, true);
|
||||
assert.equal(exitCode, 0);
|
||||
assert.equal(fixture.hasMessage('check Be sure to follow the CHANGELOG.'), false);
|
||||
});
|
||||
|
||||
it('major (accept)', async () => {
|
||||
|
@ -110,10 +111,10 @@ describe('install', () => {
|
|||
],
|
||||
};
|
||||
await install(context);
|
||||
expect(fixture.hasMessage('▲ astro can be updated to v2.0.0')).to.be.true;
|
||||
expect(prompted).to.be.true;
|
||||
expect(exitCode).to.be.undefined;
|
||||
expect(fixture.hasMessage('check Be sure to follow the CHANGELOG.')).to.be.true;
|
||||
assert.equal(fixture.hasMessage('▲ astro can be updated to v2.0.0'), true);
|
||||
assert.equal(prompted, true);
|
||||
assert.equal(exitCode, undefined);
|
||||
assert.equal(fixture.hasMessage('check Be sure to follow the CHANGELOG.'), true);
|
||||
});
|
||||
|
||||
it('multiple major', async () => {
|
||||
|
@ -148,14 +149,14 @@ describe('install', () => {
|
|||
],
|
||||
};
|
||||
await install(context);
|
||||
expect(fixture.hasMessage('▲ a can be updated to v2.0.0')).to.be.true;
|
||||
expect(fixture.hasMessage('▲ b can be updated to v7.0.0')).to.be.true;
|
||||
expect(prompted).to.be.true;
|
||||
expect(exitCode).to.be.undefined;
|
||||
assert.equal(fixture.hasMessage('▲ a can be updated to v2.0.0'), true);
|
||||
assert.equal(fixture.hasMessage('▲ b can be updated to v7.0.0'), true);
|
||||
assert.equal(prompted, true);
|
||||
assert.equal(exitCode, undefined);
|
||||
const [changelog, a, b] = fixture.messages().slice(-5);
|
||||
expect(changelog).to.match(/^check/);
|
||||
expect(a).to.match(/^a/);
|
||||
expect(b).to.match(/^b/);
|
||||
assert.match(changelog, /^check/);
|
||||
assert.match(a, /^a/);
|
||||
assert.match(b, /^b/);
|
||||
});
|
||||
|
||||
it('current patch minor major', async () => {
|
||||
|
@ -197,15 +198,15 @@ describe('install', () => {
|
|||
],
|
||||
};
|
||||
await install(context);
|
||||
expect(fixture.hasMessage('◼ current is up to date on v1.0.0')).to.be.true;
|
||||
expect(fixture.hasMessage('● patch can be updated to v1.0.1')).to.be.true;
|
||||
expect(fixture.hasMessage('● minor can be updated to v1.2.0')).to.be.true;
|
||||
expect(fixture.hasMessage('▲ major can be updated to v3.0.0')).to.be.true;
|
||||
expect(prompted).to.be.true;
|
||||
expect(exitCode).to.be.undefined;
|
||||
expect(fixture.hasMessage('check Be sure to follow the CHANGELOG.')).to.be.true;
|
||||
assert.equal(fixture.hasMessage('◼ current is up to date on v1.0.0'), true);
|
||||
assert.equal(fixture.hasMessage('● patch can be updated to v1.0.1'), true);
|
||||
assert.equal(fixture.hasMessage('● minor can be updated to v1.2.0'), true);
|
||||
assert.equal(fixture.hasMessage('▲ major can be updated to v3.0.0'), true);
|
||||
assert.equal(prompted, true);
|
||||
assert.equal(exitCode, undefined);
|
||||
assert.equal(fixture.hasMessage('check Be sure to follow the CHANGELOG.'), true);
|
||||
const [changelog, major] = fixture.messages().slice(-4);
|
||||
expect(changelog).to.match(/^check/);
|
||||
expect(major).to.match(/^major/);
|
||||
assert.match(changelog, /^check/);
|
||||
assert.match(major, /^major/)
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { before, beforeEach } from 'node:test';
|
||||
import { setStdout } from '../dist/index.js';
|
||||
import stripAnsi from 'strip-ansi';
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { expect } from 'chai';
|
||||
import { describe, it, beforeEach } from 'node:test';
|
||||
import * as assert from 'node:assert/strict';
|
||||
import { collectPackageInfo } from '../dist/index.js';
|
||||
|
||||
describe('collectPackageInfo', () => {
|
||||
|
@ -16,61 +17,61 @@ describe('collectPackageInfo', () => {
|
|||
|
||||
it('detects astro', async () => {
|
||||
collectPackageInfo(context, { astro: '1.0.0' }, {});
|
||||
expect(context.packages).deep.equal([
|
||||
assert.deepEqual(context.packages, [
|
||||
{ name: 'astro', currentVersion: '1.0.0', targetVersion: 'latest' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('detects @astrojs', async () => {
|
||||
collectPackageInfo(context, { '@astrojs/preact': '1.0.0' }, {});
|
||||
expect(context.packages).deep.equal([
|
||||
assert.deepEqual(context.packages, [
|
||||
{ name: '@astrojs/preact', currentVersion: '1.0.0', targetVersion: 'latest' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('supports ^ prefixes', async () => {
|
||||
collectPackageInfo(context, { astro: '^1.0.0' }, {});
|
||||
expect(context.packages).deep.equal([
|
||||
assert.deepEqual(context.packages, [
|
||||
{ name: 'astro', currentVersion: '^1.0.0', targetVersion: 'latest' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('supports ~ prefixes', async () => {
|
||||
collectPackageInfo(context, { astro: '~1.0.0' }, {});
|
||||
expect(context.packages).deep.equal([
|
||||
assert.deepEqual(context.packages, [
|
||||
{ name: 'astro', currentVersion: '~1.0.0', targetVersion: 'latest' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('supports prereleases', async () => {
|
||||
collectPackageInfo(context, { astro: '1.0.0-beta.0' }, {});
|
||||
expect(context.packages).deep.equal([
|
||||
assert.deepEqual(context.packages, [
|
||||
{ name: 'astro', currentVersion: '1.0.0-beta.0', targetVersion: 'latest' },
|
||||
]);
|
||||
});
|
||||
|
||||
it('ignores self', async () => {
|
||||
collectPackageInfo(context, { '@astrojs/upgrade': '0.0.1' }, {});
|
||||
expect(context.packages).deep.equal([]);
|
||||
assert.deepEqual(context.packages, []);
|
||||
});
|
||||
|
||||
it('ignores linked packages', async () => {
|
||||
collectPackageInfo(context, { '@astrojs/preact': 'link:../packages/preact' }, {});
|
||||
expect(context.packages).deep.equal([]);
|
||||
assert.deepEqual(context.packages, []);
|
||||
});
|
||||
|
||||
it('ignores workspace packages', async () => {
|
||||
collectPackageInfo(context, { '@astrojs/preact': 'workspace:*' }, {});
|
||||
expect(context.packages).deep.equal([]);
|
||||
assert.deepEqual(context.packages, []);
|
||||
});
|
||||
|
||||
it('ignores github packages', async () => {
|
||||
collectPackageInfo(context, { '@astrojs/preact': 'github:withastro/astro' }, {});
|
||||
expect(context.packages).deep.equal([]);
|
||||
assert.deepEqual(context.packages, []);
|
||||
});
|
||||
|
||||
it('ignores tag', async () => {
|
||||
collectPackageInfo(context, { '@astrojs/preact': 'beta' }, {});
|
||||
expect(context.packages).deep.equal([]);
|
||||
assert.deepEqual(context.packages, []);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -5148,12 +5148,6 @@ importers:
|
|||
astro-scripts:
|
||||
specifier: workspace:*
|
||||
version: link:../../scripts
|
||||
chai:
|
||||
specifier: ^4.3.7
|
||||
version: 4.3.10
|
||||
mocha:
|
||||
specifier: ^10.2.0
|
||||
version: 10.2.0
|
||||
strip-ansi:
|
||||
specifier: ^7.1.0
|
||||
version: 7.1.0
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
import { run } from 'node:test';
|
||||
import { spec } from 'node:test/reporters';
|
||||
import arg from 'arg';
|
||||
import glob from 'tiny-glob';
|
||||
|
||||
const isCI = !!process.env.CI;
|
||||
const defaultTimeout = isCI ? 30000 : 20000;
|
||||
|
||||
export default async function test() {
|
||||
const args = arg({
|
||||
'--match': String, // aka --test-name-pattern: https://nodejs.org/api/test.html#filtering-tests-by-name
|
||||
'--only': Boolean, // aka --test-only: https://nodejs.org/api/test.html#only-tests
|
||||
'--parallel': Boolean, // aka --test-concurrency: https://nodejs.org/api/test.html#test-runner-execution-model
|
||||
'--watch': Boolean, // experimental: https://nodejs.org/api/test.html#watch-mode
|
||||
'--timeout': Number, // Test timeout in milliseconds (default: 30000ms)
|
||||
'--setup': String, // Test setup file
|
||||
// Aliases
|
||||
'-m': '--match',
|
||||
'-o': '--only',
|
||||
'-p': '--parallel',
|
||||
'-w': '--watch',
|
||||
'-t': '--timeout',
|
||||
'-s': '--setup',
|
||||
});
|
||||
|
||||
const pattern = args._[1];
|
||||
if (!pattern) throw new Error('Missing test glob pattern');
|
||||
|
||||
const files = await glob(pattern, { filesOnly: true, absolute: true });
|
||||
|
||||
// For some reason, the `only` option does not work and we need to explicitly set the CLI flag instead.
|
||||
// Node.js requires opt-in to run .only tests :(
|
||||
// https://nodejs.org/api/test.html#only-tests
|
||||
if (args['--only']) {
|
||||
process.env.NODE_OPTIONS ??= '';
|
||||
process.env.NODE_OPTIONS += ' --test-only';
|
||||
}
|
||||
|
||||
// https://nodejs.org/api/test.html#runoptions
|
||||
run({
|
||||
files,
|
||||
testNamePatterns: args['--match'],
|
||||
concurrency: args['--parallel'],
|
||||
only: args['--only'],
|
||||
setup: args['--setup'],
|
||||
watch: args['--watch'],
|
||||
timeout: args['--timeout'] ?? defaultTimeout, // Node.js defaults to Infinity, so set better fallback
|
||||
})
|
||||
.pipe(new spec())
|
||||
.pipe(process.stdout);
|
||||
}
|
|
@ -18,6 +18,11 @@ export default async function run() {
|
|||
await prebuild(...args);
|
||||
break;
|
||||
}
|
||||
case 'test': {
|
||||
const { default: test } = await import('./cmd/test.js');
|
||||
await test(...args);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue