Skip to content

Commit

Permalink
test_runner: support test plans
Browse files Browse the repository at this point in the history
  • Loading branch information
cjihrig committed Mar 19, 2024
1 parent a21b15a commit 89d9a7e
Showing 1 changed file with 81 additions and 0 deletions.
81 changes: 81 additions & 0 deletions lib/internal/test_runner/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ const {
testOnlyFlag,
} = parseCommandLine();
let kResistStopPropagation;
let assertObj;
let findSourceMap;

function lazyFindSourceMap(file) {
Expand All @@ -95,6 +96,34 @@ function lazyFindSourceMap(file) {
return findSourceMap(file);
}

function lazyAssertObject() {
if (assertObj === undefined) {
const assert = require('assert');

assertObj = new SafeMap([
['deepEqual', assert.deepEqual],
['deepStrictEqual', assert.deepStrictEqual],
['doesNotMatch', assert.doesNotMatch],
['doesNotReject', assert.doesNotReject],
['doesNotThrow', assert.doesNotThrow],
['equal', assert.equal],
['fail', assert.fail],
['ifError', assert.ifError],
['match', assert.match],
['notDeepEqual', assert.notDeepEqual],
['notDeepStrictEqual', assert.notDeepStrictEqual],
['notEqual', assert.notEqual],
['notStrictEqual', assert.notStrictEqual],
['ok', assert.ok],
['rejects', assert.rejects],
['strictEqual', assert.strictEqual],
['throws', assert.throws],
]);
}

return assertObj;
}

function stopTest(timeout, signal) {
const deferred = createDeferredPromise();
const abortListener = addAbortListener(signal, deferred.resolve);
Expand Down Expand Up @@ -134,7 +163,25 @@ function stopTest(timeout, signal) {
return deferred.promise;
}

class TestPlan {
constructor(count) {
validateUint32(count, 'count', 0);
this.expected = count;
this.actual = 0;
}

check() {
if (this.actual !== this.expected) {
throw new ERR_TEST_FAILURE(
`plan expected ${this.expected} assertions but received ${this.actual}`,
kTestCodeFailure,
);
}
}
}

class TestContext {
#assert;
#test;

constructor(test) {
Expand All @@ -161,6 +208,38 @@ class TestContext {
this.#test.diagnostic(message);
}

plan(count) {
if (this.#test.plan !== null) {
throw new ERR_TEST_FAILURE(
'cannot set plan more than once',
kTestCodeFailure,
);
}

this.#test.plan = new TestPlan(count);
}

get assert() {
if (this.#assert === undefined) {
const { plan } = this.#test;
const map = lazyAssertObject();
const assert = { __proto__: null };

this.#assert = assert;
map.forEach((method, name) => {
assert[name] = function(...args) {
if (plan !== null) {
plan.actual++;
}

return ReflectApply(method, assert, args);
};
});
}

return this.#assert;
}

get mock() {
this.#test.mock ??= new MockTracker();
return this.#test.mock;
Expand Down Expand Up @@ -347,6 +426,7 @@ class Test extends AsyncResource {
this.fn = fn;
this.harness = null; // Configured on the root test by the test harness.
this.mock = null;
this.plan = null;
this.cancelled = false;
this.skipped = skip !== undefined && skip !== false;
this.isTodo = todo !== undefined && todo !== false;
Expand Down Expand Up @@ -708,6 +788,7 @@ class Test extends AsyncResource {
return;
}

this.plan?.check();
this.pass();
try {
await afterEach();
Expand Down

0 comments on commit 89d9a7e

Please sign in to comment.