mirror of
https://github.com/zebrajr/node.git
synced 2025-12-06 12:20:27 +01:00
test: test runner run plan
PR-URL: https://github.com/nodejs/node/pull/57304 Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Moshe Atlow <moshe@atlow.co.il>
This commit is contained in:
parent
823c9b70c7
commit
1b655c7631
7
test/fixtures/test-runner/plan/less.mjs
vendored
Normal file
7
test/fixtures/test-runner/plan/less.mjs
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import test from 'node:test';
|
||||||
|
|
||||||
|
test('less assertions than planned', (t) => {
|
||||||
|
t.plan(2);
|
||||||
|
t.assert.ok(true, 'only one assertion');
|
||||||
|
// Missing second assertion
|
||||||
|
});
|
||||||
7
test/fixtures/test-runner/plan/match.mjs
vendored
Normal file
7
test/fixtures/test-runner/plan/match.mjs
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import test from 'node:test';
|
||||||
|
|
||||||
|
test('matching assertions', (t) => {
|
||||||
|
t.plan(2);
|
||||||
|
t.assert.ok(true, 'first assertion');
|
||||||
|
t.assert.ok(true, 'second assertion');
|
||||||
|
});
|
||||||
7
test/fixtures/test-runner/plan/more.mjs
vendored
Normal file
7
test/fixtures/test-runner/plan/more.mjs
vendored
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
import test from 'node:test';
|
||||||
|
|
||||||
|
test('more assertions than planned', (t) => {
|
||||||
|
t.plan(1);
|
||||||
|
t.assert.ok(true, 'first assertion');
|
||||||
|
t.assert.ok(true, 'extra assertion'); // This should cause failure
|
||||||
|
});
|
||||||
14
test/fixtures/test-runner/plan/nested-subtests.mjs
vendored
Normal file
14
test/fixtures/test-runner/plan/nested-subtests.mjs
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import test from 'node:test';
|
||||||
|
|
||||||
|
test('deeply nested tests', async (t) => {
|
||||||
|
t.plan(1);
|
||||||
|
|
||||||
|
await t.test('level 1', async (t) => {
|
||||||
|
t.plan(1);
|
||||||
|
|
||||||
|
await t.test('level 2', (t) => {
|
||||||
|
t.plan(1);
|
||||||
|
t.assert.ok(true, 'deepest assertion');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
9
test/fixtures/test-runner/plan/plan-via-options.mjs
vendored
Normal file
9
test/fixtures/test-runner/plan/plan-via-options.mjs
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import test from 'node:test';
|
||||||
|
|
||||||
|
test('failing planning by options', { plan: 1 }, () => {
|
||||||
|
// Should fail - no assertions
|
||||||
|
});
|
||||||
|
|
||||||
|
test('passing planning by options', { plan: 1 }, (t) => {
|
||||||
|
t.assert.ok(true);
|
||||||
|
});
|
||||||
20
test/fixtures/test-runner/plan/streaming.mjs
vendored
Normal file
20
test/fixtures/test-runner/plan/streaming.mjs
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
import test from 'node:test';
|
||||||
|
import { Readable } from 'node:stream';
|
||||||
|
|
||||||
|
test('planning with streams', (t, done) => {
|
||||||
|
function* generate() {
|
||||||
|
yield 'a';
|
||||||
|
yield 'b';
|
||||||
|
yield 'c';
|
||||||
|
}
|
||||||
|
const expected = ['a', 'b', 'c'];
|
||||||
|
t.plan(expected.length);
|
||||||
|
const stream = Readable.from(generate());
|
||||||
|
stream.on('data', (chunk) => {
|
||||||
|
t.assert.strictEqual(chunk, expected.shift());
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('end', () => {
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
9
test/fixtures/test-runner/plan/subtest.mjs
vendored
Normal file
9
test/fixtures/test-runner/plan/subtest.mjs
vendored
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import test from 'node:test';
|
||||||
|
|
||||||
|
test('parent test', async (t) => {
|
||||||
|
t.plan(1);
|
||||||
|
await t.test('child test', (t) => {
|
||||||
|
t.plan(1);
|
||||||
|
t.assert.ok(true, 'child assertion');
|
||||||
|
});
|
||||||
|
});
|
||||||
15
test/fixtures/test-runner/plan/timeout-basic.mjs
vendored
Normal file
15
test/fixtures/test-runner/plan/timeout-basic.mjs
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import test from 'node:test';
|
||||||
|
|
||||||
|
test('planning with wait should PASS within timeout', async (t) => {
|
||||||
|
t.plan(1, { wait: 5000 });
|
||||||
|
setTimeout(() => {
|
||||||
|
t.assert.ok(true);
|
||||||
|
}, 250);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('planning with wait should FAIL within timeout', async (t) => {
|
||||||
|
t.plan(1, { wait: 5000 });
|
||||||
|
setTimeout(() => {
|
||||||
|
t.assert.ok(false);
|
||||||
|
}, 250);
|
||||||
|
});
|
||||||
8
test/fixtures/test-runner/plan/timeout-expired.mjs
vendored
Normal file
8
test/fixtures/test-runner/plan/timeout-expired.mjs
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import test from 'node:test';
|
||||||
|
|
||||||
|
test('planning should FAIL when wait time expires before plan is met', (t) => {
|
||||||
|
t.plan(2, { wait: 500 });
|
||||||
|
setTimeout(() => {
|
||||||
|
t.assert.ok(true);
|
||||||
|
}, 30_000).unref();
|
||||||
|
});
|
||||||
11
test/fixtures/test-runner/plan/timeout-wait-false.mjs
vendored
Normal file
11
test/fixtures/test-runner/plan/timeout-wait-false.mjs
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
import test from 'node:test';
|
||||||
|
|
||||||
|
test('should not wait for assertions and fail immediately', async (t) => {
|
||||||
|
t.plan(1, { wait: false });
|
||||||
|
|
||||||
|
// Set up an async operation that won't complete before the test finishes
|
||||||
|
// Since wait:false, the test should fail immediately without waiting
|
||||||
|
setTimeout(() => {
|
||||||
|
t.assert.ok(true);
|
||||||
|
}, 1000).unref();
|
||||||
|
});
|
||||||
17
test/fixtures/test-runner/plan/timeout-wait-true.mjs
vendored
Normal file
17
test/fixtures/test-runner/plan/timeout-wait-true.mjs
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
import test from 'node:test';
|
||||||
|
|
||||||
|
test('should pass when assertions are eventually met', async (t) => {
|
||||||
|
t.plan(1, { wait: true });
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
t.assert.ok(true);
|
||||||
|
}, 250);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should fail when assertions fail', async (t) => {
|
||||||
|
t.plan(1, { wait: true });
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
t.assert.ok(false);
|
||||||
|
}, 250).unref();
|
||||||
|
});
|
||||||
171
test/parallel/test-runner-plan.mjs
Normal file
171
test/parallel/test-runner-plan.mjs
Normal file
|
|
@ -0,0 +1,171 @@
|
||||||
|
import * as common from '../common/index.mjs';
|
||||||
|
import * as fixtures from '../common/fixtures.mjs';
|
||||||
|
import { describe, it, run } from 'node:test';
|
||||||
|
import { join } from 'node:path';
|
||||||
|
|
||||||
|
const testFixtures = fixtures.path('test-runner', 'plan');
|
||||||
|
|
||||||
|
describe('input validation', () => {
|
||||||
|
it('throws if options is not an object', (t) => {
|
||||||
|
t.assert.throws(() => {
|
||||||
|
t.plan(1, null);
|
||||||
|
}, {
|
||||||
|
code: 'ERR_INVALID_ARG_TYPE',
|
||||||
|
message: /The "options" argument must be of type object/,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws if options.wait is not a number or a boolean', (t) => {
|
||||||
|
t.assert.throws(() => {
|
||||||
|
t.plan(1, { wait: 'foo' });
|
||||||
|
}, {
|
||||||
|
code: 'ERR_INVALID_ARG_TYPE',
|
||||||
|
message: /The "options\.wait" property must be one of type boolean or number\. Received type string/,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws if count is not a number', (t) => {
|
||||||
|
t.assert.throws(() => {
|
||||||
|
t.plan('foo');
|
||||||
|
}, {
|
||||||
|
code: 'ERR_INVALID_ARG_TYPE',
|
||||||
|
message: /The "count" argument must be of type number/,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('test planning', () => {
|
||||||
|
it('should pass when assertions match plan', async () => {
|
||||||
|
const stream = run({
|
||||||
|
files: [join(testFixtures, 'match.mjs')]
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('test:fail', common.mustNotCall());
|
||||||
|
stream.on('test:pass', common.mustCall(1));
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
for await (const _ of stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail when less assertions than planned', async () => {
|
||||||
|
const stream = run({
|
||||||
|
files: [join(testFixtures, 'less.mjs')]
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('test:fail', common.mustCall(1));
|
||||||
|
stream.on('test:pass', common.mustNotCall());
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
for await (const _ of stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail when more assertions than planned', async () => {
|
||||||
|
const stream = run({
|
||||||
|
files: [join(testFixtures, 'more.mjs')]
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('test:fail', common.mustCall(1));
|
||||||
|
stream.on('test:pass', common.mustNotCall());
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
for await (const _ of stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle plan with subtests correctly', async () => {
|
||||||
|
const stream = run({
|
||||||
|
files: [join(testFixtures, 'subtest.mjs')]
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('test:fail', common.mustNotCall());
|
||||||
|
stream.on('test:pass', common.mustCall(2)); // Parent + child test
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
for await (const _ of stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle plan via options', async () => {
|
||||||
|
const stream = run({
|
||||||
|
files: [join(testFixtures, 'plan-via-options.mjs')]
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('test:fail', common.mustCall(1));
|
||||||
|
stream.on('test:pass', common.mustCall(1));
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
for await (const _ of stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle streaming with plan', async () => {
|
||||||
|
const stream = run({
|
||||||
|
files: [join(testFixtures, 'streaming.mjs')]
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('test:fail', common.mustNotCall());
|
||||||
|
stream.on('test:pass', common.mustCall(1));
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
for await (const _ of stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle nested subtests with plan', async () => {
|
||||||
|
const stream = run({
|
||||||
|
files: [join(testFixtures, 'nested-subtests.mjs')]
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('test:fail', common.mustNotCall());
|
||||||
|
stream.on('test:pass', common.mustCall(3)); // Parent + 2 levels of nesting
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
for await (const _ of stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('with timeout', () => {
|
||||||
|
it('should handle basic timeout scenarios', async () => {
|
||||||
|
const stream = run({
|
||||||
|
files: [join(testFixtures, 'timeout-basic.mjs')]
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('test:fail', common.mustCall(1));
|
||||||
|
stream.on('test:pass', common.mustCall(1));
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
for await (const _ of stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should fail when timeout expires before plan is met', async (t) => {
|
||||||
|
const stream = run({
|
||||||
|
files: [join(testFixtures, 'timeout-expired.mjs')]
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('test:fail', common.mustCall(1));
|
||||||
|
stream.on('test:pass', common.mustNotCall());
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
for await (const _ of stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle wait:true option specifically', async () => {
|
||||||
|
const stream = run({
|
||||||
|
files: [join(testFixtures, 'timeout-wait-true.mjs')]
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('test:fail', common.mustCall(1));
|
||||||
|
stream.on('test:pass', common.mustCall(1));
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
for await (const _ of stream);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle wait:false option (should not wait)', async () => {
|
||||||
|
const stream = run({
|
||||||
|
files: [join(testFixtures, 'timeout-wait-false.mjs')]
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('test:fail', common.mustCall(1)); // Fails because plan is not met immediately
|
||||||
|
stream.on('test:pass', common.mustNotCall());
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
for await (const _ of stream);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user