Skip to content

Commit b7e488c

Browse files
dario-piotrowicztargos
authored andcommitted
test: refactor repl tab complete tests
refactor the test/parallel/test-repl-tab-complete.js file by: - making the tests in the file self-contained (instead of all of them sharing the same REPL instance and constantly calling `.clear` on it) - using the test runner with appropriate descriptions to make clearer what is being tested - extracting some tests in their own js test files (to increase isolation of the tests and help with issues such as flakiness) PR-URL: #58636 Reviewed-By: Giovanni Bucci <github@puskin.it> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent ef0230a commit b7e488c

6 files changed

+1003
-734
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const ArrayStream = require('../common/arraystream');
5+
const { hijackStderr, restoreStderr } = require('../common/hijackstdio');
6+
const assert = require('assert');
7+
8+
const repl = require('repl');
9+
10+
const input = new ArrayStream();
11+
const replServer = repl.start({
12+
prompt: '',
13+
input,
14+
output: process.stdout,
15+
allowBlockingCompletions: true,
16+
});
17+
18+
// Some errors are passed to the domain, but do not callback
19+
replServer._domain.on('error', assert.ifError);
20+
21+
for (const type of [
22+
Array,
23+
Buffer,
24+
25+
Uint8Array,
26+
Uint16Array,
27+
Uint32Array,
28+
29+
Uint8ClampedArray,
30+
Int8Array,
31+
Int16Array,
32+
Int32Array,
33+
Float32Array,
34+
Float64Array,
35+
]) {
36+
input.run(['.clear']);
37+
38+
if (type === Array) {
39+
input.run([
40+
'var ele = [];',
41+
'for (let i = 0; i < 1e6 + 1; i++) ele[i] = 0;',
42+
'ele.biu = 1;',
43+
]);
44+
} else if (type === Buffer) {
45+
input.run(['var ele = Buffer.alloc(1e6 + 1); ele.biu = 1;']);
46+
} else {
47+
input.run([`var ele = new ${type.name}(1e6 + 1); ele.biu = 1;`]);
48+
}
49+
50+
hijackStderr(common.mustNotCall());
51+
replServer.complete(
52+
'ele.',
53+
common.mustCall((err, data) => {
54+
restoreStderr();
55+
assert.ifError(err);
56+
57+
const ele =
58+
type === Array ? [] : type === Buffer ? Buffer.alloc(0) : new type(0);
59+
60+
assert.strictEqual(data[0].includes('ele.biu'), true);
61+
62+
data[0].forEach((key) => {
63+
if (!key || key === 'ele.biu') return;
64+
assert.notStrictEqual(ele[key.slice(4)], undefined);
65+
});
66+
})
67+
);
68+
}
69+
70+
// check Buffer.prototype.length not crashing.
71+
// Refs: https://github.com/nodejs/node/pull/11961
72+
input.run(['.clear']);
73+
replServer.complete('Buffer.prototype.', common.mustCall());
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const ArrayStream = require('../common/arraystream');
5+
const assert = require('assert');
6+
7+
const repl = require('repl');
8+
9+
const putIn = new ArrayStream();
10+
11+
// To test custom completer function.
12+
// Sync mode.
13+
{
14+
const customCompletions = 'aaa aa1 aa2 bbb bb1 bb2 bb3 ccc ddd eee'.split(' ');
15+
const testCustomCompleterSyncMode = repl.start({
16+
prompt: '',
17+
input: putIn,
18+
output: putIn,
19+
completer: function completer(line) {
20+
const hits = customCompletions.filter((c) => c.startsWith(line));
21+
// Show all completions if none found.
22+
return [hits.length ? hits : customCompletions, line];
23+
}
24+
});
25+
26+
// On empty line should output all the custom completions
27+
// without complete anything.
28+
testCustomCompleterSyncMode.complete('', common.mustCall((error, data) => {
29+
assert.deepStrictEqual(data, [
30+
customCompletions,
31+
'',
32+
]);
33+
}));
34+
35+
// On `a` should output `aaa aa1 aa2` and complete until `aa`.
36+
testCustomCompleterSyncMode.complete('a', common.mustCall((error, data) => {
37+
assert.deepStrictEqual(data, [
38+
'aaa aa1 aa2'.split(' '),
39+
'a',
40+
]);
41+
}));
42+
}
43+
44+
// To test custom completer function.
45+
// Async mode.
46+
{
47+
const customCompletions = 'aaa aa1 aa2 bbb bb1 bb2 bb3 ccc ddd eee'.split(' ');
48+
const testCustomCompleterAsyncMode = repl.start({
49+
prompt: '',
50+
input: putIn,
51+
output: putIn,
52+
completer: function completer(line, callback) {
53+
const hits = customCompletions.filter((c) => c.startsWith(line));
54+
// Show all completions if none found.
55+
callback(null, [hits.length ? hits : customCompletions, line]);
56+
}
57+
});
58+
59+
// On empty line should output all the custom completions
60+
// without complete anything.
61+
testCustomCompleterAsyncMode.complete('', common.mustCall((error, data) => {
62+
assert.deepStrictEqual(data, [
63+
customCompletions,
64+
'',
65+
]);
66+
}));
67+
68+
// On `a` should output `aaa aa1 aa2` and complete until `aa`.
69+
testCustomCompleterAsyncMode.complete('a', common.mustCall((error, data) => {
70+
assert.deepStrictEqual(data, [
71+
'aaa aa1 aa2'.split(' '),
72+
'a',
73+
]);
74+
}));
75+
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const ArrayStream = require('../common/arraystream');
5+
const assert = require('assert');
6+
const path = require('path');
7+
8+
const { isMainThread } = require('worker_threads');
9+
10+
if (!isMainThread) {
11+
common.skip('process.chdir is not available in Workers');
12+
}
13+
14+
const repl = require('repl');
15+
16+
const replServer = repl.start({
17+
prompt: '',
18+
input: new ArrayStream(),
19+
output: process.stdout,
20+
allowBlockingCompletions: true,
21+
});
22+
23+
// Some errors are passed to the domain, but do not callback
24+
replServer._domain.on('error', assert.ifError);
25+
26+
// Tab completion for files/directories
27+
{
28+
process.chdir(__dirname);
29+
30+
const readFileSyncs = ['fs.readFileSync("', 'fs.promises.readFileSync("'];
31+
if (!common.isWindows) {
32+
readFileSyncs.forEach((readFileSync) => {
33+
const fixturePath = `${readFileSync}../fixtures/test-repl-tab-completion`;
34+
replServer.complete(
35+
fixturePath,
36+
common.mustCall((err, data) => {
37+
assert.strictEqual(err, null);
38+
assert.ok(data[0][0].includes('.hiddenfiles'));
39+
assert.ok(data[0][1].includes('hellorandom.txt'));
40+
assert.ok(data[0][2].includes('helloworld.js'));
41+
})
42+
);
43+
44+
replServer.complete(
45+
`${fixturePath}/hello`,
46+
common.mustCall((err, data) => {
47+
assert.strictEqual(err, null);
48+
assert.ok(data[0][0].includes('hellorandom.txt'));
49+
assert.ok(data[0][1].includes('helloworld.js'));
50+
})
51+
);
52+
53+
replServer.complete(
54+
`${fixturePath}/.h`,
55+
common.mustCall((err, data) => {
56+
assert.strictEqual(err, null);
57+
assert.ok(data[0][0].includes('.hiddenfiles'));
58+
})
59+
);
60+
61+
replServer.complete(
62+
`${readFileSync}./xxxRandom/random`,
63+
common.mustCall((err, data) => {
64+
assert.strictEqual(err, null);
65+
assert.strictEqual(data[0].length, 0);
66+
})
67+
);
68+
69+
const testPath = fixturePath.slice(0, -1);
70+
replServer.complete(
71+
testPath,
72+
common.mustCall((err, data) => {
73+
assert.strictEqual(err, null);
74+
assert.ok(data[0][0].includes('test-repl-tab-completion'));
75+
assert.strictEqual(data[1], path.basename(testPath));
76+
})
77+
);
78+
});
79+
}
80+
}
Lines changed: 39 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,48 @@
11
'use strict';
22

3-
require('../common');
3+
const common = require('../common');
4+
const assert = require('assert');
45
const ArrayStream = require('../common/arraystream');
56
const repl = require('repl');
67

7-
const stream = new ArrayStream();
8-
const replServer = repl.start({
9-
input: stream,
10-
output: stream,
11-
terminal: true,
12-
});
8+
// Tab completion in editor mode
9+
{
10+
const editorStream = new ArrayStream();
11+
const editor = repl.start({
12+
stream: editorStream,
13+
terminal: true,
14+
useColors: false
15+
});
1316

14-
// Editor mode
15-
replServer.write('.editor\n');
17+
editorStream.run(['.clear']);
18+
editorStream.run(['.editor']);
19+
20+
editor.completer('Uin', common.mustCall((_error, data) => {
21+
assert.deepStrictEqual(data, [['Uint'], 'Uin']);
22+
}));
23+
24+
editorStream.run(['.clear']);
25+
editorStream.run(['.editor']);
26+
27+
editor.completer('var log = console.l', common.mustCall((_error, data) => {
28+
assert.deepStrictEqual(data, [['console.log'], 'console.l']);
29+
}));
30+
}
1631

1732
// Regression test for https://github.com/nodejs/node/issues/43528
18-
replServer.write('a');
19-
replServer.write(null, { name: 'tab' }); // Should not throw
33+
{
34+
const stream = new ArrayStream();
35+
const replServer = repl.start({
36+
input: stream,
37+
output: stream,
38+
terminal: true,
39+
});
40+
41+
// Editor mode
42+
replServer.write('.editor\n');
43+
44+
replServer.write('a');
45+
replServer.write(null, { name: 'tab' }); // Should not throw
2046

21-
replServer.close();
47+
replServer.close();
48+
}

0 commit comments

Comments
 (0)