blob: 615e55bad45d1e7edec62d9f4c018a547bc441bc [file] [log] [blame]
// Copyright 2022 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* @fileoverview Tests for terminal_xterm_internal.js
*/
import {Terminal, WebglAddon} from './xterm.js';
import {XtermInternal} from './terminal_xterm_internal.js';
const COLS = 80;
const ROWS = 24;
describe('terminal_xterm_internal.js', function() {
beforeEach(function() {
this.elem = document.createElement('div');
this.elem.style.height = '500px';
this.elem.style.width = '500px';
document.body.appendChild(this.elem);
this.terminal = new Terminal({cols: COLS, rows: ROWS,
allowProposedApi: true});
this.terminal.open(this.elem);
this.terminal.options.fontFamily = '"Noto Sans Mono"';
this.terminal.options.fontSize = 16;
// Load the webgl addon to simulate the real runtime better.
this.terminal.loadAddon(new WebglAddon());
this.xtermInternal = new XtermInternal(this.terminal);
this.write = async (content) => {
return new Promise((resolve) => this.terminal.write(content, resolve));
};
});
afterEach(function() {
this.terminal.dispose();
document.body.removeChild(this.elem);
});
it('addDimensionsObserver() and getActualCellDimensions()', async function() {
const {width, height} = this.xtermInternal.getActualCellDimensions();
assert.isAbove(width, 0);
assert.isAbove(height, 0);
let dimensionsChanged = false;
const promise = new Promise((resolve) => {
this.xtermInternal.addDimensionsObserver(() => {
dimensionsChanged = true;
resolve();
});
});
assert.equal(dimensionsChanged, false);
this.terminal.options.fontSize += 1;
await promise;
const {width: width2, height: height2} =
this.xtermInternal.getActualCellDimensions();
assert.isAbove(width2, width);
assert.isAbove(height2, height);
});
it('print()', async function() {
this.xtermInternal.print('hello world');
assert.equal(this.terminal.buffer.active.getLine(0).translateToString(true),
'hello world');
});
it('newLine()', async function() {
await this.write('012');
const buffer = this.terminal.buffer.active;
assert.equal(buffer.cursorX, 3);
assert.equal(buffer.cursorY, 0);
this.xtermInternal.newLine();
assert.equal(buffer.cursorX, 0);
assert.equal(buffer.cursorY, 1);
});
it('moveCursor()', async function() {
await this.write('012\r\n345');
const buffer = this.terminal.buffer.active;
assert.equal(buffer.cursorX, 3);
assert.equal(buffer.cursorY, 1);
this.xtermInternal.moveCursor(-1, 0);
assert.equal(buffer.cursorX, 2);
assert.equal(buffer.cursorY, 1);
this.xtermInternal.moveCursor(-1, -1);
assert.equal(buffer.cursorX, 1);
assert.equal(buffer.cursorY, 0);
this.xtermInternal.moveCursor(2, 3);
assert.equal(buffer.cursorX, 3);
assert.equal(buffer.cursorY, 3);
});
it('setCursor()', async function() {
const buffer = this.terminal.buffer.active;
assert.equal(buffer.cursorX, 0);
assert.equal(buffer.cursorY, 0);
this.xtermInternal.setCursor(10, 20);
assert.equal(buffer.cursorX, 10);
assert.equal(buffer.cursorY, 20);
});
it('eraseInBufferLine()', async function() {
await this.write('012345');
this.xtermInternal.eraseInBufferLine(0, 2, 4);
assert.equal(this.terminal.buffer.active.getLine(0).translateToString(true),
'01 45');
});
it('installEscKHandler()', async function() {
await this.write('\x1bkhello world\x1b\\');
assert.equal(this.terminal.buffer.active.getLine(0).translateToString(true),
'hello world',
'before installing the handler, the string will be printed');
this.xtermInternal.installEscKHandler();
await this.write('abc\x1bk1234\x1b\\def');
assert.equal(this.terminal.buffer.active.getLine(0).translateToString(true),
'hello worldabcdef',
'after installing the handler, the string should be ignored');
this.xtermInternal.installEscKHandler();
await this.write('ghi\x1bk1234\x1b\\jkl');
assert.equal(this.terminal.buffer.active.getLine(0).translateToString(true),
'hello worldabcdefghijkl',
'installing the handler multiple times should be fine');
});
it('installTmuxControlModeHandler()', async function() {
const tmuxLines = [];
this.xtermInternal.installTmuxControlModeHandler((line) => {
tmuxLines.push(line);
});
for (const input of [
'hello world\x1bP',
'1000phello ',
'tmux\r',
'\nhello',
' again\r\nbye',
]) {
await this.write(input);
}
assert.equal(this.terminal.buffer.active.getLine(0).translateToString(true),
'hello world');
assert.deepEqual(tmuxLines, ['hello tmux', 'hello again']);
tmuxLines.length = 0;
await this.write(' tmux\r\n\x1b\\abcd');
assert.deepEqual(tmuxLines, ['bye tmux', null]);
assert.equal(this.terminal.buffer.active.getLine(0).translateToString(true),
'hello worldabcd');
});
it('enableA11y() and disableA11y()', async function() {
const terminalElement = this.terminal.element;
const pageUpButton = document.createElement('button');
const pageDownButton = document.createElement('button');
this.xtermInternal.enableA11y(pageUpButton, pageDownButton);
// Check the order of a11y elements.
const children = terminalElement.children;
assert.equal(children[0], pageUpButton);
const xtermAccessibility = children[1];
assert.isTrue(xtermAccessibility.classList.contains('xterm-accessibility'));
assert.equal(children[2], pageDownButton);
// The xterm a11y live region should be reallocated to the bottom.
const liveRegionContainer = children[children.length - 1];
const liveRegion = liveRegionContainer.querySelector('[aria-live]');
assert.exists(liveRegion);
// Test that the live region is still working after the re-positioning.
const liveRegionText = new Promise((resolve) => {
const observer = new MutationObserver((mutations, observer) => {
observer.disconnect();
resolve(liveRegion.textContent);
});
observer.observe(liveRegion, {childList: true});
});
this.write('hello world');
assert.equal(await liveRegionText, 'hello world');
this.xtermInternal.disableA11y();
for (const element of [pageUpButton, xtermAccessibility, pageDownButton,
liveRegionContainer]) {
assert.isFalse(element.isConnected);
}
});
it('setScrollbarVisible()', async function() {
assert.isTrue(this.xtermInternal.setScrollbarVisible(true));
assert.isTrue(this.xtermInternal.setScrollbarVisible(false));
});
});