946 lines
37 KiB
TypeScript
946 lines
37 KiB
TypeScript
/**
|
|
* Copyright (c) 2016 The xterm.js authors. All rights reserved.
|
|
* @license MIT
|
|
*/
|
|
|
|
import { assert, expect } from 'chai';
|
|
import { Terminal } from './Terminal';
|
|
import { MockViewport, MockCompositionHelper, MockRenderer } from './utils/TestUtils.test';
|
|
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX } from './Buffer';
|
|
|
|
const INIT_COLS = 80;
|
|
const INIT_ROWS = 24;
|
|
|
|
class TestTerminal extends Terminal {
|
|
public keyDown(ev: any): boolean { return this._keyDown(ev); }
|
|
public keyPress(ev: any): boolean { return this._keyPress(ev); }
|
|
}
|
|
|
|
describe('term.js addons', () => {
|
|
let term: TestTerminal;
|
|
const termOptions = {
|
|
cols: INIT_COLS,
|
|
rows: INIT_ROWS
|
|
};
|
|
|
|
beforeEach(() => {
|
|
term = new TestTerminal(termOptions);
|
|
term.refresh = () => {};
|
|
(<any>term).renderer = new MockRenderer();
|
|
term.viewport = new MockViewport();
|
|
(<any>term)._compositionHelper = new MockCompositionHelper();
|
|
// Force synchronous writes
|
|
term.write = (data) => {
|
|
term.writeBuffer.push(data);
|
|
(<any>term)._innerWrite();
|
|
};
|
|
(<any>term).element = {
|
|
classList: {
|
|
toggle: () => {},
|
|
remove: () => {}
|
|
}
|
|
};
|
|
});
|
|
|
|
it('should not mutate the options parameter', () => {
|
|
term.setOption('cols', 1000);
|
|
|
|
assert.deepEqual(termOptions, {
|
|
cols: INIT_COLS,
|
|
rows: INIT_ROWS
|
|
});
|
|
});
|
|
|
|
describe('getOption', () => {
|
|
it('should retrieve the option correctly', () => {
|
|
// In the `options` namespace.
|
|
term.options.cursorBlink = true;
|
|
assert.equal(term.getOption('cursorBlink'), true);
|
|
|
|
// On the Terminal instance
|
|
delete term.options.cursorBlink;
|
|
term.options.cursorBlink = false;
|
|
assert.equal(term.getOption('cursorBlink'), false);
|
|
});
|
|
it('should throw when retrieving a non-existant option', () => {
|
|
assert.throws(term.getOption.bind(term, 'fake', true));
|
|
});
|
|
});
|
|
|
|
describe('attachCustomKeyEventHandler', () => {
|
|
const evKeyDown = <KeyboardEvent>{
|
|
preventDefault: () => {},
|
|
stopPropagation: () => {},
|
|
type: 'keydown',
|
|
keyCode: 77
|
|
};
|
|
const evKeyPress = <KeyboardEvent>{
|
|
preventDefault: () => {},
|
|
stopPropagation: () => {},
|
|
type: 'keypress',
|
|
keyCode: 77
|
|
};
|
|
|
|
beforeEach(() => {
|
|
term.handler = () => {};
|
|
term.showCursor = () => {};
|
|
term.clearSelection = () => {};
|
|
});
|
|
|
|
it('should process the keydown/keypress event based on what the handler returns', () => {
|
|
assert.equal(term.keyDown(evKeyDown), true);
|
|
assert.equal(term.keyPress(evKeyPress), true);
|
|
term.attachCustomKeyEventHandler(ev => ev.keyCode === 77);
|
|
assert.equal(term.keyDown(evKeyDown), true);
|
|
assert.equal(term.keyPress(evKeyPress), true);
|
|
term.attachCustomKeyEventHandler(ev => ev.keyCode !== 77);
|
|
assert.equal(term.keyDown(evKeyDown), false);
|
|
assert.equal(term.keyPress(evKeyPress), false);
|
|
});
|
|
|
|
it('should alive after reset(ESC c Full Reset (RIS))', () => {
|
|
term.attachCustomKeyEventHandler(ev => ev.keyCode !== 77);
|
|
assert.equal(term.keyDown(evKeyDown), false);
|
|
assert.equal(term.keyPress(evKeyPress), false);
|
|
term.reset();
|
|
assert.equal(term.keyDown(evKeyDown), false);
|
|
assert.equal(term.keyPress(evKeyPress), false);
|
|
});
|
|
});
|
|
|
|
describe('setOption', () => {
|
|
it('should set the option correctly', () => {
|
|
term.setOption('cursorBlink', true);
|
|
assert.equal(term.options.cursorBlink, true);
|
|
term.setOption('cursorBlink', false);
|
|
assert.equal(term.options.cursorBlink, false);
|
|
});
|
|
it('should throw when setting a non-existant option', () => {
|
|
assert.throws(term.setOption.bind(term, 'fake', true));
|
|
});
|
|
});
|
|
|
|
describe('clear', () => {
|
|
it('should clear a buffer equal to rows', () => {
|
|
const promptLine = term.buffer.lines.get(term.buffer.ybase + term.buffer.y);
|
|
term.clear();
|
|
assert.equal(term.buffer.y, 0);
|
|
assert.equal(term.buffer.ybase, 0);
|
|
assert.equal(term.buffer.ydisp, 0);
|
|
assert.equal(term.buffer.lines.length, term.rows);
|
|
assert.deepEqual(term.buffer.lines.get(0), promptLine);
|
|
for (let i = 1; i < term.rows; i++) {
|
|
assert.deepEqual(term.buffer.lines.get(i), term.blankLine());
|
|
}
|
|
});
|
|
it('should clear a buffer larger than rows', () => {
|
|
// Fill the buffer with dummy rows
|
|
for (let i = 0; i < term.rows * 2; i++) {
|
|
term.write('test\n');
|
|
}
|
|
|
|
const promptLine = term.buffer.lines.get(term.buffer.ybase + term.buffer.y);
|
|
term.clear();
|
|
assert.equal(term.buffer.y, 0);
|
|
assert.equal(term.buffer.ybase, 0);
|
|
assert.equal(term.buffer.ydisp, 0);
|
|
assert.equal(term.buffer.lines.length, term.rows);
|
|
assert.deepEqual(term.buffer.lines.get(0), promptLine);
|
|
for (let i = 1; i < term.rows; i++) {
|
|
assert.deepEqual(term.buffer.lines.get(i), term.blankLine());
|
|
}
|
|
});
|
|
it('should not break the prompt when cleared twice', () => {
|
|
const promptLine = term.buffer.lines.get(term.buffer.ybase + term.buffer.y);
|
|
term.clear();
|
|
term.clear();
|
|
assert.equal(term.buffer.y, 0);
|
|
assert.equal(term.buffer.ybase, 0);
|
|
assert.equal(term.buffer.ydisp, 0);
|
|
assert.equal(term.buffer.lines.length, term.rows);
|
|
assert.deepEqual(term.buffer.lines.get(0), promptLine);
|
|
for (let i = 1; i < term.rows; i++) {
|
|
assert.deepEqual(term.buffer.lines.get(i), term.blankLine());
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('scroll', () => {
|
|
describe('scrollLines', () => {
|
|
let startYDisp: number;
|
|
beforeEach(() => {
|
|
for (let i = 0; i < term.rows * 2; i++) {
|
|
term.writeln('test');
|
|
}
|
|
startYDisp = term.rows + 1;
|
|
});
|
|
it('should scroll a single line', () => {
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
term.scrollLines(-1);
|
|
assert.equal(term.buffer.ydisp, startYDisp - 1);
|
|
term.scrollLines(1);
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
});
|
|
it('should scroll multiple lines', () => {
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
term.scrollLines(-5);
|
|
assert.equal(term.buffer.ydisp, startYDisp - 5);
|
|
term.scrollLines(5);
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
});
|
|
it('should not scroll beyond the bounds of the buffer', () => {
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
term.scrollLines(1);
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
for (let i = 0; i < startYDisp; i++) {
|
|
term.scrollLines(-1);
|
|
}
|
|
assert.equal(term.buffer.ydisp, 0);
|
|
term.scrollLines(-1);
|
|
assert.equal(term.buffer.ydisp, 0);
|
|
});
|
|
});
|
|
|
|
describe('scrollPages', () => {
|
|
let startYDisp: number;
|
|
beforeEach(() => {
|
|
for (let i = 0; i < term.rows * 3; i++) {
|
|
term.writeln('test');
|
|
}
|
|
startYDisp = (term.rows * 2) + 1;
|
|
});
|
|
it('should scroll a single page', () => {
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
term.scrollPages(-1);
|
|
assert.equal(term.buffer.ydisp, startYDisp - (term.rows - 1));
|
|
term.scrollPages(1);
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
});
|
|
it('should scroll a multiple pages', () => {
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
term.scrollPages(-2);
|
|
assert.equal(term.buffer.ydisp, startYDisp - (term.rows - 1) * 2);
|
|
term.scrollPages(2);
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
});
|
|
});
|
|
|
|
describe('scrollToTop', () => {
|
|
beforeEach(() => {
|
|
for (let i = 0; i < term.rows * 3; i++) {
|
|
term.writeln('test');
|
|
}
|
|
});
|
|
it('should scroll to the top', () => {
|
|
assert.notEqual(term.buffer.ydisp, 0);
|
|
term.scrollToTop();
|
|
assert.equal(term.buffer.ydisp, 0);
|
|
});
|
|
});
|
|
|
|
describe('scrollToBottom', () => {
|
|
let startYDisp: number;
|
|
beforeEach(() => {
|
|
for (let i = 0; i < term.rows * 3; i++) {
|
|
term.writeln('test');
|
|
}
|
|
startYDisp = (term.rows * 2) + 1;
|
|
});
|
|
it('should scroll to the bottom', () => {
|
|
term.scrollLines(-1);
|
|
term.scrollToBottom();
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
term.scrollPages(-1);
|
|
term.scrollToBottom();
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
term.scrollToTop();
|
|
term.scrollToBottom();
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
});
|
|
});
|
|
|
|
describe('scrollToLine', () => {
|
|
let startYDisp: number;
|
|
beforeEach(() => {
|
|
for (let i = 0; i < term.rows * 3; i++) {
|
|
term.writeln('test');
|
|
}
|
|
startYDisp = (term.rows * 2) + 1;
|
|
});
|
|
it('should scroll to requested line', () => {
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
term.scrollToLine(0);
|
|
assert.equal(term.buffer.ydisp, 0);
|
|
term.scrollToLine(10);
|
|
assert.equal(term.buffer.ydisp, 10);
|
|
term.scrollToLine(startYDisp);
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
term.scrollToLine(20);
|
|
assert.equal(term.buffer.ydisp, 20);
|
|
});
|
|
it('should not scroll beyond boundary lines', () => {
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
term.scrollToLine(-1);
|
|
assert.equal(term.buffer.ydisp, 0);
|
|
term.scrollToLine(startYDisp + 1);
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
});
|
|
});
|
|
|
|
describe('keyPress', () => {
|
|
it('should scroll down, when a key is pressed and terminal is scrolled up', () => {
|
|
const event = <KeyboardEvent>{
|
|
type: 'keydown',
|
|
key: 'a',
|
|
keyCode: 65,
|
|
preventDefault: () => {},
|
|
stopPropagation: () => {}
|
|
};
|
|
|
|
term.buffer.ydisp = 0;
|
|
term.buffer.ybase = 40;
|
|
term.keyPress(event);
|
|
|
|
// Ensure that now the terminal is scrolled to bottom
|
|
assert.equal(term.buffer.ydisp, term.buffer.ybase);
|
|
});
|
|
|
|
it('should not scroll down, when a custom keydown handler prevents the event', () => {
|
|
// Add some output to the terminal
|
|
for (let i = 0; i < term.rows * 3; i++) {
|
|
term.writeln('test');
|
|
}
|
|
const startYDisp = (term.rows * 2) + 1;
|
|
term.attachCustomKeyEventHandler(() => {
|
|
return false;
|
|
});
|
|
|
|
assert.equal(term.buffer.ydisp, startYDisp);
|
|
term.scrollLines(-1);
|
|
assert.equal(term.buffer.ydisp, startYDisp - 1);
|
|
term.keyPress(<KeyboardEvent>{ keyCode: 0 });
|
|
assert.equal(term.buffer.ydisp, startYDisp - 1);
|
|
});
|
|
});
|
|
|
|
describe('scroll() function', () => {
|
|
describe('when scrollback > 0', () => {
|
|
it('should create a new line and scroll', () => {
|
|
term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a';
|
|
term.buffer.lines.get(INIT_ROWS - 1)[0][CHAR_DATA_CHAR_INDEX] = 'b';
|
|
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
|
|
term.scroll();
|
|
assert.equal(term.buffer.lines.length, INIT_ROWS + 1);
|
|
assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'a');
|
|
assert.equal(term.buffer.lines.get(INIT_ROWS - 1)[0][CHAR_DATA_CHAR_INDEX], 'b');
|
|
assert.equal(term.buffer.lines.get(INIT_ROWS)[0][CHAR_DATA_CHAR_INDEX], ' ');
|
|
});
|
|
|
|
it('should properly scroll inside a scroll region (scrollTop set)', () => {
|
|
term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a';
|
|
term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b';
|
|
term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX] = 'c';
|
|
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
|
|
term.buffer.scrollTop = 1;
|
|
term.scroll();
|
|
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
|
assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'a');
|
|
assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], 'c');
|
|
});
|
|
|
|
it('should properly scroll inside a scroll region (scrollBottom set)', () => {
|
|
term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a';
|
|
term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b';
|
|
term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX] = 'c';
|
|
term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX] = 'd';
|
|
term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX] = 'e';
|
|
term.buffer.y = 3;
|
|
term.buffer.scrollBottom = 3;
|
|
term.scroll();
|
|
assert.equal(term.buffer.lines.length, INIT_ROWS + 1);
|
|
assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'a', '\'a\' should be pushed to the scrollback');
|
|
assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], 'b');
|
|
assert.equal(term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX], 'c');
|
|
assert.equal(term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX], 'd');
|
|
assert.equal(term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX], ' ', 'a blank line should be added at scrollBottom\'s index');
|
|
assert.equal(term.buffer.lines.get(5)[0][CHAR_DATA_CHAR_INDEX], 'e');
|
|
});
|
|
|
|
it('should properly scroll inside a scroll region (scrollTop and scrollBottom set)', () => {
|
|
term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a';
|
|
term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b';
|
|
term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX] = 'c';
|
|
term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX] = 'd';
|
|
term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX] = 'e';
|
|
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
|
|
term.buffer.scrollTop = 1;
|
|
term.buffer.scrollBottom = 3;
|
|
term.scroll();
|
|
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
|
assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'a');
|
|
assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], 'c', '\'b\' should be removed from the buffer');
|
|
assert.equal(term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX], 'd');
|
|
assert.equal(term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX], ' ', 'a blank line should be added at scrollBottom\'s index');
|
|
assert.equal(term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX], 'e');
|
|
});
|
|
});
|
|
|
|
describe('when scrollback === 0', () => {
|
|
beforeEach(() => {
|
|
term.setOption('scrollback', 0);
|
|
assert.equal(term.buffer.lines.maxLength, INIT_ROWS);
|
|
});
|
|
|
|
it('should create a new line and shift everything up', () => {
|
|
term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a';
|
|
term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b';
|
|
term.buffer.lines.get(INIT_ROWS - 1)[0][CHAR_DATA_CHAR_INDEX] = 'c';
|
|
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
|
|
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
|
term.scroll();
|
|
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
|
// 'a' gets pushed out of buffer
|
|
assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'b');
|
|
assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], ' ');
|
|
assert.equal(term.buffer.lines.get(INIT_ROWS - 2)[0][CHAR_DATA_CHAR_INDEX], 'c');
|
|
assert.equal(term.buffer.lines.get(INIT_ROWS - 1)[0][CHAR_DATA_CHAR_INDEX], ' ');
|
|
});
|
|
|
|
it('should properly scroll inside a scroll region (scrollTop set)', () => {
|
|
term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a';
|
|
term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b';
|
|
term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX] = 'c';
|
|
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
|
|
term.buffer.scrollTop = 1;
|
|
term.scroll();
|
|
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
|
assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'a');
|
|
assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], 'c');
|
|
});
|
|
|
|
it('should properly scroll inside a scroll region (scrollBottom set)', () => {
|
|
term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a';
|
|
term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b';
|
|
term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX] = 'c';
|
|
term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX] = 'd';
|
|
term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX] = 'e';
|
|
term.buffer.y = 3;
|
|
term.buffer.scrollBottom = 3;
|
|
term.scroll();
|
|
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
|
assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'b');
|
|
assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], 'c');
|
|
assert.equal(term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX], 'd');
|
|
assert.equal(term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX], ' ', 'a blank line should be added at scrollBottom\'s index');
|
|
assert.equal(term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX], 'e');
|
|
});
|
|
|
|
it('should properly scroll inside a scroll region (scrollTop and scrollBottom set)', () => {
|
|
term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX] = 'a';
|
|
term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX] = 'b';
|
|
term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX] = 'c';
|
|
term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX] = 'd';
|
|
term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX] = 'e';
|
|
term.buffer.y = INIT_ROWS - 1; // Move cursor to last line
|
|
term.buffer.scrollTop = 1;
|
|
term.buffer.scrollBottom = 3;
|
|
term.scroll();
|
|
assert.equal(term.buffer.lines.length, INIT_ROWS);
|
|
assert.equal(term.buffer.lines.get(0)[0][CHAR_DATA_CHAR_INDEX], 'a');
|
|
assert.equal(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX], 'c', '\'b\' should be removed from the buffer');
|
|
assert.equal(term.buffer.lines.get(2)[0][CHAR_DATA_CHAR_INDEX], 'd');
|
|
assert.equal(term.buffer.lines.get(3)[0][CHAR_DATA_CHAR_INDEX], ' ', 'a blank line should be added at scrollBottom\'s index');
|
|
assert.equal(term.buffer.lines.get(4)[0][CHAR_DATA_CHAR_INDEX], 'e');
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('Third level shift', () => {
|
|
let evKeyDown: any;
|
|
let evKeyPress: any;
|
|
|
|
beforeEach(() => {
|
|
term.handler = () => {};
|
|
term.showCursor = () => {};
|
|
term.clearSelection = () => {};
|
|
// term.compositionHelper = {
|
|
// isComposing: false,
|
|
// keydown: {
|
|
// bind: () => {
|
|
// return () => { return true; };
|
|
// }
|
|
// }
|
|
// };
|
|
evKeyDown = {
|
|
preventDefault: () => {},
|
|
stopPropagation: () => {},
|
|
type: 'keydown',
|
|
altKey: null,
|
|
keyCode: null
|
|
};
|
|
evKeyPress = {
|
|
preventDefault: () => {},
|
|
stopPropagation: () => {},
|
|
type: 'keypress',
|
|
altKey: null,
|
|
charCode: null,
|
|
keyCode: null
|
|
};
|
|
});
|
|
|
|
describe('with macOptionIsMeta', () => {
|
|
beforeEach(() => {
|
|
term.browser.isMac = true;
|
|
term.setOption('macOptionIsMeta', true);
|
|
});
|
|
|
|
it('should interfere with the alt key on keyDown', () => {
|
|
evKeyDown.altKey = true;
|
|
evKeyDown.keyCode = 81;
|
|
assert.equal(term.keyDown(evKeyDown), false);
|
|
evKeyDown.altKey = true;
|
|
evKeyDown.keyCode = 192;
|
|
assert.equal(term.keyDown(evKeyDown), false);
|
|
});
|
|
});
|
|
|
|
describe('On Mac OS', () => {
|
|
beforeEach(() => {
|
|
term.browser.isMac = true;
|
|
});
|
|
|
|
it('should not interfere with the alt key on keyDown', () => {
|
|
evKeyDown.altKey = true;
|
|
evKeyDown.keyCode = 81;
|
|
assert.equal(term.keyDown(evKeyDown), true);
|
|
evKeyDown.altKey = true;
|
|
evKeyDown.keyCode = 192;
|
|
assert.equal(term.keyDown(evKeyDown), true);
|
|
});
|
|
|
|
it('should interefere with the alt + arrow keys', () => {
|
|
evKeyDown.altKey = true;
|
|
evKeyDown.keyCode = 37;
|
|
assert.equal(term.keyDown(evKeyDown), false);
|
|
evKeyDown.altKey = true;
|
|
evKeyDown.keyCode = 39;
|
|
assert.equal(term.keyDown(evKeyDown), false);
|
|
});
|
|
|
|
it('should emit key with alt + key on keyPress', (done) => {
|
|
const keys = ['@', '@', '\\', '\\', '|', '|'];
|
|
|
|
term.on('keypress', (key) => {
|
|
if (key) {
|
|
const index = keys.indexOf(key);
|
|
assert(index !== -1, 'Emitted wrong key: ' + key);
|
|
keys.splice(index, 1);
|
|
}
|
|
if (keys.length === 0) done();
|
|
});
|
|
|
|
evKeyPress.altKey = true;
|
|
// @
|
|
evKeyPress.charCode = null;
|
|
evKeyPress.keyCode = 64;
|
|
term.keyPress(evKeyPress);
|
|
// Firefox @
|
|
evKeyPress.charCode = 64;
|
|
evKeyPress.keyCode = 0;
|
|
term.keyPress(evKeyPress);
|
|
// \
|
|
evKeyPress.charCode = null;
|
|
evKeyPress.keyCode = 92;
|
|
term.keyPress(evKeyPress);
|
|
// Firefox \
|
|
evKeyPress.charCode = 92;
|
|
evKeyPress.keyCode = 0;
|
|
term.keyPress(evKeyPress);
|
|
// |
|
|
evKeyPress.charCode = null;
|
|
evKeyPress.keyCode = 124;
|
|
term.keyPress(evKeyPress);
|
|
// Firefox |
|
|
evKeyPress.charCode = 124;
|
|
evKeyPress.keyCode = 0;
|
|
term.keyPress(evKeyPress);
|
|
});
|
|
});
|
|
|
|
describe('On MS Windows', () => {
|
|
beforeEach(() => {
|
|
term.browser.isMSWindows = true;
|
|
});
|
|
|
|
it('should not interfere with the alt + ctrl key on keyDown', () => {
|
|
evKeyPress.altKey = true;
|
|
evKeyPress.ctrlKey = true;
|
|
evKeyPress.keyCode = 81;
|
|
assert.equal(term.keyDown(evKeyPress), true);
|
|
evKeyDown.altKey = true;
|
|
evKeyDown.ctrlKey = true;
|
|
evKeyDown.keyCode = 81;
|
|
assert.equal(term.keyDown(evKeyDown), true);
|
|
});
|
|
|
|
it('should interefere with the alt + ctrl + arrow keys', () => {
|
|
evKeyDown.altKey = true;
|
|
evKeyDown.ctrlKey = true;
|
|
|
|
evKeyDown.keyCode = 37;
|
|
assert.equal(term.keyDown(evKeyDown), false);
|
|
evKeyDown.keyCode = 39;
|
|
assert.equal(term.keyDown(evKeyDown), false);
|
|
});
|
|
|
|
it('should emit key with alt + ctrl + key on keyPress', (done) => {
|
|
const keys = ['@', '@', '\\', '\\', '|', '|'];
|
|
|
|
term.on('keypress', (key) => {
|
|
if (key) {
|
|
const index = keys.indexOf(key);
|
|
assert(index !== -1, 'Emitted wrong key: ' + key);
|
|
keys.splice(index, 1);
|
|
}
|
|
if (keys.length === 0) done();
|
|
});
|
|
|
|
evKeyPress.altKey = true;
|
|
evKeyPress.ctrlKey = true;
|
|
|
|
// @
|
|
evKeyPress.charCode = null;
|
|
evKeyPress.keyCode = 64;
|
|
term.keyPress(evKeyPress);
|
|
// Firefox @
|
|
evKeyPress.charCode = 64;
|
|
evKeyPress.keyCode = 0;
|
|
term.keyPress(evKeyPress);
|
|
// \
|
|
evKeyPress.charCode = null;
|
|
evKeyPress.keyCode = 92;
|
|
term.keyPress(evKeyPress);
|
|
// Firefox \
|
|
evKeyPress.charCode = 92;
|
|
evKeyPress.keyCode = 0;
|
|
term.keyPress(evKeyPress);
|
|
// |
|
|
evKeyPress.charCode = null;
|
|
evKeyPress.keyCode = 124;
|
|
term.keyPress(evKeyPress);
|
|
// Firefox |
|
|
evKeyPress.charCode = 124;
|
|
evKeyPress.keyCode = 0;
|
|
term.keyPress(evKeyPress);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('unicode - surrogates', () => {
|
|
it('2 characters per cell', function (): void {
|
|
this.timeout(10000); // This is needed because istanbul patches code and slows it down
|
|
const high = String.fromCharCode(0xD800);
|
|
for (let i = 0xDC00; i <= 0xDCFF; ++i) {
|
|
term.write(high + String.fromCharCode(i));
|
|
const tchar = term.buffer.lines.get(0)[0];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(high + String.fromCharCode(i));
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1);
|
|
expect(term.buffer.lines.get(0)[1][CHAR_DATA_CHAR_INDEX]).eql(' ');
|
|
term.reset();
|
|
}
|
|
});
|
|
it('2 characters at last cell', () => {
|
|
const high = String.fromCharCode(0xD800);
|
|
for (let i = 0xDC00; i <= 0xDCFF; ++i) {
|
|
term.buffer.x = term.cols - 1;
|
|
term.write(high + String.fromCharCode(i));
|
|
expect(term.buffer.lines.get(0)[term.buffer.x - 1][CHAR_DATA_CHAR_INDEX]).eql(high + String.fromCharCode(i));
|
|
expect(term.buffer.lines.get(0)[term.buffer.x - 1][CHAR_DATA_CHAR_INDEX].length).eql(2);
|
|
expect(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX]).eql(' ');
|
|
term.reset();
|
|
}
|
|
});
|
|
it('2 characters per cell over line end with autowrap', () => {
|
|
const high = String.fromCharCode(0xD800);
|
|
for (let i = 0xDC00; i <= 0xDCFF; ++i) {
|
|
term.buffer.x = term.cols - 1;
|
|
term.wraparoundMode = true;
|
|
term.write('a' + high + String.fromCharCode(i));
|
|
expect(term.buffer.lines.get(0)[term.cols - 1][CHAR_DATA_CHAR_INDEX]).eql('a');
|
|
expect(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX]).eql(high + String.fromCharCode(i));
|
|
expect(term.buffer.lines.get(1)[0][CHAR_DATA_CHAR_INDEX].length).eql(2);
|
|
expect(term.buffer.lines.get(1)[1][CHAR_DATA_CHAR_INDEX]).eql(' ');
|
|
term.reset();
|
|
}
|
|
});
|
|
it('2 characters per cell over line end without autowrap', () => {
|
|
const high = String.fromCharCode(0xD800);
|
|
for (let i = 0xDC00; i <= 0xDCFF; ++i) {
|
|
term.buffer.x = term.cols - 1;
|
|
term.wraparoundMode = false;
|
|
term.write('a' + high + String.fromCharCode(i));
|
|
// auto wraparound mode should cut off the rest of the line
|
|
expect(term.buffer.lines.get(0)[term.cols - 1][CHAR_DATA_CHAR_INDEX]).eql('a');
|
|
expect(term.buffer.lines.get(0)[term.cols - 1][CHAR_DATA_CHAR_INDEX].length).eql(1);
|
|
expect(term.buffer.lines.get(1)[1][CHAR_DATA_CHAR_INDEX]).eql(' ');
|
|
term.reset();
|
|
}
|
|
});
|
|
it('splitted surrogates', () => {
|
|
const high = String.fromCharCode(0xD800);
|
|
for (let i = 0xDC00; i <= 0xDCFF; ++i) {
|
|
term.write(high);
|
|
term.write(String.fromCharCode(i));
|
|
const tchar = term.buffer.lines.get(0)[0];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(high + String.fromCharCode(i));
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1);
|
|
expect(term.buffer.lines.get(0)[1][CHAR_DATA_CHAR_INDEX]).eql(' ');
|
|
term.reset();
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('unicode - combining characters', () => {
|
|
it('café', () => {
|
|
term.write('cafe\u0301');
|
|
expect(term.buffer.lines.get(0)[3][CHAR_DATA_CHAR_INDEX]).eql('e\u0301');
|
|
expect(term.buffer.lines.get(0)[3][CHAR_DATA_CHAR_INDEX].length).eql(2);
|
|
expect(term.buffer.lines.get(0)[3][CHAR_DATA_WIDTH_INDEX]).eql(1);
|
|
});
|
|
it('café - end of line', () => {
|
|
term.buffer.x = term.cols - 1 - 3;
|
|
term.write('cafe\u0301');
|
|
expect(term.buffer.lines.get(0)[term.cols - 1][CHAR_DATA_CHAR_INDEX]).eql('e\u0301');
|
|
expect(term.buffer.lines.get(0)[term.cols - 1][CHAR_DATA_CHAR_INDEX].length).eql(2);
|
|
expect(term.buffer.lines.get(0)[term.cols - 1][CHAR_DATA_WIDTH_INDEX]).eql(1);
|
|
expect(term.buffer.lines.get(0)[1][CHAR_DATA_CHAR_INDEX]).eql(' ');
|
|
expect(term.buffer.lines.get(0)[1][CHAR_DATA_CHAR_INDEX].length).eql(1);
|
|
expect(term.buffer.lines.get(0)[1][CHAR_DATA_WIDTH_INDEX]).eql(1);
|
|
});
|
|
it('multiple combined é', () => {
|
|
term.wraparoundMode = true;
|
|
term.write(Array(100).join('e\u0301'));
|
|
for (let i = 0; i < term.cols; ++i) {
|
|
const tchar = term.buffer.lines.get(0)[i];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('e\u0301');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1);
|
|
}
|
|
const tchar = term.buffer.lines.get(1)[0];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('e\u0301');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1);
|
|
});
|
|
it('multiple surrogate with combined', () => {
|
|
term.wraparoundMode = true;
|
|
term.write(Array(100).join('\uD800\uDC00\u0301'));
|
|
for (let i = 0; i < term.cols; ++i) {
|
|
const tchar = term.buffer.lines.get(0)[i];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('\uD800\uDC00\u0301');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(3);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1);
|
|
}
|
|
const tchar = term.buffer.lines.get(1)[0];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('\uD800\uDC00\u0301');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(3);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1);
|
|
});
|
|
});
|
|
|
|
describe('unicode - fullwidth characters', () => {
|
|
it('cursor movement even', () => {
|
|
expect(term.buffer.x).eql(0);
|
|
term.write('¥');
|
|
expect(term.buffer.x).eql(2);
|
|
});
|
|
it('cursor movement odd', () => {
|
|
term.buffer.x = 1;
|
|
expect(term.buffer.x).eql(1);
|
|
term.write('¥');
|
|
expect(term.buffer.x).eql(3);
|
|
});
|
|
it('line of ¥ even', () => {
|
|
term.wraparoundMode = true;
|
|
term.write(Array(50).join('¥'));
|
|
for (let i = 0; i < term.cols; ++i) {
|
|
const tchar = term.buffer.lines.get(0)[i];
|
|
if (i % 2) {
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(0);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(0);
|
|
} else {
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2);
|
|
}
|
|
}
|
|
const tchar = term.buffer.lines.get(1)[0];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2);
|
|
});
|
|
it('line of ¥ odd', () => {
|
|
term.wraparoundMode = true;
|
|
term.buffer.x = 1;
|
|
term.write(Array(50).join('¥'));
|
|
for (let i = 1; i < term.cols - 1; ++i) {
|
|
const tchar = term.buffer.lines.get(0)[i];
|
|
if (!(i % 2)) {
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(0);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(0);
|
|
} else {
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2);
|
|
}
|
|
}
|
|
let tchar = term.buffer.lines.get(0)[term.cols - 1];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(' ');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1);
|
|
tchar = term.buffer.lines.get(1)[0];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2);
|
|
});
|
|
it('line of ¥ with combining odd', () => {
|
|
term.wraparoundMode = true;
|
|
term.buffer.x = 1;
|
|
term.write(Array(50).join('¥\u0301'));
|
|
for (let i = 1; i < term.cols - 1; ++i) {
|
|
const tchar = term.buffer.lines.get(0)[i];
|
|
if (!(i % 2)) {
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(0);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(0);
|
|
} else {
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥\u0301');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2);
|
|
}
|
|
}
|
|
let tchar = term.buffer.lines.get(0)[term.cols - 1];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(' ');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1);
|
|
tchar = term.buffer.lines.get(1)[0];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥\u0301');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2);
|
|
});
|
|
it('line of ¥ with combining even', () => {
|
|
term.wraparoundMode = true;
|
|
term.write(Array(50).join('¥\u0301'));
|
|
for (let i = 0; i < term.cols; ++i) {
|
|
const tchar = term.buffer.lines.get(0)[i];
|
|
if (i % 2) {
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(0);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(0);
|
|
} else {
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥\u0301');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2);
|
|
}
|
|
}
|
|
const tchar = term.buffer.lines.get(1)[0];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('¥\u0301');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(2);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2);
|
|
});
|
|
it('line of surrogate fullwidth with combining odd', () => {
|
|
term.wraparoundMode = true;
|
|
term.buffer.x = 1;
|
|
term.write(Array(50).join('\ud843\ude6d\u0301'));
|
|
for (let i = 1; i < term.cols - 1; ++i) {
|
|
const tchar = term.buffer.lines.get(0)[i];
|
|
if (!(i % 2)) {
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(0);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(0);
|
|
} else {
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('\ud843\ude6d\u0301');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(3);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2);
|
|
}
|
|
}
|
|
let tchar = term.buffer.lines.get(0)[term.cols - 1];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql(' ');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(1);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(1);
|
|
tchar = term.buffer.lines.get(1)[0];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('\ud843\ude6d\u0301');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(3);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2);
|
|
});
|
|
it('line of surrogate fullwidth with combining even', () => {
|
|
term.wraparoundMode = true;
|
|
term.write(Array(50).join('\ud843\ude6d\u0301'));
|
|
for (let i = 0; i < term.cols; ++i) {
|
|
const tchar = term.buffer.lines.get(0)[i];
|
|
if (i % 2) {
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(0);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(0);
|
|
} else {
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('\ud843\ude6d\u0301');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(3);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2);
|
|
}
|
|
}
|
|
const tchar = term.buffer.lines.get(1)[0];
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX]).eql('\ud843\ude6d\u0301');
|
|
expect(tchar[CHAR_DATA_CHAR_INDEX].length).eql(3);
|
|
expect(tchar[CHAR_DATA_WIDTH_INDEX]).eql(2);
|
|
});
|
|
});
|
|
|
|
describe('insert mode', () => {
|
|
it('halfwidth - all', () => {
|
|
term.write(Array(9).join('0123456789').slice(-80));
|
|
term.buffer.x = 10;
|
|
term.buffer.y = 0;
|
|
term.insertMode = true;
|
|
term.write('abcde');
|
|
expect(term.buffer.lines.get(0).length).eql(term.cols);
|
|
expect(term.buffer.lines.get(0)[10][CHAR_DATA_CHAR_INDEX]).eql('a');
|
|
expect(term.buffer.lines.get(0)[14][CHAR_DATA_CHAR_INDEX]).eql('e');
|
|
expect(term.buffer.lines.get(0)[15][CHAR_DATA_CHAR_INDEX]).eql('0');
|
|
expect(term.buffer.lines.get(0)[79][CHAR_DATA_CHAR_INDEX]).eql('4');
|
|
});
|
|
it('fullwidth - insert', () => {
|
|
term.write(Array(9).join('0123456789').slice(-80));
|
|
term.buffer.x = 10;
|
|
term.buffer.y = 0;
|
|
term.insertMode = true;
|
|
term.write('¥¥¥');
|
|
expect(term.buffer.lines.get(0).length).eql(term.cols);
|
|
expect(term.buffer.lines.get(0)[10][CHAR_DATA_CHAR_INDEX]).eql('¥');
|
|
expect(term.buffer.lines.get(0)[11][CHAR_DATA_CHAR_INDEX]).eql('');
|
|
expect(term.buffer.lines.get(0)[14][CHAR_DATA_CHAR_INDEX]).eql('¥');
|
|
expect(term.buffer.lines.get(0)[15][CHAR_DATA_CHAR_INDEX]).eql('');
|
|
expect(term.buffer.lines.get(0)[79][CHAR_DATA_CHAR_INDEX]).eql('3');
|
|
});
|
|
it('fullwidth - right border', () => {
|
|
term.write(Array(41).join('¥'));
|
|
term.buffer.x = 10;
|
|
term.buffer.y = 0;
|
|
term.insertMode = true;
|
|
term.write('a');
|
|
expect(term.buffer.lines.get(0).length).eql(term.cols);
|
|
expect(term.buffer.lines.get(0)[10][CHAR_DATA_CHAR_INDEX]).eql('a');
|
|
expect(term.buffer.lines.get(0)[11][CHAR_DATA_CHAR_INDEX]).eql('¥');
|
|
expect(term.buffer.lines.get(0)[79][CHAR_DATA_CHAR_INDEX]).eql(' '); // fullwidth char got replaced
|
|
term.write('b');
|
|
expect(term.buffer.lines.get(0).length).eql(term.cols);
|
|
expect(term.buffer.lines.get(0)[11][CHAR_DATA_CHAR_INDEX]).eql('b');
|
|
expect(term.buffer.lines.get(0)[12][CHAR_DATA_CHAR_INDEX]).eql('¥');
|
|
expect(term.buffer.lines.get(0)[79][CHAR_DATA_CHAR_INDEX]).eql(''); // empty cell after fullwidth
|
|
});
|
|
});
|
|
});
|