]> git.proxmox.com Git - mirror_xterm.js.git/blob - src/test/test.js
Remove logs
[mirror_xterm.js.git] / src / test / test.js
1 var assert = require('chai').assert;
2 var expect = require('chai').expect;
3 var Terminal = require('../xterm');
4
5 describe('xterm.js', function() {
6 var xterm;
7
8 beforeEach(function () {
9 xterm = new Terminal();
10 xterm.refresh = function(){};
11 xterm.viewport = {
12 syncScrollArea: function(){}
13 };
14 xterm.compositionHelper = {
15 keydown: function(){ return true; }
16 };
17 });
18
19 describe('getOption', function() {
20 it('should retrieve the option correctly', function() {
21 // In the `options` namespace.
22 xterm.options.cursorBlink = true;
23 assert.equal(xterm.getOption('cursorBlink'), true);
24
25 // On the Terminal instance
26 delete xterm.options.cursorBlink;
27 xterm.cursorBlink = false;
28 assert.equal(xterm.getOption('cursorBlink'), false);
29 });
30 it('should throw when retrieving a non-existant option', function() {
31 assert.throws(xterm.getOption.bind(xterm, 'fake', true));
32 });
33 });
34
35 describe('setOption', function() {
36 it('should set the option correctly', function() {
37 xterm.setOption('cursorBlink', true);
38 assert.equal(xterm.cursorBlink, true);
39 assert.equal(xterm.options.cursorBlink, true);
40 xterm.setOption('cursorBlink', false);
41 assert.equal(xterm.cursorBlink, false);
42 assert.equal(xterm.options.cursorBlink, false);
43 });
44 it('should throw when setting a non-existant option', function() {
45 assert.throws(xterm.setOption.bind(xterm, 'fake', true));
46 });
47 });
48
49 describe('clear', function() {
50 it('should clear a buffer equal to rows', function() {
51 var promptLine = xterm.lines.get(xterm.ybase + xterm.y);
52 xterm.clear();
53 assert.equal(xterm.y, 0);
54 assert.equal(xterm.ybase, 0);
55 assert.equal(xterm.ydisp, 0);
56 assert.equal(xterm.lines.length, xterm.rows);
57 assert.deepEqual(xterm.lines.get(0), promptLine);
58 for (var i = 1; i < xterm.rows; i++) {
59 assert.deepEqual(xterm.lines.get(i), xterm.blankLine());
60 }
61 });
62 it('should clear a buffer larger than rows', function() {
63 // Fill the buffer with dummy rows
64 for (var i = 0; i < xterm.rows * 2; i++) {
65 xterm.write('test\n');
66 }
67
68 var promptLine = xterm.lines.get(xterm.ybase + xterm.y);
69 xterm.clear();
70 assert.equal(xterm.y, 0);
71 assert.equal(xterm.ybase, 0);
72 assert.equal(xterm.ydisp, 0);
73 assert.equal(xterm.lines.length, xterm.rows);
74 assert.deepEqual(xterm.lines.get(0), promptLine);
75 for (var i = 1; i < xterm.rows; i++) {
76 assert.deepEqual(xterm.lines.get(i), xterm.blankLine());
77 }
78 });
79 it('should not break the prompt when cleared twice', function() {
80 var promptLine = xterm.lines.get(xterm.ybase + xterm.y);
81 xterm.clear();
82 xterm.clear();
83 assert.equal(xterm.y, 0);
84 assert.equal(xterm.ybase, 0);
85 assert.equal(xterm.ydisp, 0);
86 assert.equal(xterm.lines.length, xterm.rows);
87 assert.deepEqual(xterm.lines.get(0), promptLine);
88 for (var i = 1; i < xterm.rows; i++) {
89 assert.deepEqual(xterm.lines.get(i), xterm.blankLine());
90 }
91 });
92 });
93
94 describe('scroll', function() {
95 describe('scrollDisp', function() {
96 var startYDisp;
97 beforeEach(function() {
98 for (var i = 0; i < xterm.rows * 2; i++) {
99 xterm.writeln('test');
100 }
101 startYDisp = xterm.rows + 1;
102 });
103 it('should scroll a single line', function() {
104 assert.equal(xterm.ydisp, startYDisp);
105 xterm.scrollDisp(-1);
106 assert.equal(xterm.ydisp, startYDisp - 1);
107 xterm.scrollDisp(1);
108 assert.equal(xterm.ydisp, startYDisp);
109 });
110 it('should scroll multiple lines', function() {
111 assert.equal(xterm.ydisp, startYDisp);
112 xterm.scrollDisp(-5);
113 assert.equal(xterm.ydisp, startYDisp - 5);
114 xterm.scrollDisp(5);
115 assert.equal(xterm.ydisp, startYDisp);
116 });
117 it('should not scroll beyond the bounds of the buffer', function() {
118 assert.equal(xterm.ydisp, startYDisp);
119 xterm.scrollDisp(1);
120 assert.equal(xterm.ydisp, startYDisp);
121 for (var i = 0; i < startYDisp; i++) {
122 xterm.scrollDisp(-1);
123 }
124 assert.equal(xterm.ydisp, 0);
125 xterm.scrollDisp(-1);
126 assert.equal(xterm.ydisp, 0);
127 });
128 });
129
130 describe('scrollPages', function() {
131 var startYDisp;
132 beforeEach(function() {
133 for (var i = 0; i < xterm.rows * 3; i++) {
134 xterm.writeln('test');
135 }
136 startYDisp = (xterm.rows * 2) + 1;
137 });
138 it('should scroll a single page', function() {
139 assert.equal(xterm.ydisp, startYDisp);
140 xterm.scrollPages(-1);
141 assert.equal(xterm.ydisp, startYDisp - (xterm.rows - 1));
142 xterm.scrollPages(1);
143 assert.equal(xterm.ydisp, startYDisp);
144 });
145 it('should scroll a multiple pages', function() {
146 assert.equal(xterm.ydisp, startYDisp);
147 xterm.scrollPages(-2);
148 assert.equal(xterm.ydisp, startYDisp - (xterm.rows - 1) * 2);
149 xterm.scrollPages(2);
150 assert.equal(xterm.ydisp, startYDisp);
151 });
152 });
153
154 describe('scrollToTop', function() {
155 beforeEach(function() {
156 for (var i = 0; i < xterm.rows * 3; i++) {
157 xterm.writeln('test');
158 }
159 });
160 it('should scroll to the top', function() {
161 assert.notEqual(xterm.ydisp, 0);
162 xterm.scrollToTop();
163 assert.equal(xterm.ydisp, 0);
164 });
165 });
166
167 describe('scrollToBottom', function() {
168 var startYDisp;
169 beforeEach(function() {
170 for (var i = 0; i < xterm.rows * 3; i++) {
171 xterm.writeln('test');
172 }
173 startYDisp = (xterm.rows * 2) + 1;
174 });
175 it('should scroll to the bottom', function() {
176 xterm.scrollDisp(-1);
177 xterm.scrollToBottom();
178 assert.equal(xterm.ydisp, startYDisp);
179 xterm.scrollPages(-1);
180 xterm.scrollToBottom();
181 assert.equal(xterm.ydisp, startYDisp);
182 xterm.scrollToTop();
183 xterm.scrollToBottom();
184 assert.equal(xterm.ydisp, startYDisp);
185 });
186 });
187
188 describe('keyDown', function () {
189 it('should scroll down, when a key is pressed and terminal is scrolled up', function () {
190 // Override evaluateKeyEscapeSequence to return cancel code
191 xterm.evaluateKeyEscapeSequence = function() {
192 return { key: 'a' };
193 };
194 var event = {
195 type: 'keydown',
196 keyCode: 0,
197 preventDefault: function(){},
198 stopPropagation: function(){}
199 };
200
201 xterm.ydisp = 0;
202 xterm.ybase = 40;
203 assert.notEqual(xterm.ydisp, xterm.ybase);
204 xterm.keyDown(event);
205
206 // Ensure that now the terminal is scrolled to bottom
207 assert.equal(xterm.ydisp, xterm.ybase);
208 });
209
210 it('should not scroll down, when a custom keydown handler prevents the event', function () {
211 // Add some output to the terminal
212 for (var i = 0; i < xterm.rows * 3; i++) {
213 xterm.writeln('test');
214 }
215 var startYDisp = (xterm.rows * 2) + 1;
216 xterm.attachCustomKeydownHandler(function () {
217 return false;
218 });
219
220 assert.equal(xterm.ydisp, startYDisp);
221 xterm.scrollDisp(-1);
222 assert.equal(xterm.ydisp, startYDisp - 1);
223 xterm.keyDown({ keyCode: 0 });
224 assert.equal(xterm.ydisp, startYDisp - 1);
225 });
226 });
227 });
228
229 describe('evaluateKeyEscapeSequence', function() {
230 it('should return the correct escape sequence for unmodified keys', function() {
231 // Backspace
232 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 8 }).key, '\x7f'); // ^?
233 // Tab
234 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 9 }).key, '\t');
235 // Return/enter
236 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 13 }).key, '\r'); // CR
237 // Escape
238 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 27 }).key, '\x1b');
239 // Page up, page down
240 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 33 }).key, '\x1b[5~'); // CSI 5 ~
241 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 34 }).key, '\x1b[6~'); // CSI 6 ~
242 // End, Home
243 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 35 }).key, '\x1b[F'); // SS3 F
244 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 36 }).key, '\x1b[H'); // SS3 H
245 // Left, up, right, down arrows
246 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 37 }).key, '\x1b[D'); // CSI D
247 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 38 }).key, '\x1b[A'); // CSI A
248 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 39 }).key, '\x1b[C'); // CSI C
249 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 40 }).key, '\x1b[B'); // CSI B
250 // Insert
251 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 45 }).key, '\x1b[2~'); // CSI 2 ~
252 // Delete
253 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 46 }).key, '\x1b[3~'); // CSI 3 ~
254 // F1-F12
255 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 112 }).key, '\x1bOP'); // SS3 P
256 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 113 }).key, '\x1bOQ'); // SS3 Q
257 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 114 }).key, '\x1bOR'); // SS3 R
258 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 115 }).key, '\x1bOS'); // SS3 S
259 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 116 }).key, '\x1b[15~'); // CSI 1 5 ~
260 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 117 }).key, '\x1b[17~'); // CSI 1 7 ~
261 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 118 }).key, '\x1b[18~'); // CSI 1 8 ~
262 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 119 }).key, '\x1b[19~'); // CSI 1 9 ~
263 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 120 }).key, '\x1b[20~'); // CSI 2 0 ~
264 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 121 }).key, '\x1b[21~'); // CSI 2 1 ~
265 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 122 }).key, '\x1b[23~'); // CSI 2 3 ~
266 assert.equal(xterm.evaluateKeyEscapeSequence({ keyCode: 123 }).key, '\x1b[24~'); // CSI 2 4 ~
267 });
268 it('should return \\x1b[3;5~ for ctrl+delete', function() {
269 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 46 }).key, '\x1b[3;5~');
270 });
271 it('should return \\x1b[3;2~ for shift+delete', function() {
272 assert.equal(xterm.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 46 }).key, '\x1b[3;2~');
273 });
274 it('should return \\x1b[3;3~ for alt+delete', function() {
275 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 46 }).key, '\x1b[3;3~');
276 });
277 it('should return \\x1b[5D for ctrl+left', function() {
278 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 37 }).key, '\x1b[1;5D'); // CSI 5 D
279 });
280 it('should return \\x1b[5C for ctrl+right', function() {
281 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 39 }).key, '\x1b[1;5C'); // CSI 5 C
282 });
283 it('should return \\x1b[5A for ctrl+up', function() {
284 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 38 }).key, '\x1b[1;5A'); // CSI 5 A
285 });
286 it('should return \\x1b[5B for ctrl+down', function() {
287 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 40 }).key, '\x1b[1;5B'); // CSI 5 B
288 });
289
290 describe('On non-macOS platforms', function() {
291 beforeEach(function() {
292 xterm.browser.isMac = false;
293 });
294 // Evalueate alt + arrow key movement, which is a feature of terminal emulators but not VT100
295 // http://unix.stackexchange.com/a/108106
296 it('should return \\x1b[5D for alt+left', function() {
297 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 37 }).key, '\x1b[1;5D'); // CSI 5 D
298 });
299 it('should return \\x1b[5C for alt+right', function() {
300 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 39 }).key, '\x1b[1;5C'); // CSI 5 C
301 });
302 });
303
304 describe('On macOS platforms', function() {
305 beforeEach(function() {
306 xterm.browser.isMac = true;
307 });
308 it('should return \\x1bb for alt+left', function() {
309 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 37 }).key, '\x1bb'); // CSI 5 D
310 });
311 it('should return \\x1bf for alt+right', function() {
312 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 39 }).key, '\x1bf'); // CSI 5 C
313 });
314 });
315
316 it('should return \\x1b[5A for alt+up', function() {
317 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 38 }).key, '\x1b[1;5A'); // CSI 5 A
318 });
319 it('should return \\x1b[5B for alt+down', function() {
320 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 40 }).key, '\x1b[1;5B'); // CSI 5 B
321 });
322 it('should return the correct escape sequence for modified F1-F12 keys', function() {
323 assert.equal(xterm.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 112 }).key, '\x1b[1;2P');
324 assert.equal(xterm.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 113 }).key, '\x1b[1;2Q');
325 assert.equal(xterm.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 114 }).key, '\x1b[1;2R');
326 assert.equal(xterm.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 115 }).key, '\x1b[1;2S');
327 assert.equal(xterm.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 116 }).key, '\x1b[15;2~');
328 assert.equal(xterm.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 117 }).key, '\x1b[17;2~');
329 assert.equal(xterm.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 118 }).key, '\x1b[18;2~');
330 assert.equal(xterm.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 119 }).key, '\x1b[19;2~');
331 assert.equal(xterm.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 120 }).key, '\x1b[20;2~');
332 assert.equal(xterm.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 121 }).key, '\x1b[21;2~');
333 assert.equal(xterm.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 122 }).key, '\x1b[23;2~');
334 assert.equal(xterm.evaluateKeyEscapeSequence({ shiftKey: true, keyCode: 123 }).key, '\x1b[24;2~');
335 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 112 }).key, '\x1b[1;3P');
336 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 113 }).key, '\x1b[1;3Q');
337 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 114 }).key, '\x1b[1;3R');
338 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 115 }).key, '\x1b[1;3S');
339 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 116 }).key, '\x1b[15;3~');
340 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 117 }).key, '\x1b[17;3~');
341 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 118 }).key, '\x1b[18;3~');
342 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 119 }).key, '\x1b[19;3~');
343 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 120 }).key, '\x1b[20;3~');
344 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 121 }).key, '\x1b[21;3~');
345 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 122 }).key, '\x1b[23;3~');
346 assert.equal(xterm.evaluateKeyEscapeSequence({ altKey: true, keyCode: 123 }).key, '\x1b[24;3~');
347
348 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 112 }).key, '\x1b[1;5P');
349 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 113 }).key, '\x1b[1;5Q');
350 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 114 }).key, '\x1b[1;5R');
351 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 115 }).key, '\x1b[1;5S');
352 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 116 }).key, '\x1b[15;5~');
353 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 117 }).key, '\x1b[17;5~');
354 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 118 }).key, '\x1b[18;5~');
355 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 119 }).key, '\x1b[19;5~');
356 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 120 }).key, '\x1b[20;5~');
357 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 121 }).key, '\x1b[21;5~');
358 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 122 }).key, '\x1b[23;5~');
359 assert.equal(xterm.evaluateKeyEscapeSequence({ ctrlKey: true, keyCode: 123 }).key, '\x1b[24;5~');
360 });
361 });
362
363 describe('attachCustomEventHandler', function () {
364 var evKeyDown = {
365 preventDefault: function() {},
366 stopPropagation: function() {},
367 type: 'keydown'
368 }
369
370 beforeEach(function() {
371 xterm.handler = function() {};
372 xterm.showCursor = function() {};
373 xterm.clearSelection = function() {};
374 xterm.compositionHelper = {
375 keydown: {
376 bind: function() {
377 return function () { return true; }
378 }
379 }
380 }
381 });
382
383 it('should process the keydown event based on what the handler returns', function () {
384 assert.equal(xterm.keyDown(Object.assign({}, evKeyDown, { keyCode: 77 })), true);
385 xterm.attachCustomKeydownHandler(function (ev) {
386 return ev.keyCode === 77;
387 });
388 assert.equal(xterm.keyDown(Object.assign({}, evKeyDown, { keyCode: 77 })), true);
389 xterm.attachCustomKeydownHandler(function (ev) {
390 return ev.keyCode !== 77;
391 });
392 assert.equal(xterm.keyDown(Object.assign({}, evKeyDown, { keyCode: 77 })), false);
393 });
394
395 it('should alive after reset(ESC c Full Reset (RIS))', function () {
396 xterm.attachCustomKeydownHandler(function (ev) {
397 return ev.keyCode !== 77;
398 });
399 assert.equal(xterm.keyDown(Object.assign({}, evKeyDown, { keyCode: 77 })), false);
400 xterm.reset();
401 assert.equal(xterm.keyDown(Object.assign({}, evKeyDown, { keyCode: 77 })), false);
402 });
403 });
404
405 describe('Third level shift', function() {
406 var evKeyDown = {
407 preventDefault: function() {},
408 stopPropagation: function() {},
409 type: 'keydown'
410 },
411 evKeyPress = {
412 preventDefault: function() {},
413 stopPropagation: function() {},
414 type: 'keypress'
415 };
416
417 beforeEach(function() {
418 xterm.handler = function() {};
419 xterm.showCursor = function() {};
420 xterm.clearSelection = function() {};
421 xterm.compositionHelper = {
422 isComposing: false,
423 keydown: {
424 bind: function() {
425 return function() { return true; };
426 }
427 }
428 };
429 });
430
431 describe('On Mac OS', function() {
432 beforeEach(function() {
433 xterm.browser.isMac = true;
434 });
435
436 it('should not interfere with the alt key on keyDown', function() {
437 assert.equal(
438 xterm.keyDown(Object.assign({}, evKeyDown, { altKey: true, keyCode: 81 })),
439 true
440 );
441 assert.equal(
442 xterm.keyDown(Object.assign({}, evKeyDown, { altKey: true, keyCode: 192 })),
443 true
444 );
445 });
446
447 it('should interefere with the alt + arrow keys', function() {
448 assert.equal(
449 xterm.keyDown(Object.assign({}, evKeyDown, { altKey: true, keyCode: 37 })),
450 false
451 );
452 assert.equal(
453 xterm.keyDown(Object.assign({}, evKeyDown, { altKey: true, keyCode: 39 })),
454 false
455 );
456 });
457
458 it('should emit key with alt + key on keyPress', function(done) {
459 var keys = ['@', '@', '\\', '\\', '|', '|'];
460
461 xterm.on('keypress', function(key) {
462 if (key) {
463 var index = keys.indexOf(key);
464 assert(index !== -1, "Emitted wrong key: " + key);
465 keys.splice(index, 1);
466 }
467 if (keys.length === 0) done();
468 });
469
470 xterm.keyPress(Object.assign({}, evKeyPress, { altKey: true, keyCode: 64 })); // @
471 // Firefox
472 xterm.keyPress(Object.assign({}, evKeyPress, { altKey: true, charCode: 64, keyCode: 0 }));
473 xterm.keyPress(Object.assign({}, evKeyPress, { altKey: true, keyCode: 92 })); // \
474 xterm.keyPress(Object.assign({}, evKeyPress, { altKey: true, charCode: 92, keyCode: 0 }));
475 xterm.keyPress(Object.assign({}, evKeyPress, { altKey: true, keyCode: 124 })); // |
476 xterm.keyPress(Object.assign({}, evKeyPress, { altKey: true, charCode: 124, keyCode: 0 }));
477 });
478 });
479
480 describe('On MS Windows', function() {
481 beforeEach(function() {
482 xterm.browser.isMSWindows = true;
483 });
484
485 it('should not interfere with the alt + ctrl key on keyDown', function() {
486 assert.equal(
487 xterm.keyDown(Object.assign({}, evKeyDown, { altKey: true, ctrlKey: true, keyCode: 81 })),
488 true
489 );
490 assert.equal(
491 xterm.keyDown(Object.assign({}, evKeyDown, { altKey: true, ctrlKey: true, keyCode: 192 })),
492 true
493 );
494 });
495
496 it('should interefere with the alt + ctrl + arrow keys', function() {
497 assert.equal(
498 xterm.keyDown(Object.assign({}, evKeyDown, { altKey: true, ctrlKey: true, keyCode: 37 })),
499 false
500 );
501 assert.equal(
502 xterm.keyDown(Object.assign({}, evKeyDown, { altKey: true, ctrlKey: true, keyCode: 39 })),
503 false
504 );
505 });
506
507 it('should emit key with alt + ctrl + key on keyPress', function(done) {
508 var keys = ['@', '@', '\\', '\\', '|', '|'];
509
510 xterm.on('keypress', function(key) {
511 if (key) {
512 var index = keys.indexOf(key);
513 assert(index !== -1, "Emitted wrong key: " + key);
514 keys.splice(index, 1);
515 }
516 if (keys.length === 0) done();
517 });
518
519 xterm.keyPress(
520 Object.assign({}, evKeyPress, { altKey: true, ctrlKey: true, keyCode: 64 })
521 ); // @
522 xterm.keyPress(
523 Object.assign({}, evKeyPress, { altKey: true, ctrlKey: true, charCode: 64, keyCode: 0 })
524 );
525 xterm.keyPress(
526 Object.assign({}, evKeyPress, { altKey: true, ctrlKey: true, keyCode: 92 })
527 ); // \
528 xterm.keyPress(
529 Object.assign({}, evKeyPress, { altKey: true, ctrlKey: true, charCode: 92, keyCode: 0 })
530 );
531 xterm.keyPress(
532 Object.assign({}, evKeyPress, { altKey: true, ctrlKey: true, keyCode: 124 })
533 ); // |
534 xterm.keyPress(
535 Object.assign({}, evKeyPress, { altKey: true, ctrlKey: true, charCode: 124, keyCode: 0 })
536 );
537 });
538 });
539 });
540
541 describe('unicode - surrogates', function() {
542 it('2 characters per cell', function () {
543 var high = String.fromCharCode(0xD800);
544 for (var i=0xDC00; i<=0xDCFF; ++i) {
545 xterm.write(high + String.fromCharCode(i));
546 var tchar = xterm.lines.get(0)[0];
547 expect(tchar[1]).eql(high + String.fromCharCode(i));
548 expect(tchar[1].length).eql(2);
549 expect(tchar[2]).eql(1);
550 expect(xterm.lines.get(0)[1][1]).eql(' ');
551 xterm.reset();
552 }
553 });
554 it('2 characters at last cell', function() {
555 var high = String.fromCharCode(0xD800);
556 for (var i=0xDC00; i<=0xDCFF; ++i) {
557 xterm.x = xterm.cols - 1;
558 xterm.write(high + String.fromCharCode(i));
559 expect(xterm.lines.get(0)[xterm.x-1][1]).eql(high + String.fromCharCode(i));
560 expect(xterm.lines.get(0)[xterm.x-1][1].length).eql(2);
561 expect(xterm.lines.get(1)[0][1]).eql(' ');
562 xterm.reset();
563 }
564 });
565 it('2 characters per cell over line end with autowrap', function() {
566 var high = String.fromCharCode(0xD800);
567 for (var i=0xDC00; i<=0xDCFF; ++i) {
568 xterm.x = xterm.cols - 1;
569 xterm.wraparoundMode = true;
570 xterm.write('a' + high + String.fromCharCode(i));
571 expect(xterm.lines.get(0)[xterm.cols-1][1]).eql('a');
572 expect(xterm.lines.get(1)[0][1]).eql(high + String.fromCharCode(i));
573 expect(xterm.lines.get(1)[0][1].length).eql(2);
574 expect(xterm.lines.get(1)[1][1]).eql(' ');
575 xterm.reset();
576 }
577 });
578 it('2 characters per cell over line end without autowrap', function() {
579 var high = String.fromCharCode(0xD800);
580 for (var i=0xDC00; i<=0xDCFF; ++i) {
581 xterm.x = xterm.cols - 1;
582 xterm.wraparoundMode = false;
583 xterm.write('a' + high + String.fromCharCode(i));
584 expect(xterm.lines.get(0)[xterm.cols-1][1]).eql(high + String.fromCharCode(i));
585 expect(xterm.lines.get(0)[xterm.cols-1][1].length).eql(2);
586 expect(xterm.lines.get(1)[1][1]).eql(' ');
587 xterm.reset();
588 }
589 });
590 it('splitted surrogates', function() {
591 var high = String.fromCharCode(0xD800);
592 for (var i=0xDC00; i<=0xDCFF; ++i) {
593 xterm.write(high);
594 xterm.write(String.fromCharCode(i));
595 var tchar = xterm.lines.get(0)[0];
596 expect(tchar[1]).eql(high + String.fromCharCode(i));
597 expect(tchar[1].length).eql(2);
598 expect(tchar[2]).eql(1);
599 expect(xterm.lines.get(0)[1][1]).eql(' ');
600 xterm.reset();
601 }
602 });
603 });
604
605 describe('unicode - combining characters', function() {
606 it('café', function () {
607 xterm.write('cafe\u0301');
608 expect(xterm.lines.get(0)[3][1]).eql('e\u0301');
609 expect(xterm.lines.get(0)[3][1].length).eql(2);
610 expect(xterm.lines.get(0)[3][2]).eql(1);
611 });
612 it('café - end of line', function() {
613 xterm.x = xterm.cols - 1 - 3;
614 xterm.write('cafe\u0301');
615 expect(xterm.lines.get(0)[xterm.cols-1][1]).eql('e\u0301');
616 expect(xterm.lines.get(0)[xterm.cols-1][1].length).eql(2);
617 expect(xterm.lines.get(0)[xterm.cols-1][2]).eql(1);
618 expect(xterm.lines.get(0)[1][1]).eql(' ');
619 expect(xterm.lines.get(0)[1][1].length).eql(1);
620 expect(xterm.lines.get(0)[1][2]).eql(1);
621 });
622 it('multiple combined é', function() {
623 xterm.wraparoundMode = true;
624 xterm.write(Array(100).join('e\u0301'));
625 for (var i=0; i<xterm.cols; ++i) {
626 var tchar = xterm.lines.get(0)[i];
627 expect(tchar[1]).eql('e\u0301');
628 expect(tchar[1].length).eql(2);
629 expect(tchar[2]).eql(1);
630 }
631 tchar = xterm.lines.get(1)[0];
632 expect(tchar[1]).eql('e\u0301');
633 expect(tchar[1].length).eql(2);
634 expect(tchar[2]).eql(1);
635 });
636 it('multiple surrogate with combined', function() {
637 xterm.wraparoundMode = true;
638 xterm.write(Array(100).join('\uD800\uDC00\u0301'));
639 for (var i=0; i<xterm.cols; ++i) {
640 var tchar = xterm.lines.get(0)[i];
641 expect(tchar[1]).eql('\uD800\uDC00\u0301');
642 expect(tchar[1].length).eql(3);
643 expect(tchar[2]).eql(1);
644 }
645 tchar = xterm.lines.get(1)[0];
646 expect(tchar[1]).eql('\uD800\uDC00\u0301');
647 expect(tchar[1].length).eql(3);
648 expect(tchar[2]).eql(1);
649 });
650 });
651
652 describe('unicode - fullwidth characters', function() {
653 it('cursor movement even', function() {
654 expect(xterm.x).eql(0);
655 xterm.write('¥');
656 expect(xterm.x).eql(2);
657 });
658 it('cursor movement odd', function() {
659 xterm.x = 1;
660 expect(xterm.x).eql(1);
661 xterm.write('¥');
662 expect(xterm.x).eql(3);
663 });
664 it('line of ¥ even', function() {
665 xterm.wraparoundMode = true;
666 xterm.write(Array(50).join('¥'));
667 for (var i=0; i<xterm.cols; ++i) {
668 var tchar = xterm.lines.get(0)[i];
669 if (i % 2) {
670 expect(tchar[1]).eql('');
671 expect(tchar[1].length).eql(0);
672 expect(tchar[2]).eql(0);
673 } else {
674 expect(tchar[1]).eql('¥');
675 expect(tchar[1].length).eql(1);
676 expect(tchar[2]).eql(2);
677 }
678 }
679 tchar = xterm.lines.get(1)[0];
680 expect(tchar[1]).eql('¥');
681 expect(tchar[1].length).eql(1);
682 expect(tchar[2]).eql(2);
683 });
684 it('line of ¥ odd', function() {
685 xterm.wraparoundMode = true;
686 xterm.x = 1;
687 xterm.write(Array(50).join('¥'));
688 for (var i=1; i<xterm.cols-1; ++i) {
689 var tchar = xterm.lines.get(0)[i];
690 if (!(i % 2)) {
691 expect(tchar[1]).eql('');
692 expect(tchar[1].length).eql(0);
693 expect(tchar[2]).eql(0);
694 } else {
695 expect(tchar[1]).eql('¥');
696 expect(tchar[1].length).eql(1);
697 expect(tchar[2]).eql(2);
698 }
699 }
700 tchar = xterm.lines.get(0)[xterm.cols-1];
701 expect(tchar[1]).eql(' ');
702 expect(tchar[1].length).eql(1);
703 expect(tchar[2]).eql(1);
704 tchar = xterm.lines.get(1)[0];
705 expect(tchar[1]).eql('¥');
706 expect(tchar[1].length).eql(1);
707 expect(tchar[2]).eql(2);
708 });
709 it('line of ¥ with combining odd', function() {
710 xterm.wraparoundMode = true;
711 xterm.x = 1;
712 xterm.write(Array(50).join('¥\u0301'));
713 for (var i=1; i<xterm.cols-1; ++i) {
714 var tchar = xterm.lines.get(0)[i];
715 if (!(i % 2)) {
716 expect(tchar[1]).eql('');
717 expect(tchar[1].length).eql(0);
718 expect(tchar[2]).eql(0);
719 } else {
720 expect(tchar[1]).eql('¥\u0301');
721 expect(tchar[1].length).eql(2);
722 expect(tchar[2]).eql(2);
723 }
724 }
725 tchar = xterm.lines.get(0)[xterm.cols-1];
726 expect(tchar[1]).eql(' ');
727 expect(tchar[1].length).eql(1);
728 expect(tchar[2]).eql(1);
729 tchar = xterm.lines.get(1)[0];
730 expect(tchar[1]).eql('¥\u0301');
731 expect(tchar[1].length).eql(2);
732 expect(tchar[2]).eql(2);
733 });
734 it('line of ¥ with combining even', function() {
735 xterm.wraparoundMode = true;
736 xterm.write(Array(50).join('¥\u0301'));
737 for (var i=0; i<xterm.cols; ++i) {
738 var tchar = xterm.lines.get(0)[i];
739 if (i % 2) {
740 expect(tchar[1]).eql('');
741 expect(tchar[1].length).eql(0);
742 expect(tchar[2]).eql(0);
743 } else {
744 expect(tchar[1]).eql('¥\u0301');
745 expect(tchar[1].length).eql(2);
746 expect(tchar[2]).eql(2);
747 }
748 }
749 tchar = xterm.lines.get(1)[0];
750 expect(tchar[1]).eql('¥\u0301');
751 expect(tchar[1].length).eql(2);
752 expect(tchar[2]).eql(2);
753 });
754 it('line of surrogate fullwidth with combining odd', function() {
755 xterm.wraparoundMode = true;
756 xterm.x = 1;
757 xterm.write(Array(50).join('\ud843\ude6d\u0301'));
758 for (var i=1; i<xterm.cols-1; ++i) {
759 var tchar = xterm.lines.get(0)[i];
760 if (!(i % 2)) {
761 expect(tchar[1]).eql('');
762 expect(tchar[1].length).eql(0);
763 expect(tchar[2]).eql(0);
764 } else {
765 expect(tchar[1]).eql('\ud843\ude6d\u0301');
766 expect(tchar[1].length).eql(3);
767 expect(tchar[2]).eql(2);
768 }
769 }
770 tchar = xterm.lines.get(0)[xterm.cols-1];
771 expect(tchar[1]).eql(' ');
772 expect(tchar[1].length).eql(1);
773 expect(tchar[2]).eql(1);
774 tchar = xterm.lines.get(1)[0];
775 expect(tchar[1]).eql('\ud843\ude6d\u0301');
776 expect(tchar[1].length).eql(3);
777 expect(tchar[2]).eql(2);
778 });
779 it('line of surrogate fullwidth with combining even', function() {
780 xterm.wraparoundMode = true;
781 xterm.write(Array(50).join('\ud843\ude6d\u0301'));
782 for (var i=0; i<xterm.cols; ++i) {
783 var tchar = xterm.lines.get(0)[i];
784 if (i % 2) {
785 expect(tchar[1]).eql('');
786 expect(tchar[1].length).eql(0);
787 expect(tchar[2]).eql(0);
788 } else {
789 expect(tchar[1]).eql('\ud843\ude6d\u0301');
790 expect(tchar[1].length).eql(3);
791 expect(tchar[2]).eql(2);
792 }
793 }
794 tchar = xterm.lines.get(1)[0];
795 expect(tchar[1]).eql('\ud843\ude6d\u0301');
796 expect(tchar[1].length).eql(3);
797 expect(tchar[2]).eql(2);
798 });
799 });
800
801 describe('insert mode', function() {
802 it('halfwidth - all', function () {
803 xterm.write(Array(9).join('0123456789').slice(-80));
804 xterm.x = 10;
805 xterm.y = 0;
806 xterm.insertMode = true;
807 xterm.write('abcde');
808 expect(xterm.lines.get(0).length).eql(xterm.cols);
809 expect(xterm.lines.get(0)[10][1]).eql('a');
810 expect(xterm.lines.get(0)[14][1]).eql('e');
811 expect(xterm.lines.get(0)[15][1]).eql('0');
812 expect(xterm.lines.get(0)[79][1]).eql('4');
813 });
814 it('fullwidth - insert', function() {
815 xterm.write(Array(9).join('0123456789').slice(-80));
816 xterm.x = 10;
817 xterm.y = 0;
818 xterm.insertMode = true;
819 xterm.write('¥¥¥');
820 expect(xterm.lines.get(0).length).eql(xterm.cols);
821 expect(xterm.lines.get(0)[10][1]).eql('¥');
822 expect(xterm.lines.get(0)[11][1]).eql('');
823 expect(xterm.lines.get(0)[14][1]).eql('¥');
824 expect(xterm.lines.get(0)[15][1]).eql('');
825 expect(xterm.lines.get(0)[79][1]).eql('3');
826 });
827 it('fullwidth - right border', function() {
828 xterm.write(Array(41).join('¥'));
829 xterm.x = 10;
830 xterm.y = 0;
831 xterm.insertMode = true;
832 xterm.write('a');
833 expect(xterm.lines.get(0).length).eql(xterm.cols);
834 expect(xterm.lines.get(0)[10][1]).eql('a');
835 expect(xterm.lines.get(0)[11][1]).eql('¥');
836 expect(xterm.lines.get(0)[79][1]).eql(' '); // fullwidth char got replaced
837 xterm.write('b');
838 expect(xterm.lines.get(0).length).eql(xterm.cols);
839 expect(xterm.lines.get(0)[11][1]).eql('b');
840 expect(xterm.lines.get(0)[12][1]).eql('¥');
841 expect(xterm.lines.get(0)[79][1]).eql(''); // empty cell after fullwidth
842 });
843 });
844 });