diff --git a/src/CharWidth.api.ts b/src/CharWidth.api.ts new file mode 100644 index 00000000..baa8600c --- /dev/null +++ b/src/CharWidth.api.ts @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2017 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import * as puppeteer from 'puppeteer'; +import { assert } from 'chai'; +// import { getStringCellWidth } from './CharWidth'; +import { ITerminalOptions } from 'xterm'; + +const APP = 'http://127.0.0.1:3000/test'; + +let browser: puppeteer.Browser; +let page: puppeteer.Page; +const width = 800; +const height = 600; + +describe('CharWidth Integration Tests', function(): void { + this.timeout(20000); + + before(async function(): Promise { + browser = await puppeteer.launch({ + headless: process.argv.indexOf('--headless') !== -1, + slowMo: 80, + args: [`--window-size=${width},${height}`] + }); + page = (await browser.pages())[0]; + await page.setViewport({ width, height }); + await page.goto(APP); + await openTerminal({ rows: 5, cols: 30 }); + }); + + after(() => { + browser.close(); + }); + + describe('getStringCellWidth', () => { + beforeEach(async () => { + await page.evaluate(`window.term.reset()`); + }); + + it('ASCII chars', async function(): Promise { + const input = 'This is just ASCII text.#'; + await page.evaluate(`window.term.write('${input}')`); + assert.equal(25, await sumWidths(0, 1, '#')); + }); + + it('combining chars', async function(): Promise { + const input = 'e\u0301e\u0301e\u0301e\u0301e\u0301e\u0301e\u0301e\u0301e\u0301#'; + await page.evaluate(`window.term.write('${input}')`); + assert.equal(10, await sumWidths(0, 1, '#')); + }); + + it('surrogate chars', async function(): Promise { + const input = '𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞#'; + await page.evaluate(`window.term.write('${input}')`); + assert.equal(28, await sumWidths(0, 1, '#')); + }); + + it('surrogate combining chars', async function(): Promise { + const input = '𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301#'; + await page.evaluate(`window.term.write('${input}')`); + assert.equal(12, await sumWidths(0, 1, '#')); + }); + + it('fullwidth chars', async function(): Promise { + const input = '1234567890#'; + await page.evaluate(`window.term.write('${input}')`); + assert.equal(21, await sumWidths(0, 1, '#')); + }); + + it('fullwidth chars offset 1', async function(): Promise { + const input = 'a1234567890#'; + await page.evaluate(`window.term.write('${input}')`); + assert.equal(22, await sumWidths(0, 1, '#')); + }); + + // TODO: multiline tests once #1685 is resolved + }); +}); + +async function openTerminal(options: ITerminalOptions = {}): Promise { + await page.evaluate(`window.term = new Terminal(${JSON.stringify(options)})`); + await page.evaluate(`window.term.open(document.querySelector('#terminal-container'))`); + if (options.rendererType === 'dom') { + await page.waitForSelector('.xterm-rows'); + } else { + await page.waitForSelector('.xterm-text-layer'); + } +} + +async function sumWidths(start: number, end: number, sentinel: string): Promise { + await page.evaluate(` + (function() { + window.result = 0; + const buffer = window.term.buffer; + for (let i = ${start}; i < ${end}; i++) { + const line = buffer.getLine(i); + let j = 0; + while (true) { + const cell = line.getCell(j++); + if (!cell) { + break; + } + window.result += cell.width; + if (cell.char === '${sentinel}') { + return; + } + } + } + })(); + `); + return await page.evaluate(`window.result`); +} diff --git a/src/CharWidth.test.ts b/src/CharWidth.test.ts index 4aec3995..9b5a75af 100644 --- a/src/CharWidth.test.ts +++ b/src/CharWidth.test.ts @@ -3,80 +3,8 @@ * @license MIT */ -import { TestTerminal } from './TestUtils.test'; import { assert } from 'chai'; -import { getStringCellWidth, wcwidth } from './CharWidth'; -import { IBuffer } from './Types'; -import { CellData, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_CHAR_INDEX } from 'core/buffer/BufferLine'; - - -describe('getStringCellWidth', function(): void { - let terminal: TestTerminal; - - beforeEach(() => { - terminal = new TestTerminal({rows: 5, cols: 30}); - }); - - function sumWidths(buffer: IBuffer, start: number, end: number, sentinel: string): number { - let result = 0; - for (let i = start; i < end; ++i) { - const line = buffer.lines.get(i); - for (let j = 0; j < line.length; ++j) { // TODO: change to trimBorder with multiline - const ch = line.loadCell(j, new CellData()).getAsCharData(); - result += ch[CHAR_DATA_WIDTH_INDEX]; - // return on sentinel - if (ch[CHAR_DATA_CHAR_INDEX] === sentinel) { - return result; - } - } - } - return result; - } - - it('ASCII chars', function(): void { - const input = 'This is just ASCII text.#'; - terminal.writeSync(input); - const s = terminal.buffer.iterator(true).next().content; - assert.equal(input, s); - assert.equal(getStringCellWidth(s), sumWidths(terminal.buffer, 0, 1, '#')); - }); - it('combining chars', function(): void { - const input = 'e\u0301e\u0301e\u0301e\u0301e\u0301e\u0301e\u0301e\u0301e\u0301#'; - terminal.writeSync(input); - const s = terminal.buffer.iterator(true).next().content; - assert.equal(input, s); - assert.equal(getStringCellWidth(s), sumWidths(terminal.buffer, 0, 1, '#')); - }); - it('surrogate chars', function(): void { - const input = '𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞𝄞#'; - terminal.writeSync(input); - const s = terminal.buffer.iterator(true).next().content; - assert.equal(input, s); - assert.equal(getStringCellWidth(s), sumWidths(terminal.buffer, 0, 1, '#')); - }); - it('surrogate combining chars', function(): void { - const input = '𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301𓂀\u0301#'; - terminal.writeSync(input); - const s = terminal.buffer.iterator(true).next().content; - assert.equal(input, s); - assert.equal(getStringCellWidth(s), sumWidths(terminal.buffer, 0, 1, '#')); - }); - it('fullwidth chars', function(): void { - const input = '1234567890#'; - terminal.writeSync(input); - const s = terminal.buffer.iterator(true).next().content; - assert.equal(input, s); - assert.equal(getStringCellWidth(s), sumWidths(terminal.buffer, 0, 1, '#')); - }); - it('fullwidth chars offset 1', function(): void { - const input = 'a1234567890#'; - terminal.writeSync(input); - const s = terminal.buffer.iterator(true).next().content; - assert.equal(input, s); - assert.equal(getStringCellWidth(s), sumWidths(terminal.buffer, 0, 1, '#')); - }); - // TODO: multiline tests once #1685 is resolved -}); +import { wcwidth } from './CharWidth'; it('wcwidth should match all values from the old implementation', function(): void { // old implementation