Skip to content

Commit 1150991

Browse files
Self-host the built-in Node.js assert tests
Also make `test-ava` work from inside the `test` directory. Co-authored-by: Mark Wubben <mark@novemberborn.net>
1 parent 5ddc9fd commit 1150991

File tree

12 files changed

+60
-55
lines changed

12 files changed

+60
-55
lines changed

test-tap/helper/cli.js

+1-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ const childProcess = require('child_process');
44
const getStream = require('get-stream');
55

66
const cliPath = path.join(__dirname, '../../cli.js');
7-
const ttySimulator = path.join(__dirname, 'simulate-tty.js');
87

98
function execCli(args, options, cb) {
109
let dirname;
@@ -24,9 +23,7 @@ function execCli(args, options, cb) {
2423
let stderr;
2524

2625
const processPromise = new Promise(resolve => {
27-
// Spawning a child with piped IO means that the CLI will never see a TTY.
28-
// Inserting a shim here allows us to fake a TTY.
29-
child = childProcess.spawn(process.execPath, ['--require', ttySimulator, cliPath].concat(args), {
26+
child = childProcess.spawn(process.execPath, [cliPath].concat(args), {
3027
cwd: dirname,
3128
env: {AVA_FORCE_CI: 'ci', ...env}, // Force CI to ensure the correct reporter is selected
3229
// env,

test-tap/integration/node-assertions.js

-29
This file was deleted.

test/assertions/test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ const test = require('@ava/test');
22
const exec = require('../helpers/exec');
33

44
test('happy path', async t => {
5-
const result = await exec.fixture('happy-path.js');
5+
const result = await exec.fixture(['happy-path.js']);
66
t.snapshot(result.stats.passed.map(({title}) => title));
77
});

test-tap/fixture/node-assertions/assert-failure.js test/builtin-nodejs-assert/fixtures/assert-failure.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
const test = require('ava');
12
const assert = require('assert');
2-
const test = require('../../..');
33

44
test('test', () => {
55
assert(false);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"ava": {
3+
"files": [
4+
"*.js"
5+
]
6+
}
7+
}

test/builtin-nodejs-assert/test.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const test = require('@ava/test');
2+
const exec = require('../helpers/exec');
3+
4+
test('node assertion failures are reported to the console when running in a terminal', async t => {
5+
const options = {
6+
env: {
7+
// The AssertionError constructor in Node.js 10 depends on the TTY interface, so opt-in
8+
// to it being simulated.
9+
AVA_SIMULATE_TTY: true,
10+
AVA_TTY_COLOR_DEPTH: 8
11+
}
12+
};
13+
14+
const result = await t.throwsAsync(exec.fixture(['assert-failure.js'], options));
15+
const error = result.stats.getError(result.stats.failed[0]);
16+
17+
t.true(error.values.every(value => value.formatted.includes('AssertionError')));
18+
});
19+
20+
test('node assertion failures are reported to the console when not running in a terminal', async t => {
21+
const result = await t.throwsAsync(exec.fixture(['assert-failure.js']));
22+
const error = result.stats.getError(result.stats.failed[0]);
23+
24+
t.true(error.values.every(value => value.formatted.includes('AssertionError')));
25+
});

test/helpers/exec.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ const v8 = require('v8');
33

44
const test = require('@ava/test');
55
const execa = require('execa');
6+
const defaultsDeep = require('lodash/defaultsDeep');
67

78
const cliPath = path.resolve(__dirname, '../../cli.js');
9+
const ttySimulator = path.join(__dirname, './simulate-tty.js');
10+
811
const serialization = process.versions.node >= '12.16.0' ? 'advanced' : 'json';
912

1013
const normalizePath = (root, file) => path.posix.normalize(path.relative(root, file));
@@ -25,15 +28,16 @@ const compareStatObjects = (a, b) => {
2528
return 1;
2629
};
2730

28-
exports.fixture = async (...args) => {
31+
exports.fixture = async (args, options = {}) => {
2932
const cwd = path.join(path.dirname(test.meta.file), 'fixtures');
30-
const running = execa.node(cliPath, args, {
33+
const running = execa.node(cliPath, args, defaultsDeep({
3134
env: {
3235
AVA_EMIT_RUN_STATUS_OVER_IPC: 'I\'ll find a payphone baby / Take some time to talk to you'
3336
},
3437
cwd,
35-
serialization
36-
});
38+
serialization,
39+
nodeOptions: ['--require', ttySimulator]
40+
}, options));
3741

3842
// Besides buffering stderr, if this environment variable is set, also pipe
3943
// to stderr. This can be useful when debugging the tests.

test-tap/helper/simulate-tty.js test/helpers/simulate-tty.js

+8-8
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const assertHasColorsArguments = count => {
55
tty.WriteStream.prototype.hasColors(count);
66
};
77

8-
const makeHasColors = colorDepth => (count = 16, env = undefined) => {
8+
const makeHasColors = colorDepth => (count = 16, env) => { // eslint-disable-line default-param-last
99
// `count` is optional too, so make sure it's not an env object.
1010
if (env === undefined && typeof count === 'object' && count !== null) {
1111
count = 16;
@@ -15,7 +15,7 @@ const makeHasColors = colorDepth => (count = 16, env = undefined) => {
1515
return count <= 2 ** colorDepth;
1616
};
1717

18-
const simulateTTY = (stream, colorDepth, hasColors) => {
18+
const simulateTTY = (stream, colorDepth) => {
1919
stream.isTTY = true;
2020
stream.columns = 80;
2121
stream.rows = 24;
@@ -24,9 +24,10 @@ const simulateTTY = (stream, colorDepth, hasColors) => {
2424
stream.getColorDepth = () => colorDepth;
2525
}
2626

27-
if (hasColors) {
28-
stream.hasColors = makeHasColors(colorDepth);
29-
}
27+
stream.hasColors = makeHasColors(colorDepth);
28+
stream.clearLine = tty.WriteStream.prototype.clearLine;
29+
stream.cursorTo = tty.WriteStream.prototype.cursorTo;
30+
stream.moveCursor = tty.WriteStream.prototype.moveCursor;
3031
};
3132

3233
// The execCli helper spawns tests in a child process. This means that stdout is
@@ -36,8 +37,7 @@ if (process.env.AVA_SIMULATE_TTY) {
3637
const colorDepth = process.env.AVA_TTY_COLOR_DEPTH ?
3738
Number.parseInt(process.env.AVA_TTY_COLOR_DEPTH, 10) :
3839
undefined;
39-
const hasColors = process.env.AVA_TTY_HAS_COLORS !== undefined;
4040

41-
simulateTTY(process.stderr, colorDepth, hasColors);
42-
simulateTTY(process.stdout, colorDepth, hasColors);
41+
simulateTTY(process.stderr, colorDepth);
42+
simulateTTY(process.stdout, colorDepth);
4343
}

test/hook-restrictions/test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ const test = require('@ava/test');
22
const exec = require('../helpers/exec');
33

44
test('snapshots cannot be used in hooks', async t => {
5-
const result = await t.throwsAsync(exec.fixture('invalid-snapshots-in-hooks.js'));
5+
const result = await t.throwsAsync(exec.fixture(['invalid-snapshots-in-hooks.js']));
66
const error = result.stats.getError(result.stats.failedHooks[0]);
77
t.snapshot(error.message, 'error message');
88
});
99

1010
test('`t.try()` cannot be used in hooks', async t => {
11-
const result = await t.throwsAsync(exec.fixture('invalid-t-try-in-hooks.js'));
11+
const result = await t.throwsAsync(exec.fixture(['invalid-t-try-in-hooks.js']));
1212
const error = result.stats.getError(result.stats.failedHooks[0]);
1313
t.snapshot(error.message, 'error message');
1414
});

test/node_modules/.bin/test-ava

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/snapshot-updates/test.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ const test = require('@ava/test');
22
const exec = require('../helpers/exec');
33

44
test('cannot update snapshots when file contains skipped tests', async t => {
5-
const result = await t.throwsAsync(exec.fixture('contains-skip.js', '-u'));
5+
const result = await t.throwsAsync(exec.fixture(['contains-skip.js', '-u']));
66
t.snapshot(result.stats.failed, 'failed tests');
77
t.snapshot(result.stats.skipped, 'skipped tests');
88
t.snapshot(result.stats.unsavedSnapshots, 'files where snapshots could not be updated');
99
});
1010

1111
test('cannot update snapshots when file contains exclusive tests', async t => {
12-
const result = await exec.fixture('contains-only.js', '-u');
12+
const result = await exec.fixture(['contains-only.js', '-u']);
1313
t.snapshot(result.stats.failed, 'failed tests');
1414
t.snapshot(result.stats.passed, 'passed tests');
1515
t.snapshot(result.stats.unsavedSnapshots, 'files where snapshots could not be updated');
@@ -18,11 +18,11 @@ test('cannot update snapshots when file contains exclusive tests', async t => {
1818
const stripLeadingFigures = string => string.replace(/^\W+/, '');
1919

2020
test('cannot update snapshots when matching test titles', async t => {
21-
const result = await t.throwsAsync(exec.fixture('contains-skip.js', '-u', '-m=snapshot'));
21+
const result = await t.throwsAsync(exec.fixture(['contains-skip.js', '-u', '-m=snapshot']));
2222
t.snapshot(stripLeadingFigures(result.stderr.trim()));
2323
});
2424

2525
test('cannot update snapshots when selecting tests by line number', async t => {
26-
const result = await t.throwsAsync(exec.fixture('contains-skip.js:4', '-u'));
26+
const result = await t.throwsAsync(exec.fixture(['contains-skip.js:4', '-u']));
2727
t.snapshot(stripLeadingFigures(result.stderr.trim()));
2828
});

test/test-timeouts/test.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ const test = require('@ava/test');
22
const exec = require('../helpers/exec');
33

44
test('timeout message can be specified', async t => {
5-
const result = await t.throwsAsync(exec.fixture('custom-message.js'));
5+
const result = await t.throwsAsync(exec.fixture(['custom-message.js']));
66
const error = result.stats.getError(result.stats.failed[0]);
77
t.is(error.message, 'time budget exceeded');
88
});
99

1010
test('timeout messages must be strings', async t => {
11-
const result = await t.throwsAsync(exec.fixture('invalid-message.js'));
11+
const result = await t.throwsAsync(exec.fixture(['invalid-message.js']));
1212
const error = result.stats.getError(result.stats.failed[0]);
1313
t.snapshot(error.message, 'error message');
1414
t.snapshot(error.values, 'formatted values');

0 commit comments

Comments
 (0)