Skip to content

Commit fa15b75

Browse files
committed
test: add REPL multiline navigation test for viewport
Add test for cursor position consistency when REPL multiline input exceeds terminal height. Tests navigation through a 27-line input on a 20-row terminal to ensure cursor moves correctly across viewport boundaries
1 parent bfc81ca commit fa15b75

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

test/parallel/test-repl-multiline-navigation.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,3 +251,71 @@ tmpdir.refresh();
251251
checkResults
252252
);
253253
}
254+
255+
{
256+
const historyPath = tmpdir.resolve(`.${Math.floor(Math.random() * 10000)}`);
257+
258+
// Test for issue #59938: REPL cursor navigation in viewport overflow
259+
// This test just verifies cursor position consistency when input exceeds
260+
// terminal height. The actual screen rendering fix is harder to test
261+
// but can be manually verified.
262+
class MockOutput extends stream.Writable {
263+
constructor() {
264+
super({
265+
write(chunk, _, next) {
266+
next();
267+
}
268+
});
269+
this.columns = 80;
270+
this.rows = 20;
271+
}
272+
}
273+
274+
const checkResults = common.mustSucceed((r) => {
275+
r.write('const arr = [');
276+
r.input.run([{ name: 'enter' }]);
277+
278+
for (let i = 1; i <= 25; i++) {
279+
r.write(` ${i},`);
280+
r.input.run([{ name: 'enter' }]);
281+
}
282+
283+
r.write('];');
284+
285+
const endCursor = r.cursor;
286+
assert.ok(endCursor > 0);
287+
288+
for (let i = 0; i < 27; i++) {
289+
r.input.run([{ name: 'up' }]);
290+
}
291+
292+
assert.strictEqual(r.cursor, 0);
293+
294+
const prevRowsAtTop = r.prevRows;
295+
assert.ok(prevRowsAtTop !== undefined);
296+
297+
for (let i = 0; i < 10; i++) {
298+
r.input.run([{ name: 'down' }]);
299+
}
300+
301+
const midCursor = r.cursor;
302+
assert.ok(midCursor > 0 && midCursor < endCursor);
303+
304+
// Navigate back to end
305+
for (let i = 0; i < 17; i++) {
306+
r.input.run([{ name: 'down' }]);
307+
}
308+
309+
assert.strictEqual(r.cursor, endCursor);
310+
});
311+
312+
repl.createInternalRepl(
313+
{ NODE_REPL_HISTORY: historyPath },
314+
{
315+
terminal: true,
316+
input: new ActionStream(),
317+
output: new MockOutput(),
318+
},
319+
checkResults
320+
);
321+
}

0 commit comments

Comments
 (0)