Skip to content

Commit eb9e6e6

Browse files
antsmartianBethGriggs
authored andcommitted
test: adding history regression test case
PR-URL: #24843 Refs: #24385 Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
1 parent a1f0da1 commit eb9e6e6

File tree

1 file changed

+139
-0
lines changed

1 file changed

+139
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
'use strict';
2+
3+
// Flags: --expose-internals
4+
5+
const common = require('../common');
6+
const stream = require('stream');
7+
const REPL = require('internal/repl');
8+
const assert = require('assert');
9+
const fs = require('fs');
10+
const path = require('path');
11+
12+
const tmpdir = require('../common/tmpdir');
13+
tmpdir.refresh();
14+
15+
const defaultHistoryPath = path.join(tmpdir.path, '.node_repl_history');
16+
17+
// Create an input stream specialized for testing an array of actions
18+
class ActionStream extends stream.Stream {
19+
run(data) {
20+
const _iter = data[Symbol.iterator]();
21+
const doAction = () => {
22+
const next = _iter.next();
23+
if (next.done) {
24+
// Close the repl. Note that it must have a clean prompt to do so.
25+
this.emit('keypress', '', { ctrl: true, name: 'd' });
26+
return;
27+
}
28+
const action = next.value;
29+
30+
if (typeof action === 'object') {
31+
this.emit('keypress', '', action);
32+
} else {
33+
this.emit('data', `${action}`);
34+
}
35+
setImmediate(doAction);
36+
};
37+
setImmediate(doAction);
38+
}
39+
resume() {}
40+
pause() {}
41+
}
42+
ActionStream.prototype.readable = true;
43+
44+
45+
// Mock keys
46+
const ENTER = { name: 'enter' };
47+
const UP = { name: 'up' };
48+
const DOWN = { name: 'down' };
49+
50+
const prompt = '> ';
51+
52+
const tests = [
53+
{ // creates few history to navigate for
54+
env: { NODE_REPL_HISTORY: defaultHistoryPath },
55+
test: [ 'let ab = 45', ENTER,
56+
'555 + 909', ENTER,
57+
'{key : {key2 :[] }}', ENTER],
58+
expected: [],
59+
clean: false
60+
},
61+
{
62+
env: { NODE_REPL_HISTORY: defaultHistoryPath },
63+
test: [UP, UP, UP, UP, DOWN, DOWN, DOWN],
64+
expected: [prompt,
65+
`${prompt}{key : {key2 :[] }}`,
66+
`${prompt}555 + 909`,
67+
`${prompt}let ab = 45`,
68+
`${prompt}555 + 909`,
69+
`${prompt}{key : {key2 :[] }}`,
70+
prompt],
71+
clean: true
72+
}
73+
];
74+
const numtests = tests.length;
75+
76+
const runTestWrap = common.mustCall(runTest, numtests);
77+
78+
function cleanupTmpFile() {
79+
try {
80+
// Write over the file, clearing any history
81+
fs.writeFileSync(defaultHistoryPath, '');
82+
} catch (err) {
83+
if (err.code === 'ENOENT') return true;
84+
throw err;
85+
}
86+
return true;
87+
}
88+
89+
function runTest() {
90+
const opts = tests.shift();
91+
if (!opts) return; // All done
92+
93+
const env = opts.env;
94+
const test = opts.test;
95+
const expected = opts.expected;
96+
97+
REPL.createInternalRepl(env, {
98+
input: new ActionStream(),
99+
output: new stream.Writable({
100+
write(chunk, _, next) {
101+
const output = chunk.toString();
102+
103+
if (output.charCodeAt(0) === 27 || /^[\r\n]+$/.test(output)) {
104+
return next();
105+
}
106+
107+
if (expected.length) {
108+
assert.strictEqual(output, expected[0]);
109+
expected.shift();
110+
}
111+
112+
next();
113+
}
114+
}),
115+
prompt: prompt,
116+
useColors: false,
117+
terminal: true
118+
}, function(err, repl) {
119+
if (err) {
120+
console.error(`Failed test # ${numtests - tests.length}`);
121+
throw err;
122+
}
123+
124+
repl.once('close', () => {
125+
if (opts.clean)
126+
cleanupTmpFile();
127+
128+
if (expected.length !== 0) {
129+
throw new Error(`Failed test # ${numtests - tests.length}`);
130+
}
131+
setImmediate(runTestWrap, true);
132+
});
133+
134+
repl.inputStream.run(test);
135+
});
136+
}
137+
138+
// run the tests
139+
runTest();

0 commit comments

Comments
 (0)