beforeAll always resolved the readFile promise with data even when err was set, which led to calling toString on undefined. Reject the promise on err so fixture load failures surface clearly. Use res/rej callback names to avoid shadowing path.resolve. Co-authored-by: Cursor <cursoragent@cursor.com>
572 lines
31 KiB
TypeScript
572 lines
31 KiB
TypeScript
/**
|
|
* 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 '../../../test/playwright/TestUtils';
|
|
|
|
let ctx: ITestContext;
|
|
test.beforeAll(async ({ browser }) => {
|
|
ctx = await createTestContext(browser);
|
|
await openTerminal(ctx, { cols: 80, rows: 24 });
|
|
});
|
|
test.afterAll(async () => await ctx.page.close());
|
|
|
|
test.describe('Search Tests', () => {
|
|
|
|
test.beforeEach(async () => {
|
|
await ctx.proxy.reset();
|
|
await ctx.page.evaluate(`
|
|
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('onBeforeSearch and onAfterSearch', () => {
|
|
test.beforeEach(async () => {
|
|
await ctx.page.evaluate(`
|
|
window.events = [];
|
|
window.search.onBeforeSearch(() => window.events.push('before'));
|
|
window.search.onAfterSearch(() => window.events.push('after'));
|
|
`);
|
|
});
|
|
test('should fire before and after findNext', async () => {
|
|
await ctx.proxy.write('abc');
|
|
await ctx.page.evaluate(`window.search.findNext('a')`);
|
|
deepStrictEqual(await ctx.page.evaluate('window.events'), ['before', 'after']);
|
|
});
|
|
|
|
test('should fire before and after findPrevious', async () => {
|
|
await ctx.proxy.write('abc');
|
|
await ctx.page.evaluate(`window.search.findPrevious('a')`);
|
|
deepStrictEqual(await ctx.page.evaluate('window.events'), ['before', 'after']);
|
|
});
|
|
|
|
test('should fire for each search call', async () => {
|
|
await ctx.proxy.write('abc abc');
|
|
await ctx.page.evaluate(`window.search.findNext('abc')`);
|
|
await ctx.page.evaluate(`window.search.findNext('abc')`);
|
|
deepStrictEqual(await ctx.page.evaluate('window.events'), ['before', 'after', 'before', 'after']);
|
|
});
|
|
});
|
|
|
|
test.describe('Regression tests', () => {
|
|
test.describe('#2444 wrapped line content not being found', () => {
|
|
let fixture: string;
|
|
test.beforeAll(async () => {
|
|
fixture = (await new Promise<Buffer>((res, rej) => readFile(resolve(__dirname, '../fixtures/issue-2444'), (err, data) => err ? rej(err) : res(data)))).toString();
|
|
if (process.platform !== 'win32') {
|
|
fixture = fixture.replace(/\n/g, '\n\r');
|
|
}
|
|
});
|
|
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 }
|
|
]);
|
|
});
|
|
});
|
|
|
|
test.describe('Wrapped line search functionality', () => {
|
|
test('should correctly count matches across multiple wrapped lines', async () => {
|
|
await ctx.page.evaluate(`
|
|
window.calls = [];
|
|
window.search.onDidChangeResults(e => window.calls.push(e));
|
|
`);
|
|
|
|
const content = 'a'.repeat(300);
|
|
await ctx.proxy.write(content);
|
|
strictEqual(await ctx.page.evaluate(`window.search.findNext('${content}', { decorations: { activeMatchColorOverviewRuler: '#ff0000', matchOverviewRuler: '#ffff00' } })`), true);
|
|
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
|
{ resultCount: 1, resultIndex: 0 }
|
|
]);
|
|
});
|
|
|
|
test('should handle reverse search across wrapped lines', async () => {
|
|
await ctx.page.evaluate(`
|
|
window.calls = [];
|
|
window.search.onDidChangeResults(e => window.calls.push(e));
|
|
`);
|
|
|
|
const content = 'x'.repeat(300);
|
|
await ctx.proxy.write(content);
|
|
strictEqual(await ctx.page.evaluate(`window.search.findPrevious('${content}', { decorations: { activeMatchColorOverviewRuler: '#ff0000', matchOverviewRuler: '#ffff00' } })`), true);
|
|
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
|
{ resultCount: 1, resultIndex: 0 }
|
|
]);
|
|
});
|
|
|
|
test('should update counts when content changes across wrapped lines', async () => {
|
|
await ctx.page.evaluate(`
|
|
window.calls = [];
|
|
window.search.onDidChangeResults(e => window.calls.push(e));
|
|
`);
|
|
|
|
const content = 'z'.repeat(300);
|
|
await ctx.proxy.write(content);
|
|
strictEqual(await ctx.page.evaluate(`window.search.findNext('${content}', { decorations: { activeMatchColorOverviewRuler: '#ff0000', matchOverviewRuler: '#ffff00' } })`), true);
|
|
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
|
{ resultCount: 1, resultIndex: 0 }
|
|
]);
|
|
|
|
await ctx.proxy.write('\\n\\r' + content);
|
|
await timeout(300);
|
|
deepStrictEqual(await ctx.page.evaluate('window.calls'), [
|
|
{ resultCount: 1, resultIndex: 0 },
|
|
{ resultCount: 2, resultIndex: 0 }
|
|
]);
|
|
});
|
|
});
|
|
});
|
|
|
|
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;
|
|
}
|