summaryrefslogtreecommitdiff
path: root/test/parallel/test-repl-preview.js
diff options
context:
space:
mode:
Diffstat (limited to 'test/parallel/test-repl-preview.js')
-rw-r--r--test/parallel/test-repl-preview.js131
1 files changed, 131 insertions, 0 deletions
diff --git a/test/parallel/test-repl-preview.js b/test/parallel/test-repl-preview.js
new file mode 100644
index 0000000000..92e73dd245
--- /dev/null
+++ b/test/parallel/test-repl-preview.js
@@ -0,0 +1,131 @@
+'use strict';
+
+const common = require('../common');
+const ArrayStream = require('../common/arraystream');
+const assert = require('assert');
+const Repl = 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 = Repl.start({
+ 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]',
+ 'koo',
+ '\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: true }\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: true };',
+ '\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: true}',
+ '\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