Merge remote-tracking branch 'upstream/master' into de_vs

This commit is contained in:
Daniel Imms
2026-02-03 07:05:50 -08:00
51 changed files with 1328 additions and 679 deletions
+291 -227
View File
@@ -227,9 +227,9 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[2S');
await pollFor(ctx.page, () => getLinesAsArray(5), ['3', '4', '5', '', '']);
});
test.skip('CSI ? Pi ; Pa ; Pv S - XTSMGRAPHICS: Set or request graphics attribute, xterm', async () => {
// TODO: Implement
});
// This is intentionally not implemented here are image support lives within an addon
// test.skip('CSI ? Pi ; Pa ; Pv S - XTSMGRAPHICS: Set or request graphics attribute, xterm', async () => {
// });
test('CSI Ps T - SD: Scroll down Ps lines (default = 1), VT420', async () => {
await ctx.proxy.write('1\r\n2\r\n3\r\n4\r\n5');
await pollFor(ctx.page, () => getLinesAsArray(5), ['1', '2', '3', '4', '5']);
@@ -316,14 +316,16 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('abcdefg\x1b[3D\x1b[10b#\x1b[3b');
await pollFor(ctx.page, () => getLinesAsArray(3), ['#', ' #', 'abcd####']);
});
test.skip('CSI Ps c - ', async () => {
// TODO: Implement
test('CSI Ps c - ', async () => {
await ctx.proxy.write('\x1b[c');
await pollFor(ctx.page, () => recordedData, ['\x1b[?1;2c']);
});
test.skip('CSI = Ps c - ', async () => {
// TODO: Implement
});
test.skip('CSI > Ps c - ', async () => {
// TODO: Implement
test('CSI > Ps c - ', async () => {
await ctx.proxy.write('\x1b[>c');
await pollFor(ctx.page, () => recordedData, ['\x1b[>0;276;0c']);
});
test('CSI Ps d - VPA: Line Position Absolute [row] (default = [1,column])', async () => {
// Default
@@ -384,11 +386,11 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.resize(80, 24);
await ctx.proxy.setOption('windowOptions', windowOptions);
});
test.skip('Ps = 4 - Smooth (Slow) Scroll (DECSCLM), VT100', async () => {
// TODO: Implement
test('Ps = 4 - Smooth (Slow) Scroll (DECSCLM), VT100', async () => {
await assertNoModeChange('\x1b[?4h');
});
test.skip('Ps = 5 - Reverse Video (DECSCNM), VT100', async () => {
// TODO: Implement
test('Ps = 5 - Reverse Video (DECSCNM), VT100', async () => {
await assertNoModeChange('\x1b[?5h');
});
test('Ps = 6 - Origin Mode (DECOM), VT100', async () => {
await ctx.proxy.write('\x1b[?6h');
@@ -411,8 +413,8 @@ test.describe('InputHandler Integration Tests', () => {
await pollFor(ctx.page, () => getLinesAsArray(1), ['1234X']);
await ctx.proxy.resize(80, 24);
});
test.skip('Ps = 8 - Auto-Repeat Keys (DECARM), VT100', async () => {
// TODO: Implement
test('Ps = 8 - Auto-Repeat Keys (DECARM), VT100', async () => {
await assertNoModeChange('\x1b[?8h');
});
test('Ps = 9 - Send Mouse X & Y on button press', async () => {
const selectionBefore = await dragSelection();
@@ -422,23 +424,29 @@ test.describe('InputHandler Integration Tests', () => {
const selectionAfter = await dragSelection();
ok(selectionAfter === 0);
});
test.skip('Ps = 1 0 - Show toolbar (rxvt)', async () => {
// TODO: Implement
test('Ps = 1 0 - Show toolbar (rxvt)', async () => {
await assertNoModeChange('\x1b[?10h');
});
test.skip('Ps = 1 2 - Start blinking cursor (AT&T 610)', async () => {
// TODO: Implement
test('Ps = 1 2 - Start blinking cursor (AT&T 610)', async () => {
const previousQuirks = await ctx.proxy.getOption('quirks');
const previousCursorBlink = await ctx.proxy.getOption('cursorBlink');
await ctx.proxy.setOption('quirks', { ...(previousQuirks ?? {}), allowSetCursorBlink: true });
await ctx.proxy.write('\x1b[?12h');
await pollFor(ctx.page, async () => await ctx.proxy.getOption('cursorBlink'), true);
await ctx.proxy.setOption('quirks', previousQuirks);
await ctx.proxy.setOption('cursorBlink', previousCursorBlink);
});
test.skip('Ps = 1 3 - Start blinking cursor (set only via resource or menu)', async () => {
// TODO: Implement
test('Ps = 1 3 - Start blinking cursor (set only via resource or menu)', async () => {
await assertNoModeChange('\x1b[?13h');
});
test.skip('Ps = 1 4 - Enable XOR of blinking cursor control sequence and menu', async () => {
// TODO: Implement
test('Ps = 1 4 - Enable XOR of blinking cursor control sequence and menu', async () => {
await assertNoModeChange('\x1b[?14h');
});
test.skip('Ps = 1 8 - Print Form Feed (DECPFF), VT220', async () => {
// TODO: Implement
test('Ps = 1 8 - Print Form Feed (DECPFF), VT220', async () => {
await assertNoModeChange('\x1b[?18h');
});
test.skip('Ps = 1 9 - Set print extent to full screen (DECPEX), VT220', async () => {
// TODO: Implement
test('Ps = 1 9 - Set print extent to full screen (DECPEX), VT220', async () => {
await assertNoModeChange('\x1b[?19h');
});
test('Ps = 2 5 - Show cursor (DECTCEM), VT220', async () => {
await ctx.proxy.write('\x1b[?25l');
@@ -446,32 +454,32 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[?25h');
await pollFor(ctx.page, async () => (await ctx.proxy.modes).showCursor, true);
});
test.skip('Ps = 3 0 - Show scrollbar (rxvt)', async () => {
// TODO: Implement
test('Ps = 3 0 - Show scrollbar (rxvt)', async () => {
await assertNoModeChange('\x1b[?30h');
});
test.skip('Ps = 3 5 - Enable font-shifting functions (rxvt)', async () => {
// TODO: Implement
test('Ps = 3 5 - Enable font-shifting functions (rxvt)', async () => {
await assertNoModeChange('\x1b[?35h');
});
test.skip('Ps = 3 8 - Enter Tektronix mode (DECTEK), VT240, xterm', async () => {
// TODO: Implement
test('Ps = 3 8 - Enter Tektronix mode (DECTEK), VT240, xterm', async () => {
await assertNoModeChange('\x1b[?38h');
});
test.skip('Ps = 4 0 - Allow 80 ⇒ 132 mode, xterm', async () => {
// TODO: Implement
test('Ps = 4 0 - Allow 80 ⇒ 132 mode, xterm', async () => {
await assertNoModeChange('\x1b[?40h');
});
test.skip('Ps = 4 1 - more(1) fix (see curses resource)', async () => {
// TODO: Implement
test('Ps = 4 1 - more(1) fix (see curses resource)', async () => {
await assertNoModeChange('\x1b[?41h');
});
test.skip('Ps = 4 2 - Enable National Replacement Character sets (DECNRCM), VT220', async () => {
// TODO: Implement
test('Ps = 4 2 - Enable National Replacement Character sets (DECNRCM), VT220', async () => {
await assertNoModeChange('\x1b[?42h');
});
test.skip('Ps = 4 3 - Enable Graphic Expanded Print Mode (DECGEPM), VT340', async () => {
// TODO: Implement
test('Ps = 4 3 - Enable Graphic Expanded Print Mode (DECGEPM), VT340', async () => {
await assertNoModeChange('\x1b[?43h');
});
test.skip('Ps = 4 4 - Turn on margin bell, xterm', async () => {
// TODO: Implement
test('Ps = 4 4 - Turn on margin bell, xterm', async () => {
await assertNoModeChange('\x1b[?44h');
});
test.skip('Ps = 4 4 - Enable Graphic Print Color Mode (DECGPCM), VT340', async () => {
// TODO: Implement
test('Ps = 4 4 - Enable Graphic Print Color Mode (DECGPCM), VT340', async () => {
await assertNoModeChange('\x1b[?44h');
});
test('Ps = 4 5 - Reverse-wraparound mode (XTREVWRAP), xterm', async () => {
await ctx.proxy.write('\x1b[?45h');
@@ -484,13 +492,12 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.resize(80, 24);
});
test.skip('Ps = 4 5 - Enable Graphic Print Color Syntax (DECGPCS), VT340', async () => {
// TODO: Implement
});
test.skip('Ps = 4 6 - Start logging (XTLOGGING), xterm', async () => {
// TODO: Implement
test('Ps = 4 6 - Start logging (XTLOGGING), xterm', async () => {
await assertNoModeChange('\x1b[?46h');
});
test.skip('Ps = 4 6 - Graphic Print Background Mode, VT340', async () => {
// TODO: Implement
test('Ps = 4 6 - Graphic Print Background Mode, VT340', async () => {
await assertNoModeChange('\x1b[?46h');
});
test('Ps = 4 7 - Use Alternate Screen Buffer, xterm', async () => {
await ctx.proxy.write('main');
@@ -505,23 +512,21 @@ test.describe('InputHandler Integration Tests', () => {
await pollFor(ctx.page, () => getLinesAsArray(1), ['main']);
});
test.skip('Ps = 4 7 - Enable Graphic Rotated Print Mode (DECGRPM), VT340', async () => {
// TODO: Implement
});
test('Ps = 6 6 - Application keypad mode (DECNKM), VT320', async () => {
await ctx.proxy.write('\x1b[?66h');
await pollFor(ctx.page, async () => (await ctx.proxy.modes).applicationKeypadMode, true);
});
test.skip('Ps = 6 7 - Backarrow key sends backspace (DECBKM), VT340, VT420', async () => {
// TODO: Implement
test('Ps = 6 7 - Backarrow key sends backspace (DECBKM), VT340, VT420', async () => {
await assertNoModeChange('\x1b[?67h');
});
test.skip('Ps = 6 9 - Enable left and right margin mode (DECLRMM), VT420 and up', async () => {
// TODO: Implement
test('Ps = 6 9 - Enable left and right margin mode (DECLRMM), VT420 and up', async () => {
await assertNoModeChange('\x1b[?69h');
});
test.skip('Ps = 8 0 - Enable Sixel Display Mode (DECSDM), VT330, VT340, VT382', async () => {
// TODO: Implement
});
test.skip('Ps = 9 5 - Do not clear screen when DECCOLM is set/reset (DECNCSM), VT510 and up', async () => {
// TODO: Implement
// test.skip('Ps = 8 0 - Enable Sixel Display Mode (DECSDM), VT330, VT340, VT382', async () => {
// });
test('Ps = 9 5 - Do not clear screen when DECCOLM is set/reset (DECNCSM), VT510 and up', async () => {
await assertNoModeChange('\x1b[?95h');
});
test('Ps = 1 0 0 0 - Send Mouse X & Y on button press and release', async () => {
const selectionBefore = await dragSelection();
@@ -531,8 +536,8 @@ test.describe('InputHandler Integration Tests', () => {
const selectionAfter = await dragSelection();
ok(selectionAfter === 0);
});
test.skip('Ps = 1 0 0 1 - Use Hilite Mouse Tracking, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 0 1 - Use Hilite Mouse Tracking, xterm', async () => {
await assertNoModeChange('\x1b[?1001h');
});
test('Ps = 1 0 0 2 - Use Cell Motion Mouse Tracking, xterm', async () => {
const selectionBefore = await dragSelection();
@@ -577,64 +582,70 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.blur();
await pollFor(ctx.page, () => recordedData, ['\x1b[I', '\x1b[O']);
});
test.skip('Ps = 1 0 0 5 - Enable UTF-8 Mouse Mode, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 0 5 - Enable UTF-8 Mouse Mode, xterm', async () => {
await ctx.proxy.write('\x1b[?1006h');
await pollFor(ctx.page, async () => await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeEncoding), 'SGR');
await ctx.proxy.write('\x1b[?1005h');
await pollFor(ctx.page, async () => await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeEncoding), 'SGR');
});
test('Ps = 1 0 0 6 - Enable SGR Mouse Mode, xterm', async () => {
await ctx.proxy.write('\x1b[?1006h');
await pollFor(ctx.page, async () => await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeEncoding), 'SGR');
});
test.skip('Ps = 1 0 0 7 - Enable Alternate Scroll Mode, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 0 7 - Enable Alternate Scroll Mode, xterm', async () => {
await assertNoModeChange('\x1b[?1007h');
});
test.skip('Ps = 1 0 1 0 - Scroll to bottom on tty output (rxvt)', async () => {
// TODO: Implement
test('Ps = 1 0 1 0 - Scroll to bottom on tty output (rxvt)', async () => {
await assertNoModeChange('\x1b[?1010h');
});
test.skip('Ps = 1 0 1 1 - Scroll to bottom on key press (rxvt)', async () => {
// TODO: Implement
test('Ps = 1 0 1 1 - Scroll to bottom on key press (rxvt)', async () => {
await assertNoModeChange('\x1b[?1011h');
});
test.skip('Ps = 1 0 1 5 - Enable urxvt Mouse Mode', async () => {
// TODO: Implement
test('Ps = 1 0 1 5 - Enable urxvt Mouse Mode', async () => {
await ctx.proxy.write('\x1b[?1006h');
await pollFor(ctx.page, async () => await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeEncoding), 'SGR');
await ctx.proxy.write('\x1b[?1015h');
await pollFor(ctx.page, async () => await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeEncoding), 'SGR');
});
test('Ps = 1 0 1 6 - Enable SGR Mouse PixelMode, xterm', async () => {
await ctx.proxy.write('\x1b[?1016h');
await pollFor(ctx.page, async () => await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeEncoding), 'SGR_PIXELS');
});
test.skip('Ps = 1 0 3 4 - Interpret "meta" key, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 3 4 - Interpret "meta" key, xterm', async () => {
await assertNoModeChange('\x1b[?1034h');
});
test.skip('Ps = 1 0 3 5 - Enable special modifiers for Alt and NumLock keys, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 3 5 - Enable special modifiers for Alt and NumLock keys, xterm', async () => {
await assertNoModeChange('\x1b[?1035h');
});
test.skip('Ps = 1 0 3 6 - Send ESC when Meta modifies a key, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 3 6 - Send ESC when Meta modifies a key, xterm', async () => {
await assertNoModeChange('\x1b[?1036h');
});
test.skip('Ps = 1 0 3 7 - Send DEL from the editing-keypad Delete key, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 3 7 - Send DEL from the editing-keypad Delete key, xterm', async () => {
await assertNoModeChange('\x1b[?1037h');
});
test.skip('Ps = 1 0 3 9 - Send ESC when Alt modifies a key, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 3 9 - Send ESC when Alt modifies a key, xterm', async () => {
await assertNoModeChange('\x1b[?1039h');
});
test.skip('Ps = 1 0 4 0 - Keep selection even if not highlighted, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 4 0 - Keep selection even if not highlighted, xterm', async () => {
await assertNoModeChange('\x1b[?1040h');
});
test.skip('Ps = 1 0 4 1 - Use the CLIPBOARD selection, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 4 1 - Use the CLIPBOARD selection, xterm', async () => {
await assertNoModeChange('\x1b[?1041h');
});
test.skip('Ps = 1 0 4 2 - Enable Urgency window manager hint when Control-G is received, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 4 2 - Enable Urgency window manager hint when Control-G is received, xterm', async () => {
await assertNoModeChange('\x1b[?1042h');
});
test.skip('Ps = 1 0 4 3 - Enable raising of the window when Control-G is received, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 4 3 - Enable raising of the window when Control-G is received, xterm', async () => {
await assertNoModeChange('\x1b[?1043h');
});
test.skip('Ps = 1 0 4 4 - Reuse the most recent data copied to CLIPBOARD, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 4 4 - Reuse the most recent data copied to CLIPBOARD, xterm', async () => {
await assertNoModeChange('\x1b[?1044h');
});
test.skip('Ps = 1 0 4 5 - XTREVWRAP2: Extended Reverse-wraparound mode, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 4 5 - XTREVWRAP2: Extended Reverse-wraparound mode, xterm', async () => {
await assertNoModeChange('\x1b[?1045h');
});
test.skip('Ps = 1 0 4 6 - Enable switching to/from Alternate Screen Buffer, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 4 6 - Enable switching to/from Alternate Screen Buffer, xterm', async () => {
await assertNoModeChange('\x1b[?1046h');
});
test('Ps = 1 0 4 7 - Use Alternate Screen Buffer, xterm', async () => {
await ctx.proxy.write('main');
@@ -655,35 +666,45 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[?1048l');
await pollFor(ctx.page, () => getCursor(), { col: 4, row: 3 });
});
test.skip('Ps = 1 0 4 9 - Save cursor as in DECSC, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 4 9 - Save cursor as in DECSC, xterm', async () => {
await ctx.proxy.write('main');
await pollFor(ctx.page, () => getLinesAsArray(1), ['main']);
await ctx.proxy.write('\x1b[4;6H');
await ctx.proxy.write('\x1b[?1049h');
await pollFor(ctx.page, async () => await ctx.proxy.buffer.active.type, 'alternate');
await ctx.proxy.write('\x1b[Halt');
await pollFor(ctx.page, () => getLinesAsArray(1), ['alt']);
await ctx.proxy.write('\x1b[?1049l');
await pollFor(ctx.page, async () => await ctx.proxy.buffer.active.type, 'normal');
await pollFor(ctx.page, () => getLinesAsArray(1), ['main']);
await pollFor(ctx.page, () => getCursor(), { col: 5, row: 3 });
});
test.skip('Ps = 1 0 5 0 - Set terminfo/termcap function-key mode, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 5 0 - Set terminfo/termcap function-key mode, xterm', async () => {
await assertNoModeChange('\x1b[?1050h');
});
test.skip('Ps = 1 0 5 1 - Set Sun function-key mode, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 5 1 - Set Sun function-key mode, xterm', async () => {
await assertNoModeChange('\x1b[?1051h');
});
test.skip('Ps = 1 0 5 2 - Set HP function-key mode, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 5 2 - Set HP function-key mode, xterm', async () => {
await assertNoModeChange('\x1b[?1052h');
});
test.skip('Ps = 1 0 5 3 - Set SCO function-key mode, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 5 3 - Set SCO function-key mode, xterm', async () => {
await assertNoModeChange('\x1b[?1053h');
});
test.skip('Ps = 1 0 6 0 - Set legacy keyboard emulation, i.e, X11R6, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 6 0 - Set legacy keyboard emulation, i.e, X11R6, xterm', async () => {
await assertNoModeChange('\x1b[?1060h');
});
test.skip('Ps = 1 0 6 1 - Set VT220 keyboard emulation, xterm', async () => {
// TODO: Implement
test('Ps = 1 0 6 1 - Set VT220 keyboard emulation, xterm', async () => {
await assertNoModeChange('\x1b[?1061h');
});
test.skip('Ps = 2 0 0 1 - Enable readline mouse button-1, xterm', async () => {
// TODO: Implement
test('Ps = 2 0 0 1 - Enable readline mouse button-1, xterm', async () => {
await assertNoModeChange('\x1b[?2001h');
});
test.skip('Ps = 2 0 0 2 - Enable readline mouse button-2, xterm', async () => {
// TODO: Implement
test('Ps = 2 0 0 2 - Enable readline mouse button-2, xterm', async () => {
await assertNoModeChange('\x1b[?2002h');
});
test.skip('Ps = 2 0 0 3 - Enable readline mouse button-3, xterm', async () => {
// TODO: Implement
test('Ps = 2 0 0 3 - Enable readline mouse button-3, xterm', async () => {
await assertNoModeChange('\x1b[?2003h');
});
test('Pm = 2 0 0 4, Set bracketed paste mode', async () => {
if (ctx.browser.browserType().name() !== 'chromium') {
@@ -696,11 +717,11 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[?2004l');
await pollFor(ctx.page, () => simulatePaste('baz'), 'baz');
});
test.skip('Ps = 2 0 0 5 - Enable readline character-quoting, xterm', async () => {
// TODO: Implement
test('Ps = 2 0 0 5 - Enable readline character-quoting, xterm', async () => {
await assertNoModeChange('\x1b[?2005h');
});
test.skip('Ps = 2 0 0 6 - Enable readline newline pasting, xterm', async () => {
// TODO: Implement
test('Ps = 2 0 0 6 - Enable readline newline pasting, xterm', async () => {
await assertNoModeChange('\x1b[?2006h');
});
});
test.skip('CSI Ps i - MC: Media Copy', async () => {
@@ -724,17 +745,24 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[?1l');
await pollFor(ctx.page, async () => (await ctx.proxy.modes).applicationCursorKeysMode, false);
});
test.skip('Ps = 2 - Designate VT52 mode (DECANM), VT100.', async () => {
// TODO: Implement
test('Ps = 2 - Designate VT52 mode (DECANM), VT100.', async () => {
await assertNoModeChange('\x1b[?2l');
});
test.skip('Ps = 3 - 80 Column Mode (DECCOLM), VT100.', async () => {
// TODO: Implement
test('Ps = 3 - 80 Column Mode (DECCOLM), VT100.', async () => {
const windowOptions = await ctx.proxy.getOption('windowOptions');
await ctx.proxy.setOption('windowOptions', { ...windowOptions, setWinLines: true });
await ctx.proxy.write('\x1b[?3h');
await pollFor(ctx.page, async () => await ctx.proxy.cols, 132);
await ctx.proxy.write('\x1b[?3l');
await pollFor(ctx.page, async () => await ctx.proxy.cols, 80);
await ctx.proxy.resize(80, 24);
await ctx.proxy.setOption('windowOptions', windowOptions);
});
test.skip('Ps = 4 - Jump (Fast) Scroll (DECSCLM), VT100.', async () => {
// TODO: Implement
test('Ps = 4 - Jump (Fast) Scroll (DECSCLM), VT100.', async () => {
await assertNoModeChange('\x1b[?4l');
});
test.skip('Ps = 5 - Normal Video (DECSCNM), VT100.', async () => {
// TODO: Implement
test('Ps = 5 - Normal Video (DECSCNM), VT100.', async () => {
await assertNoModeChange('\x1b[?5l');
});
test('Ps = 6 - Normal Cursor Mode (DECOM), VT100.', async () => {
await ctx.proxy.write('\x1b[?6h');
@@ -758,8 +786,8 @@ test.describe('InputHandler Integration Tests', () => {
await pollFor(ctx.page, () => getLinesAsArray(2), ['12345', 'X']);
await ctx.proxy.resize(80, 24);
});
test.skip('Ps = 8 - No Auto-Repeat Keys (DECARM), VT100.', async () => {
// TODO: Implement
test('Ps = 8 - No Auto-Repeat Keys (DECARM), VT100.', async () => {
await assertNoModeChange('\x1b[?8l');
});
test('Ps = 9 - Don\'t send Mouse X & Y on button press, xterm.', async () => {
await ctx.proxy.write('\x1b[?9h');
@@ -767,23 +795,30 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[?9l');
await pollFor(ctx.page, async () => (await ctx.proxy.modes).mouseTrackingMode, 'none');
});
test.skip('Ps = 1 0 - Hide toolbar (rxvt).', async () => {
// TODO: Implement
test('Ps = 1 0 - Hide toolbar (rxvt).', async () => {
await assertNoModeChange('\x1b[?10l');
});
test.skip('Ps = 1 2 - Stop blinking cursor (AT&T 610).', async () => {
// TODO: Implement
test('Ps = 1 2 - Stop blinking cursor (AT&T 610).', async () => {
const previousQuirks = await ctx.proxy.getOption('quirks');
const previousCursorBlink = await ctx.proxy.getOption('cursorBlink');
await ctx.proxy.setOption('quirks', { ...(previousQuirks ?? {}), allowSetCursorBlink: true });
await ctx.proxy.setOption('cursorBlink', true);
await ctx.proxy.write('\x1b[?12l');
await pollFor(ctx.page, async () => await ctx.proxy.getOption('cursorBlink'), false);
await ctx.proxy.setOption('quirks', previousQuirks);
await ctx.proxy.setOption('cursorBlink', previousCursorBlink);
});
test.skip('Ps = 1 3 - Disable blinking cursor (reset only via resource or menu).', async () => {
// TODO: Implement
test('Ps = 1 3 - Disable blinking cursor (reset only via resource or menu).', async () => {
await assertNoModeChange('\x1b[?13l');
});
test.skip('Ps = 1 4 - Disable XOR of blinking cursor control sequence and menu.', async () => {
// TODO: Implement
test('Ps = 1 4 - Disable XOR of blinking cursor control sequence and menu.', async () => {
await assertNoModeChange('\x1b[?14l');
});
test.skip('Ps = 1 8 - Don\'t Print Form Feed (DECPFF), VT220.', async () => {
// TODO: Implement
test('Ps = 1 8 - Don\'t Print Form Feed (DECPFF), VT220.', async () => {
await assertNoModeChange('\x1b[?18l');
});
test.skip('Ps = 1 9 - Limit print to scrolling region (DECPEX), VT220.', async () => {
// TODO: Implement
test('Ps = 1 9 - Limit print to scrolling region (DECPEX), VT220.', async () => {
await assertNoModeChange('\x1b[?19l');
});
test('Ps = 2 5 - Hide cursor (DECTCEM), VT220.', async () => {
await ctx.proxy.write('\x1b[?25h');
@@ -791,29 +826,29 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[?25l');
await pollFor(ctx.page, async () => (await ctx.proxy.modes).showCursor, false);
});
test.skip('Ps = 3 0 - Don\'t show scrollbar (rxvt).', async () => {
// TODO: Implement
test('Ps = 3 0 - Don\'t show scrollbar (rxvt).', async () => {
await assertNoModeChange('\x1b[?30l');
});
test.skip('Ps = 3 5 - Disable font-shifting functions (rxvt).', async () => {
// TODO: Implement
test('Ps = 3 5 - Disable font-shifting functions (rxvt).', async () => {
await assertNoModeChange('\x1b[?35l');
});
test.skip('Ps = 4 0 - Disallow 80 ⇒ 132 mode, xterm.', async () => {
// TODO: Implement
test('Ps = 4 0 - Disallow 80 ⇒ 132 mode, xterm.', async () => {
await assertNoModeChange('\x1b[?40l');
});
test.skip('Ps = 4 1 - No more(1) fix (see curses resource).', async () => {
// TODO: Implement
test('Ps = 4 1 - No more(1) fix (see curses resource).', async () => {
await assertNoModeChange('\x1b[?41l');
});
test.skip('Ps = 4 2 - Disable National Replacement Character sets (DECNRCM), VT220.', async () => {
// TODO: Implement
test('Ps = 4 2 - Disable National Replacement Character sets (DECNRCM), VT220.', async () => {
await assertNoModeChange('\x1b[?42l');
});
test.skip('Ps = 4 3 - Disable Graphic Expanded Print Mode (DECGEPM), VT340.', async () => {
// TODO: Implement
test('Ps = 4 3 - Disable Graphic Expanded Print Mode (DECGEPM), VT340.', async () => {
await assertNoModeChange('\x1b[?43l');
});
test.skip('Ps = 4 4 - Turn off margin bell, xterm.', async () => {
// TODO: Implement
test('Ps = 4 4 - Turn off margin bell, xterm.', async () => {
await assertNoModeChange('\x1b[?44l');
});
test.skip('Ps = 4 4 - Disable Graphic Print Color Mode (DECGPCM), VT340.', async () => {
// TODO: Implement
test('Ps = 4 4 - Disable Graphic Print Color Mode (DECGPCM), VT340.', async () => {
await assertNoModeChange('\x1b[?44l');
});
test('Ps = 4 5 - No Reverse-wraparound mode (XTREVWRAP), xterm.', async () => {
await ctx.proxy.write('\x1b[?45h');
@@ -822,10 +857,9 @@ test.describe('InputHandler Integration Tests', () => {
await pollFor(ctx.page, async () => (await ctx.proxy.modes).reverseWraparoundMode, false);
});
test.skip('Ps = 4 5 - Disable Graphic Print Color Syntax (DECGPCS), VT340.', async () => {
// TODO: Implement
});
test.skip('Ps = 4 6 - Stop logging (XTLOGGING), xterm. This is normally disabled by a compile-time option.', async () => {
// TODO: Implement
test('Ps = 4 6 - Stop logging (XTLOGGING), xterm. This is normally disabled by a compile-time option.', async () => {
await assertNoModeChange('\x1b[?46l');
});
test('Ps = 4 7 - Use Normal Screen Buffer, xterm.', async () => {
await ctx.proxy.write('\x1b[?47h');
@@ -834,7 +868,6 @@ test.describe('InputHandler Integration Tests', () => {
await pollFor(ctx.page, async () => await ctx.proxy.buffer.active.type, 'normal');
});
test.skip('Ps = 4 7 - Disable Graphic Rotated Print Mode (DECGRPM), VT340.', async () => {
// TODO: Implement
});
test('Ps = 6 6 - Numeric keypad mode (DECNKM), VT320.', async () => {
await ctx.proxy.write('\x1b[?66h');
@@ -842,17 +875,17 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[?66l');
await pollFor(ctx.page, async () => (await ctx.proxy.modes).applicationKeypadMode, false);
});
test.skip('Ps = 6 7 - Backarrow key sends delete (DECBKM), VT340, VT420. This sets the backarrowKey resource to "false".', async () => {
// TODO: Implement
test('Ps = 6 7 - Backarrow key sends delete (DECBKM), VT340, VT420. This sets the backarrowKey resource to "false".', async () => {
await assertNoModeChange('\x1b[?67l');
});
test.skip('Ps = 6 9 - Disable left and right margin mode (DECLRMM), VT420 and up.', async () => {
// TODO: Implement
test('Ps = 6 9 - Disable left and right margin mode (DECLRMM), VT420 and up.', async () => {
await assertNoModeChange('\x1b[?69l');
});
test.skip('Ps = 8 0 - Disable Sixel Display Mode (DECSDM), VT330, VT340, VT382. Turns on "Sixel Scrolling". See the section Sixel Graphics and mode 8 4 5 2 .', async () => {
// TODO: Implement
});
test.skip('Ps = 9 5 - Clear screen when DECCOLM is set/reset (DECNCSM), VT510 and up.', async () => {
// TODO: Implement
// This is intentionally not implemented here are image support lives within an addon
// test.skip('Ps = 8 0 - Disable Sixel Display Mode (DECSDM), VT330, VT340, VT382. Turns on "Sixel Scrolling". See the section Sixel Graphics and mode 8 4 5 2 .', async () => {
// });
test('Ps = 9 5 - Clear screen when DECCOLM is set/reset (DECNCSM), VT510 and up.', async () => {
await assertNoModeChange('\x1b[?95l');
});
test('Ps = 1 0 0 0 - Don\'t send Mouse X & Y on button press and release. See the section Mouse Tracking.', async () => {
await ctx.proxy.write('\x1b[?1000h');
@@ -860,8 +893,8 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[?1000l');
await pollFor(ctx.page, async () => (await ctx.proxy.modes).mouseTrackingMode, 'none');
});
test.skip('Ps = 1 0 0 1 - Don\'t use Hilite Mouse Tracking, xterm.', async () => {
// TODO: Implement
test('Ps = 1 0 0 1 - Don\'t use Hilite Mouse Tracking, xterm.', async () => {
await assertNoModeChange('\x1b[?1001l');
});
test('Ps = 1 0 0 2 - Don\'t use Cell Motion Mouse Tracking, xterm. See the section Button-event tracking.', async () => {
await ctx.proxy.write('\x1b[?1002h');
@@ -881,8 +914,11 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[?1004l');
await pollFor(ctx.page, async () => (await ctx.proxy.modes).sendFocusMode, false);
});
test.skip('Ps = 1 0 0 5 - Disable UTF-8 Mouse Mode, xterm.', async () => {
// TODO: Implement
test('Ps = 1 0 0 5 - Disable UTF-8 Mouse Mode, xterm.', async () => {
await ctx.proxy.write('\x1b[?1006h');
await pollFor(ctx.page, async () => await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeEncoding), 'SGR');
await ctx.proxy.write('\x1b[?1005l');
await pollFor(ctx.page, async () => await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeEncoding), 'SGR');
});
test('Ps = 1 0 0 6 - Disable SGR Mouse Mode, xterm.', async () => {
await ctx.proxy.write('\x1b[?1006h');
@@ -890,17 +926,20 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[?1006l');
await pollFor(ctx.page, async () => await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeEncoding), 'DEFAULT');
});
test.skip('Ps = 1 0 0 7 - Disable Alternate Scroll Mode, xterm. This corresponds to the alternateScroll resource.', async () => {
// TODO: Implement
test('Ps = 1 0 0 7 - Disable Alternate Scroll Mode, xterm. This corresponds to the alternateScroll resource.', async () => {
await assertNoModeChange('\x1b[?1007l');
});
test.skip('Ps = 1 0 1 0 - Don\'t scroll to bottom on tty output (rxvt). This sets the scrollTtyOutput resource to "false".', async () => {
// TODO: Implement
test('Ps = 1 0 1 0 - Don\'t scroll to bottom on tty output (rxvt). This sets the scrollTtyOutput resource to "false".', async () => {
await assertNoModeChange('\x1b[?1010l');
});
test.skip('Ps = 1 0 1 1 - Don\'t scroll to bottom on key press (rxvt). This sets the scrollKey resource to "false".', async () => {
// TODO: Implement
test('Ps = 1 0 1 1 - Don\'t scroll to bottom on key press (rxvt). This sets the scrollKey resource to "false".', async () => {
await assertNoModeChange('\x1b[?1011l');
});
test.skip('Ps = 1 0 1 5 - Disable urxvt Mouse Mode.', async () => {
// TODO: Implement
test('Ps = 1 0 1 5 - Disable urxvt Mouse Mode.', async () => {
await ctx.proxy.write('\x1b[?1006h');
await pollFor(ctx.page, async () => await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeEncoding), 'SGR');
await ctx.proxy.write('\x1b[?1015l');
await pollFor(ctx.page, async () => await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeEncoding), 'SGR');
});
test('Ps = 1 0 1 6 - Disable SGR Mouse Pixel-Mode, xterm.', async () => {
await ctx.proxy.write('\x1b[?1016h');
@@ -908,38 +947,38 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[?1016l');
await pollFor(ctx.page, async () => await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeEncoding), 'DEFAULT');
});
test.skip('Ps = 1 0 3 4 - Don\'t interpret "meta" key, xterm. This disables the eightBitInput resource.', async () => {
// TODO: Implement
test('Ps = 1 0 3 4 - Don\'t interpret "meta" key, xterm. This disables the eightBitInput resource.', async () => {
await assertNoModeChange('\x1b[?1034l');
});
test.skip('Ps = 1 0 3 5 - Disable special modifiers for Alt and NumLock keys, xterm. This disables the numLock resource.', async () => {
// TODO: Implement
test('Ps = 1 0 3 5 - Disable special modifiers for Alt and NumLock keys, xterm. This disables the numLock resource.', async () => {
await assertNoModeChange('\x1b[?1035l');
});
test.skip('Ps = 1 0 3 6 - Don\'t send ESC when Meta modifies a key, xterm. This disables the metaSendsEscape resource.', async () => {
// TODO: Implement
test('Ps = 1 0 3 6 - Don\'t send ESC when Meta modifies a key, xterm. This disables the metaSendsEscape resource.', async () => {
await assertNoModeChange('\x1b[?1036l');
});
test.skip('Ps = 1 0 3 7 - Send VT220 Remove from the editing-keypad Delete key, xterm.', async () => {
// TODO: Implement
test('Ps = 1 0 3 7 - Send VT220 Remove from the editing-keypad Delete key, xterm.', async () => {
await assertNoModeChange('\x1b[?1037l');
});
test.skip('Ps = 1 0 3 9 - Don\'t send ESC when Alt modifies a key, xterm. This disables the altSendsEscape resource.', async () => {
// TODO: Implement
test('Ps = 1 0 3 9 - Don\'t send ESC when Alt modifies a key, xterm. This disables the altSendsEscape resource.', async () => {
await assertNoModeChange('\x1b[?1039l');
});
test.skip('Ps = 1 0 4 0 - Do not keep selection when not highlighted, xterm. This disables the keepSelection resource.', async () => {
// TODO: Implement
test('Ps = 1 0 4 0 - Do not keep selection when not highlighted, xterm. This disables the keepSelection resource.', async () => {
await assertNoModeChange('\x1b[?1040l');
});
test.skip('Ps = 1 0 4 1 - Use the PRIMARY selection, xterm. This disables the selectToClipboard resource.', async () => {
// TODO: Implement
test('Ps = 1 0 4 1 - Use the PRIMARY selection, xterm. This disables the selectToClipboard resource.', async () => {
await assertNoModeChange('\x1b[?1041l');
});
test.skip('Ps = 1 0 4 2 - Disable Urgency window manager hint when Control-G is received, xterm. This disables the bellIsUrgent resource.', async () => {
// TODO: Implement
test('Ps = 1 0 4 2 - Disable Urgency window manager hint when Control-G is received, xterm. This disables the bellIsUrgent resource.', async () => {
await assertNoModeChange('\x1b[?1042l');
});
test.skip('Ps = 1 0 4 3 - Disable raising of the window when Control- G is received, xterm. This disables the popOnBell resource.', async () => {
// TODO: Implement
test('Ps = 1 0 4 3 - Disable raising of the window when Control- G is received, xterm. This disables the popOnBell resource.', async () => {
await assertNoModeChange('\x1b[?1043l');
});
test.skip('Ps = 1 0 4 5 - No Extended Reverse-wraparound mode (XTREVWRAP2), xterm.', async () => {
// TODO: Implement
test('Ps = 1 0 4 5 - No Extended Reverse-wraparound mode (XTREVWRAP2), xterm.', async () => {
await assertNoModeChange('\x1b[?1045l');
});
test.skip('Ps = 1 0 4 6 - Disable switching to/from Alternate Screen Buffer, xterm. This works for terminfo-based systems, updating the titeInhibit resource. If currently using the Alternate Screen Buffer, xterm switches to the Normal Screen Buffer.', async () => {
// TODO: Implement
test('Ps = 1 0 4 6 - Disable switching to/from Alternate Screen Buffer, xterm. This works for terminfo-based systems, updating the titeInhibit resource. If currently using the Alternate Screen Buffer, xterm switches to the Normal Screen Buffer.', async () => {
await assertNoModeChange('\x1b[?1046l');
});
test('Ps = 1 0 4 7 - Use Normal Screen Buffer, xterm. Clear the screen first if in the Alternate Screen Buffer. This may be disabled by the titeInhibit resource.', async () => {
await ctx.proxy.write('\x1b[?1047h');
@@ -964,32 +1003,32 @@ test.describe('InputHandler Integration Tests', () => {
await pollFor(ctx.page, async () => await ctx.proxy.buffer.active.type, 'normal');
await pollFor(ctx.page, () => getCursor(), { col: 3, row: 2 });
});
test.skip('Ps = 1 0 5 0 - Reset terminfo/termcap function-key mode, xterm.', async () => {
// TODO: Implement
test('Ps = 1 0 5 0 - Reset terminfo/termcap function-key mode, xterm.', async () => {
await assertNoModeChange('\x1b[?1050l');
});
test.skip('Ps = 1 0 5 1 - Reset Sun function-key mode, xterm.', async () => {
// TODO: Implement
test('Ps = 1 0 5 1 - Reset Sun function-key mode, xterm.', async () => {
await assertNoModeChange('\x1b[?1051l');
});
test.skip('Ps = 1 0 5 2 - Reset HP function-key mode, xterm.', async () => {
// TODO: Implement
test('Ps = 1 0 5 2 - Reset HP function-key mode, xterm.', async () => {
await assertNoModeChange('\x1b[?1052l');
});
test.skip('Ps = 1 0 5 3 - Reset SCO function-key mode, xterm.', async () => {
// TODO: Implement
test('Ps = 1 0 5 3 - Reset SCO function-key mode, xterm.', async () => {
await assertNoModeChange('\x1b[?1053l');
});
test.skip('Ps = 1 0 6 0 - Reset legacy keyboard emulation, i.e, X11R6, xterm.', async () => {
// TODO: Implement
test('Ps = 1 0 6 0 - Reset legacy keyboard emulation, i.e, X11R6, xterm.', async () => {
await assertNoModeChange('\x1b[?1060l');
});
test.skip('Ps = 1 0 6 1 - Reset keyboard emulation to Sun/PC style, xterm.', async () => {
// TODO: Implement
test('Ps = 1 0 6 1 - Reset keyboard emulation to Sun/PC style, xterm.', async () => {
await assertNoModeChange('\x1b[?1061l');
});
test.skip('Ps = 2 0 0 1 - Disable readline mouse button-1, xterm.', async () => {
// TODO: Implement
test('Ps = 2 0 0 1 - Disable readline mouse button-1, xterm.', async () => {
await assertNoModeChange('\x1b[?2001l');
});
test.skip('Ps = 2 0 0 2 - Disable readline mouse button-2, xterm.', async () => {
// TODO: Implement
test('Ps = 2 0 0 2 - Disable readline mouse button-2, xterm.', async () => {
await assertNoModeChange('\x1b[?2002l');
});
test.skip('Ps = 2 0 0 3 - Disable readline mouse button-3, xterm.', async () => {
// TODO: Implement
test('Ps = 2 0 0 3 - Disable readline mouse button-3, xterm.', async () => {
await assertNoModeChange('\x1b[?2003l');
});
test('Ps = 2 0 0 4 - Reset bracketed paste mode, xterm.', async () => {
await ctx.proxy.write('\x1b[?2004h');
@@ -997,11 +1036,11 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[?2004l');
await pollFor(ctx.page, async () => (await ctx.proxy.modes).bracketedPasteMode, false);
});
test.skip('Ps = 2 0 0 5 - Disable readline character-quoting, xterm.', async () => {
// TODO: Implement
test('Ps = 2 0 0 5 - Disable readline character-quoting, xterm.', async () => {
await assertNoModeChange('\x1b[?2005l');
});
test.skip('Ps = 2 0 0 6 - Disable readline newline pasting, xterm.', async () => {
// TODO: Implement
test('Ps = 2 0 0 6 - Disable readline newline pasting, xterm.', async () => {
await assertNoModeChange('\x1b[?2006l');
});
});
test.describe('CSI Pm m - SGR: Character Attributes', () => {
@@ -1492,8 +1531,14 @@ test.describe('InputHandler Integration Tests', () => {
await ctx.proxy.write('\x1b[0 q');
deepStrictEqual(await getCursorMode(), { style: undefined, blink: undefined });
});
test.skip('CSI Ps " q - Select character protection attribute (DECSCA), VT220.', async () => {
// TODO: Implement
test('CSI Ps " q - Select character protection attribute (DECSCA), VT220.', async () => {
await ctx.proxy.write('\x1b[1"q');
await ctx.proxy.write('PROT');
await ctx.proxy.write('\x1b[2"q');
await ctx.proxy.write('open');
await pollFor(ctx.page, () => getLinesAsArray(1), ['PROTopen']);
await ctx.proxy.write('\x1b[1;1H\x1b[?2K');
await pollFor(ctx.page, () => getLinesAsArray(1), ['PROT']);
});
test.skip('CSI # q - Pop video attributes from stack (XTPOPSGR), xterm.', async () => {
// TODO: Implement
@@ -1797,6 +1842,25 @@ test.describe('InputHandler Integration Tests', () => {
});
async function getModeSnapshot(): Promise<any> {
return {
modes: await ctx.proxy.modes,
cursorBlink: await ctx.proxy.getOption('cursorBlink'),
cols: await ctx.proxy.cols,
rows: await ctx.proxy.rows,
bufferType: await ctx.proxy.buffer.active.type,
mouseProtocol: await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeProtocol),
mouseEncoding: await ctx.proxy.core.evaluate(([core]) => core.coreMouseService.activeEncoding)
};
}
async function assertNoModeChange(sequence: string): Promise<void> {
const before = await getModeSnapshot();
await ctx.proxy.write(sequence);
deepStrictEqual(await getModeSnapshot(), before);
}
async function getLinesAsArray(count: number, start: number = 0): Promise<string[]> {
let text = '';
for (let i = start; i < start + count; i++) {
+169 -59
View File
@@ -13,6 +13,7 @@ export interface ISharedRendererTestContext {
skipDomExceptions?: boolean;
}
export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void {
test.beforeEach(async () => {
await ctx.value.proxy.reset();
@@ -66,7 +67,7 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
window.term.options.drawBoldTextInBrightColors = true;
`);
await ctx.value.proxy.write(`\x1b[1;30m■\x1b[1;31m■\x1b[1;32m■\x1b[1;33m■\x1b[1;34m■\x1b[1;35m■\x1b[1;36m■\x1b[1;37m■`);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [1, 2, 3, 255]);
await pollForCellColorFresh(ctx.value, 1, 1, [1, 2, 3, 255]);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [4, 5, 6, 255]);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 1), [7, 8, 9, 255]);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 4, 1), [10, 11, 12, 255]);
@@ -180,15 +181,16 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
white: '#161718'
};
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
await ctx.value.proxy.write(`\x1b[8;40m■\x1b[8;41m■\x1b[8;42m■\x1b[8;43m■\x1b[8;44m■\x1b[8;45m■\x1b[8;46m■\x1b[8;47m■`);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [1, 2, 3, 255]);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [4, 5, 6, 255]);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 1), [7, 8, 9, 255]);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 4, 1), [10, 11, 12, 255]);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 5, 1), [13, 14, 15, 255]);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 6, 1), [16, 17, 18, 255]);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 7, 1), [19, 20, 21, 255]);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 8, 1), [22, 23, 24, 255]);
await waitForRenderAfter(ctx.value, () => ctx.value.proxy.write(`\x1b[8;40m■\x1b[8;41m■\x1b[8;42m■\x1b[8;43m■\x1b[8;44m■\x1b[8;45m■\x1b[8;46m■\x1b[8;47m■`));
const getBgColor = (col: number, row: number): Promise<[number, number, number, number]> => getCellDomBackgroundColor(ctx.value, col, row);
await pollFor(ctx.value.page, () => getBgColor(1, 1), [1, 2, 3, 255]);
await pollFor(ctx.value.page, () => getBgColor(2, 1), [4, 5, 6, 255]);
await pollFor(ctx.value.page, () => getBgColor(3, 1), [7, 8, 9, 255]);
await pollFor(ctx.value.page, () => getBgColor(4, 1), [10, 11, 12, 255]);
await pollFor(ctx.value.page, () => getBgColor(5, 1), [13, 14, 15, 255]);
await pollFor(ctx.value.page, () => getBgColor(6, 1), [16, 17, 18, 255]);
await pollFor(ctx.value.page, () => getBgColor(7, 1), [19, 20, 21, 255]);
await pollFor(ctx.value.page, () => getBgColor(8, 1), [22, 23, 24, 255]);
});
test('foreground 0-15 bright', async () => {
@@ -245,7 +247,7 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
}
data += '\r\n';
}
await ctx.value.proxy.write(data);
await waitForRenderAfter(ctx.value, () => ctx.value.proxy.write(data));
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
const cssColor = COLORS_16_TO_255[y * 16 + x];
@@ -265,7 +267,7 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
}
data += '\r\n';
}
await ctx.value.proxy.write(data);
await waitForRenderAfter(ctx.value, () => ctx.value.proxy.write(data));
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
const cssColor = COLORS_16_TO_255[y * 16 + x];
@@ -285,7 +287,7 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
}
data += '\r\n';
}
await ctx.value.proxy.write(data);
await waitForRenderAfter(ctx.value, () => ctx.value.proxy.write(data));
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
const cssColor = COLORS_16_TO_255[y * 16 + x];
@@ -305,7 +307,7 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
}
data += '\r\n';
}
await ctx.value.proxy.write(data);
await waitForRenderAfter(ctx.value, () => ctx.value.proxy.write(data));
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
const cssColor = COLORS_16_TO_255[y * 16 + x];
@@ -341,14 +343,20 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
}
data += '\r\n';
}
await ctx.value.proxy.write(data);
await waitForRenderAfter(ctx.value, () => ctx.value.proxy.write(data));
const getBgColor = (col: number, row: number): Promise<[number, number, number, number]> => getCellDomBackgroundColor(ctx.value, col, row);
const firstCssColor = COLORS_16_TO_255[1];
const firstR = parseInt(firstCssColor.slice(1, 3), 16);
const firstG = parseInt(firstCssColor.slice(3, 5), 16);
const firstB = parseInt(firstCssColor.slice(5, 7), 16);
await pollFor(ctx.value.page, () => getBgColor(2, 1), [firstR, firstG, firstB, 255]);
for (let y = 0; y < 240 / 16; y++) {
for (let x = 0; x < 16; x++) {
const cssColor = COLORS_16_TO_255[y * 16 + x];
const r = parseInt(cssColor.slice(1, 3), 16);
const g = parseInt(cssColor.slice(3, 5), 16);
const b = parseInt(cssColor.slice(5, 7), 16);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, x + 1, y + 1), [r, g, b, 255]);
await pollFor(ctx.value.page, () => getBgColor(x + 1, y + 1), [r, g, b, 255]);
}
}
});
@@ -716,11 +724,13 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
}
data += '\r\n';
}
await ctx.value.proxy.write(data);
await waitForRenderAfter(ctx.value, () => ctx.value.proxy.write(data));
const getBgColor = (col: number, row: number): Promise<[number, number, number, number]> => getCellDomBackgroundColor(ctx.value, col, row);
await pollFor(ctx.value.page, () => getBgColor(2, 1), [1, 1, 1, 255]);
for (let y = 0; y < 16; y++) {
for (let x = 0; x < 16; x++) {
const i = y * 16 + x;
await pollFor(ctx.value.page, () => getCellColor(ctx.value, x + 1, y + 1), [i, i, i, 255]);
await pollFor(ctx.value.page, () => getBgColor(x + 1, y + 1), [i, i, i, 255]);
}
}
});
@@ -886,50 +896,61 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
window.term.options.theme = ${JSON.stringify(theme)};
window.term.options.minimumContrastRatio = 1;
`);
await ctx.value.proxy.write(
await waitForRenderAfter(ctx.value, () => ctx.value.proxy.write(
'\x1b[2m' +
`\x1b[30m■\x1b[31m■\x1b[32m■\x1b[33m■\x1b[34m■\x1b[35m■\x1b[36m■\x1b[37m■\r\n` +
`\x1b[90m■\x1b[91m■\x1b[92m■\x1b[93m■\x1b[94m■\x1b[95m■\x1b[96m■\x1b[97m■`
);
));
// Validate before minimumContrastRatio is applied
const marginOfError = 1;
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 1, 1), [Math.floor((255 + 0x2e) / 2), Math.floor((255 + 0x34) / 2), Math.floor((255 + 0x36) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 2, 1), [Math.floor((255 + 0xcc) / 2), Math.floor((255 + 0x00) / 2), Math.floor((255 + 0x00) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 3, 1), [Math.floor((255 + 0x4e) / 2), Math.floor((255 + 0x9a) / 2), Math.floor((255 + 0x06) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 4, 1), [Math.floor((255 + 0xc4) / 2), Math.floor((255 + 0xa0) / 2), Math.floor((255 + 0x00) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 5, 1), [Math.floor((255 + 0x34) / 2), Math.floor((255 + 0x65) / 2), Math.floor((255 + 0xa4) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 6, 1), [Math.floor((255 + 0x75) / 2), Math.floor((255 + 0x50) / 2), Math.floor((255 + 0x7b) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 7, 1), [Math.floor((255 + 0x06) / 2), Math.floor((255 + 0x98) / 2), Math.floor((255 + 0x9a) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 8, 1), [Math.floor((255 + 0xd3) / 2), Math.floor((255 + 0xd7) / 2), Math.floor((255 + 0xcf) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 1, 2), [Math.floor((255 + 0x55) / 2), Math.floor((255 + 0x57) / 2), Math.floor((255 + 0x53) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 2, 2), [Math.floor((255 + 0xef) / 2), Math.floor((255 + 0x29) / 2), Math.floor((255 + 0x29) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 3, 2), [Math.floor((255 + 0x8a) / 2), Math.floor((255 + 0xe2) / 2), Math.floor((255 + 0x34) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 4, 2), [Math.floor((255 + 0xfc) / 2), Math.floor((255 + 0xe9) / 2), Math.floor((255 + 0x4f) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 5, 2), [Math.floor((255 + 0x72) / 2), Math.floor((255 + 0x9f) / 2), Math.floor((255 + 0xcf) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 6, 2), [Math.floor((255 + 0xad) / 2), Math.floor((255 + 0x7f) / 2), Math.floor((255 + 0xa8) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 7, 2), [Math.floor((255 + 0x34) / 2), Math.floor((255 + 0xe2) / 2), Math.floor((255 + 0xe2) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 8, 2), [Math.floor((255 + 0xee) / 2), Math.floor((255 + 0xee) / 2), Math.floor((255 + 0xec) / 2), 255]);
const background: [number, number, number, number] = [255, 255, 255, 255];
const compositeOverBackground = (fg: [number, number, number, number]): [number, number, number, number] => {
const alpha = fg[3] / 255;
const inv = 1 - alpha;
return [
Math.round(fg[0] * alpha + background[0] * inv),
Math.round(fg[1] * alpha + background[1] * inv),
Math.round(fg[2] * alpha + background[2] * inv),
255
];
};
const getFgColor = async (col: number, row: number): Promise<[number, number, number, number]> => compositeOverBackground(await getCellDomForegroundColor(ctx.value, col, row));
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(1, 1), [Math.floor((255 + 0x2e) / 2), Math.floor((255 + 0x34) / 2), Math.floor((255 + 0x36) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(2, 1), [Math.floor((255 + 0xcc) / 2), Math.floor((255 + 0x00) / 2), Math.floor((255 + 0x00) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(3, 1), [Math.floor((255 + 0x4e) / 2), Math.floor((255 + 0x9a) / 2), Math.floor((255 + 0x06) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(4, 1), [Math.floor((255 + 0xc4) / 2), Math.floor((255 + 0xa0) / 2), Math.floor((255 + 0x00) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(5, 1), [Math.floor((255 + 0x34) / 2), Math.floor((255 + 0x65) / 2), Math.floor((255 + 0xa4) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(6, 1), [Math.floor((255 + 0x75) / 2), Math.floor((255 + 0x50) / 2), Math.floor((255 + 0x7b) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(7, 1), [Math.floor((255 + 0x06) / 2), Math.floor((255 + 0x98) / 2), Math.floor((255 + 0x9a) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(8, 1), [Math.floor((255 + 0xd3) / 2), Math.floor((255 + 0xd7) / 2), Math.floor((255 + 0xcf) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(1, 2), [Math.floor((255 + 0x55) / 2), Math.floor((255 + 0x57) / 2), Math.floor((255 + 0x53) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(2, 2), [Math.floor((255 + 0xef) / 2), Math.floor((255 + 0x29) / 2), Math.floor((255 + 0x29) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(3, 2), [Math.floor((255 + 0x8a) / 2), Math.floor((255 + 0xe2) / 2), Math.floor((255 + 0x34) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(4, 2), [Math.floor((255 + 0xfc) / 2), Math.floor((255 + 0xe9) / 2), Math.floor((255 + 0x4f) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(5, 2), [Math.floor((255 + 0x72) / 2), Math.floor((255 + 0x9f) / 2), Math.floor((255 + 0xcf) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(6, 2), [Math.floor((255 + 0xad) / 2), Math.floor((255 + 0x7f) / 2), Math.floor((255 + 0xa8) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(7, 2), [Math.floor((255 + 0x34) / 2), Math.floor((255 + 0xe2) / 2), Math.floor((255 + 0xe2) / 2), 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(8, 2), [Math.floor((255 + 0xee) / 2), Math.floor((255 + 0xee) / 2), Math.floor((255 + 0xec) / 2), 255]);
// Setting and check for minimum contrast values, note that these are not
// exact to the contrast ratio, if the increase luminance algorithm
// changes then these will probably fail
await ctx.value.page.evaluate(`window.term.options.minimumContrastRatio = 10;`);
frameDetails = undefined;
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 1, 1), [150, 153, 154, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 2, 1), [229, 127, 127, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 3, 1), [63, 124, 4, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 4, 1), [127, 104, 0, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 5, 1), [153, 178, 209, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 6, 1), [186, 167, 189, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 7, 1), [4, 122, 124, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 8, 1), [110, 112, 108, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 1, 2), [170, 171, 169, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 2, 2), [215, 36, 36, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 3, 2), [72, 117, 25, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 4, 2), [117, 109, 36, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 5, 2), [72, 103, 135, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 6, 2), [125, 91, 121, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 7, 2), [25, 117, 117, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getCellColor(ctx.value, 8, 2), [111, 111, 110, 255]);
await waitForRenderAfter(ctx.value, () => ctx.value.page.evaluate(`window.term.options.minimumContrastRatio = 10;`));
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(1, 1), [150, 153, 154, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(2, 1), [229, 127, 127, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(3, 1), [63, 124, 4, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(4, 1), [127, 104, 0, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(5, 1), [153, 178, 209, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(6, 1), [186, 167, 189, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(7, 1), [4, 122, 124, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(8, 1), [110, 112, 108, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(1, 2), [170, 171, 169, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(2, 2), [215, 36, 36, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(3, 2), [72, 117, 25, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(4, 2), [117, 109, 36, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(5, 2), [72, 103, 135, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(6, 2), [125, 91, 121, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(7, 2), [25, 117, 117, 255]);
await pollForApproximate(ctx.value.page, marginOfError, () => getFgColor(8, 2), [111, 111, 110, 255]);
});
});
@@ -1160,11 +1181,11 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
// Regression test: #4758 when multiple invisible characters are used
await ctx.value.proxy.writeln(`■\x1b[8m■■`);
// Full refresh as the before result is the same as after
await ctx.value.proxy.refresh(0, await ctx.value.proxy.rows - 1);
// Control to ensure rendering has occurred
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [255, 255, 255, 255]);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [0, 0, 0, 255]);
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 1), [0, 0, 0, 255]);
const rows = await ctx.value.proxy.rows;
await waitForRenderAfter(ctx.value, () => ctx.value.proxy.refresh(0, rows - 1));
await pollFor(ctx.value.page, () => getCellDomChar(ctx.value, 1, 1), '■');
await pollFor(ctx.value.page, () => getCellDomChar(ctx.value, 2, 1), ' ');
await pollFor(ctx.value.page, () => getCellDomChar(ctx.value, 3, 1), ' ');
});
// HACK: It's not clear why DOM is failing here
(ctx.skipDomExceptions ? test.skip : test)('#4759: minimum contrast ratio should be respected on inverse text', async () => {
@@ -1341,6 +1362,95 @@ export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void
});
}
async function waitForRender(ctx: ITestContext): Promise<void> {
await new Promise<void>(resolve => {
const disposable = ctx.proxy.onRender(() => {
disposable.dispose();
resolve();
});
});
}
async function waitForRenderAfter(ctx: ITestContext, action: () => Promise<void>): Promise<void> {
const renderPromise = waitForRender(ctx);
await action();
await renderPromise;
frameDetails = undefined;
}
async function pollForCellColorFresh(ctx: ITestContext, col: number, row: number, expected: [number, number, number, number], position: CellColorPosition = CellColorPosition.CENTER): Promise<void> {
await pollFor(ctx.page, () => getCellColor(ctx, col, row, position), expected, async () => {
frameDetails = undefined;
});
}
interface ICellDomInfo {
fg: string;
bg: string;
char: string;
}
function parseCssColor(value: string): [number, number, number, number] {
if (value === 'transparent') {
return [0, 0, 0, 0];
}
const match = value.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([0-9.]+))?\)$/);
if (!match) {
throw new Error(`Unsupported color format: ${value}`);
}
const r = Number(match[1]);
const g = Number(match[2]);
const b = Number(match[3]);
const a = match[4] === undefined ? 255 : Math.round(Number(match[4]) * 255);
return [r, g, b, a];
}
async function getCellDomInfo(ctx: ITestContext, col: number, row: number): Promise<ICellDomInfo> {
const info = await ctx.page.evaluate(({ col, row }) => {
const rows = document.querySelectorAll('#terminal-container .xterm-rows > div');
const rowEl = rows[row - 1];
if (!rowEl) {
return undefined;
}
let currentCol = 1;
for (const el of Array.from(rowEl.children)) {
const text = el.textContent ?? '';
const chars = Array.from(text);
const nextCol = currentCol + chars.length;
if (col >= currentCol && col < nextCol) {
const style = window.getComputedStyle(el as HTMLElement);
return {
fg: style.color,
bg: style.backgroundColor,
char: chars[col - currentCol] ?? ''
};
}
currentCol = nextCol;
}
return undefined;
}, { col, row });
if (!info) {
throw new Error(`Cell not found: ${col},${row}`);
}
return info;
}
async function getCellDomBackgroundColor(ctx: ITestContext, col: number, row: number): Promise<[number, number, number, number]> {
const info = await getCellDomInfo(ctx, col, row);
return parseCssColor(info.bg);
}
async function getCellDomForegroundColor(ctx: ITestContext, col: number, row: number): Promise<[number, number, number, number]> {
const info = await getCellDomInfo(ctx, col, row);
return parseCssColor(info.fg);
}
async function getCellDomChar(ctx: ITestContext, col: number, row: number): Promise<string> {
const info = await getCellDomInfo(ctx, col, row);
return info.char;
}
enum CellColorPosition {
CENTER = 0,
FIRST = 1
+2 -3
View File
@@ -5,10 +5,9 @@ const config: PlaywrightTestConfig = {
timeout: 10000,
projects: [
{
name: 'ChromeStable',
name: 'Chromium',
use: {
browserName: 'chromium',
channel: 'chrome'
browserName: 'chromium'
}
},
{