| 'use strict'; |
| |
| // Flags: --expose-internals |
| |
| const common = require('../common'); |
| const readline = require('readline/promises'); |
| const assert = require('assert'); |
| const { EventEmitter } = require('events'); |
| const { getStringWidth } = require('internal/util/inspect'); |
| |
| common.skipIfDumbTerminal(); |
| |
| // This test verifies that the tab completion supports unicode and the writes |
| // are limited to the minimum. |
| [ |
| 'あ', |
| '𐐷', |
| '🐕', |
| ].forEach((char) => { |
| [true, false].forEach((lineBreak) => { |
| [ |
| (line) => [ |
| ['First group', '', |
| `${char}${'a'.repeat(10)}`, |
| `${char}${'b'.repeat(10)}`, |
| char.repeat(11), |
| ], |
| line, |
| ], |
| |
| async (line) => [ |
| ['First group', '', |
| `${char}${'a'.repeat(10)}`, |
| `${char}${'b'.repeat(10)}`, |
| char.repeat(11), |
| ], |
| line, |
| ], |
| ].forEach((completer) => { |
| |
| let output = ''; |
| const width = getStringWidth(char) - 1; |
| |
| class FakeInput extends EventEmitter { |
| columns = ((width + 1) * 10 + (lineBreak ? 0 : 10)) * 3; |
| |
| write = common.mustCall((data) => { |
| output += data; |
| }, 6); |
| |
| resume() {} |
| pause() {} |
| end() {} |
| } |
| |
| const fi = new FakeInput(); |
| const rli = new readline.Interface({ |
| input: fi, |
| output: fi, |
| terminal: true, |
| completer: common.mustCallAtLeast(completer), |
| }); |
| |
| const last = '\r\nFirst group\r\n\r\n' + |
| `${char}${'a'.repeat(10)}${' '.repeat(2 + width * 10)}` + |
| `${char}${'b'.repeat(10)}` + |
| (lineBreak ? '\r\n' : ' '.repeat(2 + width * 10)) + |
| `${char.repeat(11)}\r\n` + |
| `\r\n\u001b[1G\u001b[0J> ${char}\u001b[${4 + width}G`; |
| |
| const expectations = [char, '', last]; |
| |
| rli.on('line', common.mustNotCall()); |
| for (const character of `${char}\t\t`) { |
| fi.emit('data', character); |
| queueMicrotask(() => { |
| assert.strictEqual(output, expectations.shift()); |
| output = ''; |
| }); |
| } |
| rli.close(); |
| }); |
| }); |
| }); |
| |
| { |
| let output = ''; |
| class FakeInput extends EventEmitter { |
| columns = 80; |
| |
| write = common.mustCall((data) => { |
| output += data; |
| }, 1); |
| |
| resume() {} |
| pause() {} |
| end() {} |
| } |
| |
| const fi = new FakeInput(); |
| const rli = new readline.Interface({ |
| input: fi, |
| output: fi, |
| terminal: true, |
| completer: |
| common.mustCallAtLeast(() => Promise.reject(new Error('message'))), |
| }); |
| |
| rli.on('line', common.mustNotCall()); |
| fi.emit('data', '\t'); |
| queueMicrotask(() => { |
| assert.match(output, /^Tab completion error: Error: message/); |
| output = ''; |
| }); |
| rli.close(); |
| } |