Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions test/common/repl.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict';

const ArrayStream = require('../common/arraystream');
const repl = require('node:repl');
const assert = require('node:assert');

function startNewREPLServer(replOpts = {}, testingOpts = {}) {
const input = new ArrayStream();
const output = new ArrayStream();

output.accumulator = '';
output.write = (data) => (output.accumulator += `${data}`.replaceAll('\r', ''));

const replServer = repl.start({
prompt: '',
input,
output,
terminal: true,
allowBlockingCompletions: true,
...replOpts,
});

if (!testingOpts.disableDomainErrorAssert) {
// Some errors are passed to the domain, but do not callback
replServer._domain.on('error', assert.ifError);
}

return { replServer, input, output };
}

module.exports = { startNewREPLServer };
4 changes: 2 additions & 2 deletions test/parallel/test-repl-autolibs.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@
'use strict';
const common = require('../common');
const ArrayStream = require('../common/arraystream');
const { startNewREPLServer } = require('../common/repl');
const assert = require('assert');
const util = require('util');
const repl = require('repl');

const putIn = new ArrayStream();
repl.start('', putIn, null, true);
startNewREPLServer({ input: putIn, output: putIn, useGlobal: true, terminal: false });

test1();

Expand Down
14 changes: 3 additions & 11 deletions test/parallel/test-repl-completion-on-getters-disabled.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,11 @@ const common = require('../common');
const assert = require('node:assert');
const { describe, test } = require('node:test');

const ArrayStream = require('../common/arraystream');

const repl = require('node:repl');
const { startNewREPLServer } = require('../common/repl');

function runCompletionTests(replInit, tests) {
const stream = new ArrayStream();
const testRepl = repl.start({ stream });

// Some errors are passed to the domain
testRepl._domain.on('error', assert.ifError);

testRepl.write(replInit);
testRepl.write('\n');
const { replServer: testRepl, input } = startNewREPLServer();
input.run([replInit]);

tests.forEach(([query, expectedCompletions]) => {
testRepl.complete(query, common.mustCall((error, data) => {
Expand Down
72 changes: 32 additions & 40 deletions test/parallel/test-repl-context.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,28 @@
'use strict';
require('../common');
const ArrayStream = require('../common/arraystream');
const assert = require('assert');
const repl = require('repl');
const vm = require('vm');

// Create a dummy stream that does nothing.
const stream = new ArrayStream();
const { startNewREPLServer } = require('../common/repl');

// Test context when useGlobal is false.
{
const r = repl.start({
input: stream,
output: stream,
const { replServer, output } = startNewREPLServer({
terminal: false,
useGlobal: false
});

let output = '';
stream.write = function(d) {
output += d;
};

// Ensure that the repl context gets its own "console" instance.
assert(r.context.console);
assert(replServer.context.console);

// Ensure that the repl console instance is not the global one.
assert.notStrictEqual(r.context.console, console);
assert.notStrictEqual(r.context.Object, Object);
assert.notStrictEqual(replServer.context.console, console);
assert.notStrictEqual(replServer.context.Object, Object);

stream.run(['({} instanceof Object)']);
replServer.write('({} instanceof Object)\n');

assert.strictEqual(output, 'true\n> ');
assert.strictEqual(output.accumulator, 'true\n');

const context = r.createContext();
const context = replServer.createContext();
// Ensure that the repl context gets its own "console" instance.
assert(context.console instanceof require('console').Console);

Expand All @@ -41,44 +31,46 @@ const stream = new ArrayStream();

// Ensure that the repl console instance is writable.
context.console = 'foo';
r.close();
replServer.close();
}

// Test for context side effects.
{
const server = repl.start({ input: stream, output: stream });
const { replServer } = startNewREPLServer({
useGlobal: false
});

assert.ok(!server.underscoreAssigned);
assert.strictEqual(server.lines.length, 0);
assert.ok(!replServer.underscoreAssigned);
assert.strictEqual(replServer.lines.length, 0);

// An assignment to '_' in the repl server
server.write('_ = 500;\n');
assert.ok(server.underscoreAssigned);
assert.strictEqual(server.lines.length, 1);
assert.strictEqual(server.lines[0], '_ = 500;');
assert.strictEqual(server.last, 500);
replServer.write('_ = 500;\n');
assert.ok(replServer.underscoreAssigned);
assert.strictEqual(replServer.lines.length, 1);
assert.strictEqual(replServer.lines[0], '_ = 500;');
assert.strictEqual(replServer.last, 500);

// Use the server to create a new context
const context = server.createContext();
const context = replServer.createContext();

// Ensure that creating a new context does not
// have side effects on the server
assert.ok(server.underscoreAssigned);
assert.strictEqual(server.lines.length, 1);
assert.strictEqual(server.lines[0], '_ = 500;');
assert.strictEqual(server.last, 500);
assert.ok(replServer.underscoreAssigned);
assert.strictEqual(replServer.lines.length, 1);
assert.strictEqual(replServer.lines[0], '_ = 500;');
assert.strictEqual(replServer.last, 500);

// Reset the server context
server.resetContext();
assert.ok(!server.underscoreAssigned);
assert.strictEqual(server.lines.length, 0);
replServer.resetContext();
assert.ok(!replServer.underscoreAssigned);
assert.strictEqual(replServer.lines.length, 0);

// Ensure that assigning to '_' in the new context
// does not change the value in our server.
assert.ok(!server.underscoreAssigned);
assert.ok(!replServer.underscoreAssigned);
vm.runInContext('_ = 1000;\n', context);

assert.ok(!server.underscoreAssigned);
assert.strictEqual(server.lines.length, 0);
server.close();
assert.ok(!replServer.underscoreAssigned);
assert.strictEqual(replServer.lines.length, 0);
replServer.close();
}
29 changes: 10 additions & 19 deletions test/parallel/test-repl-custom-eval-previews.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,35 @@
'use strict';

const common = require('../common');
const ArrayStream = require('../common/arraystream');
const assert = require('assert');
const { describe, it } = require('node:test');

common.skipIfInspectorDisabled();

const repl = require('repl');
const { startNewREPLServer } = require('../common/repl');

const testingReplPrompt = '_REPL_TESTING_PROMPT_>';

// Processes some input in a REPL instance and returns a promise that
// resolves to the produced output (as a string).
function getReplRunOutput(input, replOptions) {
function getReplRunOutput(inputStr, replOptions) {
return new Promise((resolve) => {
const inputStream = new ArrayStream();
const outputStream = new ArrayStream();
const { replServer, input, output } = startNewREPLServer({ prompt: testingReplPrompt, ...replOptions });

const replServer = repl.start({
input: inputStream,
output: outputStream,
prompt: testingReplPrompt,
...replOptions,
});
output.accumulator = '';

let output = '';

outputStream.write = (chunk) => {
output += chunk;
output.write = (chunk) => {
output.accumulator += chunk;
// The prompt appears after the input has been processed
if (output.includes(testingReplPrompt)) {
if (output.accumulator.includes(testingReplPrompt)) {
replServer.close();
resolve(output);
resolve(output.accumulator);
}
};

inputStream.emit('data', input);
input.emit('data', inputStr);

inputStream.run(['']);
input.run(['']);
});
}

Expand Down
52 changes: 21 additions & 31 deletions test/parallel/test-repl-custom-eval.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,32 @@
'use strict';

require('../common');
const ArrayStream = require('../common/arraystream');
const { startNewREPLServer } = require('../common/repl');
const assert = require('assert');
const { describe, it } = require('node:test');

const repl = require('repl');
const testingReplPrompt = '_REPL_TESTING_PROMPT_>';

// Processes some input in a REPL instance and returns a promise that
// resolves to the produced output (as a string).
function getReplRunOutput(input, replOptions) {
function getReplRunOutput(inputStr, replOptions) {
return new Promise((resolve) => {
const inputStream = new ArrayStream();
const outputStream = new ArrayStream();
const { replServer, input, output } = startNewREPLServer({ prompt: testingReplPrompt, ...replOptions });

const testingReplPrompt = '_REPL_TESTING_PROMPT_>';
output.accumulator = '';

const replServer = repl.start({
input: inputStream,
output: outputStream,
prompt: testingReplPrompt,
...replOptions,
});

let output = '';

outputStream.write = (chunk) => {
output += chunk;
output.write = (chunk) => {
output.accumulator += chunk;
// The prompt appears after the input has been processed
if (output.includes(testingReplPrompt)) {
if (output.accumulator.includes(testingReplPrompt)) {
replServer.close();
resolve(output);
resolve(output.accumulator);
}
};

inputStream.emit('data', input);
input.emit('data', inputStr);

inputStream.run(['']);
input.run(['']);
});
}

Expand All @@ -62,23 +52,23 @@ describe('repl with custom eval', { concurrency: true }, () => {

it('provides a repl context to the eval callback', async () => {
const context = await new Promise((resolve) => {
const r = repl.start({
const { replServer } = startNewREPLServer({
eval: (_cmd, context) => resolve(context),
});
r.context = { foo: 'bar' };
r.write('\n.exit\n');
replServer.context = { foo: 'bar' };
replServer.write('\n.exit\n');
});
assert.strictEqual(context.foo, 'bar');
});

it('provides the global context to the eval callback', async () => {
const context = await new Promise((resolve) => {
const r = repl.start({
useGlobal: true,
const { replServer } = startNewREPLServer({
eval: (_cmd, context) => resolve(context),
useGlobal: true
});
global.foo = 'global_foo';
r.write('\n.exit\n');
replServer.write('\n.exit\n');
});

assert.strictEqual(context.foo, 'global_foo');
Expand All @@ -88,12 +78,12 @@ describe('repl with custom eval', { concurrency: true }, () => {
it('inherits variables from the global context but does not use it afterwords if `useGlobal` is false', async () => {
global.bar = 'global_bar';
const context = await new Promise((resolve) => {
const r = repl.start({
const { replServer } = startNewREPLServer({
useGlobal: false,
eval: (_cmd, context) => resolve(context),
});
global.baz = 'global_baz';
r.write('\n.exit\n');
replServer.write('\n.exit\n');
});

assert.strictEqual(context.bar, 'global_bar');
Expand All @@ -111,10 +101,10 @@ describe('repl with custom eval', { concurrency: true }, () => {
*/
it('preserves the original input', async () => {
const cmd = await new Promise((resolve) => {
const r = repl.start({
const { replServer } = startNewREPLServer({
eval: (cmd) => resolve(cmd),
});
r.write('function f() {}\n.exit\n');
replServer.write('function f() {}\n.exit\n');
});
assert.strictEqual(cmd, 'function f() {}\n');
});
Expand Down
Loading
Loading