11cb0ef41Sopenharmony_ci// Copyright Joyent, Inc. and other Node contributors.
21cb0ef41Sopenharmony_ci//
31cb0ef41Sopenharmony_ci// Permission is hereby granted, free of charge, to any person obtaining a
41cb0ef41Sopenharmony_ci// copy of this software and associated documentation files (the
51cb0ef41Sopenharmony_ci// "Software"), to deal in the Software without restriction, including
61cb0ef41Sopenharmony_ci// without limitation the rights to use, copy, modify, merge, publish,
71cb0ef41Sopenharmony_ci// distribute, sublicense, and/or sell copies of the Software, and to permit
81cb0ef41Sopenharmony_ci// persons to whom the Software is furnished to do so, subject to the
91cb0ef41Sopenharmony_ci// following conditions:
101cb0ef41Sopenharmony_ci//
111cb0ef41Sopenharmony_ci// The above copyright notice and this permission notice shall be included
121cb0ef41Sopenharmony_ci// in all copies or substantial portions of the Software.
131cb0ef41Sopenharmony_ci//
141cb0ef41Sopenharmony_ci// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
151cb0ef41Sopenharmony_ci// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
161cb0ef41Sopenharmony_ci// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
171cb0ef41Sopenharmony_ci// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
181cb0ef41Sopenharmony_ci// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
191cb0ef41Sopenharmony_ci// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
201cb0ef41Sopenharmony_ci// USE OR OTHER DEALINGS IN THE SOFTWARE.
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci// Flags: --expose-internals
231cb0ef41Sopenharmony_ci'use strict';
241cb0ef41Sopenharmony_ciconst common = require('../common');
251cb0ef41Sopenharmony_cicommon.skipIfDumbTerminal();
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ciconst assert = require('assert');
281cb0ef41Sopenharmony_ciconst readline = require('readline');
291cb0ef41Sopenharmony_ciconst util = require('util');
301cb0ef41Sopenharmony_ciconst {
311cb0ef41Sopenharmony_ci  getStringWidth,
321cb0ef41Sopenharmony_ci  stripVTControlCharacters
331cb0ef41Sopenharmony_ci} = require('internal/util/inspect');
341cb0ef41Sopenharmony_ciconst { EventEmitter, getEventListeners } = require('events');
351cb0ef41Sopenharmony_ciconst { Writable, Readable } = require('stream');
361cb0ef41Sopenharmony_ci
371cb0ef41Sopenharmony_ciclass FakeInput extends EventEmitter {
381cb0ef41Sopenharmony_ci  resume() {}
391cb0ef41Sopenharmony_ci  pause() {}
401cb0ef41Sopenharmony_ci  write() {}
411cb0ef41Sopenharmony_ci  end() {}
421cb0ef41Sopenharmony_ci}
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_cifunction isWarned(emitter) {
451cb0ef41Sopenharmony_ci  for (const name in emitter) {
461cb0ef41Sopenharmony_ci    const listeners = emitter[name];
471cb0ef41Sopenharmony_ci    if (listeners.warned) return true;
481cb0ef41Sopenharmony_ci  }
491cb0ef41Sopenharmony_ci  return false;
501cb0ef41Sopenharmony_ci}
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_cifunction getInterface(options) {
531cb0ef41Sopenharmony_ci  const fi = new FakeInput();
541cb0ef41Sopenharmony_ci  const rli = new readline.Interface({
551cb0ef41Sopenharmony_ci    input: fi,
561cb0ef41Sopenharmony_ci    output: fi,
571cb0ef41Sopenharmony_ci    ...options,
581cb0ef41Sopenharmony_ci  });
591cb0ef41Sopenharmony_ci  return [rli, fi];
601cb0ef41Sopenharmony_ci}
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_cifunction assertCursorRowsAndCols(rli, rows, cols) {
631cb0ef41Sopenharmony_ci  const cursorPos = rli.getCursorPos();
641cb0ef41Sopenharmony_ci  assert.strictEqual(cursorPos.rows, rows);
651cb0ef41Sopenharmony_ci  assert.strictEqual(cursorPos.cols, cols);
661cb0ef41Sopenharmony_ci}
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci{
691cb0ef41Sopenharmony_ci  const input = new FakeInput();
701cb0ef41Sopenharmony_ci  const rl = readline.Interface({ input });
711cb0ef41Sopenharmony_ci  assert(rl instanceof readline.Interface);
721cb0ef41Sopenharmony_ci}
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_ci{
751cb0ef41Sopenharmony_ci  const fi = new FakeInput();
761cb0ef41Sopenharmony_ci  const rli = new readline.Interface(
771cb0ef41Sopenharmony_ci    fi,
781cb0ef41Sopenharmony_ci    fi,
791cb0ef41Sopenharmony_ci    common.mustCall((line) => [[], line]),
801cb0ef41Sopenharmony_ci    true,
811cb0ef41Sopenharmony_ci  );
821cb0ef41Sopenharmony_ci  assert(rli instanceof readline.Interface);
831cb0ef41Sopenharmony_ci  fi.emit('data', 'a\t');
841cb0ef41Sopenharmony_ci  rli.close();
851cb0ef41Sopenharmony_ci}
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci[
881cb0ef41Sopenharmony_ci  undefined,
891cb0ef41Sopenharmony_ci  50,
901cb0ef41Sopenharmony_ci  0,
911cb0ef41Sopenharmony_ci  100.5,
921cb0ef41Sopenharmony_ci  5000,
931cb0ef41Sopenharmony_ci].forEach((crlfDelay) => {
941cb0ef41Sopenharmony_ci  const [rli] = getInterface({ crlfDelay });
951cb0ef41Sopenharmony_ci  assert.strictEqual(rli.crlfDelay, Math.max(crlfDelay || 100, 100));
961cb0ef41Sopenharmony_ci  rli.close();
971cb0ef41Sopenharmony_ci});
981cb0ef41Sopenharmony_ci
991cb0ef41Sopenharmony_ci{
1001cb0ef41Sopenharmony_ci  const input = new FakeInput();
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_ci  // Constructor throws if completer is not a function or undefined
1031cb0ef41Sopenharmony_ci  ['not an array', 123, 123n, {}, true, Symbol(), null].forEach((invalid) => {
1041cb0ef41Sopenharmony_ci    assert.throws(() => {
1051cb0ef41Sopenharmony_ci      readline.createInterface({
1061cb0ef41Sopenharmony_ci        input,
1071cb0ef41Sopenharmony_ci        completer: invalid
1081cb0ef41Sopenharmony_ci      });
1091cb0ef41Sopenharmony_ci    }, {
1101cb0ef41Sopenharmony_ci      name: 'TypeError',
1111cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_VALUE'
1121cb0ef41Sopenharmony_ci    });
1131cb0ef41Sopenharmony_ci  });
1141cb0ef41Sopenharmony_ci
1151cb0ef41Sopenharmony_ci  // Constructor throws if history is not an array
1161cb0ef41Sopenharmony_ci  ['not an array', 123, 123n, {}, true, Symbol(), null].forEach((history) => {
1171cb0ef41Sopenharmony_ci    assert.throws(() => {
1181cb0ef41Sopenharmony_ci      readline.createInterface({
1191cb0ef41Sopenharmony_ci        input,
1201cb0ef41Sopenharmony_ci        history,
1211cb0ef41Sopenharmony_ci      });
1221cb0ef41Sopenharmony_ci    }, {
1231cb0ef41Sopenharmony_ci      name: 'TypeError',
1241cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_TYPE'
1251cb0ef41Sopenharmony_ci    });
1261cb0ef41Sopenharmony_ci  });
1271cb0ef41Sopenharmony_ci
1281cb0ef41Sopenharmony_ci  // Constructor throws if historySize is not a positive number
1291cb0ef41Sopenharmony_ci  ['not a number', -1, NaN, {}, true, Symbol(), null].forEach((historySize) => {
1301cb0ef41Sopenharmony_ci    assert.throws(() => {
1311cb0ef41Sopenharmony_ci      readline.createInterface({
1321cb0ef41Sopenharmony_ci        input,
1331cb0ef41Sopenharmony_ci        historySize,
1341cb0ef41Sopenharmony_ci      });
1351cb0ef41Sopenharmony_ci    }, {
1361cb0ef41Sopenharmony_ci      name: 'RangeError',
1371cb0ef41Sopenharmony_ci      code: 'ERR_INVALID_ARG_VALUE'
1381cb0ef41Sopenharmony_ci    });
1391cb0ef41Sopenharmony_ci  });
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci  // Check for invalid tab sizes.
1421cb0ef41Sopenharmony_ci  assert.throws(
1431cb0ef41Sopenharmony_ci    () => new readline.Interface({
1441cb0ef41Sopenharmony_ci      input,
1451cb0ef41Sopenharmony_ci      tabSize: 0
1461cb0ef41Sopenharmony_ci    }),
1471cb0ef41Sopenharmony_ci    { code: 'ERR_OUT_OF_RANGE' }
1481cb0ef41Sopenharmony_ci  );
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  assert.throws(
1511cb0ef41Sopenharmony_ci    () => new readline.Interface({
1521cb0ef41Sopenharmony_ci      input,
1531cb0ef41Sopenharmony_ci      tabSize: '4'
1541cb0ef41Sopenharmony_ci    }),
1551cb0ef41Sopenharmony_ci    { code: 'ERR_INVALID_ARG_TYPE' }
1561cb0ef41Sopenharmony_ci  );
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci  assert.throws(
1591cb0ef41Sopenharmony_ci    () => new readline.Interface({
1601cb0ef41Sopenharmony_ci      input,
1611cb0ef41Sopenharmony_ci      tabSize: 4.5
1621cb0ef41Sopenharmony_ci    }),
1631cb0ef41Sopenharmony_ci    {
1641cb0ef41Sopenharmony_ci      code: 'ERR_OUT_OF_RANGE',
1651cb0ef41Sopenharmony_ci      message: 'The value of "tabSize" is out of range. ' +
1661cb0ef41Sopenharmony_ci                'It must be an integer. Received 4.5'
1671cb0ef41Sopenharmony_ci    }
1681cb0ef41Sopenharmony_ci  );
1691cb0ef41Sopenharmony_ci}
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci// Sending a single character with no newline
1721cb0ef41Sopenharmony_ci{
1731cb0ef41Sopenharmony_ci  const fi = new FakeInput();
1741cb0ef41Sopenharmony_ci  const rli = new readline.Interface(fi, {});
1751cb0ef41Sopenharmony_ci  rli.on('line', common.mustNotCall());
1761cb0ef41Sopenharmony_ci  fi.emit('data', 'a');
1771cb0ef41Sopenharmony_ci  rli.close();
1781cb0ef41Sopenharmony_ci}
1791cb0ef41Sopenharmony_ci
1801cb0ef41Sopenharmony_ci// Sending multiple newlines at once that does not end with a new line and a
1811cb0ef41Sopenharmony_ci// `end` event(last line is). \r should behave like \n when alone.
1821cb0ef41Sopenharmony_ci{
1831cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true });
1841cb0ef41Sopenharmony_ci  const expectedLines = ['foo', 'bar', 'baz', 'bat'];
1851cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
1861cb0ef41Sopenharmony_ci    assert.strictEqual(line, expectedLines.shift());
1871cb0ef41Sopenharmony_ci  }, expectedLines.length - 1));
1881cb0ef41Sopenharmony_ci  fi.emit('data', expectedLines.join('\r'));
1891cb0ef41Sopenharmony_ci  rli.close();
1901cb0ef41Sopenharmony_ci}
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ci// \r at start of input should output blank line
1931cb0ef41Sopenharmony_ci{
1941cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true });
1951cb0ef41Sopenharmony_ci  const expectedLines = ['', 'foo' ];
1961cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
1971cb0ef41Sopenharmony_ci    assert.strictEqual(line, expectedLines.shift());
1981cb0ef41Sopenharmony_ci  }, expectedLines.length));
1991cb0ef41Sopenharmony_ci  fi.emit('data', '\rfoo\r');
2001cb0ef41Sopenharmony_ci  rli.close();
2011cb0ef41Sopenharmony_ci}
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci// \t does not become part of the input when there is a completer function
2041cb0ef41Sopenharmony_ci{
2051cb0ef41Sopenharmony_ci  const completer = (line) => [[], line];
2061cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, completer });
2071cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
2081cb0ef41Sopenharmony_ci    assert.strictEqual(line, 'foo');
2091cb0ef41Sopenharmony_ci  }));
2101cb0ef41Sopenharmony_ci  for (const character of '\tfo\to\t') {
2111cb0ef41Sopenharmony_ci    fi.emit('data', character);
2121cb0ef41Sopenharmony_ci  }
2131cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
2141cb0ef41Sopenharmony_ci  rli.close();
2151cb0ef41Sopenharmony_ci}
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci// \t when there is no completer function should behave like an ordinary
2181cb0ef41Sopenharmony_ci// character
2191cb0ef41Sopenharmony_ci{
2201cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true });
2211cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
2221cb0ef41Sopenharmony_ci    assert.strictEqual(line, '\t');
2231cb0ef41Sopenharmony_ci  }));
2241cb0ef41Sopenharmony_ci  fi.emit('data', '\t');
2251cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
2261cb0ef41Sopenharmony_ci  rli.close();
2271cb0ef41Sopenharmony_ci}
2281cb0ef41Sopenharmony_ci
2291cb0ef41Sopenharmony_ci// Adding history lines should emit the history event with
2301cb0ef41Sopenharmony_ci// the history array
2311cb0ef41Sopenharmony_ci{
2321cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true });
2331cb0ef41Sopenharmony_ci  const expectedLines = ['foo', 'bar', 'baz', 'bat'];
2341cb0ef41Sopenharmony_ci  rli.on('history', common.mustCall((history) => {
2351cb0ef41Sopenharmony_ci    const expectedHistory = expectedLines.slice(0, history.length).reverse();
2361cb0ef41Sopenharmony_ci    assert.deepStrictEqual(history, expectedHistory);
2371cb0ef41Sopenharmony_ci  }, expectedLines.length));
2381cb0ef41Sopenharmony_ci  for (const line of expectedLines) {
2391cb0ef41Sopenharmony_ci    fi.emit('data', `${line}\n`);
2401cb0ef41Sopenharmony_ci  }
2411cb0ef41Sopenharmony_ci  rli.close();
2421cb0ef41Sopenharmony_ci}
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci// Altering the history array in the listener should not alter
2451cb0ef41Sopenharmony_ci// the line being processed
2461cb0ef41Sopenharmony_ci{
2471cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true });
2481cb0ef41Sopenharmony_ci  const expectedLine = 'foo';
2491cb0ef41Sopenharmony_ci  rli.on('history', common.mustCall((history) => {
2501cb0ef41Sopenharmony_ci    assert.strictEqual(history[0], expectedLine);
2511cb0ef41Sopenharmony_ci    history.shift();
2521cb0ef41Sopenharmony_ci  }));
2531cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
2541cb0ef41Sopenharmony_ci    assert.strictEqual(line, expectedLine);
2551cb0ef41Sopenharmony_ci    assert.strictEqual(rli.history.length, 0);
2561cb0ef41Sopenharmony_ci  }));
2571cb0ef41Sopenharmony_ci  fi.emit('data', `${expectedLine}\n`);
2581cb0ef41Sopenharmony_ci  rli.close();
2591cb0ef41Sopenharmony_ci}
2601cb0ef41Sopenharmony_ci
2611cb0ef41Sopenharmony_ci// Duplicate lines are removed from history when
2621cb0ef41Sopenharmony_ci// `options.removeHistoryDuplicates` is `true`
2631cb0ef41Sopenharmony_ci{
2641cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({
2651cb0ef41Sopenharmony_ci    terminal: true,
2661cb0ef41Sopenharmony_ci    removeHistoryDuplicates: true
2671cb0ef41Sopenharmony_ci  });
2681cb0ef41Sopenharmony_ci  const expectedLines = ['foo', 'bar', 'baz', 'bar', 'bat', 'bat'];
2691cb0ef41Sopenharmony_ci  // ['foo', 'baz', 'bar', bat'];
2701cb0ef41Sopenharmony_ci  let callCount = 0;
2711cb0ef41Sopenharmony_ci  rli.on('line', (line) => {
2721cb0ef41Sopenharmony_ci    assert.strictEqual(line, expectedLines[callCount]);
2731cb0ef41Sopenharmony_ci    callCount++;
2741cb0ef41Sopenharmony_ci  });
2751cb0ef41Sopenharmony_ci  fi.emit('data', `${expectedLines.join('\n')}\n`);
2761cb0ef41Sopenharmony_ci  assert.strictEqual(callCount, expectedLines.length);
2771cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'bat'
2781cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, expectedLines[--callCount]);
2791cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'bar'
2801cb0ef41Sopenharmony_ci  assert.notStrictEqual(rli.line, expectedLines[--callCount]);
2811cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, expectedLines[--callCount]);
2821cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'baz'
2831cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, expectedLines[--callCount]);
2841cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'foo'
2851cb0ef41Sopenharmony_ci  assert.notStrictEqual(rli.line, expectedLines[--callCount]);
2861cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, expectedLines[--callCount]);
2871cb0ef41Sopenharmony_ci  assert.strictEqual(callCount, 0);
2881cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'down' }); // 'baz'
2891cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'baz');
2901cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, 2);
2911cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'n', ctrl: true }); // 'bar'
2921cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'bar');
2931cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, 1);
2941cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'n', ctrl: true });
2951cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'bat');
2961cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, 0);
2971cb0ef41Sopenharmony_ci  // Activate the substring history search.
2981cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'down' }); // 'bat'
2991cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'bat');
3001cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, -1);
3011cb0ef41Sopenharmony_ci  // Deactivate substring history search.
3021cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'backspace' }); // 'ba'
3031cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, -1);
3041cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'ba');
3051cb0ef41Sopenharmony_ci  // Activate the substring history search.
3061cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'down' }); // 'ba'
3071cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, -1);
3081cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'ba');
3091cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'down' }); // 'ba'
3101cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, -1);
3111cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'ba');
3121cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'bat'
3131cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, 0);
3141cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'bat');
3151cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'bar'
3161cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, 1);
3171cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'bar');
3181cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'baz'
3191cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, 2);
3201cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'baz');
3211cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'ba'
3221cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, 4);
3231cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'ba');
3241cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'ba'
3251cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, 4);
3261cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'ba');
3271cb0ef41Sopenharmony_ci  // Deactivate substring history search and reset history index.
3281cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'right' }); // 'ba'
3291cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, -1);
3301cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'ba');
3311cb0ef41Sopenharmony_ci  // Substring history search activated.
3321cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'ba'
3331cb0ef41Sopenharmony_ci  assert.strictEqual(rli.historyIndex, 0);
3341cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'bat');
3351cb0ef41Sopenharmony_ci  rli.close();
3361cb0ef41Sopenharmony_ci}
3371cb0ef41Sopenharmony_ci
3381cb0ef41Sopenharmony_ci// Duplicate lines are not removed from history when
3391cb0ef41Sopenharmony_ci// `options.removeHistoryDuplicates` is `false`
3401cb0ef41Sopenharmony_ci{
3411cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({
3421cb0ef41Sopenharmony_ci    terminal: true,
3431cb0ef41Sopenharmony_ci    removeHistoryDuplicates: false
3441cb0ef41Sopenharmony_ci  });
3451cb0ef41Sopenharmony_ci  const expectedLines = ['foo', 'bar', 'baz', 'bar', 'bat', 'bat'];
3461cb0ef41Sopenharmony_ci  let callCount = 0;
3471cb0ef41Sopenharmony_ci  rli.on('line', (line) => {
3481cb0ef41Sopenharmony_ci    assert.strictEqual(line, expectedLines[callCount]);
3491cb0ef41Sopenharmony_ci    callCount++;
3501cb0ef41Sopenharmony_ci  });
3511cb0ef41Sopenharmony_ci  fi.emit('data', `${expectedLines.join('\n')}\n`);
3521cb0ef41Sopenharmony_ci  assert.strictEqual(callCount, expectedLines.length);
3531cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'bat'
3541cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, expectedLines[--callCount]);
3551cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'bar'
3561cb0ef41Sopenharmony_ci  assert.notStrictEqual(rli.line, expectedLines[--callCount]);
3571cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, expectedLines[--callCount]);
3581cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'baz'
3591cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, expectedLines[--callCount]);
3601cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'bar'
3611cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, expectedLines[--callCount]);
3621cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'up' }); // 'foo'
3631cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, expectedLines[--callCount]);
3641cb0ef41Sopenharmony_ci  assert.strictEqual(callCount, 0);
3651cb0ef41Sopenharmony_ci  rli.close();
3661cb0ef41Sopenharmony_ci}
3671cb0ef41Sopenharmony_ci
3681cb0ef41Sopenharmony_ci// Regression test for repl freeze, #1968:
3691cb0ef41Sopenharmony_ci// check that nothing fails if 'keypress' event throws.
3701cb0ef41Sopenharmony_ci{
3711cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true });
3721cb0ef41Sopenharmony_ci  const keys = [];
3731cb0ef41Sopenharmony_ci  const err = new Error('bad thing happened');
3741cb0ef41Sopenharmony_ci  fi.on('keypress', (key) => {
3751cb0ef41Sopenharmony_ci    keys.push(key);
3761cb0ef41Sopenharmony_ci    if (key === 'X') {
3771cb0ef41Sopenharmony_ci      throw err;
3781cb0ef41Sopenharmony_ci    }
3791cb0ef41Sopenharmony_ci  });
3801cb0ef41Sopenharmony_ci  assert.throws(
3811cb0ef41Sopenharmony_ci    () => fi.emit('data', 'fooX'),
3821cb0ef41Sopenharmony_ci    (e) => {
3831cb0ef41Sopenharmony_ci      assert.strictEqual(e, err);
3841cb0ef41Sopenharmony_ci      return true;
3851cb0ef41Sopenharmony_ci    }
3861cb0ef41Sopenharmony_ci  );
3871cb0ef41Sopenharmony_ci  fi.emit('data', 'bar');
3881cb0ef41Sopenharmony_ci  assert.strictEqual(keys.join(''), 'fooXbar');
3891cb0ef41Sopenharmony_ci  rli.close();
3901cb0ef41Sopenharmony_ci}
3911cb0ef41Sopenharmony_ci
3921cb0ef41Sopenharmony_ci// History is bound
3931cb0ef41Sopenharmony_ci{
3941cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, historySize: 2 });
3951cb0ef41Sopenharmony_ci  const lines = ['line 1', 'line 2', 'line 3'];
3961cb0ef41Sopenharmony_ci  fi.emit('data', lines.join('\n') + '\n');
3971cb0ef41Sopenharmony_ci  assert.strictEqual(rli.history.length, 2);
3981cb0ef41Sopenharmony_ci  assert.strictEqual(rli.history[0], 'line 3');
3991cb0ef41Sopenharmony_ci  assert.strictEqual(rli.history[1], 'line 2');
4001cb0ef41Sopenharmony_ci}
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci// Question
4031cb0ef41Sopenharmony_ci{
4041cb0ef41Sopenharmony_ci  const [rli] = getInterface({ terminal: true });
4051cb0ef41Sopenharmony_ci  const expectedLines = ['foo'];
4061cb0ef41Sopenharmony_ci  rli.question(expectedLines[0], () => rli.close());
4071cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, expectedLines[0].length);
4081cb0ef41Sopenharmony_ci  rli.close();
4091cb0ef41Sopenharmony_ci}
4101cb0ef41Sopenharmony_ci
4111cb0ef41Sopenharmony_ci// Sending a multi-line question
4121cb0ef41Sopenharmony_ci{
4131cb0ef41Sopenharmony_ci  const [rli] = getInterface({ terminal: true });
4141cb0ef41Sopenharmony_ci  const expectedLines = ['foo', 'bar'];
4151cb0ef41Sopenharmony_ci  rli.question(expectedLines.join('\n'), () => rli.close());
4161cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(
4171cb0ef41Sopenharmony_ci    rli, expectedLines.length - 1, expectedLines.slice(-1)[0].length);
4181cb0ef41Sopenharmony_ci  rli.close();
4191cb0ef41Sopenharmony_ci}
4201cb0ef41Sopenharmony_ci
4211cb0ef41Sopenharmony_ci{
4221cb0ef41Sopenharmony_ci  // Beginning and end of line
4231cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
4241cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
4251cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'a' });
4261cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 0);
4271cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'e' });
4281cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 19);
4291cb0ef41Sopenharmony_ci  rli.close();
4301cb0ef41Sopenharmony_ci}
4311cb0ef41Sopenharmony_ci
4321cb0ef41Sopenharmony_ci{
4331cb0ef41Sopenharmony_ci  // Back and Forward one character
4341cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
4351cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
4361cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 19);
4371cb0ef41Sopenharmony_ci
4381cb0ef41Sopenharmony_ci  // Back one character
4391cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'b' });
4401cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 18);
4411cb0ef41Sopenharmony_ci  // Back one character
4421cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'b' });
4431cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 17);
4441cb0ef41Sopenharmony_ci  // Forward one character
4451cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'f' });
4461cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 18);
4471cb0ef41Sopenharmony_ci  // Forward one character
4481cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'f' });
4491cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 19);
4501cb0ef41Sopenharmony_ci  rli.close();
4511cb0ef41Sopenharmony_ci}
4521cb0ef41Sopenharmony_ci
4531cb0ef41Sopenharmony_ci// Back and Forward one astral character
4541cb0ef41Sopenharmony_ci{
4551cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
4561cb0ef41Sopenharmony_ci  fi.emit('data', '�');
4571cb0ef41Sopenharmony_ci
4581cb0ef41Sopenharmony_ci  // Move left one character/code point
4591cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'left' });
4601cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 0);
4611cb0ef41Sopenharmony_ci
4621cb0ef41Sopenharmony_ci  // Move right one character/code point
4631cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'right' });
4641cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 2);
4651cb0ef41Sopenharmony_ci
4661cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
4671cb0ef41Sopenharmony_ci    assert.strictEqual(line, '�');
4681cb0ef41Sopenharmony_ci  }));
4691cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
4701cb0ef41Sopenharmony_ci  rli.close();
4711cb0ef41Sopenharmony_ci}
4721cb0ef41Sopenharmony_ci
4731cb0ef41Sopenharmony_ci// Two astral characters left
4741cb0ef41Sopenharmony_ci{
4751cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
4761cb0ef41Sopenharmony_ci  fi.emit('data', '�');
4771cb0ef41Sopenharmony_ci
4781cb0ef41Sopenharmony_ci  // Move left one character/code point
4791cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'left' });
4801cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 0);
4811cb0ef41Sopenharmony_ci
4821cb0ef41Sopenharmony_ci  fi.emit('data', '�');
4831cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 2);
4841cb0ef41Sopenharmony_ci
4851cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
4861cb0ef41Sopenharmony_ci    assert.strictEqual(line, '��');
4871cb0ef41Sopenharmony_ci  }));
4881cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
4891cb0ef41Sopenharmony_ci  rli.close();
4901cb0ef41Sopenharmony_ci}
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci// Two astral characters right
4931cb0ef41Sopenharmony_ci{
4941cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
4951cb0ef41Sopenharmony_ci  fi.emit('data', '�');
4961cb0ef41Sopenharmony_ci
4971cb0ef41Sopenharmony_ci  // Move left one character/code point
4981cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { name: 'right' });
4991cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 2);
5001cb0ef41Sopenharmony_ci
5011cb0ef41Sopenharmony_ci  fi.emit('data', '�');
5021cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 4);
5031cb0ef41Sopenharmony_ci
5041cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
5051cb0ef41Sopenharmony_ci    assert.strictEqual(line, '��');
5061cb0ef41Sopenharmony_ci  }));
5071cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
5081cb0ef41Sopenharmony_ci  rli.close();
5091cb0ef41Sopenharmony_ci}
5101cb0ef41Sopenharmony_ci
5111cb0ef41Sopenharmony_ci{
5121cb0ef41Sopenharmony_ci  // `wordLeft` and `wordRight`
5131cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
5141cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
5151cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'left' });
5161cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 16);
5171cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { meta: true, name: 'b' });
5181cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 10);
5191cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'right' });
5201cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 16);
5211cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { meta: true, name: 'f' });
5221cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 19);
5231cb0ef41Sopenharmony_ci  rli.close();
5241cb0ef41Sopenharmony_ci}
5251cb0ef41Sopenharmony_ci
5261cb0ef41Sopenharmony_ci// `deleteWordLeft`
5271cb0ef41Sopenharmony_ci[
5281cb0ef41Sopenharmony_ci  { ctrl: true, name: 'w' },
5291cb0ef41Sopenharmony_ci  { ctrl: true, name: 'backspace' },
5301cb0ef41Sopenharmony_ci  { meta: true, name: 'backspace' },
5311cb0ef41Sopenharmony_ci].forEach((deleteWordLeftKey) => {
5321cb0ef41Sopenharmony_ci  let [rli, fi] = getInterface({ terminal: true, prompt: '' });
5331cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
5341cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'left' });
5351cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
5361cb0ef41Sopenharmony_ci    assert.strictEqual(line, 'the quick fox');
5371cb0ef41Sopenharmony_ci  }));
5381cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', deleteWordLeftKey);
5391cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
5401cb0ef41Sopenharmony_ci  rli.close();
5411cb0ef41Sopenharmony_ci
5421cb0ef41Sopenharmony_ci  // No effect if pressed at beginning of line
5431cb0ef41Sopenharmony_ci  [rli, fi] = getInterface({ terminal: true, prompt: '' });
5441cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
5451cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'a' });
5461cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
5471cb0ef41Sopenharmony_ci    assert.strictEqual(line, 'the quick brown fox');
5481cb0ef41Sopenharmony_ci  }));
5491cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', deleteWordLeftKey);
5501cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
5511cb0ef41Sopenharmony_ci  rli.close();
5521cb0ef41Sopenharmony_ci});
5531cb0ef41Sopenharmony_ci
5541cb0ef41Sopenharmony_ci// `deleteWordRight`
5551cb0ef41Sopenharmony_ci[
5561cb0ef41Sopenharmony_ci  { ctrl: true, name: 'delete' },
5571cb0ef41Sopenharmony_ci  { meta: true, name: 'delete' },
5581cb0ef41Sopenharmony_ci  { meta: true, name: 'd' },
5591cb0ef41Sopenharmony_ci].forEach((deleteWordRightKey) => {
5601cb0ef41Sopenharmony_ci  let [rli, fi] = getInterface({ terminal: true, prompt: '' });
5611cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
5621cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'left' });
5631cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'left' });
5641cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
5651cb0ef41Sopenharmony_ci    assert.strictEqual(line, 'the quick fox');
5661cb0ef41Sopenharmony_ci  }));
5671cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', deleteWordRightKey);
5681cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
5691cb0ef41Sopenharmony_ci  rli.close();
5701cb0ef41Sopenharmony_ci
5711cb0ef41Sopenharmony_ci  // No effect if pressed at end of line
5721cb0ef41Sopenharmony_ci  [rli, fi] = getInterface({ terminal: true, prompt: '' });
5731cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
5741cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
5751cb0ef41Sopenharmony_ci    assert.strictEqual(line, 'the quick brown fox');
5761cb0ef41Sopenharmony_ci  }));
5771cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', deleteWordRightKey);
5781cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
5791cb0ef41Sopenharmony_ci  rli.close();
5801cb0ef41Sopenharmony_ci});
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_ci// deleteLeft
5831cb0ef41Sopenharmony_ci{
5841cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
5851cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
5861cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 19);
5871cb0ef41Sopenharmony_ci
5881cb0ef41Sopenharmony_ci  // Delete left character
5891cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'h' });
5901cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 18);
5911cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
5921cb0ef41Sopenharmony_ci    assert.strictEqual(line, 'the quick brown fo');
5931cb0ef41Sopenharmony_ci  }));
5941cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
5951cb0ef41Sopenharmony_ci  rli.close();
5961cb0ef41Sopenharmony_ci}
5971cb0ef41Sopenharmony_ci
5981cb0ef41Sopenharmony_ci// deleteLeft astral character
5991cb0ef41Sopenharmony_ci{
6001cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
6011cb0ef41Sopenharmony_ci  fi.emit('data', '�');
6021cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 2);
6031cb0ef41Sopenharmony_ci  // Delete left character
6041cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'h' });
6051cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 0);
6061cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
6071cb0ef41Sopenharmony_ci    assert.strictEqual(line, '');
6081cb0ef41Sopenharmony_ci  }));
6091cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
6101cb0ef41Sopenharmony_ci  rli.close();
6111cb0ef41Sopenharmony_ci}
6121cb0ef41Sopenharmony_ci
6131cb0ef41Sopenharmony_ci// deleteRight
6141cb0ef41Sopenharmony_ci{
6151cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
6161cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
6171cb0ef41Sopenharmony_ci
6181cb0ef41Sopenharmony_ci  // Go to the start of the line
6191cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'a' });
6201cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 0);
6211cb0ef41Sopenharmony_ci
6221cb0ef41Sopenharmony_ci  // Delete right character
6231cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'd' });
6241cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 0);
6251cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
6261cb0ef41Sopenharmony_ci    assert.strictEqual(line, 'he quick brown fox');
6271cb0ef41Sopenharmony_ci  }));
6281cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
6291cb0ef41Sopenharmony_ci  rli.close();
6301cb0ef41Sopenharmony_ci}
6311cb0ef41Sopenharmony_ci
6321cb0ef41Sopenharmony_ci// deleteRight astral character
6331cb0ef41Sopenharmony_ci{
6341cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
6351cb0ef41Sopenharmony_ci  fi.emit('data', '�');
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_ci  // Go to the start of the line
6381cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'a' });
6391cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 0);
6401cb0ef41Sopenharmony_ci
6411cb0ef41Sopenharmony_ci  // Delete right character
6421cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'd' });
6431cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 0);
6441cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
6451cb0ef41Sopenharmony_ci    assert.strictEqual(line, '');
6461cb0ef41Sopenharmony_ci  }));
6471cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
6481cb0ef41Sopenharmony_ci  rli.close();
6491cb0ef41Sopenharmony_ci}
6501cb0ef41Sopenharmony_ci
6511cb0ef41Sopenharmony_ci// deleteLineLeft
6521cb0ef41Sopenharmony_ci{
6531cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
6541cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
6551cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 19);
6561cb0ef41Sopenharmony_ci
6571cb0ef41Sopenharmony_ci  // Delete from current to start of line
6581cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, shift: true, name: 'backspace' });
6591cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 0);
6601cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
6611cb0ef41Sopenharmony_ci    assert.strictEqual(line, '');
6621cb0ef41Sopenharmony_ci  }));
6631cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
6641cb0ef41Sopenharmony_ci  rli.close();
6651cb0ef41Sopenharmony_ci}
6661cb0ef41Sopenharmony_ci
6671cb0ef41Sopenharmony_ci// deleteLineRight
6681cb0ef41Sopenharmony_ci{
6691cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
6701cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
6711cb0ef41Sopenharmony_ci
6721cb0ef41Sopenharmony_ci  // Go to the start of the line
6731cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'a' });
6741cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 0);
6751cb0ef41Sopenharmony_ci
6761cb0ef41Sopenharmony_ci  // Delete from current to end of line
6771cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, shift: true, name: 'delete' });
6781cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 0);
6791cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
6801cb0ef41Sopenharmony_ci    assert.strictEqual(line, '');
6811cb0ef41Sopenharmony_ci  }));
6821cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
6831cb0ef41Sopenharmony_ci  rli.close();
6841cb0ef41Sopenharmony_ci}
6851cb0ef41Sopenharmony_ci
6861cb0ef41Sopenharmony_ci// yank
6871cb0ef41Sopenharmony_ci{
6881cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
6891cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
6901cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 19);
6911cb0ef41Sopenharmony_ci
6921cb0ef41Sopenharmony_ci  // Go to the start of the line
6931cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'a' });
6941cb0ef41Sopenharmony_ci  // Move forward one char
6951cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'f' });
6961cb0ef41Sopenharmony_ci  // Delete the right part
6971cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, shift: true, name: 'delete' });
6981cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 1);
6991cb0ef41Sopenharmony_ci
7001cb0ef41Sopenharmony_ci  // Yank
7011cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'y' });
7021cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 19);
7031cb0ef41Sopenharmony_ci
7041cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
7051cb0ef41Sopenharmony_ci    assert.strictEqual(line, 'the quick brown fox');
7061cb0ef41Sopenharmony_ci  }));
7071cb0ef41Sopenharmony_ci
7081cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
7091cb0ef41Sopenharmony_ci  rli.close();
7101cb0ef41Sopenharmony_ci}
7111cb0ef41Sopenharmony_ci
7121cb0ef41Sopenharmony_ci// yank pop
7131cb0ef41Sopenharmony_ci{
7141cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
7151cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
7161cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 19);
7171cb0ef41Sopenharmony_ci
7181cb0ef41Sopenharmony_ci  // Go to the start of the line
7191cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'a' });
7201cb0ef41Sopenharmony_ci  // Move forward one char
7211cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'f' });
7221cb0ef41Sopenharmony_ci  // Delete the right part
7231cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, shift: true, name: 'delete' });
7241cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 1);
7251cb0ef41Sopenharmony_ci  // Yank
7261cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'y' });
7271cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 19);
7281cb0ef41Sopenharmony_ci
7291cb0ef41Sopenharmony_ci  // Go to the start of the line
7301cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'a' });
7311cb0ef41Sopenharmony_ci  // Move forward four chars
7321cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'f' });
7331cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'f' });
7341cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'f' });
7351cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'f' });
7361cb0ef41Sopenharmony_ci  // Delete the right part
7371cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, shift: true, name: 'delete' });
7381cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 4);
7391cb0ef41Sopenharmony_ci  // Go to the start of the line
7401cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'a' });
7411cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 0);
7421cb0ef41Sopenharmony_ci
7431cb0ef41Sopenharmony_ci  // Yank: 'quick brown fox|the '
7441cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'y' });
7451cb0ef41Sopenharmony_ci  // Yank pop: 'he quick brown fox|the'
7461cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { meta: true, name: 'y' });
7471cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 18);
7481cb0ef41Sopenharmony_ci
7491cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
7501cb0ef41Sopenharmony_ci    assert.strictEqual(line, 'he quick brown foxthe ');
7511cb0ef41Sopenharmony_ci  }));
7521cb0ef41Sopenharmony_ci
7531cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
7541cb0ef41Sopenharmony_ci  rli.close();
7551cb0ef41Sopenharmony_ci}
7561cb0ef41Sopenharmony_ci
7571cb0ef41Sopenharmony_ci// Close readline interface
7581cb0ef41Sopenharmony_ci{
7591cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
7601cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'c' });
7611cb0ef41Sopenharmony_ci  assert(rli.closed);
7621cb0ef41Sopenharmony_ci}
7631cb0ef41Sopenharmony_ci
7641cb0ef41Sopenharmony_ci// Multi-line input cursor position
7651cb0ef41Sopenharmony_ci{
7661cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
7671cb0ef41Sopenharmony_ci  fi.columns = 10;
7681cb0ef41Sopenharmony_ci  fi.emit('data', 'multi-line text');
7691cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 1, 5);
7701cb0ef41Sopenharmony_ci  rli.close();
7711cb0ef41Sopenharmony_ci}
7721cb0ef41Sopenharmony_ci
7731cb0ef41Sopenharmony_ci// Multi-line input cursor position and long tabs
7741cb0ef41Sopenharmony_ci{
7751cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ tabSize: 16, terminal: true, prompt: '' });
7761cb0ef41Sopenharmony_ci  fi.columns = 10;
7771cb0ef41Sopenharmony_ci  fi.emit('data', 'multi-line\ttext \t');
7781cb0ef41Sopenharmony_ci  assert.strictEqual(rli.cursor, 17);
7791cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 3, 2);
7801cb0ef41Sopenharmony_ci  rli.close();
7811cb0ef41Sopenharmony_ci}
7821cb0ef41Sopenharmony_ci
7831cb0ef41Sopenharmony_ci// Check for the default tab size.
7841cb0ef41Sopenharmony_ci{
7851cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
7861cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick\tbrown\tfox');
7871cb0ef41Sopenharmony_ci  assert.strictEqual(rli.cursor, 19);
7881cb0ef41Sopenharmony_ci  // The first tab is 7 spaces long, the second one 3 spaces.
7891cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 27);
7901cb0ef41Sopenharmony_ci}
7911cb0ef41Sopenharmony_ci
7921cb0ef41Sopenharmony_ci// Multi-line prompt cursor position
7931cb0ef41Sopenharmony_ci{
7941cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({
7951cb0ef41Sopenharmony_ci    terminal: true,
7961cb0ef41Sopenharmony_ci    prompt: '\nfilledline\nwraping text\n> '
7971cb0ef41Sopenharmony_ci  });
7981cb0ef41Sopenharmony_ci  fi.columns = 10;
7991cb0ef41Sopenharmony_ci  fi.emit('data', 't');
8001cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 4, 3);
8011cb0ef41Sopenharmony_ci  rli.close();
8021cb0ef41Sopenharmony_ci}
8031cb0ef41Sopenharmony_ci
8041cb0ef41Sopenharmony_ci// Undo & Redo
8051cb0ef41Sopenharmony_ci{
8061cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
8071cb0ef41Sopenharmony_ci  fi.emit('data', 'the quick brown fox');
8081cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 19);
8091cb0ef41Sopenharmony_ci
8101cb0ef41Sopenharmony_ci  // Delete the last eight chars
8111cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, shift: false, name: 'b' });
8121cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, shift: false, name: 'b' });
8131cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, shift: false, name: 'b' });
8141cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, shift: false, name: 'b' });
8151cb0ef41Sopenharmony_ci  fi.emit('keypress', ',', { ctrl: true, shift: false, name: 'k' });
8161cb0ef41Sopenharmony_ci
8171cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, shift: false, name: 'b' });
8181cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, shift: false, name: 'b' });
8191cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, shift: false, name: 'b' });
8201cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, shift: false, name: 'b' });
8211cb0ef41Sopenharmony_ci  fi.emit('keypress', ',', { ctrl: true, shift: false, name: 'k' });
8221cb0ef41Sopenharmony_ci
8231cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 11);
8241cb0ef41Sopenharmony_ci  // Perform undo twice
8251cb0ef41Sopenharmony_ci  fi.emit('keypress', ',', { sequence: '\x1F' });
8261cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'the quick brown');
8271cb0ef41Sopenharmony_ci  fi.emit('keypress', ',', { sequence: '\x1F' });
8281cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'the quick brown fox');
8291cb0ef41Sopenharmony_ci  // Perform redo twice
8301cb0ef41Sopenharmony_ci  fi.emit('keypress', ',', { sequence: '\x1E' });
8311cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'the quick brown');
8321cb0ef41Sopenharmony_ci  fi.emit('keypress', ',', { sequence: '\x1E' });
8331cb0ef41Sopenharmony_ci  assert.strictEqual(rli.line, 'the quick b');
8341cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
8351cb0ef41Sopenharmony_ci  rli.close();
8361cb0ef41Sopenharmony_ci}
8371cb0ef41Sopenharmony_ci
8381cb0ef41Sopenharmony_ci// Clear the whole screen
8391cb0ef41Sopenharmony_ci{
8401cb0ef41Sopenharmony_ci  const [rli, fi] = getInterface({ terminal: true, prompt: '' });
8411cb0ef41Sopenharmony_ci  const lines = ['line 1', 'line 2', 'line 3'];
8421cb0ef41Sopenharmony_ci  fi.emit('data', lines.join('\n'));
8431cb0ef41Sopenharmony_ci  fi.emit('keypress', '.', { ctrl: true, name: 'l' });
8441cb0ef41Sopenharmony_ci  assertCursorRowsAndCols(rli, 0, 6);
8451cb0ef41Sopenharmony_ci  rli.on('line', common.mustCall((line) => {
8461cb0ef41Sopenharmony_ci    assert.strictEqual(line, 'line 3');
8471cb0ef41Sopenharmony_ci  }));
8481cb0ef41Sopenharmony_ci  fi.emit('data', '\n');
8491cb0ef41Sopenharmony_ci  rli.close();
8501cb0ef41Sopenharmony_ci}
8511cb0ef41Sopenharmony_ci
8521cb0ef41Sopenharmony_ci// Wide characters should be treated as two columns.
8531cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('a'), 1);
8541cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('あ'), 2);
8551cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('谢'), 2);
8561cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('고'), 2);
8571cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth(String.fromCodePoint(0x1f251)), 2);
8581cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('abcde'), 5);
8591cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('古池や'), 6);
8601cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('ノード.js'), 9);
8611cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('你好'), 4);
8621cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('안녕하세요'), 10);
8631cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('A\ud83c\ude00BC'), 5);
8641cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('�‍�‍�‍�'), 8);
8651cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('��あ��'), 9);
8661cb0ef41Sopenharmony_ci// TODO(BridgeAR): This should have a width of 4.
8671cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('⓬⓪'), 2);
8681cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('\u0301\u200D\u200E'), 0);
8691cb0ef41Sopenharmony_ci
8701cb0ef41Sopenharmony_ci// Check if vt control chars are stripped
8711cb0ef41Sopenharmony_ciassert.strictEqual(stripVTControlCharacters('\u001b[31m> \u001b[39m'), '> ');
8721cb0ef41Sopenharmony_ciassert.strictEqual(
8731cb0ef41Sopenharmony_ci  stripVTControlCharacters('\u001b[31m> \u001b[39m> '),
8741cb0ef41Sopenharmony_ci  '> > '
8751cb0ef41Sopenharmony_ci);
8761cb0ef41Sopenharmony_ciassert.strictEqual(stripVTControlCharacters('\u001b[31m\u001b[39m'), '');
8771cb0ef41Sopenharmony_ciassert.strictEqual(stripVTControlCharacters('> '), '> ');
8781cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('\u001b[31m> \u001b[39m'), 2);
8791cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('\u001b[31m> \u001b[39m> '), 4);
8801cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('\u001b[31m\u001b[39m'), 0);
8811cb0ef41Sopenharmony_ciassert.strictEqual(getStringWidth('> '), 2);
8821cb0ef41Sopenharmony_ci
8831cb0ef41Sopenharmony_ci// Check EventEmitter memory leak
8841cb0ef41Sopenharmony_cifor (let i = 0; i < 12; i++) {
8851cb0ef41Sopenharmony_ci  const rl = readline.createInterface({
8861cb0ef41Sopenharmony_ci    input: process.stdin,
8871cb0ef41Sopenharmony_ci    output: process.stdout
8881cb0ef41Sopenharmony_ci  });
8891cb0ef41Sopenharmony_ci  rl.close();
8901cb0ef41Sopenharmony_ci  assert.strictEqual(isWarned(process.stdin._events), false);
8911cb0ef41Sopenharmony_ci  assert.strictEqual(isWarned(process.stdout._events), false);
8921cb0ef41Sopenharmony_ci}
8931cb0ef41Sopenharmony_ci
8941cb0ef41Sopenharmony_ci[true, false].forEach((terminal) => {
8951cb0ef41Sopenharmony_ci  // Disable history
8961cb0ef41Sopenharmony_ci  {
8971cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal, historySize: 0 });
8981cb0ef41Sopenharmony_ci    assert.strictEqual(rli.historySize, 0);
8991cb0ef41Sopenharmony_ci
9001cb0ef41Sopenharmony_ci    fi.emit('data', 'asdf\n');
9011cb0ef41Sopenharmony_ci    assert.deepStrictEqual(rli.history, []);
9021cb0ef41Sopenharmony_ci    rli.close();
9031cb0ef41Sopenharmony_ci  }
9041cb0ef41Sopenharmony_ci
9051cb0ef41Sopenharmony_ci  // Default history size 30
9061cb0ef41Sopenharmony_ci  {
9071cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal });
9081cb0ef41Sopenharmony_ci    assert.strictEqual(rli.historySize, 30);
9091cb0ef41Sopenharmony_ci
9101cb0ef41Sopenharmony_ci    fi.emit('data', 'asdf\n');
9111cb0ef41Sopenharmony_ci    assert.deepStrictEqual(rli.history, terminal ? ['asdf'] : []);
9121cb0ef41Sopenharmony_ci    rli.close();
9131cb0ef41Sopenharmony_ci  }
9141cb0ef41Sopenharmony_ci
9151cb0ef41Sopenharmony_ci  // Sending a full line
9161cb0ef41Sopenharmony_ci  {
9171cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal });
9181cb0ef41Sopenharmony_ci    rli.on('line', common.mustCall((line) => {
9191cb0ef41Sopenharmony_ci      assert.strictEqual(line, 'asdf');
9201cb0ef41Sopenharmony_ci    }));
9211cb0ef41Sopenharmony_ci    fi.emit('data', 'asdf\n');
9221cb0ef41Sopenharmony_ci  }
9231cb0ef41Sopenharmony_ci
9241cb0ef41Sopenharmony_ci  // Ensure that options.signal.removeEventListener was called
9251cb0ef41Sopenharmony_ci  {
9261cb0ef41Sopenharmony_ci    const ac = new AbortController();
9271cb0ef41Sopenharmony_ci    const signal = ac.signal;
9281cb0ef41Sopenharmony_ci    const [rli] = getInterface({ terminal });
9291cb0ef41Sopenharmony_ci    signal.removeEventListener = common.mustCall(
9301cb0ef41Sopenharmony_ci      (event, onAbortFn) => {
9311cb0ef41Sopenharmony_ci        assert.strictEqual(event, 'abort');
9321cb0ef41Sopenharmony_ci        assert.strictEqual(onAbortFn.name, 'onAbort');
9331cb0ef41Sopenharmony_ci      });
9341cb0ef41Sopenharmony_ci
9351cb0ef41Sopenharmony_ci    rli.question('hello?', { signal }, common.mustCall());
9361cb0ef41Sopenharmony_ci
9371cb0ef41Sopenharmony_ci    rli.write('bar\n');
9381cb0ef41Sopenharmony_ci    ac.abort();
9391cb0ef41Sopenharmony_ci    rli.close();
9401cb0ef41Sopenharmony_ci  }
9411cb0ef41Sopenharmony_ci
9421cb0ef41Sopenharmony_ci  // Sending a blank line
9431cb0ef41Sopenharmony_ci  {
9441cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal });
9451cb0ef41Sopenharmony_ci    rli.on('line', common.mustCall((line) => {
9461cb0ef41Sopenharmony_ci      assert.strictEqual(line, '');
9471cb0ef41Sopenharmony_ci    }));
9481cb0ef41Sopenharmony_ci    fi.emit('data', '\n');
9491cb0ef41Sopenharmony_ci  }
9501cb0ef41Sopenharmony_ci
9511cb0ef41Sopenharmony_ci  // Sending a single character with no newline and then a newline
9521cb0ef41Sopenharmony_ci  {
9531cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal });
9541cb0ef41Sopenharmony_ci    let called = false;
9551cb0ef41Sopenharmony_ci    rli.on('line', (line) => {
9561cb0ef41Sopenharmony_ci      called = true;
9571cb0ef41Sopenharmony_ci      assert.strictEqual(line, 'a');
9581cb0ef41Sopenharmony_ci    });
9591cb0ef41Sopenharmony_ci    fi.emit('data', 'a');
9601cb0ef41Sopenharmony_ci    assert.ok(!called);
9611cb0ef41Sopenharmony_ci    fi.emit('data', '\n');
9621cb0ef41Sopenharmony_ci    assert.ok(called);
9631cb0ef41Sopenharmony_ci    rli.close();
9641cb0ef41Sopenharmony_ci  }
9651cb0ef41Sopenharmony_ci
9661cb0ef41Sopenharmony_ci  // Sending multiple newlines at once
9671cb0ef41Sopenharmony_ci  {
9681cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal });
9691cb0ef41Sopenharmony_ci    const expectedLines = ['foo', 'bar', 'baz'];
9701cb0ef41Sopenharmony_ci    rli.on('line', common.mustCall((line) => {
9711cb0ef41Sopenharmony_ci      assert.strictEqual(line, expectedLines.shift());
9721cb0ef41Sopenharmony_ci    }, expectedLines.length));
9731cb0ef41Sopenharmony_ci    fi.emit('data', `${expectedLines.join('\n')}\n`);
9741cb0ef41Sopenharmony_ci    rli.close();
9751cb0ef41Sopenharmony_ci  }
9761cb0ef41Sopenharmony_ci
9771cb0ef41Sopenharmony_ci  // Sending multiple newlines at once that does not end with a new line
9781cb0ef41Sopenharmony_ci  {
9791cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal });
9801cb0ef41Sopenharmony_ci    const expectedLines = ['foo', 'bar', 'baz', 'bat'];
9811cb0ef41Sopenharmony_ci    rli.on('line', common.mustCall((line) => {
9821cb0ef41Sopenharmony_ci      assert.strictEqual(line, expectedLines.shift());
9831cb0ef41Sopenharmony_ci    }, expectedLines.length - 1));
9841cb0ef41Sopenharmony_ci    fi.emit('data', expectedLines.join('\n'));
9851cb0ef41Sopenharmony_ci    rli.close();
9861cb0ef41Sopenharmony_ci  }
9871cb0ef41Sopenharmony_ci
9881cb0ef41Sopenharmony_ci  // Sending multiple newlines at once that does not end with a new(empty)
9891cb0ef41Sopenharmony_ci  // line and a `end` event
9901cb0ef41Sopenharmony_ci  {
9911cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal });
9921cb0ef41Sopenharmony_ci    const expectedLines = ['foo', 'bar', 'baz', ''];
9931cb0ef41Sopenharmony_ci    rli.on('line', common.mustCall((line) => {
9941cb0ef41Sopenharmony_ci      assert.strictEqual(line, expectedLines.shift());
9951cb0ef41Sopenharmony_ci    }, expectedLines.length - 1));
9961cb0ef41Sopenharmony_ci    rli.on('close', common.mustCall());
9971cb0ef41Sopenharmony_ci    fi.emit('data', expectedLines.join('\n'));
9981cb0ef41Sopenharmony_ci    fi.emit('end');
9991cb0ef41Sopenharmony_ci    rli.close();
10001cb0ef41Sopenharmony_ci  }
10011cb0ef41Sopenharmony_ci
10021cb0ef41Sopenharmony_ci  // Sending a multi-byte utf8 char over multiple writes
10031cb0ef41Sopenharmony_ci  {
10041cb0ef41Sopenharmony_ci    const buf = Buffer.from('☮', 'utf8');
10051cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal });
10061cb0ef41Sopenharmony_ci    let callCount = 0;
10071cb0ef41Sopenharmony_ci    rli.on('line', (line) => {
10081cb0ef41Sopenharmony_ci      callCount++;
10091cb0ef41Sopenharmony_ci      assert.strictEqual(line, buf.toString('utf8'));
10101cb0ef41Sopenharmony_ci    });
10111cb0ef41Sopenharmony_ci    for (const i of buf) {
10121cb0ef41Sopenharmony_ci      fi.emit('data', Buffer.from([i]));
10131cb0ef41Sopenharmony_ci    }
10141cb0ef41Sopenharmony_ci    assert.strictEqual(callCount, 0);
10151cb0ef41Sopenharmony_ci    fi.emit('data', '\n');
10161cb0ef41Sopenharmony_ci    assert.strictEqual(callCount, 1);
10171cb0ef41Sopenharmony_ci    rli.close();
10181cb0ef41Sopenharmony_ci  }
10191cb0ef41Sopenharmony_ci
10201cb0ef41Sopenharmony_ci  // Calling readline without `new`
10211cb0ef41Sopenharmony_ci  {
10221cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal });
10231cb0ef41Sopenharmony_ci    rli.on('line', common.mustCall((line) => {
10241cb0ef41Sopenharmony_ci      assert.strictEqual(line, 'asdf');
10251cb0ef41Sopenharmony_ci    }));
10261cb0ef41Sopenharmony_ci    fi.emit('data', 'asdf\n');
10271cb0ef41Sopenharmony_ci    rli.close();
10281cb0ef41Sopenharmony_ci  }
10291cb0ef41Sopenharmony_ci
10301cb0ef41Sopenharmony_ci  // Calling the question callback
10311cb0ef41Sopenharmony_ci  {
10321cb0ef41Sopenharmony_ci    const [rli] = getInterface({ terminal });
10331cb0ef41Sopenharmony_ci    rli.question('foo?', common.mustCall((answer) => {
10341cb0ef41Sopenharmony_ci      assert.strictEqual(answer, 'bar');
10351cb0ef41Sopenharmony_ci    }));
10361cb0ef41Sopenharmony_ci    rli.write('bar\n');
10371cb0ef41Sopenharmony_ci    rli.close();
10381cb0ef41Sopenharmony_ci  }
10391cb0ef41Sopenharmony_ci
10401cb0ef41Sopenharmony_ci  // Calling the question callback with abort signal
10411cb0ef41Sopenharmony_ci  {
10421cb0ef41Sopenharmony_ci    const [rli] = getInterface({ terminal });
10431cb0ef41Sopenharmony_ci    const { signal } = new AbortController();
10441cb0ef41Sopenharmony_ci    rli.question('foo?', { signal }, common.mustCall((answer) => {
10451cb0ef41Sopenharmony_ci      assert.strictEqual(answer, 'bar');
10461cb0ef41Sopenharmony_ci    }));
10471cb0ef41Sopenharmony_ci    rli.write('bar\n');
10481cb0ef41Sopenharmony_ci    rli.close();
10491cb0ef41Sopenharmony_ci  }
10501cb0ef41Sopenharmony_ci
10511cb0ef41Sopenharmony_ci  // Calling the question multiple times
10521cb0ef41Sopenharmony_ci  {
10531cb0ef41Sopenharmony_ci    const [rli] = getInterface({ terminal });
10541cb0ef41Sopenharmony_ci    rli.question('foo?', common.mustCall((answer) => {
10551cb0ef41Sopenharmony_ci      assert.strictEqual(answer, 'baz');
10561cb0ef41Sopenharmony_ci    }));
10571cb0ef41Sopenharmony_ci    rli.question('bar?', common.mustNotCall());
10581cb0ef41Sopenharmony_ci    rli.write('baz\n');
10591cb0ef41Sopenharmony_ci    rli.close();
10601cb0ef41Sopenharmony_ci  }
10611cb0ef41Sopenharmony_ci
10621cb0ef41Sopenharmony_ci  // Calling the promisified question
10631cb0ef41Sopenharmony_ci  {
10641cb0ef41Sopenharmony_ci    const [rli] = getInterface({ terminal });
10651cb0ef41Sopenharmony_ci    const question = util.promisify(rli.question).bind(rli);
10661cb0ef41Sopenharmony_ci    question('foo?')
10671cb0ef41Sopenharmony_ci    .then(common.mustCall((answer) => {
10681cb0ef41Sopenharmony_ci      assert.strictEqual(answer, 'bar');
10691cb0ef41Sopenharmony_ci    }));
10701cb0ef41Sopenharmony_ci    rli.write('bar\n');
10711cb0ef41Sopenharmony_ci    rli.close();
10721cb0ef41Sopenharmony_ci  }
10731cb0ef41Sopenharmony_ci
10741cb0ef41Sopenharmony_ci  // Calling the promisified question with abort signal
10751cb0ef41Sopenharmony_ci  {
10761cb0ef41Sopenharmony_ci    const [rli] = getInterface({ terminal });
10771cb0ef41Sopenharmony_ci    const question = util.promisify(rli.question).bind(rli);
10781cb0ef41Sopenharmony_ci    const { signal } = new AbortController();
10791cb0ef41Sopenharmony_ci    question('foo?', { signal })
10801cb0ef41Sopenharmony_ci    .then(common.mustCall((answer) => {
10811cb0ef41Sopenharmony_ci      assert.strictEqual(answer, 'bar');
10821cb0ef41Sopenharmony_ci    }));
10831cb0ef41Sopenharmony_ci    rli.write('bar\n');
10841cb0ef41Sopenharmony_ci    rli.close();
10851cb0ef41Sopenharmony_ci  }
10861cb0ef41Sopenharmony_ci
10871cb0ef41Sopenharmony_ci  // Aborting a question
10881cb0ef41Sopenharmony_ci  {
10891cb0ef41Sopenharmony_ci    const ac = new AbortController();
10901cb0ef41Sopenharmony_ci    const signal = ac.signal;
10911cb0ef41Sopenharmony_ci    const [rli] = getInterface({ terminal });
10921cb0ef41Sopenharmony_ci    rli.on('line', common.mustCall((line) => {
10931cb0ef41Sopenharmony_ci      assert.strictEqual(line, 'bar');
10941cb0ef41Sopenharmony_ci    }));
10951cb0ef41Sopenharmony_ci    rli.question('hello?', { signal }, common.mustNotCall());
10961cb0ef41Sopenharmony_ci    ac.abort();
10971cb0ef41Sopenharmony_ci    rli.write('bar\n');
10981cb0ef41Sopenharmony_ci    rli.close();
10991cb0ef41Sopenharmony_ci  }
11001cb0ef41Sopenharmony_ci
11011cb0ef41Sopenharmony_ci  // Aborting a promisified question
11021cb0ef41Sopenharmony_ci  {
11031cb0ef41Sopenharmony_ci    const ac = new AbortController();
11041cb0ef41Sopenharmony_ci    const signal = ac.signal;
11051cb0ef41Sopenharmony_ci    const [rli] = getInterface({ terminal });
11061cb0ef41Sopenharmony_ci    const question = util.promisify(rli.question).bind(rli);
11071cb0ef41Sopenharmony_ci    rli.on('line', common.mustCall((line) => {
11081cb0ef41Sopenharmony_ci      assert.strictEqual(line, 'bar');
11091cb0ef41Sopenharmony_ci    }));
11101cb0ef41Sopenharmony_ci    question('hello?', { signal })
11111cb0ef41Sopenharmony_ci    .then(common.mustNotCall())
11121cb0ef41Sopenharmony_ci    .catch(common.mustCall((error) => {
11131cb0ef41Sopenharmony_ci      assert.strictEqual(error.name, 'AbortError');
11141cb0ef41Sopenharmony_ci    }));
11151cb0ef41Sopenharmony_ci    ac.abort();
11161cb0ef41Sopenharmony_ci    rli.write('bar\n');
11171cb0ef41Sopenharmony_ci    rli.close();
11181cb0ef41Sopenharmony_ci  }
11191cb0ef41Sopenharmony_ci
11201cb0ef41Sopenharmony_ci  // pre-aborted signal
11211cb0ef41Sopenharmony_ci  {
11221cb0ef41Sopenharmony_ci    const signal = AbortSignal.abort();
11231cb0ef41Sopenharmony_ci    const [rli] = getInterface({ terminal });
11241cb0ef41Sopenharmony_ci    rli.pause();
11251cb0ef41Sopenharmony_ci    rli.on('resume', common.mustNotCall());
11261cb0ef41Sopenharmony_ci    rli.question('hello?', { signal }, common.mustNotCall());
11271cb0ef41Sopenharmony_ci    rli.close();
11281cb0ef41Sopenharmony_ci  }
11291cb0ef41Sopenharmony_ci
11301cb0ef41Sopenharmony_ci  // pre-aborted signal promisified question
11311cb0ef41Sopenharmony_ci  {
11321cb0ef41Sopenharmony_ci    const signal = AbortSignal.abort();
11331cb0ef41Sopenharmony_ci    const [rli] = getInterface({ terminal });
11341cb0ef41Sopenharmony_ci    const question = util.promisify(rli.question).bind(rli);
11351cb0ef41Sopenharmony_ci    rli.on('resume', common.mustNotCall());
11361cb0ef41Sopenharmony_ci    rli.pause();
11371cb0ef41Sopenharmony_ci    question('hello?', { signal })
11381cb0ef41Sopenharmony_ci    .then(common.mustNotCall())
11391cb0ef41Sopenharmony_ci    .catch(common.mustCall((error) => {
11401cb0ef41Sopenharmony_ci      assert.strictEqual(error.name, 'AbortError');
11411cb0ef41Sopenharmony_ci    }));
11421cb0ef41Sopenharmony_ci    rli.close();
11431cb0ef41Sopenharmony_ci  }
11441cb0ef41Sopenharmony_ci
11451cb0ef41Sopenharmony_ci  // Call question after close
11461cb0ef41Sopenharmony_ci  {
11471cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal });
11481cb0ef41Sopenharmony_ci    rli.question('What\'s your name?', common.mustCall((name) => {
11491cb0ef41Sopenharmony_ci      assert.strictEqual(name, 'Node.js');
11501cb0ef41Sopenharmony_ci      rli.close();
11511cb0ef41Sopenharmony_ci      assert.throws(() => {
11521cb0ef41Sopenharmony_ci        rli.question('How are you?', common.mustNotCall());
11531cb0ef41Sopenharmony_ci      }, {
11541cb0ef41Sopenharmony_ci        name: 'Error',
11551cb0ef41Sopenharmony_ci        code: 'ERR_USE_AFTER_CLOSE'
11561cb0ef41Sopenharmony_ci      });
11571cb0ef41Sopenharmony_ci      assert.notStrictEqual(rli.getPrompt(), 'How are you?');
11581cb0ef41Sopenharmony_ci    }));
11591cb0ef41Sopenharmony_ci    fi.emit('data', 'Node.js\n');
11601cb0ef41Sopenharmony_ci  }
11611cb0ef41Sopenharmony_ci
11621cb0ef41Sopenharmony_ci  // Call promisified question after close
11631cb0ef41Sopenharmony_ci  {
11641cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal });
11651cb0ef41Sopenharmony_ci    const question = util.promisify(rli.question).bind(rli);
11661cb0ef41Sopenharmony_ci    question('What\'s your name?').then(common.mustCall((name) => {
11671cb0ef41Sopenharmony_ci      assert.strictEqual(name, 'Node.js');
11681cb0ef41Sopenharmony_ci      rli.close();
11691cb0ef41Sopenharmony_ci      question('How are you?')
11701cb0ef41Sopenharmony_ci        .then(common.mustNotCall(), common.expectsError({
11711cb0ef41Sopenharmony_ci          code: 'ERR_USE_AFTER_CLOSE',
11721cb0ef41Sopenharmony_ci          name: 'Error'
11731cb0ef41Sopenharmony_ci        }));
11741cb0ef41Sopenharmony_ci      assert.notStrictEqual(rli.getPrompt(), 'How are you?');
11751cb0ef41Sopenharmony_ci    }));
11761cb0ef41Sopenharmony_ci    fi.emit('data', 'Node.js\n');
11771cb0ef41Sopenharmony_ci  }
11781cb0ef41Sopenharmony_ci
11791cb0ef41Sopenharmony_ci  // Can create a new readline Interface with a null output argument
11801cb0ef41Sopenharmony_ci  {
11811cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ output: null, terminal });
11821cb0ef41Sopenharmony_ci    rli.on('line', common.mustCall((line) => {
11831cb0ef41Sopenharmony_ci      assert.strictEqual(line, 'asdf');
11841cb0ef41Sopenharmony_ci    }));
11851cb0ef41Sopenharmony_ci    fi.emit('data', 'asdf\n');
11861cb0ef41Sopenharmony_ci
11871cb0ef41Sopenharmony_ci    rli.setPrompt('ddd> ');
11881cb0ef41Sopenharmony_ci    rli.prompt();
11891cb0ef41Sopenharmony_ci    rli.write("really shouldn't be seeing this");
11901cb0ef41Sopenharmony_ci    rli.question('What do you think of node.js? ', (answer) => {
11911cb0ef41Sopenharmony_ci      console.log('Thank you for your valuable feedback:', answer);
11921cb0ef41Sopenharmony_ci      rli.close();
11931cb0ef41Sopenharmony_ci    });
11941cb0ef41Sopenharmony_ci  }
11951cb0ef41Sopenharmony_ci
11961cb0ef41Sopenharmony_ci  // Calling the getPrompt method
11971cb0ef41Sopenharmony_ci  {
11981cb0ef41Sopenharmony_ci    const expectedPrompts = ['$ ', '> '];
11991cb0ef41Sopenharmony_ci    const [rli] = getInterface({ terminal });
12001cb0ef41Sopenharmony_ci    for (const prompt of expectedPrompts) {
12011cb0ef41Sopenharmony_ci      rli.setPrompt(prompt);
12021cb0ef41Sopenharmony_ci      assert.strictEqual(rli.getPrompt(), prompt);
12031cb0ef41Sopenharmony_ci    }
12041cb0ef41Sopenharmony_ci  }
12051cb0ef41Sopenharmony_ci
12061cb0ef41Sopenharmony_ci  {
12071cb0ef41Sopenharmony_ci    const expected = terminal ?
12081cb0ef41Sopenharmony_ci      ['\u001b[1G', '\u001b[0J', '$ ', '\u001b[3G'] :
12091cb0ef41Sopenharmony_ci      ['$ '];
12101cb0ef41Sopenharmony_ci
12111cb0ef41Sopenharmony_ci    const output = new Writable({
12121cb0ef41Sopenharmony_ci      write: common.mustCall((chunk, enc, cb) => {
12131cb0ef41Sopenharmony_ci        assert.strictEqual(chunk.toString(), expected.shift());
12141cb0ef41Sopenharmony_ci        cb();
12151cb0ef41Sopenharmony_ci        rl.close();
12161cb0ef41Sopenharmony_ci      }, expected.length)
12171cb0ef41Sopenharmony_ci    });
12181cb0ef41Sopenharmony_ci
12191cb0ef41Sopenharmony_ci    const rl = readline.createInterface({
12201cb0ef41Sopenharmony_ci      input: new Readable({ read: common.mustCall() }),
12211cb0ef41Sopenharmony_ci      output,
12221cb0ef41Sopenharmony_ci      prompt: '$ ',
12231cb0ef41Sopenharmony_ci      terminal
12241cb0ef41Sopenharmony_ci    });
12251cb0ef41Sopenharmony_ci
12261cb0ef41Sopenharmony_ci    rl.prompt();
12271cb0ef41Sopenharmony_ci
12281cb0ef41Sopenharmony_ci    assert.strictEqual(rl.getPrompt(), '$ ');
12291cb0ef41Sopenharmony_ci  }
12301cb0ef41Sopenharmony_ci
12311cb0ef41Sopenharmony_ci  {
12321cb0ef41Sopenharmony_ci    const fi = new FakeInput();
12331cb0ef41Sopenharmony_ci    assert.deepStrictEqual(fi.listeners(terminal ? 'keypress' : 'data'), []);
12341cb0ef41Sopenharmony_ci  }
12351cb0ef41Sopenharmony_ci
12361cb0ef41Sopenharmony_ci  // Emit two line events when the delay
12371cb0ef41Sopenharmony_ci  // between \r and \n exceeds crlfDelay
12381cb0ef41Sopenharmony_ci  {
12391cb0ef41Sopenharmony_ci    const crlfDelay = 200;
12401cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal, crlfDelay });
12411cb0ef41Sopenharmony_ci    let callCount = 0;
12421cb0ef41Sopenharmony_ci    rli.on('line', () => {
12431cb0ef41Sopenharmony_ci      callCount++;
12441cb0ef41Sopenharmony_ci    });
12451cb0ef41Sopenharmony_ci    fi.emit('data', '\r');
12461cb0ef41Sopenharmony_ci    setTimeout(common.mustCall(() => {
12471cb0ef41Sopenharmony_ci      fi.emit('data', '\n');
12481cb0ef41Sopenharmony_ci      assert.strictEqual(callCount, 2);
12491cb0ef41Sopenharmony_ci      rli.close();
12501cb0ef41Sopenharmony_ci    }), crlfDelay + 10);
12511cb0ef41Sopenharmony_ci  }
12521cb0ef41Sopenharmony_ci
12531cb0ef41Sopenharmony_ci  // For the purposes of the following tests, we do not care about the exact
12541cb0ef41Sopenharmony_ci  // value of crlfDelay, only that the behaviour conforms to what's expected.
12551cb0ef41Sopenharmony_ci  // Setting it to Infinity allows the test to succeed even under extreme
12561cb0ef41Sopenharmony_ci  // CPU stress.
12571cb0ef41Sopenharmony_ci  const crlfDelay = Infinity;
12581cb0ef41Sopenharmony_ci
12591cb0ef41Sopenharmony_ci  // Set crlfDelay to `Infinity` is allowed
12601cb0ef41Sopenharmony_ci  {
12611cb0ef41Sopenharmony_ci    const delay = 200;
12621cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal, crlfDelay });
12631cb0ef41Sopenharmony_ci    let callCount = 0;
12641cb0ef41Sopenharmony_ci    rli.on('line', () => {
12651cb0ef41Sopenharmony_ci      callCount++;
12661cb0ef41Sopenharmony_ci    });
12671cb0ef41Sopenharmony_ci    fi.emit('data', '\r');
12681cb0ef41Sopenharmony_ci    setTimeout(common.mustCall(() => {
12691cb0ef41Sopenharmony_ci      fi.emit('data', '\n');
12701cb0ef41Sopenharmony_ci      assert.strictEqual(callCount, 1);
12711cb0ef41Sopenharmony_ci      rli.close();
12721cb0ef41Sopenharmony_ci    }), delay);
12731cb0ef41Sopenharmony_ci  }
12741cb0ef41Sopenharmony_ci
12751cb0ef41Sopenharmony_ci  // Sending multiple newlines at once that does not end with a new line
12761cb0ef41Sopenharmony_ci  // and a `end` event(last line is)
12771cb0ef41Sopenharmony_ci
12781cb0ef41Sopenharmony_ci  // \r\n should emit one line event, not two
12791cb0ef41Sopenharmony_ci  {
12801cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal, crlfDelay });
12811cb0ef41Sopenharmony_ci    const expectedLines = ['foo', 'bar', 'baz', 'bat'];
12821cb0ef41Sopenharmony_ci    rli.on('line', common.mustCall((line) => {
12831cb0ef41Sopenharmony_ci      assert.strictEqual(line, expectedLines.shift());
12841cb0ef41Sopenharmony_ci    }, expectedLines.length - 1));
12851cb0ef41Sopenharmony_ci    fi.emit('data', expectedLines.join('\r\n'));
12861cb0ef41Sopenharmony_ci    rli.close();
12871cb0ef41Sopenharmony_ci  }
12881cb0ef41Sopenharmony_ci
12891cb0ef41Sopenharmony_ci  // \r\n should emit one line event when split across multiple writes.
12901cb0ef41Sopenharmony_ci  {
12911cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal, crlfDelay });
12921cb0ef41Sopenharmony_ci    const expectedLines = ['foo', 'bar', 'baz', 'bat'];
12931cb0ef41Sopenharmony_ci    let callCount = 0;
12941cb0ef41Sopenharmony_ci    rli.on('line', common.mustCall((line) => {
12951cb0ef41Sopenharmony_ci      assert.strictEqual(line, expectedLines[callCount]);
12961cb0ef41Sopenharmony_ci      callCount++;
12971cb0ef41Sopenharmony_ci    }, expectedLines.length));
12981cb0ef41Sopenharmony_ci    expectedLines.forEach((line) => {
12991cb0ef41Sopenharmony_ci      fi.emit('data', `${line}\r`);
13001cb0ef41Sopenharmony_ci      fi.emit('data', '\n');
13011cb0ef41Sopenharmony_ci    });
13021cb0ef41Sopenharmony_ci    rli.close();
13031cb0ef41Sopenharmony_ci  }
13041cb0ef41Sopenharmony_ci
13051cb0ef41Sopenharmony_ci  // Emit one line event when the delay between \r and \n is
13061cb0ef41Sopenharmony_ci  // over the default crlfDelay but within the setting value.
13071cb0ef41Sopenharmony_ci  {
13081cb0ef41Sopenharmony_ci    const delay = 125;
13091cb0ef41Sopenharmony_ci    const [rli, fi] = getInterface({ terminal, crlfDelay });
13101cb0ef41Sopenharmony_ci    let callCount = 0;
13111cb0ef41Sopenharmony_ci    rli.on('line', () => callCount++);
13121cb0ef41Sopenharmony_ci    fi.emit('data', '\r');
13131cb0ef41Sopenharmony_ci    setTimeout(common.mustCall(() => {
13141cb0ef41Sopenharmony_ci      fi.emit('data', '\n');
13151cb0ef41Sopenharmony_ci      assert.strictEqual(callCount, 1);
13161cb0ef41Sopenharmony_ci      rli.close();
13171cb0ef41Sopenharmony_ci    }), delay);
13181cb0ef41Sopenharmony_ci  }
13191cb0ef41Sopenharmony_ci});
13201cb0ef41Sopenharmony_ci
13211cb0ef41Sopenharmony_ci// Ensure that the _wordLeft method works even for large input
13221cb0ef41Sopenharmony_ci{
13231cb0ef41Sopenharmony_ci  const input = new Readable({
13241cb0ef41Sopenharmony_ci    read() {
13251cb0ef41Sopenharmony_ci      this.push('\x1B[1;5D'); // CTRL + Left
13261cb0ef41Sopenharmony_ci      this.push(null);
13271cb0ef41Sopenharmony_ci    },
13281cb0ef41Sopenharmony_ci  });
13291cb0ef41Sopenharmony_ci  const output = new Writable({
13301cb0ef41Sopenharmony_ci    write: common.mustCall((data, encoding, cb) => {
13311cb0ef41Sopenharmony_ci      assert.strictEqual(rl.cursor, rl.line.length - 1);
13321cb0ef41Sopenharmony_ci      cb();
13331cb0ef41Sopenharmony_ci    }),
13341cb0ef41Sopenharmony_ci  });
13351cb0ef41Sopenharmony_ci  const rl = new readline.createInterface({
13361cb0ef41Sopenharmony_ci    input,
13371cb0ef41Sopenharmony_ci    output,
13381cb0ef41Sopenharmony_ci    terminal: true,
13391cb0ef41Sopenharmony_ci  });
13401cb0ef41Sopenharmony_ci  rl.line = `a${' '.repeat(1e6)}a`;
13411cb0ef41Sopenharmony_ci  rl.cursor = rl.line.length;
13421cb0ef41Sopenharmony_ci}
13431cb0ef41Sopenharmony_ci
13441cb0ef41Sopenharmony_ci{
13451cb0ef41Sopenharmony_ci  const fi = new FakeInput();
13461cb0ef41Sopenharmony_ci  const signal = AbortSignal.abort();
13471cb0ef41Sopenharmony_ci
13481cb0ef41Sopenharmony_ci  const rl = readline.createInterface({
13491cb0ef41Sopenharmony_ci    input: fi,
13501cb0ef41Sopenharmony_ci    output: fi,
13511cb0ef41Sopenharmony_ci    signal,
13521cb0ef41Sopenharmony_ci  });
13531cb0ef41Sopenharmony_ci  rl.on('close', common.mustCall());
13541cb0ef41Sopenharmony_ci  assert.strictEqual(getEventListeners(signal, 'abort').length, 0);
13551cb0ef41Sopenharmony_ci}
13561cb0ef41Sopenharmony_ci
13571cb0ef41Sopenharmony_ci{
13581cb0ef41Sopenharmony_ci  const fi = new FakeInput();
13591cb0ef41Sopenharmony_ci  const ac = new AbortController();
13601cb0ef41Sopenharmony_ci  const { signal } = ac;
13611cb0ef41Sopenharmony_ci  const rl = readline.createInterface({
13621cb0ef41Sopenharmony_ci    input: fi,
13631cb0ef41Sopenharmony_ci    output: fi,
13641cb0ef41Sopenharmony_ci    signal,
13651cb0ef41Sopenharmony_ci  });
13661cb0ef41Sopenharmony_ci  assert.strictEqual(getEventListeners(signal, 'abort').length, 1);
13671cb0ef41Sopenharmony_ci  rl.on('close', common.mustCall());
13681cb0ef41Sopenharmony_ci  ac.abort();
13691cb0ef41Sopenharmony_ci  assert.strictEqual(getEventListeners(signal, 'abort').length, 0);
13701cb0ef41Sopenharmony_ci}
13711cb0ef41Sopenharmony_ci
13721cb0ef41Sopenharmony_ci{
13731cb0ef41Sopenharmony_ci  const fi = new FakeInput();
13741cb0ef41Sopenharmony_ci  const ac = new AbortController();
13751cb0ef41Sopenharmony_ci  const { signal } = ac;
13761cb0ef41Sopenharmony_ci  const rl = readline.createInterface({
13771cb0ef41Sopenharmony_ci    input: fi,
13781cb0ef41Sopenharmony_ci    output: fi,
13791cb0ef41Sopenharmony_ci    signal,
13801cb0ef41Sopenharmony_ci  });
13811cb0ef41Sopenharmony_ci  assert.strictEqual(getEventListeners(signal, 'abort').length, 1);
13821cb0ef41Sopenharmony_ci  rl.close();
13831cb0ef41Sopenharmony_ci  assert.strictEqual(getEventListeners(signal, 'abort').length, 0);
13841cb0ef41Sopenharmony_ci}
13851cb0ef41Sopenharmony_ci
13861cb0ef41Sopenharmony_ci{
13871cb0ef41Sopenharmony_ci  // Constructor throws if signal is not an abort signal
13881cb0ef41Sopenharmony_ci  assert.throws(() => {
13891cb0ef41Sopenharmony_ci    readline.createInterface({
13901cb0ef41Sopenharmony_ci      input: new FakeInput(),
13911cb0ef41Sopenharmony_ci      signal: {},
13921cb0ef41Sopenharmony_ci    });
13931cb0ef41Sopenharmony_ci  }, {
13941cb0ef41Sopenharmony_ci    name: 'TypeError',
13951cb0ef41Sopenharmony_ci    code: 'ERR_INVALID_ARG_TYPE'
13961cb0ef41Sopenharmony_ci  });
13971cb0ef41Sopenharmony_ci}
1398