mirror of
https://github.com/nodejs/node.git
synced 2025-05-10 14:09:34 +00:00

This improves the coverage for the preview feature signficantly. Quite a few edge cases get testet here to prevent regressions. PR-URL: https://github.com/nodejs/node/pull/30907 Reviewed-By: Michaël Zasso <targos@protonmail.com> Reviewed-By: Rich Trott <rtrott@gmail.com>
132 lines
4.1 KiB
JavaScript
132 lines
4.1 KiB
JavaScript
'use strict';
|
|
|
|
const common = require('../common');
|
|
const ArrayStream = require('../common/arraystream');
|
|
const assert = require('assert');
|
|
const { REPLServer } = require('repl');
|
|
|
|
common.skipIfInspectorDisabled();
|
|
|
|
const PROMPT = 'repl > ';
|
|
|
|
class REPLStream extends ArrayStream {
|
|
constructor() {
|
|
super();
|
|
this.lines = [''];
|
|
}
|
|
write(chunk) {
|
|
const chunkLines = chunk.toString('utf8').split('\n');
|
|
this.lines[this.lines.length - 1] += chunkLines[0];
|
|
if (chunkLines.length > 1) {
|
|
this.lines.push(...chunkLines.slice(1));
|
|
}
|
|
this.emit('line');
|
|
return true;
|
|
}
|
|
wait() {
|
|
this.lines = [''];
|
|
return new Promise((resolve, reject) => {
|
|
const onError = (err) => {
|
|
this.removeListener('line', onLine);
|
|
reject(err);
|
|
};
|
|
const onLine = () => {
|
|
if (this.lines[this.lines.length - 1].includes(PROMPT)) {
|
|
this.removeListener('error', onError);
|
|
this.removeListener('line', onLine);
|
|
resolve(this.lines);
|
|
}
|
|
};
|
|
this.once('error', onError);
|
|
this.on('line', onLine);
|
|
});
|
|
}
|
|
}
|
|
|
|
function runAndWait(cmds, repl) {
|
|
const promise = repl.inputStream.wait();
|
|
for (const cmd of cmds) {
|
|
repl.inputStream.run([cmd]);
|
|
}
|
|
return promise;
|
|
}
|
|
|
|
async function tests(options) {
|
|
const repl = REPLServer({
|
|
prompt: PROMPT,
|
|
stream: new REPLStream(),
|
|
ignoreUndefined: true,
|
|
useColors: true,
|
|
...options
|
|
});
|
|
|
|
repl.inputStream.run([
|
|
'function foo(x) { return x; }',
|
|
'function koo() { console.log("abc"); }',
|
|
'a = undefined;'
|
|
]);
|
|
const testCases = [
|
|
['foo', [2, 4], '[Function: foo]',
|
|
'foo',
|
|
'\x1B[90m[Function: foo]\x1B[39m\x1B[1A\x1B[11G\x1B[1B\x1B[2K\x1B[1A\r',
|
|
'\x1B[36m[Function: foo]\x1B[39m',
|
|
'\x1B[1G\x1B[0Jrepl > \x1B[8G'],
|
|
['koo', [2, 4], '[Function: koo]',
|
|
'k\x1B[90moo\x1B[39m\x1B[9G\x1B[0Ko\x1B[90mo\x1B[39m\x1B[10G\x1B[0Ko',
|
|
'\x1B[90m[Function: koo]\x1B[39m\x1B[1A\x1B[11G\x1B[1B\x1B[2K\x1B[1A\r',
|
|
'\x1B[36m[Function: koo]\x1B[39m',
|
|
'\x1B[1G\x1B[0Jrepl > \x1B[8G'],
|
|
['a', [1, 2], undefined],
|
|
['{ a: true }', [2, 3], '{ a: \x1B[33mtrue\x1B[39m }',
|
|
'{ a: tru\x1B[90me\x1B[39m\x1B[16G\x1B[0Ke }\r',
|
|
'{ a: \x1B[33mtrue\x1B[39m }',
|
|
'\x1B[1G\x1B[0Jrepl > \x1B[8G'],
|
|
['1n + 2n', [2, 5], '\x1B[33m3n\x1B[39m',
|
|
'1n + 2',
|
|
'\x1B[90mType[39m\x1B[1A\x1B[14G\x1B[1B\x1B[2K\x1B[1An',
|
|
'\x1B[90m3n\x1B[39m\x1B[1A\x1B[15G\x1B[1B\x1B[2K\x1B[1A\r',
|
|
'\x1B[33m3n\x1B[39m',
|
|
'\x1B[1G\x1B[0Jrepl > \x1B[8G'],
|
|
['{ a: true };', [2, 4], '\x1B[33mtrue\x1B[39m',
|
|
'{ a: tru\x1B[90me\x1B[39m\x1B[16G\x1B[0Ke };',
|
|
'\x1B[90mtrue\x1B[39m\x1B[1A\x1B[20G\x1B[1B\x1B[2K\x1B[1A\r',
|
|
'\x1B[33mtrue\x1B[39m',
|
|
'\x1B[1G\x1B[0Jrepl > \x1B[8G'],
|
|
[' \t { a: true};', [2, 5], '\x1B[33mtrue\x1B[39m',
|
|
' \t { a: tru\x1B[90me\x1B[39m\x1B[19G\x1B[0Ke}',
|
|
'\x1B[90m{ a: true }\x1B[39m\x1B[1A\x1B[21G\x1B[1B\x1B[2K\x1B[1A;',
|
|
'\x1B[90mtrue\x1B[39m\x1B[1A\x1B[22G\x1B[1B\x1B[2K\x1B[1A\r',
|
|
'\x1B[33mtrue\x1B[39m',
|
|
'\x1B[1G\x1B[0Jrepl > \x1B[8G']
|
|
];
|
|
|
|
const hasPreview = repl.terminal &&
|
|
(options.preview !== undefined ? !!options.preview : true);
|
|
|
|
for (const [input, length, expected, ...preview] of testCases) {
|
|
console.log(`Testing ${input}`);
|
|
|
|
const toBeRun = input.split('\n');
|
|
let lines = await runAndWait(toBeRun, repl);
|
|
|
|
assert.strictEqual(lines.length, length[+hasPreview]);
|
|
if (expected === undefined) {
|
|
assert(!lines.some((e) => e.includes('undefined')));
|
|
} else if (hasPreview) {
|
|
// Remove error messages. That allows the code to run in different
|
|
// engines.
|
|
// eslint-disable-next-line no-control-regex
|
|
lines = lines.map((line) => line.replace(/Error: .+?\x1B/, ''));
|
|
assert.deepStrictEqual(lines, preview);
|
|
} else {
|
|
assert.ok(lines[0].includes(expected), lines);
|
|
}
|
|
}
|
|
}
|
|
|
|
tests({ terminal: false }); // No preview
|
|
tests({ terminal: true }); // Preview
|
|
tests({ terminal: false, preview: false }); // No preview
|
|
tests({ terminal: false, preview: true }); // No preview
|
|
tests({ terminal: true, preview: true }); // Preview
|