mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge pull request #5079 from Tyriar/more_playwright
Migrate more API tests to playwright
This commit is contained in:
@@ -1,50 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import WebSocket = require('ws');
|
||||
import { openTerminal, pollFor, launchBrowser } from '../../../out-test/api/TestUtils';
|
||||
import { Browser, Page } from '@playwright/test';
|
||||
|
||||
const APP = 'http://127.0.0.1:3001/test';
|
||||
|
||||
let browser: Browser;
|
||||
let page: Page;
|
||||
const width = 800;
|
||||
const height = 600;
|
||||
|
||||
describe('AttachAddon', () => {
|
||||
before(async function(): Promise<any> {
|
||||
browser = await launchBrowser();
|
||||
page = await (await browser.newContext()).newPage();
|
||||
await page.setViewportSize({ width, height });
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
beforeEach(async () => await page.goto(APP));
|
||||
|
||||
it('string', async function(): Promise<any> {
|
||||
await openTerminal(page);
|
||||
const port = 8080;
|
||||
const server = new WebSocket.Server({ port });
|
||||
server.on('connection', socket => socket.send('foo'));
|
||||
await page.evaluate(`window.term.loadAddon(new window.AttachAddon(new WebSocket('ws://localhost:${port}')))`);
|
||||
await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo');
|
||||
server.close();
|
||||
});
|
||||
|
||||
it('utf8', async function(): Promise<any> {
|
||||
await openTerminal(page);
|
||||
const port = 8080;
|
||||
const server = new WebSocket.Server({ port });
|
||||
const data = new Uint8Array([102, 111, 111]);
|
||||
server.on('connection', socket => socket.send(data));
|
||||
await page.evaluate(`window.term.loadAddon(new window.AttachAddon(new WebSocket('ws://localhost:${port}')))`);
|
||||
await pollFor(page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo');
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import WebSocket = require('ws');
|
||||
|
||||
import test from '@playwright/test';
|
||||
import { ITestContext, createTestContext, openTerminal, pollFor, timeout } from '../../../out-test/playwright/TestUtils';
|
||||
|
||||
let ctx: ITestContext;
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
ctx = await createTestContext(browser);
|
||||
await openTerminal(ctx);
|
||||
});
|
||||
test.afterAll(async () => await ctx.page.close());
|
||||
|
||||
test.describe('Search Tests', () => {
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await ctx.proxy.reset();
|
||||
});
|
||||
|
||||
test('string', async function(): Promise<any> {
|
||||
const port = 8080;
|
||||
const server = new WebSocket.Server({ port });
|
||||
server.on('connection', socket => socket.send('foo'));
|
||||
await ctx.page.evaluate(`window.term.loadAddon(new window.AttachAddon(new WebSocket('ws://localhost:${port}')))`);
|
||||
await pollFor(ctx.page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo');
|
||||
server.close();
|
||||
});
|
||||
|
||||
test('utf8', async function(): Promise<any> {
|
||||
const port = 8080;
|
||||
const server = new WebSocket.Server({ port });
|
||||
const data = new Uint8Array([102, 111, 111]);
|
||||
server.on('connection', socket => socket.send(data));
|
||||
await ctx.page.evaluate(`window.term.loadAddon(new window.AttachAddon(new WebSocket('ws://localhost:${port}')))`);
|
||||
await pollFor(ctx.page, `window.term.buffer.active.getLine(0).translateToString(true)`, 'foo');
|
||||
server.close();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { PlaywrightTestConfig } from '@playwright/test';
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
testDir: '.',
|
||||
timeout: 10000,
|
||||
projects: [
|
||||
{
|
||||
name: 'ChromeStable',
|
||||
use: {
|
||||
browserName: 'chromium',
|
||||
channel: 'chrome'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'FirefoxStable',
|
||||
use: {
|
||||
browserName: 'firefox'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'WebKit',
|
||||
use: {
|
||||
browserName: 'webkit'
|
||||
}
|
||||
}
|
||||
],
|
||||
reporter: 'list',
|
||||
webServer: {
|
||||
command: 'npm run start-server-only',
|
||||
port: 3000,
|
||||
timeout: 120000,
|
||||
reuseExistingServer: !process.env.CI
|
||||
}
|
||||
};
|
||||
export default config;
|
||||
@@ -3,21 +3,37 @@
|
||||
"module": "commonjs",
|
||||
"target": "es2021",
|
||||
"lib": [
|
||||
"es2015"
|
||||
"es2021",
|
||||
],
|
||||
"rootDir": ".",
|
||||
"outDir": "../out-test",
|
||||
"sourceMap": true,
|
||||
"removeComments": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
"../../../src/browser/*"
|
||||
]
|
||||
},
|
||||
"strict": true,
|
||||
"types": [
|
||||
"../../../node_modules/@types/mocha",
|
||||
"../../../node_modules/@types/node",
|
||||
"../../../out-test/api/TestUtils"
|
||||
"../../../out-test/playwright/TestUtils"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"./**/*",
|
||||
"../../../typings/xterm.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../../src/common"
|
||||
},
|
||||
{
|
||||
"path": "../../../src/browser"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,88 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2023 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { openTerminal, launchBrowser, writeSync, getBrowserType } from '../../../out-test/api/TestUtils';
|
||||
import { Browser, BrowserContext, Page } from '@playwright/test';
|
||||
import { beforeEach } from 'mocha';
|
||||
|
||||
const APP = 'http://127.0.0.1:3001/test';
|
||||
|
||||
let browser: Browser;
|
||||
let context: BrowserContext;
|
||||
let page: Page;
|
||||
const width = 800;
|
||||
const height = 600;
|
||||
|
||||
describe('ClipboardAddon', () => {
|
||||
before(async function (): Promise<any> {
|
||||
browser = await launchBrowser({
|
||||
// Enable clipboard access in firefox, mainly for readText
|
||||
firefoxUserPrefs: {
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
'dom.events.testing.asyncClipboard': true,
|
||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||
'dom.events.asyncClipboard.readText': true
|
||||
}
|
||||
});
|
||||
context = await browser.newContext();
|
||||
if (getBrowserType().name() !== 'webkit') {
|
||||
// Enable clipboard access in chromium without user gesture
|
||||
context.grantPermissions(['clipboard-read', 'clipboard-write']);
|
||||
}
|
||||
page = await context.newPage();
|
||||
await page.setViewportSize({ width, height });
|
||||
await page.goto(APP);
|
||||
await openTerminal(page);
|
||||
await page.evaluate(`
|
||||
window.clipboardAddon = new ClipboardAddon();
|
||||
window.term.loadAddon(window.clipboardAddon);
|
||||
`);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
browser.close();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await page.evaluate(`window.term.reset()`);
|
||||
});
|
||||
|
||||
const testDataEncoded = 'aGVsbG8gd29ybGQ=';
|
||||
const testDataDecoded = 'hello world';
|
||||
|
||||
describe('write data', async function (): Promise<any> {
|
||||
it('simple string', async () => {
|
||||
await writeSync(page, `\x1b]52;c;${testDataEncoded}\x07`);
|
||||
assert.deepEqual(await page.evaluate(() => window.navigator.clipboard.readText()), testDataDecoded);
|
||||
});
|
||||
it('invalid base64 string', async () => {
|
||||
await writeSync(page, `\x1b]52;c;${testDataEncoded}invalid\x07`);
|
||||
assert.deepEqual(await page.evaluate(() => window.navigator.clipboard.readText()), '');
|
||||
});
|
||||
it('empty string', async () => {
|
||||
await writeSync(page, `\x1b]52;c;${testDataEncoded}\x07`);
|
||||
await writeSync(page, `\x1b]52;c;\x07`);
|
||||
assert.deepEqual(await page.evaluate(() => window.navigator.clipboard.readText()), '');
|
||||
});
|
||||
});
|
||||
|
||||
describe('read data', async function (): Promise<any> {
|
||||
it('simple string', async () => {
|
||||
await page.evaluate(`
|
||||
window.data = [];
|
||||
window.term.onData(e => data.push(e));
|
||||
`);
|
||||
await page.evaluate(() => window.navigator.clipboard.writeText('hello world'));
|
||||
await writeSync(page, `\x1b]52;c;?\x07`);
|
||||
assert.deepEqual(await page.evaluate('window.data'), [`\x1b]52;c;${testDataEncoded}\x07`]);
|
||||
});
|
||||
it('clear clipboard', async () => {
|
||||
await writeSync(page, `\x1b]52;c;!\x07`);
|
||||
await writeSync(page, `\x1b]52;c;?\x07`);
|
||||
assert.deepEqual(await page.evaluate(() => window.navigator.clipboard.readText()), '');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* Copyright (c) 2023 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import test from '@playwright/test';
|
||||
import { deepEqual, ok, strictEqual } from 'assert';
|
||||
import { ITestContext, createTestContext, launchBrowser, openTerminal, timeout } from '../../../out-test/playwright/TestUtils';
|
||||
|
||||
let ctx: ITestContext;
|
||||
test.beforeAll(async ({ browser }, testInfo) => {
|
||||
ctx = await createTestContext(browser);
|
||||
await openTerminal(ctx);
|
||||
});
|
||||
test.afterAll(async () => {
|
||||
await ctx.page.close();
|
||||
});
|
||||
|
||||
test.describe('ClipboardAddon', () => {
|
||||
|
||||
test.beforeEach(async ({}, testInfo) => {
|
||||
// DEBT: This test doesn't work since the migration to @playwright/test
|
||||
if (ctx.browser.browserType().name() !== 'chromium') {
|
||||
testInfo.skip();
|
||||
return;
|
||||
}
|
||||
if (ctx.browser.browserType().name() === 'chromium') {
|
||||
// Enable clipboard access in chromium without user gesture
|
||||
await ctx.page.context().grantPermissions(['clipboard-read', 'clipboard-write']);
|
||||
}
|
||||
await ctx.page.evaluate(`
|
||||
window.term.reset()
|
||||
window.clipboard?.dispose();
|
||||
window.clipboard = new ClipboardAddon();
|
||||
window.term.loadAddon(window.clipboard);
|
||||
`);
|
||||
});
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await ctx.proxy.reset();
|
||||
});
|
||||
|
||||
const testDataEncoded = 'aGVsbG8gd29ybGQ=';
|
||||
const testDataDecoded = 'hello world';
|
||||
|
||||
test.describe('write data', async function (): Promise<any> {
|
||||
test('simple string', async () => {
|
||||
await ctx.proxy.write(`\x1b]52;c;${testDataEncoded}\x07`);
|
||||
deepEqual(await ctx.page.evaluate(() => window.navigator.clipboard.readText()), testDataDecoded);
|
||||
});
|
||||
test('invalid base64 string', async () => {
|
||||
await ctx.proxy.write(`\x1b]52;c;${testDataEncoded}invalid\x07`);
|
||||
deepEqual(await ctx.page.evaluate(() => window.navigator.clipboard.readText()), '');
|
||||
});
|
||||
test('empty string', async () => {
|
||||
await ctx.proxy.write(`\x1b]52;c;${testDataEncoded}\x07`);
|
||||
await ctx.proxy.write(`\x1b]52;c;\x07`);
|
||||
deepEqual(await ctx.page.evaluate(() => window.navigator.clipboard.readText()), '');
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('read data', async function (): Promise<any> {
|
||||
test('simple string', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.data = [];
|
||||
window.term.onData(e => data.push(e));
|
||||
`);
|
||||
await ctx.page.evaluate(() => window.navigator.clipboard.writeText('hello world'));
|
||||
await ctx.proxy.write(`\x1b]52;c;?\x07`);
|
||||
deepEqual(await ctx.page.evaluate('window.data'), [`\x1b]52;c;${testDataEncoded}\x07`]);
|
||||
});
|
||||
test('clear clipboard', async () => {
|
||||
await ctx.proxy.write(`\x1b]52;c;!\x07`);
|
||||
await ctx.proxy.write(`\x1b]52;c;?\x07`);
|
||||
deepEqual(await ctx.page.evaluate(() => window.navigator.clipboard.readText()), '');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,35 @@
|
||||
import { PlaywrightTestConfig } from '@playwright/test';
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
testDir: '.',
|
||||
timeout: 10000,
|
||||
projects: [
|
||||
{
|
||||
name: 'ChromeStable',
|
||||
use: {
|
||||
browserName: 'chromium',
|
||||
channel: 'chrome'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'FirefoxStable',
|
||||
use: {
|
||||
browserName: 'firefox'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'WebKit',
|
||||
use: {
|
||||
browserName: 'webkit'
|
||||
}
|
||||
}
|
||||
],
|
||||
reporter: 'list',
|
||||
webServer: {
|
||||
command: 'npm run start-server-only',
|
||||
port: 3000,
|
||||
timeout: 120000,
|
||||
reuseExistingServer: !process.env.CI
|
||||
}
|
||||
};
|
||||
export default config;
|
||||
@@ -3,21 +3,37 @@
|
||||
"module": "commonjs",
|
||||
"target": "es2021",
|
||||
"lib": [
|
||||
"es2015"
|
||||
"es2021",
|
||||
],
|
||||
"rootDir": ".",
|
||||
"outDir": "../out-test",
|
||||
"sourceMap": true,
|
||||
"removeComments": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
"../../../src/browser/*"
|
||||
]
|
||||
},
|
||||
"strict": true,
|
||||
"types": [
|
||||
"../../../node_modules/@types/mocha",
|
||||
"../../../node_modules/@types/node",
|
||||
"../../../out-test/api/TestUtils"
|
||||
"../../../out-test/playwright/TestUtils"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"./**/*",
|
||||
"../../../typings/xterm.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../../src/common"
|
||||
},
|
||||
{
|
||||
"path": "../../../src/browser"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
/**
|
||||
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { assert } from 'chai';
|
||||
import { openTerminal, launchBrowser, timeout } from '../../../out-test/api/TestUtils';
|
||||
import { Browser, Page } from '@playwright/test';
|
||||
|
||||
const APP = 'http://127.0.0.1:3001/test';
|
||||
|
||||
let browser: Browser;
|
||||
let page: Page;
|
||||
const width = 1024;
|
||||
const height = 768;
|
||||
|
||||
describe('FitAddon', () => {
|
||||
before(async function(): Promise<any> {
|
||||
browser = await launchBrowser();
|
||||
page = await (await browser.newContext()).newPage();
|
||||
await page.setViewportSize({ width, height });
|
||||
await page.goto(APP);
|
||||
});
|
||||
|
||||
beforeEach(async function(): Promise<any> {
|
||||
await page.evaluate(`document.querySelector('#terminal-container').style.display=''`);
|
||||
await openTerminal(page);
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await browser.close();
|
||||
});
|
||||
|
||||
afterEach(async function(): Promise<any> {
|
||||
await page.evaluate(`window.term.dispose()`);
|
||||
});
|
||||
|
||||
it('no terminal', async function(): Promise<any> {
|
||||
await page.evaluate(`window.fit = new FitAddon();`);
|
||||
assert.equal(await page.evaluate(`window.fit.proposeDimensions()`), undefined);
|
||||
});
|
||||
|
||||
describe('proposeDimensions', () => {
|
||||
afterEach(() => unloadFit());
|
||||
|
||||
it('default', async function(): Promise<any> {
|
||||
await loadFit();
|
||||
const dimensions: {cols: number, rows: number} = await page.evaluate(`window.fit.proposeDimensions()`);
|
||||
assert.isAbove(dimensions.cols, 85);
|
||||
assert.isBelow(dimensions.cols, 88);
|
||||
assert.isAbove(dimensions.rows, 24);
|
||||
assert.isBelow(dimensions.rows, 29);
|
||||
});
|
||||
|
||||
it('width', async function(): Promise<any> {
|
||||
await loadFit(1008);
|
||||
const dimensions: {cols: number, rows: number} = await page.evaluate(`window.fit.proposeDimensions()`);
|
||||
assert.isAbove(dimensions.cols, 108);
|
||||
assert.isBelow(dimensions.cols, 111);
|
||||
assert.isAbove(dimensions.rows, 24);
|
||||
assert.isBelow(dimensions.rows, 29);
|
||||
});
|
||||
|
||||
it('small', async function(): Promise<any> {
|
||||
await loadFit(1, 1);
|
||||
assert.deepEqual(await page.evaluate(`window.fit.proposeDimensions()`), {
|
||||
cols: 2,
|
||||
rows: 1
|
||||
});
|
||||
});
|
||||
|
||||
it('hidden', async function(): Promise<any> {
|
||||
await page.evaluate(`window.term.dispose()`);
|
||||
await page.evaluate(`document.querySelector('#terminal-container').style.display='none'`);
|
||||
await page.evaluate(`window.term = new Terminal()`);
|
||||
await page.evaluate(`window.term.open(document.querySelector('#terminal-container'))`);
|
||||
await loadFit();
|
||||
const dimensions: { cols: number, rows: number } | undefined = await page.evaluate(`window.fit.proposeDimensions()`);
|
||||
// The value of dims will be undefined if the char measure strategy falls back to the DOM
|
||||
// method, so only assert if it's not undefined.
|
||||
if (dimensions) {
|
||||
assert.isAbove(dimensions.cols, 85);
|
||||
assert.isBelow(dimensions.cols, 88);
|
||||
assert.isAbove(dimensions.rows, 24);
|
||||
assert.isBelow(dimensions.rows, 29);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('fit', () => {
|
||||
afterEach(() => unloadFit());
|
||||
|
||||
it('default', async function(): Promise<any> {
|
||||
await loadFit();
|
||||
await page.evaluate(`window.fit.fit()`);
|
||||
const cols: number = await page.evaluate(`window.term.cols`);
|
||||
const rows: number = await page.evaluate(`window.term.rows`);
|
||||
assert.isAbove(cols, 85);
|
||||
assert.isBelow(cols, 88);
|
||||
assert.isAbove(rows, 24);
|
||||
assert.isBelow(rows, 29);
|
||||
});
|
||||
|
||||
it('width', async function(): Promise<any> {
|
||||
await loadFit(1008);
|
||||
await page.evaluate(`window.fit.fit()`);
|
||||
const cols: number = await page.evaluate(`window.term.cols`);
|
||||
const rows: number = await page.evaluate(`window.term.rows`);
|
||||
assert.isAbove(cols, 108);
|
||||
assert.isBelow(cols, 111);
|
||||
assert.isAbove(rows, 24);
|
||||
assert.isBelow(rows, 29);
|
||||
});
|
||||
|
||||
it('small', async function(): Promise<any> {
|
||||
await loadFit(1, 1);
|
||||
await page.evaluate(`window.fit.fit()`);
|
||||
assert.equal(await page.evaluate(`window.term.cols`), 2);
|
||||
assert.equal(await page.evaluate(`window.term.rows`), 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function loadFit(width: number = 800, height: number = 450): Promise<void> {
|
||||
await page.evaluate(`
|
||||
window.fit = new FitAddon();
|
||||
window.term.loadAddon(window.fit);
|
||||
document.querySelector('#terminal-container').style.width='${width}px';
|
||||
document.querySelector('#terminal-container').style.height='${height}px';
|
||||
`);
|
||||
}
|
||||
|
||||
async function unloadFit(): Promise<void> {
|
||||
await page.evaluate(`window.fit.dispose();`);
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/**
|
||||
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import test from '@playwright/test';
|
||||
import { deepEqual, ok, strictEqual } from 'assert';
|
||||
import { ITestContext, createTestContext, openTerminal, timeout } from '../../../out-test/playwright/TestUtils';
|
||||
|
||||
let ctx: ITestContext;
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
ctx = await createTestContext(browser);
|
||||
await openTerminal(ctx);
|
||||
});
|
||||
test.afterAll(async () => await ctx.page.close());
|
||||
|
||||
test.describe('FitAddon', () => {
|
||||
test.beforeEach(async function(): Promise<any> {
|
||||
await ctx.page.evaluate(`
|
||||
window.term.reset()
|
||||
window.fit?.dispose();
|
||||
window.fit = new FitAddon();
|
||||
window.term.loadAddon(window.fit);
|
||||
`);
|
||||
});
|
||||
|
||||
// test.beforeEach(async function(): Promise<any> {
|
||||
// await ctx.page.evaluate(`document.querySelector('#terminal-container').style.display=''`);
|
||||
// await openTerminal(page);
|
||||
// });
|
||||
|
||||
// after(async () => {
|
||||
// await browser.close();
|
||||
// });
|
||||
|
||||
// afterEach(async function(): Promise<any> {
|
||||
// await ctx.proxy.dispose();
|
||||
// });
|
||||
|
||||
test('no terminal', async function(): Promise<any> {
|
||||
await ctx.page.evaluate(`window.fit = new FitAddon();`);
|
||||
strictEqual(await ctx.page.evaluate(`window.fit.proposeDimensions()`), undefined);
|
||||
});
|
||||
|
||||
test.describe('proposeDimensions', () => {
|
||||
// test.afterEach(() => unloadFit());
|
||||
|
||||
test('default', async function(): Promise<any> {
|
||||
await loadFit();
|
||||
const dimensions: {cols: number, rows: number} = await ctx.page.evaluate(`window.fit.proposeDimensions()`);
|
||||
ok(dimensions.cols > 85);
|
||||
ok(dimensions.cols < 88);
|
||||
ok(dimensions.rows > 24);
|
||||
ok(dimensions.rows < 29);
|
||||
});
|
||||
|
||||
test('width', async function(): Promise<any> {
|
||||
await loadFit(1008);
|
||||
const dimensions: {cols: number, rows: number} = await ctx.page.evaluate(`window.fit.proposeDimensions()`);
|
||||
ok(dimensions.cols > 108);
|
||||
ok(dimensions.cols < 111);
|
||||
ok(dimensions.rows > 24);
|
||||
ok(dimensions.rows < 29);
|
||||
});
|
||||
|
||||
test('small', async function(): Promise<any> {
|
||||
await loadFit(1, 1);
|
||||
deepEqual(await ctx.page.evaluate(`window.fit.proposeDimensions()`), {
|
||||
cols: 2,
|
||||
rows: 1
|
||||
});
|
||||
});
|
||||
|
||||
test('hidden', async function(): Promise<any> {
|
||||
await ctx.proxy.dispose();
|
||||
await ctx.page.evaluate(`document.querySelector('#terminal-container').style.display='none'`);
|
||||
await ctx.page.evaluate(`window.term = new Terminal()`);
|
||||
await ctx.page.evaluate(`window.term.open(document.querySelector('#terminal-container'))`);
|
||||
await loadFit();
|
||||
const dimensions: { cols: number, rows: number } | undefined = await ctx.page.evaluate(`window.fit.proposeDimensions()`);
|
||||
// The value of dims will be undefined if the char measure strategy falls back to the DOM
|
||||
// method, so only assert if it's not undefined.
|
||||
if (dimensions) {
|
||||
ok(dimensions.cols > 85);
|
||||
ok(dimensions.cols < 88);
|
||||
ok(dimensions.rows > 24);
|
||||
ok(dimensions.rows < 29);
|
||||
}
|
||||
await ctx.page.evaluate(`document.querySelector('#terminal-container').style.display='block'`);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('fit', () => {
|
||||
test.afterEach(() => unloadFit());
|
||||
|
||||
test('default', async function(): Promise<any> {
|
||||
await loadFit();
|
||||
await ctx.page.evaluate(`window.fit.fit()`);
|
||||
const cols: number = await ctx.proxy.cols;
|
||||
const rows: number = await ctx.proxy.rows;
|
||||
ok(cols > 85);
|
||||
ok(cols < 88);
|
||||
ok(rows > 24);
|
||||
ok(rows < 29);
|
||||
});
|
||||
|
||||
test('width', async function(): Promise<any> {
|
||||
await loadFit(1008);
|
||||
await ctx.page.evaluate(`window.fit.fit()`);
|
||||
const cols: number = await ctx.proxy.cols;
|
||||
const rows: number = await ctx.proxy.rows;
|
||||
ok(cols > 108);
|
||||
ok(cols < 111);
|
||||
ok(rows > 24);
|
||||
ok(rows < 29);
|
||||
});
|
||||
|
||||
test('small', async function(): Promise<any> {
|
||||
await loadFit(1, 1);
|
||||
await ctx.page.evaluate(`window.fit.fit()`);
|
||||
strictEqual(await ctx.proxy.cols, 2);
|
||||
strictEqual(await ctx.proxy.rows, 1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
async function loadFit(width: number = 800, height: number = 450): Promise<void> {
|
||||
await ctx.page.evaluate(`
|
||||
window.fit = new FitAddon();
|
||||
window.term.loadAddon(window.fit);
|
||||
document.querySelector('#terminal-container').style.width='${width}px';
|
||||
document.querySelector('#terminal-container').style.height='${height}px';
|
||||
`);
|
||||
}
|
||||
|
||||
async function unloadFit(): Promise<void> {
|
||||
await ctx.page.evaluate(`window.fit.dispose();`);
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { PlaywrightTestConfig } from '@playwright/test';
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
testDir: '.',
|
||||
timeout: 10000,
|
||||
projects: [
|
||||
{
|
||||
name: 'ChromeStable',
|
||||
use: {
|
||||
browserName: 'chromium',
|
||||
channel: 'chrome'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'FirefoxStable',
|
||||
use: {
|
||||
browserName: 'firefox'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'WebKit',
|
||||
use: {
|
||||
browserName: 'webkit'
|
||||
}
|
||||
}
|
||||
],
|
||||
reporter: 'list',
|
||||
webServer: {
|
||||
command: 'npm run start-server-only',
|
||||
port: 3000,
|
||||
timeout: 120000,
|
||||
reuseExistingServer: !process.env.CI
|
||||
}
|
||||
};
|
||||
export default config;
|
||||
@@ -3,21 +3,37 @@
|
||||
"module": "commonjs",
|
||||
"target": "es2021",
|
||||
"lib": [
|
||||
"es2015"
|
||||
"es2021",
|
||||
],
|
||||
"rootDir": ".",
|
||||
"outDir": "../out-test",
|
||||
"sourceMap": true,
|
||||
"removeComments": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
"../../../src/browser/*"
|
||||
]
|
||||
},
|
||||
"strict": true,
|
||||
"types": [
|
||||
"../../../node_modules/@types/mocha",
|
||||
"../../../node_modules/@types/node",
|
||||
"../../../out-test/api/TestUtils"
|
||||
"../../../out-test/playwright/TestUtils"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"./**/*",
|
||||
"../../../typings/xterm.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../../src/common"
|
||||
},
|
||||
{
|
||||
"path": "../../../src/browser"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,489 @@
|
||||
/**
|
||||
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import test from '@playwright/test';
|
||||
import { deepStrictEqual, strictEqual } from 'assert';
|
||||
import { readFile } from 'fs';
|
||||
import { resolve } from 'path';
|
||||
import { ITestContext, createTestContext, openTerminal, timeout } from '../../../out-test/playwright/TestUtils';
|
||||
|
||||
let ctx: ITestContext;
|
||||
test.beforeAll(async ({ browser }) => {
|
||||
ctx = await createTestContext(browser);
|
||||
await openTerminal(ctx);
|
||||
});
|
||||
test.afterAll(async () => await ctx.page.close());
|
||||
|
||||
test.describe('Search Tests', () => {
|
||||
|
||||
test.beforeEach(async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.term.reset()
|
||||
window.search?.dispose();
|
||||
window.search = new SearchAddon();
|
||||
window.term.loadAddon(window.search);
|
||||
`);
|
||||
});
|
||||
|
||||
test('Simple Search', async () => {
|
||||
await ctx.proxy.write('dafhdjfldshafhldsahfkjhldhjkftestlhfdsakjfhdjhlfdsjkafhjdlk');
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('test')`), true);
|
||||
deepStrictEqual(await ctx.proxy.getSelection(), 'test');
|
||||
});
|
||||
|
||||
test('Scrolling Search', async () => {
|
||||
let dataString = '';
|
||||
for (let i = 0; i < 100; i++) {
|
||||
if (i === 52) {
|
||||
dataString += '$^1_3{}test$#';
|
||||
}
|
||||
dataString += makeData(50);
|
||||
}
|
||||
await ctx.proxy.write(dataString);
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('$^1_3{}test$#')`), true);
|
||||
deepStrictEqual(await ctx.proxy.getSelection(), '$^1_3{}test$#');
|
||||
});
|
||||
test('Incremental Find Previous', async () => {
|
||||
await ctx.proxy.writeln(`package.jsonc\n`);
|
||||
await ctx.proxy.write('package.json pack package.lock');
|
||||
await ctx.page.evaluate(`window.search.findPrevious('pack', {incremental: true})`);
|
||||
let selectionPosition: { start: { x: number, y: number }, end: { x: number, y: number } } = (await ctx.proxy.getSelectionPosition())!;
|
||||
let line: string = await (await ctx.proxy.buffer.active.getLine(selectionPosition.start.y))!.translateToString();
|
||||
// We look further ahead in the line to ensure that pack was selected from package.lock
|
||||
deepStrictEqual(line.substring(selectionPosition.start.x, selectionPosition.end.x + 8), 'package.lock');
|
||||
await ctx.page.evaluate(`window.search.findPrevious('package.j', {incremental: true})`);
|
||||
selectionPosition = (await ctx.proxy.getSelectionPosition())!;
|
||||
deepStrictEqual(line.substring(selectionPosition.start.x, selectionPosition.end.x + 3), 'package.json');
|
||||
await ctx.page.evaluate(`window.search.findPrevious('package.jsonc', {incremental: true})`);
|
||||
// We have to reevaluate line because it should have switched starting rows at this point
|
||||
selectionPosition = (await ctx.proxy.getSelectionPosition())!;
|
||||
line = await (await ctx.proxy.buffer.active.getLine(selectionPosition.start.y))!.translateToString();
|
||||
deepStrictEqual(line.substring(selectionPosition.start.x, selectionPosition.end.x), 'package.jsonc');
|
||||
});
|
||||
test('Incremental Find Next', async () => {
|
||||
await ctx.proxy.writeln(`package.lock pack package.json package.ups\n`);
|
||||
await ctx.proxy.write('package.jsonc');
|
||||
await ctx.page.evaluate(`window.search.findNext('pack', {incremental: true})`);
|
||||
let selectionPosition: { start: { x: number, y: number }, end: { x: number, y: number } } = (await ctx.proxy.getSelectionPosition())!;
|
||||
let line: string = await (await ctx.proxy.buffer.active.getLine(selectionPosition.start.y))!.translateToString();
|
||||
// We look further ahead in the line to ensure that pack was selected from package.lock
|
||||
deepStrictEqual(line.substring(selectionPosition.start.x, selectionPosition.end.x + 8), 'package.lock');
|
||||
await ctx.page.evaluate(`window.search.findNext('package.j', {incremental: true})`);
|
||||
selectionPosition = (await ctx.proxy.getSelectionPosition())!;
|
||||
deepStrictEqual(line.substring(selectionPosition.start.x, selectionPosition.end.x + 3), 'package.json');
|
||||
await ctx.page.evaluate(`window.search.findNext('package.jsonc', {incremental: true})`);
|
||||
// We have to reevaluate line because it should have switched starting rows at this point
|
||||
selectionPosition = (await ctx.proxy.getSelectionPosition())!;
|
||||
line = await (await ctx.proxy.buffer.active.getLine(selectionPosition.start.y))!.translateToString();
|
||||
deepStrictEqual(line.substring(selectionPosition.start.x, selectionPosition.end.x), 'package.jsonc');
|
||||
});
|
||||
test('Simple Regex', async () => {
|
||||
await ctx.proxy.write('abc123defABCD');
|
||||
await ctx.page.evaluate(`window.search.findNext('[a-z]+', {regex: true})`);
|
||||
deepStrictEqual(await ctx.proxy.getSelection(), 'abc');
|
||||
await ctx.page.evaluate(`window.search.findNext('[A-Z]+', {regex: true, caseSensitive: true})`);
|
||||
deepStrictEqual(await ctx.proxy.getSelection(), 'ABCD');
|
||||
});
|
||||
|
||||
test('Search for single result twice should not unselect it', async () => {
|
||||
await ctx.proxy.write('abc def');
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('abc')`), true);
|
||||
deepStrictEqual(await ctx.proxy.getSelection(), 'abc');
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('abc')`), true);
|
||||
deepStrictEqual(await ctx.proxy.getSelection(), 'abc');
|
||||
});
|
||||
|
||||
test('Search for result bounding with wide unicode chars', async () => {
|
||||
await ctx.proxy.write('中文xx𝄞𝄞');
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('中')`), true);
|
||||
deepStrictEqual(await ctx.proxy.getSelection(), '中');
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('xx')`), true);
|
||||
deepStrictEqual(await ctx.proxy.getSelection(), 'xx');
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('𝄞')`), true);
|
||||
deepStrictEqual(await ctx.proxy.getSelection(), '𝄞');
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('𝄞')`), true);
|
||||
deepStrictEqual(await ctx.proxy.getSelectionPosition(), {
|
||||
start: {
|
||||
x: 7,
|
||||
y: 0
|
||||
},
|
||||
end: {
|
||||
x: 8,
|
||||
y: 0
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('onDidChangeResults', async () => {
|
||||
test.describe('findNext', () => {
|
||||
test('should not fire unless the decorations option is set', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.calls = [];
|
||||
window.search.onDidChangeResults(e => window.calls.push(e));
|
||||
`);
|
||||
await ctx.proxy.write('abc');
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findNext('a')`), true);
|
||||
strictEqual(await ctx.page.evaluate('window.calls.length'), 0);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findNext('b', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
strictEqual(await ctx.page.evaluate('window.calls.length'), 1);
|
||||
});
|
||||
test('should fire with correct event values', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.calls = [];
|
||||
window.search.onDidChangeResults(e => window.calls.push(e));
|
||||
`);
|
||||
await ctx.proxy.write('abc bc c');
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findNext('a', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1, resultIndex: 0 }
|
||||
]);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findNext('b', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 0 }
|
||||
]);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findNext('d', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), false);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 0 },
|
||||
{ resultCount: 0, resultIndex: -1 }
|
||||
]);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findNext('c', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findNext('c', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findNext('c', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 0 },
|
||||
{ resultCount: 0, resultIndex: -1 },
|
||||
{ resultCount: 3, resultIndex: 0 },
|
||||
{ resultCount: 3, resultIndex: 1 },
|
||||
{ resultCount: 3, resultIndex: 2 }
|
||||
]);
|
||||
});
|
||||
test('should fire with correct event values (incremental)', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.calls = [];
|
||||
window.search.onDidChangeResults(e => window.calls.push(e));
|
||||
`);
|
||||
await ctx.proxy.write('d abc aabc d');
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('a', { incremental: true, decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 3, resultIndex: 0 }
|
||||
]);
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('ab', { incremental: true, decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 3, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 0 }
|
||||
]);
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('abc', { incremental: true, decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 3, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 0 }
|
||||
]);
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('abc', { incremental: true, decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 3, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 1 }
|
||||
]);
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('d', { incremental: true, decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 3, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 2, resultIndex: 1 }
|
||||
]);
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('abcd', { incremental: true, decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), false);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 3, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 0, resultIndex: -1 }
|
||||
]);
|
||||
});
|
||||
test('should fire with more than 1k matches', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.calls = [];
|
||||
window.search.onDidChangeResults(e => window.calls.push(e));
|
||||
`);
|
||||
const data = ('a bc'.repeat(10) + '\\n\\r').repeat(150);
|
||||
await ctx.proxy.write(data);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findNext('a', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1000, resultIndex: 0 }
|
||||
]);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findNext('a', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1000, resultIndex: 0 },
|
||||
{ resultCount: 1000, resultIndex: 1 }
|
||||
]);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findNext('bc', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1000, resultIndex: 0 },
|
||||
{ resultCount: 1000, resultIndex: 1 },
|
||||
{ resultCount: 1000, resultIndex: 1 }
|
||||
]);
|
||||
});
|
||||
test('should fire when writing to terminal', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.calls = [];
|
||||
window.search.onDidChangeResults(e => window.calls.push(e));
|
||||
`);
|
||||
await ctx.proxy.write('abc bc c\\n\\r'.repeat(2));
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findNext('abc', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 2, resultIndex: 0 }
|
||||
]);
|
||||
await ctx.proxy.write('abc bc c\\n\\r');
|
||||
await timeout(300);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 2, resultIndex: 0 },
|
||||
{ resultCount: 3, resultIndex: 0 }
|
||||
]);
|
||||
});
|
||||
});
|
||||
test.describe('findPrevious', () => {
|
||||
test('should not fire unless the decorations option is set', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.calls = [];
|
||||
window.search.onDidChangeResults(e => window.calls.push(e));
|
||||
`);
|
||||
await ctx.proxy.write('abc');
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('a')`), true);
|
||||
strictEqual(await ctx.page.evaluate('window.calls.length'), 0);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('b', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
strictEqual(await ctx.page.evaluate('window.calls.length'), 1);
|
||||
});
|
||||
test('should fire with correct event values', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.calls = [];
|
||||
window.search.onDidChangeResults(e => window.calls.push(e));
|
||||
`);
|
||||
await ctx.proxy.write('abc bc c');
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('a', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1, resultIndex: 0 }
|
||||
]);
|
||||
await ctx.page.evaluate(`window.term.clearSelection()`);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('b', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 1 }
|
||||
]);
|
||||
await timeout(2000);
|
||||
strictEqual(await ctx.page.evaluate(`debugger; window.search.findPrevious('d', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), false);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 0, resultIndex: -1 }
|
||||
]);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('c', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('c', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('c', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 0, resultIndex: -1 },
|
||||
{ resultCount: 3, resultIndex: 2 },
|
||||
{ resultCount: 3, resultIndex: 1 },
|
||||
{ resultCount: 3, resultIndex: 0 }
|
||||
]);
|
||||
});
|
||||
test('should fire with correct event values (incremental)', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.calls = [];
|
||||
window.search.onDidChangeResults(e => window.calls.push(e));
|
||||
`);
|
||||
await ctx.proxy.write('d abc aabc d');
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('a', { incremental: true, decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 3, resultIndex: 2 }
|
||||
]);
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('ab', { incremental: true, decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 3, resultIndex: 2 },
|
||||
{ resultCount: 2, resultIndex: 1 }
|
||||
]);
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('abc', { incremental: true, decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 3, resultIndex: 2 },
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 2, resultIndex: 1 }
|
||||
]);
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('abc', { incremental: true, decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 3, resultIndex: 2 },
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 2, resultIndex: 0 }
|
||||
]);
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('d', { incremental: true, decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 3, resultIndex: 2 },
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 2, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 1 }
|
||||
]);
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('abcd', { incremental: true, decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), false);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 3, resultIndex: 2 },
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 2, resultIndex: 0 },
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 0, resultIndex: -1 }
|
||||
]);
|
||||
});
|
||||
test('should fire with more than 1k matches', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.calls = [];
|
||||
window.search.onDidChangeResults(e => window.calls.push(e));
|
||||
`);
|
||||
const data = ('a bc'.repeat(10) + '\\n\\r').repeat(150);
|
||||
await ctx.proxy.write(data);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('a', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1000, resultIndex: -1 }
|
||||
]);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('a', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1000, resultIndex: -1 },
|
||||
{ resultCount: 1000, resultIndex: -1 }
|
||||
]);
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('bc', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 1000, resultIndex: -1 },
|
||||
{ resultCount: 1000, resultIndex: -1 },
|
||||
{ resultCount: 1000, resultIndex: -1 }
|
||||
]);
|
||||
});
|
||||
test('should fire when writing to terminal', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.calls = [];
|
||||
window.search.onDidChangeResults(e => window.calls.push(e));
|
||||
`);
|
||||
await ctx.proxy.write('abc bc c\\n\\r'.repeat(2));
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('abc', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 2, resultIndex: 1 }
|
||||
]);
|
||||
await ctx.proxy.write('abc bc c\\n\\r');
|
||||
await timeout(300);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 2, resultIndex: 1 },
|
||||
{ resultCount: 3, resultIndex: 1 }
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Regression tests', () => {
|
||||
test.describe('#2444 wrapped line content not being found', () => {
|
||||
let fixture: string;
|
||||
test.beforeAll(async () => {
|
||||
fixture = (await new Promise<Buffer>(r => readFile(resolve(__dirname, '../fixtures/issue-2444'), (err, data) => r(data)))).toString();
|
||||
});
|
||||
test('should find all occurrences using findNext', async () => {
|
||||
await ctx.proxy.write(fixture);
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('opencv')`), true);
|
||||
let selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 24, y: 53 }, end: { x: 30, y: 53 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 24, y: 76 }, end: { x: 30, y: 76 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 24, y: 96 }, end: { x: 30, y: 96 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 1, y: 114 }, end: { x: 7, y: 114 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 11, y: 115 }, end: { x: 17, y: 115 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 1, y: 126 }, end: { x: 7, y: 126 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 11, y: 127 }, end: { x: 17, y: 127 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 1, y: 135 }, end: { x: 7, y: 135 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 11, y: 136 }, end: { x: 17, y: 136 } });
|
||||
// Wrap around to first result
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findNext('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 24, y: 53 }, end: { x: 30, y: 53 } });
|
||||
});
|
||||
|
||||
test('should y all occurrences using findPrevious', async () => {
|
||||
await ctx.proxy.write(fixture);
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('opencv')`), true);
|
||||
let selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 11, y: 136 }, end: { x: 17, y: 136 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 1, y: 135 }, end: { x: 7, y: 135 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 11, y: 127 }, end: { x: 17, y: 127 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 1, y: 126 }, end: { x: 7, y: 126 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 11, y: 115 }, end: { x: 17, y: 115 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 1, y: 114 }, end: { x: 7, y: 114 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 24, y: 96 }, end: { x: 30, y: 96 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 24, y: 76 }, end: { x: 30, y: 76 } });
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 24, y: 53 }, end: { x: 30, y: 53 } });
|
||||
// Wrap around to first result
|
||||
deepStrictEqual(await ctx.page.evaluate(`window.search.findPrevious('opencv')`), true);
|
||||
selectionPosition = await ctx.proxy.getSelectionPosition();
|
||||
deepStrictEqual(selectionPosition, { start: { x: 11, y: 136 }, end: { x: 17, y: 136 } });
|
||||
});
|
||||
});
|
||||
});
|
||||
test.describe('#3834 lines with null characters before search terms', () => {
|
||||
// This case can be triggered by the prompt when using starship under conpty
|
||||
test('should find all matches on a line containing null characters', async () => {
|
||||
await ctx.page.evaluate(`
|
||||
window.calls = [];
|
||||
window.search.onDidChangeResults(e => window.calls.push(e));
|
||||
`);
|
||||
// Move cursor forward 1 time to create a null character, as opposed to regular whitespace
|
||||
await ctx.proxy.write('\\x1b[CHi Hi');
|
||||
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('h', { decorations: { activeMatchColorOverviewRuler: '#ff0000' } })`), true);
|
||||
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
||||
{ resultCount: 2, resultIndex: 1 }
|
||||
]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function makeData(length: number): string {
|
||||
let result = '';
|
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
for (let i = 0; i < length; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * characters.length));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import { PlaywrightTestConfig } from '@playwright/test';
|
||||
|
||||
const config: PlaywrightTestConfig = {
|
||||
testDir: '.',
|
||||
timeout: 10000,
|
||||
projects: [
|
||||
{
|
||||
name: 'Chrome Stable',
|
||||
use: {
|
||||
browserName: 'chromium',
|
||||
channel: 'chrome'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'Firefox Stable',
|
||||
use: {
|
||||
browserName: 'firefox'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'WebKit',
|
||||
use: {
|
||||
browserName: 'webkit'
|
||||
}
|
||||
}
|
||||
],
|
||||
reporter: 'list',
|
||||
webServer: {
|
||||
command: 'npm run start-server-only',
|
||||
port: 3000,
|
||||
timeout: 120000,
|
||||
reuseExistingServer: !process.env.CI
|
||||
}
|
||||
};
|
||||
export default config;
|
||||
@@ -9,15 +9,31 @@
|
||||
"outDir": "../out-test",
|
||||
"sourceMap": true,
|
||||
"removeComments": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"common/*": [
|
||||
"../../../src/common/*"
|
||||
],
|
||||
"browser/*": [
|
||||
"../../../src/browser/*"
|
||||
]
|
||||
},
|
||||
"strict": true,
|
||||
"types": [
|
||||
"../../../node_modules/@types/mocha",
|
||||
"../../../node_modules/@types/node",
|
||||
"../../../out-test/api/TestUtils"
|
||||
"../../../out-test/playwright/TestUtils"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"./**/*",
|
||||
"../../../typings/xterm.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "../../../src/common"
|
||||
},
|
||||
{
|
||||
"path": "../../../src/browser"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -18,9 +18,13 @@ while (argv.some(e => e.startsWith('--suite='))) {
|
||||
}
|
||||
|
||||
let configs = [
|
||||
{ name: 'core', path: 'out-test/playwright/playwright.config.js' },
|
||||
{ name: 'addon-canvas', path: 'addons/addon-canvas/out-test/playwright.config.js' },
|
||||
{ name: 'addon-webgl', path: 'addons/addon-webgl/out-test/playwright.config.js' }
|
||||
{ name: 'core', path: 'out-test/playwright/playwright.config.js' },
|
||||
{ name: 'addon-attach', path: 'addons/addon-attach/out-test/playwright.config.js' },
|
||||
{ name: 'addon-canvas', path: 'addons/addon-canvas/out-test/playwright.config.js' },
|
||||
{ name: 'addon-clipboard', path: 'addons/addon-clipboard/out-test/playwright.config.js' },
|
||||
{ name: 'addon-fit', path: 'addons/addon-fit/out-test/playwright.config.js' },
|
||||
{ name: 'addon-search', path: 'addons/addon-search/out-test/playwright.config.js' },
|
||||
{ name: 'addon-webgl', path: 'addons/addon-webgl/out-test/playwright.config.js' }
|
||||
];
|
||||
|
||||
if (suiteFilter) {
|
||||
|
||||
Reference in New Issue
Block a user