/
WebLinksAddon.api.ts
139 lines (122 loc) · 5.62 KB
/
WebLinksAddon.api.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/**
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
* @license MIT
*/
import { assert } from 'chai';
import { openTerminal, pollFor, writeSync, launchBrowser } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright';
const APP = 'http://127.0.0.1:3001/test';
let browser: Browser;
let page: Page;
const width = 800;
const height = 600;
interface ILinkStateData {
uri?: string;
range?: {
start: {
x: number;
y: number;
};
end: {
x: number;
y: number;
};
};
}
describe('WebLinksAddon', () => {
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('.com', async function(): Promise<any> {
await testHostName('foo.com');
});
it('.com.au', async function(): Promise<any> {
await testHostName('foo.com.au');
});
it('.io', async function(): Promise<any> {
await testHostName('foo.io');
});
describe('correct buffer offsets & uri', () => {
it('all half width', async () => {
setupCustom();
await writeSync(page, 'aaa http://example.com aaa http://example.com aaa');
await resetAndHover(5, 1);
await evalLinkStateData('http://example.com', { start: { x: 5, y: 1 }, end: { x: 22, y: 1 } });
await resetAndHover(1, 2);
await evalLinkStateData('http://example.com', { start: { x: 28, y: 1 }, end: { x: 5, y: 2 } });
});
it('url after full width', async () => {
setupCustom();
await writeSync(page, '¥¥¥ http://example.com ¥¥¥ http://example.com aaa');
await resetAndHover(8, 1);
await evalLinkStateData('http://example.com', { start: { x: 8, y: 1 }, end: { x: 25, y: 1 } });
await resetAndHover(1, 2);
await evalLinkStateData('http://example.com', { start: { x: 34, y: 1 }, end: { x: 11, y: 2 } });
});
it('full width within url and before', async () => {
setupCustom();
await writeSync(page, '¥¥¥ https://ko.wikipedia.org/wiki/위키백과:대문 aaa https://ko.wikipedia.org/wiki/위키백과:대문 ¥¥¥');
await resetAndHover(8, 1);
await evalLinkStateData('https://ko.wikipedia.org/wiki/위키백과:대문', { start: { x: 8, y: 1 }, end: { x: 11, y: 2 } });
await resetAndHover(1, 2);
await evalLinkStateData('https://ko.wikipedia.org/wiki/위키백과:대문', { start: { x: 8, y: 1 }, end: { x: 11, y: 2 } });
await resetAndHover(17, 2);
await evalLinkStateData('https://ko.wikipedia.org/wiki/위키백과:대문', { start: { x: 17, y: 2 }, end: { x: 19, y: 3 } });
});
it('name + password url after full width and combining', async () => {
setupCustom();
await writeSync(page, '¥¥¥cafe\u0301 http://test:password@example.com/some_path');
await resetAndHover(12, 1);
await evalLinkStateData('http://test:password@example.com/some_path', { start: { x: 12, y: 1 }, end: { x: 13, y: 2 } });
await resetAndHover(13, 2);
await evalLinkStateData('http://test:password@example.com/some_path', { start: { x: 12, y: 1 }, end: { x: 13, y: 2 } });
});
});
});
async function testHostName(hostname: string): Promise<void> {
await openTerminal(page, { cols: 40 });
await page.evaluate(`window.term.loadAddon(new window.WebLinksAddon())`);
const data = ` http://${hostname} \\r\\n` +
` http://${hostname}/a~b#c~d?e~f \\r\\n` +
` http://${hostname}/colon:test \\r\\n` +
` http://${hostname}/colon:test: \\r\\n` +
`"http://${hostname}/"\\r\\n` +
`\\'http://${hostname}/\\'\\r\\n` +
`http://${hostname}/subpath/+/id`;
await writeSync(page, data);
await pollForLinkAtCell(3, 1, `http://${hostname}`);
await pollForLinkAtCell(3, 2, `http://${hostname}/a~b#c~d?e~f`);
await pollForLinkAtCell(3, 3, `http://${hostname}/colon:test`);
await pollForLinkAtCell(3, 4, `http://${hostname}/colon:test`);
await pollForLinkAtCell(2, 5, `http://${hostname}/`);
await pollForLinkAtCell(2, 6, `http://${hostname}/`);
await pollForLinkAtCell(1, 7, `http://${hostname}/subpath/+/id`);
}
async function pollForLinkAtCell(col: number, row: number, value: string): Promise<void> {
const rowSelector = `.xterm-rows > :nth-child(${row})`;
// Ensure the hover element exists before trying to hover it
await pollFor(page, `!!document.querySelector('${rowSelector} > :nth-child(${col})')`, true);
await pollFor(page, `document.querySelectorAll('${rowSelector} > span[style]').length >= ${value.length}`, true, async () => page.hover(`${rowSelector} > :nth-child(${col})`));
assert.equal(await page.evaluate(`Array.prototype.reduce.call(document.querySelectorAll('${rowSelector} > span[style]'), (a, b) => a + b.textContent, '');`), value);
}
async function setupCustom(): Promise<void> {
await openTerminal(page, { cols: 40 });
await page.evaluate(`window._linkStateData = {};
window._linkaddon = new window.WebLinksAddon();
window._linkaddon._options.hover = (event, uri, range) => { window._linkStateData = { uri, range }; };
window.term.loadAddon(window._linkaddon);`);
}
async function resetAndHover(col: number, row: number): Promise<void> {
await page.evaluate(`window._linkStateData = {};`);
const rowSelector = `.xterm-rows > :nth-child(${row})`;
await page.hover(`${rowSelector} > :nth-child(${col})`);
}
async function evalLinkStateData(uri: string, range: any): Promise<void> {
const data: ILinkStateData = await page.evaluate(`window._linkStateData`);
assert.equal(data.uri, uri);
assert.deepEqual(data.range, range);
}