1'use strict'; 2 3// Flags: --expose-internals 4 5const common = require('../common'); 6const readline = require('readline/promises'); 7const assert = require('assert'); 8const { EventEmitter } = require('events'); 9const { getStringWidth } = require('internal/util/inspect'); 10 11common.skipIfDumbTerminal(); 12 13// This test verifies that the tab completion supports unicode and the writes 14// are limited to the minimum. 15[ 16 'あ', 17 '', 18 '', 19].forEach((char) => { 20 [true, false].forEach((lineBreak) => { 21 [ 22 (line) => [ 23 ['First group', '', 24 `${char}${'a'.repeat(10)}`, 25 `${char}${'b'.repeat(10)}`, 26 char.repeat(11), 27 ], 28 line, 29 ], 30 31 async (line) => [ 32 ['First group', '', 33 `${char}${'a'.repeat(10)}`, 34 `${char}${'b'.repeat(10)}`, 35 char.repeat(11), 36 ], 37 line, 38 ], 39 ].forEach((completer) => { 40 41 let output = ''; 42 const width = getStringWidth(char) - 1; 43 44 class FakeInput extends EventEmitter { 45 columns = ((width + 1) * 10 + (lineBreak ? 0 : 10)) * 3; 46 47 write = common.mustCall((data) => { 48 output += data; 49 }, 6); 50 51 resume() {} 52 pause() {} 53 end() {} 54 } 55 56 const fi = new FakeInput(); 57 const rli = new readline.Interface({ 58 input: fi, 59 output: fi, 60 terminal: true, 61 completer: common.mustCallAtLeast(completer), 62 }); 63 64 const last = '\r\nFirst group\r\n\r\n' + 65 `${char}${'a'.repeat(10)}${' '.repeat(2 + width * 10)}` + 66 `${char}${'b'.repeat(10)}` + 67 (lineBreak ? '\r\n' : ' '.repeat(2 + width * 10)) + 68 `${char.repeat(11)}\r\n` + 69 `\r\n\u001b[1G\u001b[0J> ${char}\u001b[${4 + width}G`; 70 71 const expectations = [char, '', last]; 72 73 rli.on('line', common.mustNotCall()); 74 for (const character of `${char}\t\t`) { 75 fi.emit('data', character); 76 queueMicrotask(() => { 77 assert.strictEqual(output, expectations.shift()); 78 output = ''; 79 }); 80 } 81 rli.close(); 82 }); 83 }); 84}); 85 86{ 87 let output = ''; 88 class FakeInput extends EventEmitter { 89 columns = 80; 90 91 write = common.mustCall((data) => { 92 output += data; 93 }, 1); 94 95 resume() {} 96 pause() {} 97 end() {} 98 } 99 100 const fi = new FakeInput(); 101 const rli = new readline.Interface({ 102 input: fi, 103 output: fi, 104 terminal: true, 105 completer: 106 common.mustCallAtLeast(() => Promise.reject(new Error('message'))), 107 }); 108 109 rli.on('line', common.mustNotCall()); 110 fi.emit('data', '\t'); 111 queueMicrotask(() => { 112 assert.match(output, /^Tab completion error: Error: message/); 113 output = ''; 114 }); 115 rli.close(); 116} 117