ava/test-tap/assert.js
Mark Wubben 9f3bf7e4d3
Remove references to older AVA versions
* Remove obsolete recipes

ES modules is supported out of the box.

The React recipe applies to AVA 3.

* Remove code guards against obsolete API usage

* Remove references to older AVA versions from documentation
2023-12-30 20:58:44 +01:00

1824 lines
48 KiB
JavaScript

import path from 'node:path';
import {fileURLToPath} from 'node:url';
import stripAnsi from 'strip-ansi';
import {test} from 'tap';
import * as assert from '../lib/assert.js';
import * as snapshotManager from '../lib/snapshot-manager.js';
import {set as setOptions} from '../lib/worker/options.cjs';
setOptions({chalkOptions: {level: 0}});
let lastFailure = null;
let lastPassed = false;
class AssertionFailed extends Error {
constructor() {
super('Assertion failed');
this.name = 'AssertionFailed';
}
}
const AssertionsBase = class extends assert.Assertions {
constructor(overwrites = {}) {
super({
pass() {
lastPassed = true;
// Match behavior in lib/test.js, not great for this test suite but refactoring is a much larger task.
return true;
},
pending(promise) {
promise.then(() => {
lastPassed = true;
}, error => {
if (error.name !== 'AssertionFailed') {
lastFailure = error;
}
});
},
fail(error) {
lastFailure = error;
return new AssertionFailed();
},
failPending(error) {
if (error.name !== 'AssertionFailed') {
lastFailure = error;
}
return new AssertionFailed();
},
skip() {},
experiments: {},
...overwrites,
});
}
};
const assertions = new AssertionsBase();
function assertFailure(t, subset) {
if (!lastFailure) {
t.fail('Expected assertion to fail');
return;
}
t.equal(lastFailure.assertion, subset.assertion);
t.equal(lastFailure.message, subset.message);
t.equal(lastFailure.name, 'AssertionError');
if (subset.formattedDetails) {
t.equal(lastFailure.formattedDetails.length, subset.formattedDetails.length);
for (const [i, s] of lastFailure.formattedDetails.entries()) {
t.equal(stripAnsi(s.label), subset.formattedDetails[i].label);
t.match(stripAnsi(s.formatted), subset.formattedDetails[i].formatted);
}
} else {
t.same(lastFailure.formattedDetails, []);
}
}
let gathering = false;
let gatheringPromise = Promise.resolve();
function gather(run) {
return t => {
if (gathering) {
throw new Error('Cannot nest gather()');
}
gathering = true;
try {
run(t);
return gatheringPromise;
} finally {
gathering = false;
gatheringPromise = Promise.resolve();
}
};
}
function add(fn) {
if (!gathering) {
throw new Error('Cannot add promise, must be called from gather() callback');
}
gatheringPromise = gatheringPromise.then(fn);
return gatheringPromise;
}
function failsWith(t, fn, subset) {
lastFailure = null;
try {
fn();
} catch (error) {
if (error.name !== 'AssertionFailed') {
throw error;
}
}
assertFailure(t, subset);
}
async function failsWithAsync(t, fn, subset) {
lastFailure = null;
try {
await fn();
} catch (error) {
if (error.name !== 'AssertionFailed') {
throw error;
}
}
assertFailure(t, subset);
}
function throwsAsyncFails(t, fn, subset) {
return add(() => {
lastFailure = null;
return fn().catch(error => {
if (error.name === 'AssertionFailed') {
assertFailure(t, subset);
} else {
throw error;
}
});
});
}
function notThrowsAsyncFails(t, fn, subset) {
return add(() => {
lastFailure = null;
return fn().catch(error => {
if (error.name === 'AssertionFailed') {
assertFailure(t, subset);
} else {
throw error;
}
});
});
}
function fails(t, fn) {
lastFailure = null;
let retval;
try {
retval = fn();
} catch (error) {
if (error.name !== 'AssertionFailed') {
throw error;
}
}
if (lastFailure) {
t.notOk(retval);
} else {
t.fail('Expected assertion to fail');
}
}
function passes(t, fn, {expectBoolean = true} = {}) {
lastPassed = false;
lastFailure = null;
const retval = fn();
if (lastPassed) {
if (expectBoolean) {
t.equal(retval, true);
} else {
t.pass();
}
} else {
t.error(lastFailure, 'Expected assertion to pass');
}
}
function throwsAsyncPasses(t, fn) {
return add(() => {
lastPassed = false;
lastFailure = null;
return fn().then(() => {
if (lastPassed) {
t.pass();
} else {
t.error(lastFailure, 'Expected assertion to pass');
}
});
});
}
const notThrowsAsyncPasses = throwsAsyncPasses;
test('.pass()', t => {
passes(t, () => assertions.pass());
passes(t, () => assertions.pass());
t.end();
});
test('.fail()', t => {
failsWith(t, () => assertions.fail(), {
assertion: 't.fail()',
message: 'Test failed via `t.fail()`',
});
failsWith(t, () => assertions.fail('my message'), {
assertion: 't.fail()',
message: 'my message',
});
failsWith(t, () => assertions.fail(), {
assertion: 't.fail()',
message: 'Test failed via `t.fail()`',
});
failsWith(t, () => assertions.fail(null), {
assertion: 't.fail()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
t.end();
});
test('.is()', t => {
passes(t, () => assertions.is('foo', 'foo'));
passes(t, () => assertions.is('foo', 'foo'));
passes(t, () => assertions.is('', ''));
passes(t, () => assertions.is(true, true));
passes(t, () => assertions.is(false, false));
passes(t, () => assertions.is(null, null));
passes(t, () => assertions.is(undefined, undefined));
passes(t, () => assertions.is(1, 1));
passes(t, () => assertions.is(0, 0));
passes(t, () => assertions.is(-0, -0));
passes(t, () => assertions.is(Number.NaN, Number.NaN));
passes(t, () => assertions.is(0 / 0, Number.NaN));
passes(t, () => {
const someRef = {foo: 'bar'};
return assertions.is(someRef, someRef);
});
fails(t, () => assertions.is(0, -0));
fails(t, () => assertions.is(0, false));
fails(t, () => assertions.is('', false));
fails(t, () => assertions.is('0', 0));
fails(t, () => assertions.is('17', 17));
fails(t, () => assertions.is([1, 2], '1,2'));
fails(t, () =>
// eslint-disable-next-line no-new-wrappers, unicorn/new-for-builtins
assertions.is(new String('foo'), 'foo'),
);
fails(t, () => assertions.is(null, undefined));
fails(t, () => assertions.is(null, false));
fails(t, () => assertions.is(undefined, false));
fails(t, () =>
// eslint-disable-next-line no-new-wrappers, unicorn/new-for-builtins
assertions.is(new String('foo'), new String('foo')),
);
fails(t, () => assertions.is(0, null));
fails(t, () => assertions.is(0, Number.NaN));
fails(t, () => assertions.is('foo', Number.NaN));
failsWith(t, () => assertions.is({foo: 'bar'}, {foo: 'bar'}), {
assertion: 't.is()',
message: '',
actual: {foo: 'bar'},
expected: {foo: 'bar'},
formattedDetails: [{
label: 'Values are deeply equal to each other, but they are not the same:',
formatted: /foo/,
}],
});
failsWith(t, () => assertions.is('foo', 'bar'), {
assertion: 't.is()',
message: '',
formattedDetails: [
{label: 'Difference (- actual, + expected):', formatted: /- 'foo'\n\+ 'bar'/},
],
});
failsWith(t, () => assertions.is('foo', 42), {
actual: 'foo',
assertion: 't.is()',
expected: 42,
message: '',
formattedDetails: [
{label: 'Difference (- actual, + expected):', formatted: /- 'foo'\n\+ 42/},
],
});
failsWith(t, () => assertions.is('foo', 42, 'my message'), {
assertion: 't.is()',
message: 'my message',
formattedDetails: [
{label: 'Difference (- actual, + expected):', formatted: /- 'foo'\n\+ 42/},
],
});
failsWith(t, () => assertions.is(0, -0, 'my message'), {
assertion: 't.is()',
message: 'my message',
formattedDetails: [
{label: 'Difference (- actual, + expected):', formatted: /- 0\n\+ -0/},
],
});
failsWith(t, () => assertions.is(-0, 0, 'my message'), {
assertion: 't.is()',
message: 'my message',
formattedDetails: [
{label: 'Difference (- actual, + expected):', formatted: /- -0\n\+ 0/},
],
});
failsWith(t, () => assertions.is(0, 0, null), {
assertion: 't.is()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
t.end();
});
test('.not()', t => {
passes(t, () => assertions.not('foo', 'bar'));
passes(t, () => assertions.not('foo', 'bar'));
fails(t, () => assertions.not(Number.NaN, Number.NaN));
fails(t, () => assertions.not(0 / 0, Number.NaN));
failsWith(t, () => assertions.not('foo', 'foo'), {
assertion: 't.not()',
message: '',
formattedDetails: [{label: 'Value is the same as:', formatted: /foo/}],
});
failsWith(t, () => assertions.not('foo', 'foo', 'my message'), {
assertion: 't.not()',
message: 'my message',
formattedDetails: [{label: 'Value is the same as:', formatted: /foo/}],
});
failsWith(t, () => assertions.not(0, 1, null), {
assertion: 't.not()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
t.end();
});
test('.deepEqual()', t => {
// Tests starting here are to detect regressions in the underlying libraries
// used to test deep object equality
fails(t, () => assertions.deepEqual({a: false}, {a: 0}));
passes(t, () => assertions.deepEqual({
a: 'a',
b: 'b',
}, {
b: 'b',
a: 'a',
}));
passes(t, () => assertions.deepEqual({a: 'a', b: 'b'}, {b: 'b', a: 'a'}));
passes(t, () => assertions.deepEqual({
a: 'a',
b: 'b',
c: {
d: 'd',
},
}, {
c: {
d: 'd',
},
b: 'b',
a: 'a',
}));
fails(t, () => assertions.deepEqual([1, 2, 3], [1, 2, 3, 4]));
passes(t, () => assertions.deepEqual([1, 2, 3], [1, 2, 3]));
fails(t, () => {
const fnA = a => a;
const fnB = a => a;
return assertions.deepEqual(fnA, fnB);
});
passes(t, () => {
const x1 = {z: 4};
const y1 = {x: x1};
x1.y = y1;
const x2 = {z: 4};
const y2 = {x: x2};
x2.y = y2;
return assertions.deepEqual(x1, x2);
});
passes(t, () => {
function Foo(a) {
this.a = a;
}
const x = new Foo(1);
const y = new Foo(1);
return assertions.deepEqual(x, y);
});
fails(t, () => {
function Foo(a) {
this.a = a;
}
function Bar(a) {
this.a = a;
}
const x = new Foo(1);
const y = new Bar(1);
return assertions.deepEqual(x, y);
});
fails(t, () => assertions.deepEqual({
a: 'a',
b: 'b',
c: {
d: false,
},
}, {
c: {
d: 0,
},
b: 'b',
a: 'a',
}));
fails(t, () => assertions.deepEqual({}, []));
fails(t, () => assertions.deepEqual({0: 'a', 1: 'b'}, ['a', 'b']));
fails(t, () => assertions.deepEqual({a: 1}, {a: 1, b: undefined}));
fails(t, () => assertions.deepEqual(new Date('1972-08-01'), null));
fails(t, () => assertions.deepEqual(new Date('1972-08-01'), undefined));
passes(t, () => assertions.deepEqual(new Date('1972-08-01'), new Date('1972-08-01')));
passes(t, () => assertions.deepEqual({x: new Date('1972-08-01')}, {x: new Date('1972-08-01')}));
fails(t, () => assertions.deepEqual(() => {}, () => {}));
passes(t, () => assertions.deepEqual(undefined, undefined)
&& assertions.deepEqual({x: undefined}, {x: undefined})
&& assertions.deepEqual({x: [undefined]}, {x: [undefined]}));
passes(t, () => assertions.deepEqual(null, null)
&& assertions.deepEqual({x: null}, {x: null})
&& assertions.deepEqual({x: [null]}, {x: [null]}));
passes(t, () => assertions.deepEqual(0, 0)
&& assertions.deepEqual(1, 1)
&& assertions.deepEqual(3.14, 3.14));
fails(t, () => assertions.deepEqual(0, 1));
fails(t, () => assertions.deepEqual(1, -1));
fails(t, () => assertions.deepEqual(3.14, 2.72));
fails(t, () => assertions.deepEqual({0: 'a', 1: 'b'}, ['a', 'b']));
passes(t, () => assertions.deepEqual(
[
{foo: {z: 100, y: 200, x: 300}},
'bar',
11,
{baz: {d: 4, a: 1, b: 2, c: 3}},
],
[
{foo: {x: 300, y: 200, z: 100}},
'bar',
11,
{baz: {c: 3, b: 2, a: 1, d: 4}},
],
));
passes(t, () => assertions.deepEqual(
{x: {a: 1, b: 2}, y: {c: 3, d: 4}},
{y: {d: 4, c: 3}, x: {b: 2, a: 1}},
));
// Regression test end here
passes(t, () => assertions.deepEqual({a: 'a'}, {a: 'a'}));
passes(t, () => assertions.deepEqual(['a', 'b'], ['a', 'b']));
fails(t, () => assertions.deepEqual({a: 'a'}, {a: 'b'}));
fails(t, () => assertions.deepEqual(['a', 'b'], ['a', 'a']));
fails(t, () => assertions.deepEqual([['a', 'b'], 'c'], [['a', 'b'], 'd']));
fails(t, () => {
const circular = ['a', 'b'];
circular.push(circular);
return assertions.deepEqual([circular, 'c'], [circular, 'd']);
});
failsWith(t, () => assertions.deepEqual('foo', 'bar'), {
assertion: 't.deepEqual()',
message: '',
formattedDetails: [{label: 'Difference (- actual, + expected):', formatted: /- 'foo'\n\+ 'bar'/}],
});
failsWith(t, () => assertions.deepEqual('foo', 42), {
assertion: 't.deepEqual()',
message: '',
formattedDetails: [{label: 'Difference (- actual, + expected):', formatted: /- 'foo'\n\+ 42/}],
});
failsWith(t, () => assertions.deepEqual('foo', 42, 'my message'), {
assertion: 't.deepEqual()',
message: 'my message',
formattedDetails: [{label: 'Difference (- actual, + expected):', formatted: /- 'foo'\n\+ 42/}],
});
failsWith(t, () => assertions.deepEqual({}, {}, null), {
assertion: 't.deepEqual()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
t.end();
});
test('.notDeepEqual()', t => {
passes(t, () => assertions.notDeepEqual({a: 'a'}, {a: 'b'}));
passes(t, () => assertions.notDeepEqual({a: 'a'}, {a: 'b'}));
passes(t, () => assertions.notDeepEqual(['a', 'b'], ['c', 'd']));
const actual = {a: 'a'};
const expected = {a: 'a'};
failsWith(t, () => assertions.notDeepEqual(actual, expected), {
actual,
assertion: 't.notDeepEqual()',
expected,
message: '',
formattedDetails: [{label: 'Value is deeply equal:', formatted: /.*{.*\n.*a: 'a'/}],
});
failsWith(t, () => assertions.notDeepEqual(['a', 'b'], ['a', 'b'], 'my message'), {
assertion: 't.notDeepEqual()',
message: 'my message',
formattedDetails: [{label: 'Value is deeply equal:', formatted: /.*\[.*\n.*'a',\n.*'b',/}],
});
failsWith(t, () => assertions.notDeepEqual({}, [], null), {
assertion: 't.notDeepEqual()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
t.end();
});
test('.like()', t => {
fails(t, () => assertions.like({a: false}, {a: 0}));
passes(t, () => assertions.like({
a: 'a',
b: 'b',
}, {
b: 'b',
a: 'a',
}));
passes(t, () => assertions.like({a: 'a', b: 'b'}, {b: 'b', a: 'a'}));
passes(t, () => assertions.like({
a: 'a',
b: 'b',
c: {
d: 'd',
x: 'x',
},
x: 'x',
}, {
c: {
d: 'd',
},
b: 'b',
a: 'a',
}));
fails(t, () => assertions.like([1, 2, 3], [1, 2, 3, 4]));
fails(t, () => assertions.like({
a: [1, 2, 3],
}, {
a: [1, 2, 3, 4],
}));
passes(t, () => assertions.like({
a: [1, 2, 3],
x: 'x',
}, {
a: [1, 2, 3],
}));
passes(t, () => {
const actual = {
a: 'a',
extra: 'irrelevant',
};
actual.circular = actual;
const likePattern = {
a: 'a',
};
return assertions.like(actual, likePattern);
});
fails(t, () => {
const fnA = a => a;
const fnB = a => a;
return assertions.like(fnA, fnB);
});
fails(t, () => {
const fnA = a => a;
const fnB = a => a;
return assertions.like({
fn: fnA,
}, {
fn: fnB,
});
});
fails(t, () => {
function Foo(a) {
this.a = a;
}
function Bar(a) {
this.a = a;
}
const x = new Foo(1);
const y = new Bar(1);
return assertions.like(x, y);
});
passes(t, () => assertions.like({a: 'a'}, {a: 'a'}));
passes(t, () => assertions.like({a: 'a', b: 'b'}, {a: 'a'}));
passes(t, () => assertions.like({ab: ['a', 'b']}, {ab: ['a', 'b']}));
passes(t, () => assertions.like({ab: ['a', 'b'], c: 'c'}, {ab: ['a', 'b']}));
fails(t, () => assertions.like({a: 'a'}, {a: 'b'}));
fails(t, () => assertions.like({a: 'a', b: 'b'}, {a: 'b'}));
fails(t, () => assertions.like({ab: ['a', 'b']}, {ab: ['a', 'a']}));
fails(t, () => assertions.like({ab: ['a', 'b'], c: 'c'}, {ab: ['a', 'a']}));
fails(t, () => assertions.like([['a', 'b'], 'c'], [['a', 'b'], 'd']));
fails(t, () => {
const circular = ['a', 'b'];
circular.push(circular);
return assertions.like([circular, 'c'], [circular, 'd']);
});
fails(t, () => {
const circular = ['a', 'b'];
circular.push(circular);
return assertions.like({xc: [circular, 'c']}, {xc: [circular, 'd']});
});
failsWith(t, () => assertions.like({a: 'a'}, Object.defineProperties({}, {ignored: {}})), {
assertion: 't.like()',
message: '`t.like()` selector must be a non-empty object',
formattedDetails: [{label: 'Called with:', formatted: '{}'}],
});
failsWith(t, () => assertions.like('foo', 'bar'), {
assertion: 't.like()',
message: '`t.like()` selector must be a non-empty object',
formattedDetails: [{label: 'Called with:', formatted: '\'bar\''}],
});
passes(t, () => {
const specimen = {[Symbol.toStringTag]: 'Custom', extra: true};
const selector = Object.defineProperties(
{[Symbol.toStringTag]: 'Custom'},
{ignored: {value: true}},
);
return assertions.like(specimen, selector);
});
passes(t, () => {
const array = ['c1', 'c2'];
return assertions.like({a: 'a', b: 'b', c: ['c1', 'c2'], d: ['c1', 'c2']}, {b: 'b', d: array, c: array});
});
failsWith(t, () => {
const likePattern = {
a: 'a',
};
likePattern.circular = likePattern;
return assertions.like({}, likePattern);
}, {
assertion: 't.like()',
message: '`t.like()` selector must not contain circular references',
formattedDetails: [{label: 'Called with:', formatted: '{\n a: \'a\',\n circular: [Circular],\n}'}],
});
failsWith(t, () => assertions.like({}, {}, null), {
assertion: 't.like()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
failsWith(t, () => assertions.like({a: 'foo', b: 'irrelevant'}, {a: 'bar'}), {
assertion: 't.like()',
message: '',
formattedDetails: [{label: 'Difference (- actual, + expected):', formatted: /{\n-\s*a: 'foo',\n\+\s*a: 'bar',\n\s*}/}],
});
passes(t, () => assertions.like({a: [{a: 1, b: 2}]}, {a: [{a: 1}]}));
passes(t, () => assertions.like([{a: 1, b: 2}], [{a: 1}]));
passes(t, () => assertions.like([{a: 1, b: 2}, {c: 3}], [{a: 1}]));
passes(t, () => assertions.like([1, 2, 3], [1, 2, 3]));
passes(t, () => assertions.like([1, 2, 3], [1, 2]));
// eslint-disable-next-line no-sparse-arrays
passes(t, () => assertions.like([1, 2, 3], [1, , 3]));
fails(t, () => assertions.like([1, 2, 3], [3, 2, 1]));
// eslint-disable-next-line no-sparse-arrays
fails(t, () => assertions.like([1, 2, 3], [1, , 4]));
fails(t, () => assertions.like([1, 2], [1, 2, 3]));
t.end();
});
test('.throws()', gather(t => {
// Fails because function doesn't throw.
failsWith(t, () => assertions.throws(() => {}), {
assertion: 't.throws()',
message: '',
formattedDetails: [{label: 'Function returned:', formatted: /undefined/}],
});
failsWith(t, () => assertions.throws(() => {}), {
assertion: 't.throws()',
message: '',
formattedDetails: [{label: 'Function returned:', formatted: /undefined/}],
});
// Fails because function doesn't throw. Asserts that 'my message' is used
// as the assertion message (*not* compared against the error).
failsWith(t, () => assertions.throws(() => {}, undefined, 'my message'), {
assertion: 't.throws()',
message: 'my message',
formattedDetails: [{label: 'Function returned:', formatted: /undefined/}],
});
// Fails because the function returned a promise.
failsWith(t, () => assertions.throws(() => Promise.resolve()), {
assertion: 't.throws()',
message: '',
formattedDetails: [{label: 'Function returned a promise. Use `t.throwsAsync()` instead:', formatted: /Promise/}],
});
// Fails because thrown exception is not an error
failsWith(t, () => assertions.throws(() => {
const error = 'foo';
throw error;
}), {
assertion: 't.throws()',
message: '',
formattedDetails: [
{label: 'Function threw exception that is not an error:', formatted: /'foo'/},
],
});
// Passes because an error is thrown.
passes(t, () => assertions.throws(() => {
throw new Error('foo');
}), {expectBoolean: false});
// Passes when string is thrown, only when any is set to true.
passes(t, () => assertions.throws(() => {
throw 'foo'; // eslint-disable-line no-throw-literal
}, {any: true}), {expectBoolean: false});
// Passes because the correct error is thrown.
passes(t, () => {
const error = new Error('foo');
return assertions.throws(() => {
throw error;
}, {is: error});
}, {expectBoolean: false});
// Fails because the thrown value is not an error
fails(t, () => {
const object = {};
return assertions.throws(() => {
throw object;
}, {is: object});
});
// Fails because the thrown value is not the right one
fails(t, () => {
const error = new Error('foo');
return assertions.throws(() => {
throw error;
}, {is: {}});
});
// Passes because the correct error is thrown.
passes(t, () => assertions.throws(() => {
throw new TypeError();
}, {name: 'TypeError'}), {expectBoolean: false});
// Fails because the thrown value is not an error
fails(t, () => assertions.throws(() => {
const error = {name: 'Bob'};
throw error;
}, {name: 'Bob'}));
// Fails because the thrown value is not the right one
fails(t, () => assertions.throws(() => {
throw new Error('foo');
}, {name: 'TypeError'}));
// Passes because the correct error is thrown.
passes(t, () => assertions.throws(() => {
const error = new TypeError();
error.code = 'ERR_TEST';
throw error;
}, {code: 'ERR_TEST'}), {expectBoolean: false});
// Passes because the correct error is thrown.
passes(t, () => assertions.throws(() => {
const error = new TypeError();
error.code = 42;
throw error;
}, {code: 42}), {expectBoolean: false});
// Fails because the thrown value is not the right one
fails(t, () => assertions.throws(() => {
const error = new TypeError();
error.code = 'ERR_NOPE';
throw error;
}, {code: 'ERR_TEST'}));
fails(t, () => assertions.throws(() => {
const error = new TypeError();
error.code = 1;
throw error;
}, {code: 42}));
// Regression test for https://github.com/avajs/ava/issues/1676
fails(t, () => assertions.throws(() => {
throw new Error('foo');
}, false));
passes(t, () => assertions.throws(() => {
throw new Error('foo');
}, undefined), {expectBoolean: false});
passes(t, async () => {
await assertions.throwsAsync(() => Promise.reject(new Error('foo')), undefined);
}, {expectBoolean: false});
failsWith(t, () => assertions.throws(() => {}, undefined, null), {
assertion: 't.throws()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
// Fails because the string in the message is incorrect
failsWith(
t,
() =>
assertions.throws(
() => {
throw new Error('error');
},
{message: 'my error'},
),
{
assertion: 't.throws()',
message: '',
formattedDetails: [
{label: 'Function threw unexpected exception:', formatted: /error/},
{label: 'Expected message to equal:', formatted: /my error/},
],
},
);
passes(t, () => assertions.throws(() => {
throw new Error('error');
}, {message: 'error'}), {expectBoolean: false});
// Fails because the regular expression in the message is incorrect
failsWith(
t,
() =>
assertions.throws(
() => {
throw new Error('error');
},
{message: /my error/},
),
{
assertion: 't.throws()',
message: '',
formattedDetails: [
{label: 'Function threw unexpected exception:', formatted: /error/},
{label: 'Expected message to match:', formatted: /my error/},
],
},
);
passes(t, () => assertions.throws(() => {
throw new Error('error');
}, {message: /error/}), {expectBoolean: false});
// Fails because the function in the message returns false
failsWith(
t,
() =>
assertions.throws(
() => {
throw new Error('error');
},
{message: () => false},
),
{
assertion: 't.throws()',
message: '',
formattedDetails: [
{label: 'Function threw unexpected exception:', formatted: /error/},
{label: 'Expected message to return true:', formatted: /Function/},
],
},
);
passes(t, () => assertions.throws(() => {
throw new Error('error');
}, {message: () => true}), {expectBoolean: false});
}));
test('.throws() returns the thrown error', t => {
const expected = new Error();
const actual = assertions.throws(() => {
throw expected;
});
t.equal(actual, expected);
t.end();
});
test('.throwsAsync()', gather(t => {
// Fails because the promise is resolved, not rejected.
throwsAsyncFails(t, () => assertions.throwsAsync(Promise.resolve('foo')), {
assertion: 't.throwsAsync()',
message: '',
formattedDetails: [{label: 'Promise resolved with:', formatted: /'foo'/}],
});
throwsAsyncFails(t, () => assertions.throwsAsync(Promise.resolve('foo')), {
assertion: 't.throwsAsync()',
message: '',
formattedDetails: [{label: 'Promise resolved with:', formatted: /'foo'/}],
});
// Fails because the promise is resolved with an Error
throwsAsyncFails(t, () => assertions.throwsAsync(Promise.resolve(new Error())), {
assertion: 't.throwsAsync()',
message: '',
formattedDetails: [{label: 'Promise resolved with:', formatted: /Error/}],
});
// Fails because the function returned a promise that resolved, not rejected.
throwsAsyncFails(t, () => assertions.throwsAsync(() => Promise.resolve('foo')), {
assertion: 't.throwsAsync()',
message: '',
formattedDetails: [{label: 'Returned promise resolved with:', formatted: /'foo'/}],
});
// Fails because the function returned a promise that rejected, but not with an error.
throwsAsyncFails(t, () => assertions.throwsAsync(() => Promise.reject('foo')), { // eslint-disable-line prefer-promise-reject-errors
assertion: 't.throwsAsync()',
message: '',
formattedDetails: [{label: 'Returned promise rejected with exception that is not an error:', formatted: /'foo'/}],
});
// Passes because the promise was rejected with an error.
throwsAsyncPasses(t, () => assertions.throwsAsync(Promise.reject(new Error())));
// Passes because the promise was rejected with an with an non-error exception, & set `any` to true in expectation.
throwsAsyncPasses(t, () => assertions.throwsAsync(Promise.reject('foo'), {any: true})); // eslint-disable-line prefer-promise-reject-errors
// Passes because the function returned a promise rejected with an error.
throwsAsyncPasses(t, () => assertions.throwsAsync(() => Promise.reject(new Error())));
// Fails because the function throws synchronously
throwsAsyncFails(t, () => assertions.throwsAsync(() => {
throw new Error('sync');
}, undefined, 'message'), {
assertion: 't.throwsAsync()',
message: 'message',
formattedDetails: [
{label: 'Function threw synchronously. Use `t.throws()` instead:', formatted: /Error/},
],
});
// Fails because the function did not return a promise
throwsAsyncFails(t, () => assertions.throwsAsync(() => {}, undefined, 'message'), {
assertion: 't.throwsAsync()',
message: 'message',
formattedDetails: [
{label: 'Function returned:', formatted: /undefined/},
],
});
throwsAsyncFails(t, () => assertions.throwsAsync(Promise.resolve(), undefined, null), {
assertion: 't.throwsAsync()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
}));
test('.throwsAsync() returns the rejection reason of promise', t => {
const expected = new Error();
return assertions.throwsAsync(Promise.reject(expected)).then(actual => {
t.equal(actual, expected);
t.end();
});
});
test('.throwsAsync() returns the rejection reason of a promise returned by the function', t => {
const expected = new Error();
return assertions.throwsAsync(() => Promise.reject(expected)).then(actual => {
t.equal(actual, expected);
t.end();
});
});
test('.throws() fails if passed a bad value', t => {
failsWith(t, () => assertions.throws('not a function'), {
assertion: 't.throws()',
message: '`t.throws()` must be called with a function',
formattedDetails: [{label: 'Called with:', formatted: /not a function/}],
});
t.end();
});
test('.throwsAsync() fails if passed a bad value', gather(t => {
throwsAsyncFails(t, () => assertions.throwsAsync('not a function'), {
assertion: 't.throwsAsync()',
message: '`t.throwsAsync()` must be called with a function or promise',
formattedDetails: [{label: 'Called with:', formatted: /not a function/}],
});
}));
test('.throws() fails if passed a bad expectation', t => {
failsWith(t, () => assertions.throws(() => {}, true), {
assertion: 't.throws()',
message: 'The second argument to `t.throws()` must be an expectation object, `null` or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /true/}],
});
failsWith(t, () => assertions.throws(() => {}, 'foo'), {
assertion: 't.throws()',
message: 'The second argument to `t.throws()` must be an expectation object, `null` or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /foo/}],
});
failsWith(t, () => assertions.throws(() => {}, /baz/), {
assertion: 't.throws()',
message: 'The second argument to `t.throws()` must be an expectation object, `null` or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /baz/}],
});
failsWith(t, () => assertions.throws(() => {}, class Bar {}), {
assertion: 't.throws()',
message: 'The second argument to `t.throws()` must be an expectation object, `null` or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /Bar/}],
});
failsWith(t, () => assertions.throws(() => {}, {}), {
assertion: 't.throws()',
message: 'The second argument to `t.throws()` must be an expectation object, `null` or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /{}/}],
});
failsWith(t, () => assertions.throws(() => {}, []), {
assertion: 't.throws()',
message: 'The second argument to `t.throws()` must be an expectation object, `null` or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /\[]/}],
});
failsWith(t, () => assertions.throws(() => {}, {any: {}}), {
assertion: 't.throws()',
message: 'The `any` property of the second argument to `t.throws()` must be a boolean',
formattedDetails: [{label: 'Called with:', formatted: /any: {}/}],
});
failsWith(t, () => assertions.throws(() => {}, {code: {}}), {
assertion: 't.throws()',
message: 'The `code` property of the second argument to `t.throws()` must be a string or number',
formattedDetails: [{label: 'Called with:', formatted: /code: {}/}],
});
failsWith(t, () => assertions.throws(() => {}, {instanceOf: null}), {
assertion: 't.throws()',
message: 'The `instanceOf` property of the second argument to `t.throws()` must be a function',
formattedDetails: [{label: 'Called with:', formatted: /instanceOf: null/}],
});
failsWith(t, () => assertions.throws(() => {}, {message: null}), {
assertion: 't.throws()',
message: 'The `message` property of the second argument to `t.throws()` must be a string, regular expression or a function',
formattedDetails: [{label: 'Called with:', formatted: /message: null/}],
});
failsWith(t, () => assertions.throws(() => {}, {name: null}), {
assertion: 't.throws()',
message: 'The `name` property of the second argument to `t.throws()` must be a string',
formattedDetails: [{label: 'Called with:', formatted: /name: null/}],
});
failsWith(t, () => assertions.throws(() => {}, {is: {}, message: '', name: '', of() {}, foo: null}), {
assertion: 't.throws()',
message: 'The second argument to `t.throws()` contains unexpected properties',
formattedDetails: [{label: 'Called with:', formatted: /foo: null/}],
});
t.end();
});
test('.throwsAsync() fails if passed a bad expectation', async t => {
await failsWithAsync(t, () => assertions.throwsAsync(() => {}, true), {
assertion: 't.throwsAsync()',
message: 'The second argument to `t.throwsAsync()` must be an expectation object, `null` or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /true/}],
});
await failsWithAsync(t, () => assertions.throwsAsync(() => {}, 'foo'), {
assertion: 't.throwsAsync()',
message: 'The second argument to `t.throwsAsync()` must be an expectation object, `null` or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /foo/}],
});
await failsWithAsync(t, () => assertions.throwsAsync(() => {}, /baz/), {
assertion: 't.throwsAsync()',
message: 'The second argument to `t.throwsAsync()` must be an expectation object, `null` or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /baz/}],
});
await failsWithAsync(t, () => assertions.throwsAsync(() => {}, class Bar {}), {
assertion: 't.throwsAsync()',
message: 'The second argument to `t.throwsAsync()` must be an expectation object, `null` or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /Bar/}],
});
await failsWithAsync(t, () => assertions.throwsAsync(() => {}, {}), {
assertion: 't.throwsAsync()',
message: 'The second argument to `t.throwsAsync()` must be an expectation object, `null` or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /{}/}],
});
await failsWithAsync(t, () => assertions.throwsAsync(() => {}, []), {
assertion: 't.throwsAsync()',
message: 'The second argument to `t.throwsAsync()` must be an expectation object, `null` or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /\[]/}],
});
await failsWithAsync(t, () => assertions.throwsAsync(() => {}, {any: {}}), {
assertion: 't.throwsAsync()',
message: 'The `any` property of the second argument to `t.throwsAsync()` must be a boolean',
formattedDetails: [{label: 'Called with:', formatted: /any: {}/}],
});
await failsWithAsync(t, () => assertions.throwsAsync(() => {}, {code: {}}), {
assertion: 't.throwsAsync()',
message: 'The `code` property of the second argument to `t.throwsAsync()` must be a string or number',
formattedDetails: [{label: 'Called with:', formatted: /code: {}/}],
});
await failsWithAsync(t, () => assertions.throwsAsync(() => {}, {instanceOf: null}), {
assertion: 't.throwsAsync()',
message: 'The `instanceOf` property of the second argument to `t.throwsAsync()` must be a function',
formattedDetails: [{label: 'Called with:', formatted: /instanceOf: null/}],
});
await failsWithAsync(t, () => assertions.throwsAsync(() => {}, {message: null}), {
assertion: 't.throwsAsync()',
message: 'The `message` property of the second argument to `t.throwsAsync()` must be a string, regular expression or a function',
formattedDetails: [{label: 'Called with:', formatted: /message: null/}],
});
await failsWithAsync(t, () => assertions.throwsAsync(() => {}, {name: null}), {
assertion: 't.throwsAsync()',
message: 'The `name` property of the second argument to `t.throwsAsync()` must be a string',
formattedDetails: [{label: 'Called with:', formatted: /name: null/}],
});
await failsWithAsync(t, () => assertions.throwsAsync(() => {}, {is: {}, message: '', name: '', of() {}, foo: null}), {
assertion: 't.throwsAsync()',
message: 'The second argument to `t.throwsAsync()` contains unexpected properties',
formattedDetails: [{label: 'Called with:', formatted: /foo: null/}],
});
t.end();
});
test('.throws() fails if passed null expectation', t => {
const asserter = new AssertionsBase();
failsWith(t, () => {
asserter.throws(() => {}, null);
}, {
assertion: 't.throws()',
message: 'The second argument to `t.throws()` must be an expectation object or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /null/}],
});
t.end();
});
test('.throwsAsync() fails if passed null', async t => {
const asserter = new AssertionsBase();
await failsWithAsync(t, () => asserter.throwsAsync(() => {}, null), {
assertion: 't.throwsAsync()',
message: 'The second argument to `t.throwsAsync()` must be an expectation object or `undefined`',
formattedDetails: [{label: 'Called with:', formatted: /null/}],
});
t.end();
});
test('.notThrows()', gather(t => {
// Passes because the function doesn't throw
passes(t, () => assertions.notThrows(() => {}));
passes(t, () => assertions.notThrows(() => {}));
// Fails because the function throws.
failsWith(t, () => assertions.notThrows(() => {
throw new Error('foo');
}), {
assertion: 't.notThrows()',
message: '',
formattedDetails: [{label: 'Function threw:', formatted: /foo/}],
});
// Fails because the function throws. Asserts that message is used for the
// assertion, not to validate the thrown error.
failsWith(t, () => assertions.notThrows(() => {
throw new Error('foo');
}, 'my message'), {
assertion: 't.notThrows()',
message: 'my message',
formattedDetails: [{label: 'Function threw:', formatted: /foo/}],
});
failsWith(t, () => assertions.notThrows(() => {}, null), {
assertion: 't.notThrows()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
}));
test('.notThrowsAsync()', gather(t => {
// Passes because the promise is resolved
notThrowsAsyncPasses(t, () => assertions.notThrowsAsync(Promise.resolve()));
notThrowsAsyncPasses(t, () => assertions.notThrowsAsync(Promise.resolve()));
// Fails because the promise is rejected
notThrowsAsyncFails(t, () => assertions.notThrowsAsync(Promise.reject(new Error())), {
assertion: 't.notThrowsAsync()',
message: '',
formattedDetails: [{label: 'Promise rejected with:', formatted: /Error/}],
});
// Passes because the function returned a resolved promise
notThrowsAsyncPasses(t, () => assertions.notThrowsAsync(() => Promise.resolve()));
// Fails because the function returned a rejected promise
notThrowsAsyncFails(t, () => assertions.notThrowsAsync(() => Promise.reject(new Error())), {
assertion: 't.notThrowsAsync()',
message: '',
formattedDetails: [{label: 'Returned promise rejected with:', formatted: /Error/}],
});
// Fails because the function throws synchronously
notThrowsAsyncFails(t, () => assertions.notThrowsAsync(() => {
throw new Error('sync');
}, 'message'), {
assertion: 't.notThrowsAsync()',
message: 'message',
formattedDetails: [
{label: 'Function threw:', formatted: /Error/},
],
});
// Fails because the function did not return a promise
notThrowsAsyncFails(t, () => assertions.notThrowsAsync(() => {}, 'message'), {
assertion: 't.notThrowsAsync()',
message: 'message',
formattedDetails: [
{label: 'Function did not return a promise. Use `t.notThrows()` instead:', formatted: /undefined/},
],
});
notThrowsAsyncFails(t, () => assertions.notThrowsAsync(Promise.resolve(), null), {
assertion: 't.notThrowsAsync()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
}));
test('.notThrows() fails if passed a bad value', t => {
failsWith(t, () => assertions.notThrows('not a function'), {
assertion: 't.notThrows()',
message: '`t.notThrows()` must be called with a function',
formattedDetails: [{label: 'Called with:', formatted: /not a function/}],
});
t.end();
});
test('.notThrowsAsync() fails if passed a bad value', async t => {
await failsWithAsync(t, () => assertions.notThrowsAsync('not a function'), {
assertion: 't.notThrowsAsync()',
message: '`t.notThrowsAsync()` must be called with a function or promise',
formattedDetails: [{label: 'Called with:', formatted: /not a function/}],
});
t.end();
});
test('.snapshot()', async t => {
// Set to `true` to update the snapshot, then run:
// npx tap test-tap/assert.js
//
// Ignore errors and make sure not to run tests with the `-b` (bail) option.
const updating = false;
const projectDir = fileURLToPath(new URL('fixture', import.meta.url));
const manager = snapshotManager.load({
file: path.join(projectDir, 'assert.cjs'),
projectDir,
fixedLocation: null,
recordNewSnapshots: updating,
updating,
});
const setup = _title => new class extends assertions.constructor {
constructor(title) {
super({
compareWithSnapshot: assertionOptions => {
const {record, ...result} = manager.compare({
belongsTo: this.title,
expected: assertionOptions.expected,
index: this.snapshotInvocationCount++,
label: assertionOptions.message ?? `Snapshot ${this.snapshotInvocationCount}`,
});
if (record) {
record();
}
return result;
},
});
this.title = title;
this.snapshotInvocationCount = 0;
}
}(_title);
{
const assertions = setup('passes');
passes(t, () => assertions.snapshot({foo: 'bar'}));
passes(t, () => assertions.snapshot({foo: 'bar'}));
}
{
const assertions = setup('fails');
if (updating) {
return assertions.snapshot({foo: 'bar'});
}
failsWith(t, () => assertions.snapshot({foo: 'not bar'}), {
assertion: 't.snapshot()',
message: 'Did not match snapshot',
formattedDetails: [{label: 'Difference (- actual, + expected):', formatted: ' {\n- foo: \'not bar\',\n+ foo: \'bar\',\n }'}],
});
}
{
const assertions = setup('fails');
if (updating) {
return assertions.snapshot({foo: 'bar'}, 'my message');
}
failsWith(t, () => assertions.snapshot({foo: 'not bar'}, 'my message'), {
assertion: 't.snapshot()',
message: 'my message',
formattedDetails: [{label: 'Difference (- actual, + expected):', formatted: ' {\n- foo: \'not bar\',\n+ foo: \'bar\',\n }'}],
});
}
{
const assertions = setup('bad message');
failsWith(t, () => assertions.snapshot(null, null), {
assertion: 't.snapshot()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
failsWith(t, () => assertions.snapshot(null, ''), {
assertion: 't.snapshot()',
message: 'The snapshot assertion message must be a non-empty string',
formattedDetails: [{
label: 'Called with:',
formatted: '\'\'',
}],
});
}
await manager.save();
t.end();
});
test('.truthy()', t => {
failsWith(t, () => assertions.truthy(0), {
assertion: 't.truthy()',
message: '',
formattedDetails: [{label: 'Value is not truthy:', formatted: /0/}],
});
failsWith(t, () => assertions.truthy(false, 'my message'), {
assertion: 't.truthy()',
message: 'my message',
formattedDetails: [{label: 'Value is not truthy:', formatted: /false/}],
});
passes(t, () => assertions.truthy(1)
&& assertions.truthy(true));
passes(t, () => assertions.truthy(1) && assertions.truthy(true));
failsWith(t, () => assertions.truthy(true, null), {
assertion: 't.truthy()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
t.end();
});
test('.falsy()', t => {
failsWith(t, () => assertions.falsy(1), {
assertion: 't.falsy()',
message: '',
formattedDetails: [{label: 'Value is not falsy:', formatted: /1/}],
});
failsWith(t, () => assertions.falsy(true, 'my message'), {
assertion: 't.falsy()',
message: 'my message',
formattedDetails: [{label: 'Value is not falsy:', formatted: /true/}],
});
passes(t, () => assertions.falsy(0)
&& assertions.falsy(false));
passes(t, () => assertions.falsy(0)
&& assertions.falsy(false));
failsWith(t, () => assertions.falsy(false, null), {
assertion: 't.falsy()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
t.end();
});
test('.true()', t => {
failsWith(t, () => assertions.true(1), {
assertion: 't.true()',
message: '',
formattedDetails: [{label: 'Value is not `true`:', formatted: /1/}],
});
failsWith(t, () => assertions.true(0), {
assertion: 't.true()',
message: '',
formattedDetails: [{label: 'Value is not `true`:', formatted: /0/}],
});
failsWith(t, () => assertions.true(false), {
assertion: 't.true()',
message: '',
formattedDetails: [{label: 'Value is not `true`:', formatted: /false/}],
});
failsWith(t, () => assertions.true('foo', 'my message'), {
assertion: 't.true()',
message: 'my message',
formattedDetails: [{label: 'Value is not `true`:', formatted: /foo/}],
});
passes(t, () => assertions.true(true));
passes(t, () => {
const {true: trueFn} = assertions;
return trueFn(true);
});
failsWith(t, () => assertions.true(true, null), {
assertion: 't.true()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
t.end();
});
test('.false()', t => {
failsWith(t, () => assertions.false(0), {
assertion: 't.false()',
message: '',
formattedDetails: [{label: 'Value is not `false`:', formatted: /0/}],
});
failsWith(t, () => assertions.false(1), {
assertion: 't.false()',
message: '',
formattedDetails: [{label: 'Value is not `false`:', formatted: /1/}],
});
failsWith(t, () => assertions.false(true), {
assertion: 't.false()',
message: '',
formattedDetails: [{label: 'Value is not `false`:', formatted: /true/}],
});
failsWith(t, () => assertions.false('foo', 'my message'), {
assertion: 't.false()',
message: 'my message',
formattedDetails: [{label: 'Value is not `false`:', formatted: /foo/}],
});
passes(t, () => assertions.false(false));
passes(t, () => {
const {false: falseFn} = assertions;
return falseFn(false);
});
failsWith(t, () => assertions.false(false, null), {
assertion: 't.false()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
t.end();
});
test('.regex()', t => {
passes(t, () => assertions.regex('abc', /^abc$/));
passes(t, () => assertions.regex('abc', /^abc$/));
failsWith(t, () => assertions.regex('foo', /^abc$/), {
assertion: 't.regex()',
message: '',
formattedDetails: [
{label: 'Value must match expression:', formatted: /foo/},
{label: 'Regular expression:', formatted: /\/\^abc\$\//},
],
});
failsWith(t, () => assertions.regex('foo', /^abc$/, 'my message'), {
assertion: 't.regex()',
message: 'my message',
formattedDetails: [
{label: 'Value must match expression:', formatted: /foo/},
{label: 'Regular expression:', formatted: /\/\^abc\$\//},
],
});
failsWith(t, () => assertions.regex('foo', /^abc$/, null), {
assertion: 't.regex()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
t.end();
});
test('.regex() fails if passed a bad value', t => {
failsWith(t, () => assertions.regex(42, /foo/), {
assertion: 't.regex()',
message: '`t.regex()` must be called with a string',
formattedDetails: [{label: 'Called with:', formatted: /42/}],
});
failsWith(t, () => assertions.regex('42', {}), {
assertion: 't.regex()',
message: '`t.regex()` must be called with a regular expression',
formattedDetails: [{label: 'Called with:', formatted: /{}/}],
});
t.end();
});
test('.notRegex()', t => {
passes(t, () => assertions.notRegex('abc', /def/));
passes(t, () => assertions.notRegex('abc', /def/));
failsWith(t, () => assertions.notRegex('abc', /abc/), {
assertion: 't.notRegex()',
message: '',
formattedDetails: [
{label: 'Value must not match expression:', formatted: /abc/},
{label: 'Regular expression:', formatted: /\/abc\//},
],
});
failsWith(t, () => assertions.notRegex('abc', /abc/, 'my message'), {
assertion: 't.notRegex()',
message: 'my message',
formattedDetails: [
{label: 'Value must not match expression:', formatted: /abc/},
{label: 'Regular expression:', formatted: /\/abc\//},
],
});
failsWith(t, () => assertions.notRegex('abc', /abc/, null), {
assertion: 't.notRegex()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
t.end();
});
test('.notRegex() fails if passed a bad value', t => {
failsWith(t, () => assertions.notRegex(42, /foo/), {
assertion: 't.notRegex()',
message: '`t.notRegex()` must be called with a string',
formattedDetails: [{label: 'Called with:', formatted: /42/}],
});
failsWith(t, () => assertions.notRegex('42', {}), {
assertion: 't.notRegex()',
message: '`t.notRegex()` must be called with a regular expression',
formattedDetails: [{label: 'Called with:', formatted: /{}/}],
});
t.end();
});
test('.assert()', t => {
failsWith(t, () => assertions.assert(0), {
assertion: 't.assert()',
message: '',
formattedDetails: [{label: 'Value is not truthy:', formatted: /0/}],
});
failsWith(t, () => assertions.assert(false, 'my message'), {
assertion: 't.assert()',
message: 'my message',
formattedDetails: [{label: 'Value is not truthy:', formatted: /false/}],
});
passes(t, () => assertions.assert(1)
&& assertions.assert(true));
passes(t, () => assertions.assert(1) && assertions.assert(true));
failsWith(t, () => assertions.assert(null, null), {
assertion: 't.assert()',
message: 'The assertion message must be a string',
formattedDetails: [{
label: 'Called with:',
formatted: /null/,
}],
});
t.end();
});