node/test/parallel/test-runner-plan.mjs
Pietro Marchini 1b655c7631
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>
2025-03-10 22:23:23 +00:00

172 lines
4.9 KiB
JavaScript

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);
});
});
});