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