From 968dd93ba78d9cc479c3cb2c761efc6989f2512d Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 21 May 2019 10:57:26 -0700 Subject: [PATCH 1/8] Fix status reporting Fixes #2107 --- src/InputHandler.api.ts | 86 +++++++++++++++++++++++++++++++++++++++++ src/Terminal.ts | 1 + 2 files changed, 87 insertions(+) create mode 100644 src/InputHandler.api.ts diff --git a/src/InputHandler.api.ts b/src/InputHandler.api.ts new file mode 100644 index 00000000..a373f7b9 --- /dev/null +++ b/src/InputHandler.api.ts @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2019 The xterm.js authors. All rights reserved. + * @license MIT + */ + +import * as puppeteer from 'puppeteer'; +import { assert } from 'chai'; +import { ITerminalOptions } from './Types'; + +const APP = 'http://127.0.0.1:3000/test'; + +let browser: puppeteer.Browser; +let page: puppeteer.Page; +const width = 800; +const height = 600; + +describe('InputHandler Integration Tests', () => { + before(async function(): Promise { + this.timeout(10000); + 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 }); + }); + + after(() => { + browser.close(); + }); + + beforeEach(async () => { + await page.goto(APP); + }); + + describe('Device Status Report (DSR)', () => { + it('Status Report - CSI 5 n', async function(): Promise { + this.timeout(10000); + await openTerminal(); + await page.evaluate(` + window.term.onData(e => window.result = e); + window.term.write('\\x1b[5n'); + `); + assert.equal(await page.evaluate(`window.result`), '\x1b[0n'); + }); + + it('Report Cursor Position (CPR) - CSI 6 n', async function(): Promise { + this.timeout(10000); + await openTerminal(); + await page.evaluate(`window.term.write('\\n\\nfoo')`); + assert.deepEqual(await page.evaluate(` + [window.term.buffer.cursorY, window.term.buffer.cursorX] + `), [2, 3]); + await page.evaluate(` + window.term.onData(e => window.result = e); + window.term.write('\\x1b[6n'); + `); + assert.equal(await page.evaluate(`window.result`), '\x1b[3;4R'); + }); + + it('Report Cursor Position (DECXCPR) - CSI ? 6 n', async function(): Promise { + this.timeout(10000); + await openTerminal(); + await page.evaluate(`window.term.write('\\n\\nfoo')`); + assert.deepEqual(await page.evaluate(` + [window.term.buffer.cursorY, window.term.buffer.cursorX] + `), [2, 3]); + await page.evaluate(` + window.term.onData(e => window.result = e); + window.term.write('\\x1b[?6n'); + `); + assert.equal(await page.evaluate(`window.result`), '\x1b[?3;4R'); + }); + }); +}); + +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'); + } +} diff --git a/src/Terminal.ts b/src/Terminal.ts index f55a84f6..7bea0b54 100644 --- a/src/Terminal.ts +++ b/src/Terminal.ts @@ -353,6 +353,7 @@ export class Terminal extends EventEmitter implements ITerminal, IDisposable, II this._inputHandler = new InputHandler(this); this._inputHandler.onCursorMove(() => this._onCursorMove.fire()); this._inputHandler.onLineFeed(() => this._onLineFeed.fire()); + this._inputHandler.onData(e => this._onData.fire(e)); this.register(this._inputHandler); this.selectionManager = this.selectionManager || null; From d0a3164e9953902b9bc0f2999eb126ed6902ef31 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 21 May 2019 11:01:40 -0700 Subject: [PATCH 2/8] Fix lint --- src/InputHandler.api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/InputHandler.api.ts b/src/InputHandler.api.ts index a373f7b9..06f4cf23 100644 --- a/src/InputHandler.api.ts +++ b/src/InputHandler.api.ts @@ -58,7 +58,7 @@ describe('InputHandler Integration Tests', () => { `); assert.equal(await page.evaluate(`window.result`), '\x1b[3;4R'); }); - + it('Report Cursor Position (DECXCPR) - CSI ? 6 n', async function(): Promise { this.timeout(10000); await openTerminal(); From 37ed1e4796aea97839347ee69ae35f482eeda138 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 21 May 2019 11:12:29 -0700 Subject: [PATCH 3/8] Split out integration tests into its own job This will make Linux finish faster and release trigger faster --- azure-pipelines.yml | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f6acee37..e3c5b356 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -22,11 +22,6 @@ jobs: - script: | yarn mocha displayName: 'Unit tests' - - script: | - yarn start & - sleep 5 - yarn test-api --headless - displayName: 'Integration tests' - script: | yarn lint displayName: 'Lint' @@ -71,12 +66,34 @@ jobs: - script: | yarn lint displayName: 'Lint' + +- job: 'Integration tests' + pool: + vmImage: 'ubuntu-16.04' + steps: + - task: NodeTool@0 + inputs: + versionSpec: '8.x' + displayName: 'Install Node.js' + - task: geeklearningio.gl-vsts-tasks-yarn.yarn-installer-task.YarnInstaller@2 + inputs: + versionSpec: "1.9.4" + displayName: 'Install Yarn' + - script: | + yarn + displayName: 'Install dependencies and build' + - script: | + yarn start & + sleep 5 + yarn test-api --headless + displayName: 'Integration tests' - job: Release dependsOn: - Linux - macOS - Windows + - 'Integration tests' condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master')) pool: vmImage: 'ubuntu-16.04' From ab0eedc513d5521ce675bf668163bb8d68a4bfef Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 21 May 2019 11:17:07 -0700 Subject: [PATCH 4/8] Fix job name --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index e3c5b356..a8f03125 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -67,7 +67,7 @@ jobs: yarn lint displayName: 'Lint' -- job: 'Integration tests' +- job: IntegrationTests pool: vmImage: 'ubuntu-16.04' steps: @@ -93,7 +93,7 @@ jobs: - Linux - macOS - Windows - - 'Integration tests' + - IntegrationTests condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master')) pool: vmImage: 'ubuntu-16.04' From f81d1cb1cf7c9655c0f5bc0385d18b5096491925 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 21 May 2019 14:20:58 -0700 Subject: [PATCH 5/8] Increase integration test sleep --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a8f03125..17c98198 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -84,7 +84,7 @@ jobs: displayName: 'Install dependencies and build' - script: | yarn start & - sleep 5 + sleep 10 yarn test-api --headless displayName: 'Integration tests' From d3ff32da728e61378cce2d11e7028d1ae3bad3ee Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 21 May 2019 14:24:52 -0700 Subject: [PATCH 6/8] Run release against builds on release/* branches Fixes #2111 --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f6acee37..a4ecc943 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -77,7 +77,7 @@ jobs: - Linux - macOS - Windows - condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master')) + condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(variables['Build.SourceBranch'], 'refs/heads/release/*'))) pool: vmImage: 'ubuntu-16.04' steps: From acea979fe048fc10f0de01ac86a88b81c01de4fe Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 21 May 2019 14:46:22 -0700 Subject: [PATCH 7/8] Move API test timeout to top-level describe I learned a thing. --- src/InputHandler.api.ts | 8 +++----- src/public/Terminal.api.ts | 35 +++-------------------------------- 2 files changed, 6 insertions(+), 37 deletions(-) diff --git a/src/InputHandler.api.ts b/src/InputHandler.api.ts index 06f4cf23..878925ba 100644 --- a/src/InputHandler.api.ts +++ b/src/InputHandler.api.ts @@ -14,9 +14,10 @@ let page: puppeteer.Page; const width = 800; const height = 600; -describe('InputHandler Integration Tests', () => { +describe('InputHandler Integration Tests', function() { + this.timeout(10000); + before(async function(): Promise { - this.timeout(10000); browser = await puppeteer.launch({ headless: process.argv.indexOf('--headless') !== -1, slowMo: 80, @@ -36,7 +37,6 @@ describe('InputHandler Integration Tests', () => { describe('Device Status Report (DSR)', () => { it('Status Report - CSI 5 n', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` window.term.onData(e => window.result = e); @@ -46,7 +46,6 @@ describe('InputHandler Integration Tests', () => { }); it('Report Cursor Position (CPR) - CSI 6 n', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(`window.term.write('\\n\\nfoo')`); assert.deepEqual(await page.evaluate(` @@ -60,7 +59,6 @@ describe('InputHandler Integration Tests', () => { }); it('Report Cursor Position (DECXCPR) - CSI ? 6 n', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(`window.term.write('\\n\\nfoo')`); assert.deepEqual(await page.evaluate(` diff --git a/src/public/Terminal.api.ts b/src/public/Terminal.api.ts index d8325229..c784471e 100644 --- a/src/public/Terminal.api.ts +++ b/src/public/Terminal.api.ts @@ -14,9 +14,10 @@ let page: puppeteer.Page; const width = 800; const height = 600; -describe('API Integration Tests', () => { +describe('API Integration Tests', function() { + this.timeout(10000); + before(async function(): Promise { - this.timeout(10000); browser = await puppeteer.launch({ headless: process.argv.indexOf('--headless') !== -1, slowMo: 80, @@ -35,14 +36,12 @@ describe('API Integration Tests', () => { }); it('Default options', async function(): Promise { - this.timeout(10000); await openTerminal(); assert.equal(await page.evaluate(`window.term.cols`), 80); assert.equal(await page.evaluate(`window.term.rows`), 24); }); it('write', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` window.term.write('foo'); @@ -53,7 +52,6 @@ describe('API Integration Tests', () => { }); it('writeln', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` window.term.writeln('foo'); @@ -66,7 +64,6 @@ describe('API Integration Tests', () => { }); it('writeUtf8', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` // foo @@ -80,7 +77,6 @@ describe('API Integration Tests', () => { }); it('clear', async function(): Promise { - this.timeout(10000); await openTerminal({ rows: 5 }); await page.evaluate(` window.term.write('test0'); @@ -97,7 +93,6 @@ describe('API Integration Tests', () => { }); it('getOption, setOption', async function(): Promise { - this.timeout(10000); await openTerminal(); assert.equal(await page.evaluate(`window.term.getOption('rendererType')`), 'canvas'); await page.evaluate(`window.term.setOption('rendererType', 'dom')`); @@ -106,7 +101,6 @@ describe('API Integration Tests', () => { describe('renderer', () => { it('foreground', async function(): Promise { - this.timeout(10000); await openTerminal({ rendererType: 'dom' }); await page.evaluate(`window.term.write('\\x1b[30m0\\x1b[31m1\\x1b[32m2\\x1b[33m3\\x1b[34m4\\x1b[35m5\\x1b[36m6\\x1b[37m7')`); assert.deepEqual(await page.evaluate(` @@ -131,7 +125,6 @@ describe('API Integration Tests', () => { }); it('background', async function(): Promise { - this.timeout(10000); await openTerminal({ rendererType: 'dom' }); await page.evaluate(`window.term.write('\\x1b[40m0\\x1b[41m1\\x1b[42m2\\x1b[43m3\\x1b[44m4\\x1b[45m5\\x1b[46m6\\x1b[47m7')`); assert.deepEqual(await page.evaluate(` @@ -157,7 +150,6 @@ describe('API Integration Tests', () => { }); it('selection', async function(): Promise { - this.timeout(10000); await openTerminal({ rows: 5, cols: 5 }); await page.evaluate(`window.term.write('\\n\\nfoo\\n\\n\\rbar\\n\\n\\rbaz')`); assert.equal(await page.evaluate(`window.term.hasSelection()`), false); @@ -178,7 +170,6 @@ describe('API Integration Tests', () => { }); it('focus, blur', async function(): Promise { - this.timeout(10000); await openTerminal(); assert.equal(await page.evaluate(`document.activeElement.className`), ''); await page.evaluate(`window.term.focus()`); @@ -189,7 +180,6 @@ describe('API Integration Tests', () => { describe('loadAddon', () => { it('constructor', async function(): Promise { - this.timeout(10000); await openTerminal({ cols: 5 }); await page.evaluate(` window.cols = 0; @@ -202,7 +192,6 @@ describe('API Integration Tests', () => { }); it('dispose (addon)', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` window.disposeCalled = false @@ -218,7 +207,6 @@ describe('API Integration Tests', () => { }); it('dispose (terminal)', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` window.disposeCalled = false @@ -235,7 +223,6 @@ describe('API Integration Tests', () => { describe('Events', () => { it('onCursorMove', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` window.callCount = 0; @@ -248,7 +235,6 @@ describe('API Integration Tests', () => { }); it('onData', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` window.calls = []; @@ -259,7 +245,6 @@ describe('API Integration Tests', () => { }); it('onKey', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` window.calls = []; @@ -270,7 +255,6 @@ describe('API Integration Tests', () => { }); it('onLineFeed', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` window.callCount = 0; @@ -283,7 +267,6 @@ describe('API Integration Tests', () => { }); it('onScroll', async function(): Promise { - this.timeout(10000); await openTerminal({ rows: 5 }); await page.evaluate(` window.calls = []; @@ -300,7 +283,6 @@ describe('API Integration Tests', () => { }); it('onSelectionChange', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` window.callCount = 0; @@ -314,7 +296,6 @@ describe('API Integration Tests', () => { }); it('onRender', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` window.calls = []; @@ -328,7 +309,6 @@ describe('API Integration Tests', () => { }); it('onResize', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` window.calls = []; @@ -342,7 +322,6 @@ describe('API Integration Tests', () => { }); it('onTitleChange', async function(): Promise { - this.timeout(10000); await openTerminal(); await page.evaluate(` window.calls = []; @@ -356,7 +335,6 @@ describe('API Integration Tests', () => { describe('buffer', () => { it('cursorX, cursorY', async function(): Promise { - this.timeout(10000); await openTerminal({ rows: 5, cols: 5 }); assert.equal(await page.evaluate(`window.term.buffer.cursorX`), 0); assert.equal(await page.evaluate(`window.term.buffer.cursorY`), 0); @@ -378,7 +356,6 @@ describe('API Integration Tests', () => { }); it('viewportY', async function(): Promise { - this.timeout(10000); await openTerminal({ rows: 5 }); assert.equal(await page.evaluate(`window.term.buffer.viewportY`), 0); await page.evaluate(`window.term.write('\\n\\n\\n\\n')`); @@ -394,7 +371,6 @@ describe('API Integration Tests', () => { }); it('baseY', async function(): Promise { - this.timeout(10000); await openTerminal({ rows: 5 }); assert.equal(await page.evaluate(`window.term.buffer.baseY`), 0); await page.evaluate(`window.term.write('\\n\\n\\n\\n')`); @@ -410,7 +386,6 @@ describe('API Integration Tests', () => { }); it('length', async function(): Promise { - this.timeout(10000); await openTerminal({ rows: 5 }); assert.equal(await page.evaluate(`window.term.buffer.length`), 5); await page.evaluate(`window.term.write('\\n\\n\\n\\n')`); @@ -423,14 +398,12 @@ describe('API Integration Tests', () => { describe('getLine', () => { it('invalid index', async function(): Promise { - this.timeout(10000); await openTerminal({ rows: 5 }); assert.equal(await page.evaluate(`window.term.buffer.getLine(-1)`), undefined); assert.equal(await page.evaluate(`window.term.buffer.getLine(5)`), undefined); }); it('isWrapped', async function(): Promise { - this.timeout(10000); await openTerminal({ cols: 5 }); assert.equal(await page.evaluate(`window.term.buffer.getLine(0).isWrapped`), false); assert.equal(await page.evaluate(`window.term.buffer.getLine(1).isWrapped`), false); @@ -443,7 +416,6 @@ describe('API Integration Tests', () => { }); it('translateToString', async function(): Promise { - this.timeout(10000); await openTerminal({ cols: 5 }); assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString()`), ' '); assert.equal(await page.evaluate(`window.term.buffer.getLine(0).translateToString(true)`), ''); @@ -459,7 +431,6 @@ describe('API Integration Tests', () => { }); it('getCell', async function(): Promise { - this.timeout(10000); await openTerminal({ cols: 5 }); assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(-1)`), undefined); assert.equal(await page.evaluate(`window.term.buffer.getLine(0).getCell(5)`), undefined); From 922e594fcf7a6b4e1d2bce1d88992b45c54f6118 Mon Sep 17 00:00:00 2001 From: Daniel Imms Date: Tue, 21 May 2019 14:51:41 -0700 Subject: [PATCH 8/8] Fix lint --- src/InputHandler.api.ts | 2 +- src/public/Terminal.api.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/InputHandler.api.ts b/src/InputHandler.api.ts index 878925ba..ef92f29d 100644 --- a/src/InputHandler.api.ts +++ b/src/InputHandler.api.ts @@ -14,7 +14,7 @@ let page: puppeteer.Page; const width = 800; const height = 600; -describe('InputHandler Integration Tests', function() { +describe('InputHandler Integration Tests', function(): void { this.timeout(10000); before(async function(): Promise { diff --git a/src/public/Terminal.api.ts b/src/public/Terminal.api.ts index c784471e..afad2699 100644 --- a/src/public/Terminal.api.ts +++ b/src/public/Terminal.api.ts @@ -14,7 +14,7 @@ let page: puppeteer.Page; const width = 800; const height = 600; -describe('API Integration Tests', function() { +describe('API Integration Tests', function(): void { this.timeout(10000); before(async function(): Promise {