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