| 'use strict'; |
| |
| require('../common'); |
| const { startNewREPLServer } = require('../common/repl'); |
| const assert = require('assert'); |
| const { describe, it } = require('node:test'); |
| |
| 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(inputStr, replOptions) { |
| return new Promise((resolve) => { |
| const { replServer, input, output } = startNewREPLServer({ prompt: testingReplPrompt, ...replOptions }); |
| |
| output.accumulator = ''; |
| |
| output.write = (chunk) => { |
| output.accumulator += chunk; |
| // The prompt appears after the input has been processed |
| if (output.accumulator.includes(testingReplPrompt)) { |
| replServer.close(); |
| resolve(output.accumulator); |
| } |
| }; |
| |
| input.emit('data', inputStr); |
| |
| input.run(['']); |
| }); |
| } |
| |
| describe('repl with custom eval', { concurrency: true }, () => { |
| it('uses the custom eval function as expected', async () => { |
| const output = await getReplRunOutput('Convert this to upper case', { |
| terminal: true, |
| eval: (code, _ctx, _replRes, cb) => cb(null, code.toUpperCase()), |
| }); |
| assert.match( |
| output, |
| /Convert this to upper case\r\n'CONVERT THIS TO UPPER CASE\\n'/ |
| ); |
| }); |
| |
| it('surfaces errors as expected', async () => { |
| const output = await getReplRunOutput('Convert this to upper case', { |
| terminal: true, |
| eval: (_code, _ctx, _replRes, cb) => cb(new Error('Testing Error')), |
| }); |
| assert.match(output, /Uncaught Error: Testing Error\n/); |
| }); |
| |
| it('provides a repl context to the eval callback', async () => { |
| const context = await new Promise((resolve) => { |
| const { replServer } = startNewREPLServer({ |
| eval: (_cmd, context) => resolve(context), |
| }); |
| 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 { replServer } = startNewREPLServer({ |
| eval: (_cmd, context) => resolve(context), |
| useGlobal: true |
| }); |
| global.foo = 'global_foo'; |
| replServer.write('\n.exit\n'); |
| }); |
| |
| assert.strictEqual(context.foo, 'global_foo'); |
| delete global.foo; |
| }); |
| |
| 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 { replServer } = startNewREPLServer({ |
| useGlobal: false, |
| eval: (_cmd, context) => resolve(context), |
| }); |
| global.baz = 'global_baz'; |
| replServer.write('\n.exit\n'); |
| }); |
| |
| assert.strictEqual(context.bar, 'global_bar'); |
| assert.notStrictEqual(context.baz, 'global_baz'); |
| delete global.bar; |
| delete global.baz; |
| }); |
| |
| /** |
| * Default preprocessor transforms |
| * function f() {} to |
| * var f = function f() {} |
| * This test ensures that original input is preserved. |
| * Reference: https://github.com/nodejs/node/issues/9743 |
| */ |
| it('preserves the original input', async () => { |
| const cmd = await new Promise((resolve) => { |
| const { replServer } = startNewREPLServer({ |
| eval: (cmd) => resolve(cmd), |
| }); |
| replServer.write('function f() {}\n.exit\n'); |
| }); |
| assert.strictEqual(cmd, 'function f() {}\n'); |
| }); |
| }); |