• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Flags: --expose-internals
2'use strict';
3
4const common = require('../common');
5const assert = require('assert');
6const readline = require('readline');
7const { Writable } = require('stream');
8const { CSI } = require('internal/readline/utils');
9
10{
11  assert(CSI);
12  assert.strictEqual(CSI.kClearToLineBeginning, '\x1b[1K');
13  assert.strictEqual(CSI.kClearToLineEnd, '\x1b[0K');
14  assert.strictEqual(CSI.kClearLine, '\x1b[2K');
15  assert.strictEqual(CSI.kClearScreenDown, '\x1b[0J');
16  assert.strictEqual(CSI`1${2}3`, '\x1b[123');
17}
18
19class TestWritable extends Writable {
20  constructor() {
21    super();
22    this.data = '';
23  }
24  _write(chunk, encoding, callback) {
25    this.data += chunk.toString();
26    callback();
27  }
28}
29
30const writable = new TestWritable();
31
32assert.strictEqual(readline.clearScreenDown(writable), true);
33assert.deepStrictEqual(writable.data, CSI.kClearScreenDown);
34assert.strictEqual(readline.clearScreenDown(writable, common.mustCall()), true);
35
36// Verify that clearScreenDown() throws on invalid callback.
37assert.throws(() => {
38  readline.clearScreenDown(writable, null);
39}, /ERR_INVALID_ARG_TYPE/);
40
41// Verify that clearScreenDown() does not throw on null or undefined stream.
42assert.strictEqual(readline.clearScreenDown(null, common.mustCall((err) => {
43  assert.strictEqual(err, null);
44})), true);
45assert.strictEqual(readline.clearScreenDown(undefined, common.mustCall()),
46                   true);
47
48writable.data = '';
49assert.strictEqual(readline.clearLine(writable, -1), true);
50assert.deepStrictEqual(writable.data, CSI.kClearToLineBeginning);
51
52writable.data = '';
53assert.strictEqual(readline.clearLine(writable, 1), true);
54assert.deepStrictEqual(writable.data, CSI.kClearToLineEnd);
55
56writable.data = '';
57assert.strictEqual(readline.clearLine(writable, 0), true);
58assert.deepStrictEqual(writable.data, CSI.kClearLine);
59
60writable.data = '';
61assert.strictEqual(readline.clearLine(writable, -1, common.mustCall()), true);
62assert.deepStrictEqual(writable.data, CSI.kClearToLineBeginning);
63
64// Verify that clearLine() throws on invalid callback.
65assert.throws(() => {
66  readline.clearLine(writable, 0, null);
67}, /ERR_INVALID_ARG_TYPE/);
68
69// Verify that clearLine() does not throw on null or undefined stream.
70assert.strictEqual(readline.clearLine(null, 0), true);
71assert.strictEqual(readline.clearLine(undefined, 0), true);
72assert.strictEqual(readline.clearLine(null, 0, common.mustCall((err) => {
73  assert.strictEqual(err, null);
74})), true);
75assert.strictEqual(readline.clearLine(undefined, 0, common.mustCall()), true);
76
77// Nothing is written when moveCursor 0, 0
78[
79  [0, 0, ''],
80  [1, 0, '\x1b[1C'],
81  [-1, 0, '\x1b[1D'],
82  [0, 1, '\x1b[1B'],
83  [0, -1, '\x1b[1A'],
84  [1, 1, '\x1b[1C\x1b[1B'],
85  [-1, 1, '\x1b[1D\x1b[1B'],
86  [-1, -1, '\x1b[1D\x1b[1A'],
87  [1, -1, '\x1b[1C\x1b[1A'],
88].forEach((set) => {
89  writable.data = '';
90  assert.strictEqual(readline.moveCursor(writable, set[0], set[1]), true);
91  assert.deepStrictEqual(writable.data, set[2]);
92  writable.data = '';
93  assert.strictEqual(
94    readline.moveCursor(writable, set[0], set[1], common.mustCall()),
95    true
96  );
97  assert.deepStrictEqual(writable.data, set[2]);
98});
99
100// Verify that moveCursor() throws on invalid callback.
101assert.throws(() => {
102  readline.moveCursor(writable, 1, 1, null);
103}, /ERR_INVALID_ARG_TYPE/);
104
105// Verify that moveCursor() does not throw on null or undefined stream.
106assert.strictEqual(readline.moveCursor(null, 1, 1), true);
107assert.strictEqual(readline.moveCursor(undefined, 1, 1), true);
108assert.strictEqual(readline.moveCursor(null, 1, 1, common.mustCall((err) => {
109  assert.strictEqual(err, null);
110})), true);
111assert.strictEqual(readline.moveCursor(undefined, 1, 1, common.mustCall()),
112                   true);
113
114// Undefined or null as stream should not throw.
115assert.strictEqual(readline.cursorTo(null), true);
116assert.strictEqual(readline.cursorTo(), true);
117assert.strictEqual(readline.cursorTo(null, 1, 1, common.mustCall()), true);
118assert.strictEqual(readline.cursorTo(undefined, 1, 1, common.mustCall((err) => {
119  assert.strictEqual(err, null);
120})), true);
121
122writable.data = '';
123assert.strictEqual(readline.cursorTo(writable, 'a'), true);
124assert.strictEqual(writable.data, '');
125
126writable.data = '';
127assert.strictEqual(readline.cursorTo(writable, 'a', 'b'), true);
128assert.strictEqual(writable.data, '');
129
130writable.data = '';
131assert.throws(
132  () => readline.cursorTo(writable, 'a', 1),
133  {
134    name: 'TypeError',
135    code: 'ERR_INVALID_CURSOR_POS',
136    message: 'Cannot set cursor row without setting its column'
137  });
138assert.strictEqual(writable.data, '');
139
140writable.data = '';
141assert.strictEqual(readline.cursorTo(writable, 1, 'a'), true);
142assert.strictEqual(writable.data, '\x1b[2G');
143
144writable.data = '';
145assert.strictEqual(readline.cursorTo(writable, 1), true);
146assert.strictEqual(writable.data, '\x1b[2G');
147
148writable.data = '';
149assert.strictEqual(readline.cursorTo(writable, 1, 2), true);
150assert.strictEqual(writable.data, '\x1b[3;2H');
151
152writable.data = '';
153assert.strictEqual(readline.cursorTo(writable, 1, 2, common.mustCall()), true);
154assert.strictEqual(writable.data, '\x1b[3;2H');
155
156writable.data = '';
157assert.strictEqual(readline.cursorTo(writable, 1, common.mustCall()), true);
158assert.strictEqual(writable.data, '\x1b[2G');
159
160// Verify that cursorTo() throws on invalid callback.
161assert.throws(() => {
162  readline.cursorTo(writable, 1, 1, null);
163}, /ERR_INVALID_ARG_TYPE/);
164
165// Verify that cursorTo() throws if x or y is NaN.
166assert.throws(() => {
167  readline.cursorTo(writable, NaN);
168}, /ERR_INVALID_ARG_VALUE/);
169
170assert.throws(() => {
171  readline.cursorTo(writable, 1, NaN);
172}, /ERR_INVALID_ARG_VALUE/);
173
174assert.throws(() => {
175  readline.cursorTo(writable, NaN, NaN);
176}, /ERR_INVALID_ARG_VALUE/);
177