When a with bg is selected, the cell's regular background will be blended with 50% opacity selectionBackground in order to retain the bg color info as well as getting the color to change and getting decent contrast. This commit also fixes a terrible, nasty bug where the standalone shared renderer tests were causing the terminal to open multiple times and not get the WebGL addon activated the second time. So some tests were actually testing the DOM renderer :o Fixes #4918
1347 lines
64 KiB
TypeScript
1347 lines
64 KiB
TypeScript
/**
|
|
* Copyright (c) 2019 The xterm.js authors. All rights reserved.
|
|
* @license MIT
|
|
*/
|
|
|
|
import { IImage32, decodePng } from '@lunapaint/png-codec';
|
|
import { LocatorScreenshotOptions, test } from '@playwright/test';
|
|
import { ITheme } from '@xterm/xterm';
|
|
import { ITestContext, MaybeAsync, openTerminal, pollFor, pollForApproximate } from './TestUtils';
|
|
|
|
export interface ISharedRendererTestContext {
|
|
value: ITestContext;
|
|
skipCanvasExceptions?: boolean;
|
|
skipDomExceptions?: boolean;
|
|
}
|
|
|
|
export function injectSharedRendererTests(ctx: ISharedRendererTestContext): void {
|
|
test.beforeEach(async () => {
|
|
await ctx.value.proxy.reset();
|
|
ctx.value.page.evaluate(`
|
|
window.term.options.minimumContrastRatio = 1;
|
|
window.term.options.allowTransparency = false;
|
|
window.term.options.theme = undefined;
|
|
`);
|
|
// Clear the cached screenshot before each test
|
|
frameDetails = undefined;
|
|
});
|
|
|
|
test.describe('colors', () => {
|
|
test('foreground 0-15', async () => {
|
|
const theme: ITheme = {
|
|
black: '#010203',
|
|
red: '#040506',
|
|
green: '#070809',
|
|
yellow: '#0a0b0c',
|
|
blue: '#0d0e0f',
|
|
magenta: '#101112',
|
|
cyan: '#131415',
|
|
white: '#161718'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.write(`\x1b[30m■\x1b[31m■\x1b[32m■\x1b[33m■\x1b[34m■\x1b[35m■\x1b[36m■\x1b[37m■`);
|
|
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]);
|
|
});
|
|
});
|
|
|
|
test('foreground 0-7 drawBoldTextInBrightColors', async () => {
|
|
const theme: ITheme = {
|
|
brightBlack: '#010203',
|
|
brightRed: '#040506',
|
|
brightGreen: '#070809',
|
|
brightYellow: '#0a0b0c',
|
|
brightBlue: '#0d0e0f',
|
|
brightMagenta: '#101112',
|
|
brightCyan: '#131415',
|
|
brightWhite: '#161718'
|
|
};
|
|
await ctx.value.page.evaluate(`
|
|
window.term.options.theme = ${JSON.stringify(theme)};
|
|
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 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]);
|
|
});
|
|
|
|
test('background 0-15', async () => {
|
|
const theme: ITheme = {
|
|
black: '#010203',
|
|
red: '#040506',
|
|
green: '#070809',
|
|
yellow: '#0a0b0c',
|
|
blue: '#0d0e0f',
|
|
magenta: '#101112',
|
|
cyan: '#131415',
|
|
white: '#161718'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.write(`\x1b[40m \x1b[41m \x1b[42m \x1b[43m \x1b[44m \x1b[45m \x1b[46m \x1b[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]);
|
|
});
|
|
|
|
test('foreground 0-15 inverse', async () => {
|
|
const theme: ITheme = {
|
|
black: '#010203',
|
|
red: '#040506',
|
|
green: '#070809',
|
|
yellow: '#0a0b0c',
|
|
blue: '#0d0e0f',
|
|
magenta: '#101112',
|
|
cyan: '#131415',
|
|
white: '#161718'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.write(`\x1b[7;30m \x1b[7;31m \x1b[7;32m \x1b[7;33m \x1b[7;34m \x1b[7;35m \x1b[7;36m \x1b[7;37m `);
|
|
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]);
|
|
});
|
|
|
|
test('background 0-15 inverse', async () => {
|
|
const theme: ITheme = {
|
|
black: '#010203',
|
|
red: '#040506',
|
|
green: '#070809',
|
|
yellow: '#0a0b0c',
|
|
blue: '#0d0e0f',
|
|
magenta: '#101112',
|
|
cyan: '#131415',
|
|
white: '#161718'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.write(`\x1b[7;40m■\x1b[7;41m■\x1b[7;42m■\x1b[7;43m■\x1b[7;44m■\x1b[7;45m■\x1b[7;46m■\x1b[7;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]);
|
|
});
|
|
|
|
test('foreground 0-15 invisible', async () => {
|
|
const theme: ITheme = {
|
|
black: '#010203',
|
|
red: '#040506',
|
|
green: '#070809',
|
|
yellow: '#0a0b0c',
|
|
blue: '#0d0e0f',
|
|
magenta: '#101112',
|
|
cyan: '#131415',
|
|
white: '#161718'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.write(`\x1b[8;30m \x1b[8;31m \x1b[8;32m \x1b[8;33m \x1b[8;34m \x1b[8;35m \x1b[8;36m \x1b[8;37m `);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 0, 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]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 4, 1), [0, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 5, 1), [0, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 6, 1), [0, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 7, 1), [0, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 8, 1), [0, 0, 0, 255]);
|
|
});
|
|
|
|
test('background 0-15 invisible', async () => {
|
|
const theme: ITheme = {
|
|
black: '#010203',
|
|
red: '#040506',
|
|
green: '#070809',
|
|
yellow: '#0a0b0c',
|
|
blue: '#0d0e0f',
|
|
magenta: '#101112',
|
|
cyan: '#131415',
|
|
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]);
|
|
});
|
|
|
|
test('foreground 0-15 bright', async () => {
|
|
const theme: ITheme = {
|
|
brightBlack: '#010203',
|
|
brightRed: '#040506',
|
|
brightGreen: '#070809',
|
|
brightYellow: '#0a0b0c',
|
|
brightBlue: '#0d0e0f',
|
|
brightMagenta: '#101112',
|
|
brightCyan: '#131415',
|
|
brightWhite: '#161718'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.write(`\x1b[90m■\x1b[91m■\x1b[92m■\x1b[93m■\x1b[94m■\x1b[95m■\x1b[96m■\x1b[97m■`);
|
|
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]);
|
|
});
|
|
|
|
test('background 0-15 bright', async () => {
|
|
const theme: ITheme = {
|
|
brightBlack: '#010203',
|
|
brightRed: '#040506',
|
|
brightGreen: '#070809',
|
|
brightYellow: '#0a0b0c',
|
|
brightBlue: '#0d0e0f',
|
|
brightMagenta: '#101112',
|
|
brightCyan: '#131415',
|
|
brightWhite: '#161718'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.write(`\x1b[100m \x1b[101m \x1b[102m \x1b[103m \x1b[104m \x1b[105m \x1b[106m \x1b[107m `);
|
|
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]);
|
|
});
|
|
|
|
test('foreground 16-255', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 240 / 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
data += `\x1b[38;5;${16 + y * 16 + x}m■\x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await 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];
|
|
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]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('background 16-255', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 240 / 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
data += `\x1b[48;5;${16 + y * 16 + x}m \x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await 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];
|
|
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]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('foreground 16-255 inverse', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 240 / 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
data += `\x1b[7;38;5;${16 + y * 16 + x}m \x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await 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];
|
|
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]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('background 16-255 inverse', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 240 / 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
data += `\x1b[7;48;5;${16 + y * 16 + x}m■\x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await 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];
|
|
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]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('foreground 16-255 invisible', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 240 / 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
data += `\x1b[8;38;5;${16 + y * 16 + x}m \x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
for (let y = 0; y < 240 / 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, x + 1, y + 1), [0, 0, 0, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('background 16-255 invisible', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 240 / 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
data += `\x1b[8;48;5;${16 + y * 16 + x}m■\x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await 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];
|
|
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]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('foreground 16-255 dim', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 240 / 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
data += `\x1b[2;38;5;${16 + y * 16 + x}m■\x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await 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];
|
|
const r = parseInt(cssColor.slice(1, 3), 16);
|
|
const g = parseInt(cssColor.slice(3, 5), 16);
|
|
const b = parseInt(cssColor.slice(5, 7), 16);
|
|
// It's difficult to assert the exact color due to rounding, just ensure the color differs
|
|
// to the regular color
|
|
await pollFor(ctx.value.page, async () => {
|
|
const c = await getCellColor(ctx.value, x + 1, y + 1);
|
|
return (
|
|
(c[0] === 0 || c[0] !== r) &&
|
|
(c[1] === 0 || c[1] !== g) &&
|
|
(c[2] === 0 || c[2] !== b)
|
|
);
|
|
}, true);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('background 16-255 dim', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 240 / 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
data += `\x1b[2;48;5;${16 + y * 16 + x}m \x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await 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];
|
|
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]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('foreground true color red', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[38;2;${i};0;0m■\x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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, 0, 0, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('background true color red', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[48;2;${i};0;0m \x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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, 0, 0, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('foreground true color green', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[38;2;0;${i};0m■\x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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), [0, i, 0, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('background true color green', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[48;2;0;${i};0m \x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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), [0, i, 0, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('foreground true color blue', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[38;2;0;0;${i}m■\x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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), [0, 0, i, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('background true color blue', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[48;2;0;0;${i}m \x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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), [0, 0, i, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('foreground true color grey', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[38;2;${i};${i};${i}m■\x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('background true color grey', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[48;2;${i};${i};${i}m \x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('foreground true color red inverse', async function(): Promise<void> {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[7;38;2;${i};0;0m \x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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, 0, 0, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('background true color red inverse', async function(): Promise<void> {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[7;48;2;${i};0;0m■\x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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, 0, 0, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('foreground true color green inverse', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[7;38;2;0;${i};0m \x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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), [0, i, 0, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('background true color green inverse', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[7;48;2;0;${i};0m■\x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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), [0, i, 0, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('foreground true color blue inverse', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[7;38;2;0;0;${i}m \x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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), [0, 0, i, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('background true color blue inverse', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[7;48;2;0;0;${i}m■\x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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), [0, 0, i, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('foreground true color grey inverse', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[7;38;2;${i};${i};${i}m \x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('background true color grey inverse', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[7;48;2;${i};${i};${i}m■\x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('foreground true color grey invisible', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[8;38;2;${i};${i};${i}m \x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, x + 1, y + 1), [0, 0, 0, 255]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test('background true color grey invisible', async () => {
|
|
let data = '';
|
|
for (let y = 0; y < 16; y++) {
|
|
for (let x = 0; x < 16; x++) {
|
|
const i = y * 16 + x;
|
|
data += `\x1b[8;48;2;${i};${i};${i}m■\x1b[0m`;
|
|
}
|
|
data += '\r\n';
|
|
}
|
|
await ctx.value.proxy.write(data);
|
|
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]);
|
|
}
|
|
}
|
|
});
|
|
|
|
test.describe('minimumContrastRatio', async () => {
|
|
test('should adjust 0-15 colors on black background', async () => {
|
|
const theme: ITheme = {
|
|
black: '#2e3436',
|
|
red: '#cc0000',
|
|
green: '#4e9a06',
|
|
yellow: '#c4a000',
|
|
blue: '#3465a4',
|
|
magenta: '#75507b',
|
|
cyan: '#06989a',
|
|
white: '#d3d7cf',
|
|
brightBlack: '#555753',
|
|
brightRed: '#ef2929',
|
|
brightGreen: '#8ae234',
|
|
brightYellow: '#fce94f',
|
|
brightBlue: '#729fcf',
|
|
brightMagenta: '#ad7fa8',
|
|
brightCyan: '#34e2e2',
|
|
brightWhite: '#eeeeec'
|
|
};
|
|
await ctx.value.page.evaluate(`
|
|
window.term.options.theme = ${JSON.stringify(theme)};
|
|
window.term.options.minimumContrastRatio = 1;
|
|
`);
|
|
await ctx.value.proxy.write(
|
|
`\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
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0x2e, 0x34, 0x36, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [0xcc, 0x00, 0x00, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 1), [0x4e, 0x9a, 0x06, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 4, 1), [0xc4, 0xa0, 0x00, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 5, 1), [0x34, 0x65, 0xa4, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 6, 1), [0x75, 0x50, 0x7b, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 7, 1), [0x06, 0x98, 0x9a, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 8, 1), [0xd3, 0xd7, 0xcf, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 2), [0x55, 0x57, 0x53, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 2), [0xef, 0x29, 0x29, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 2), [0x8a, 0xe2, 0x34, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 4, 2), [0xfc, 0xe9, 0x4f, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 5, 2), [0x72, 0x9f, 0xcf, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 6, 2), [0xad, 0x7f, 0xa8, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 7, 2), [0x34, 0xe2, 0xe2, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 8, 2), [0xee, 0xee, 0xec, 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 pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [176, 180, 180, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [238, 158, 158, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 1), [152, 198, 110, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 4, 1), [208, 179, 49, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 5, 1), [161, 183, 215, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 6, 1), [191, 174, 194, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 7, 1), [110, 197, 198, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 8, 1), [211, 215, 207, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 2), [183, 185, 183, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 2), [249, 156, 156, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 2), [138, 226, 52, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 4, 2), [252, 233, 79, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 5, 2), [154, 186, 221, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 6, 2), [203, 173, 199, 255]);
|
|
// Unchanged
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 7, 2), [0x34, 0xe2, 0xe2, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 8, 2), [0xee, 0xee, 0xec, 255]);
|
|
});
|
|
|
|
test('should adjust 0-15 colors on white background', async () => {
|
|
const theme: ITheme = {
|
|
background: '#ffffff',
|
|
black: '#2e3436',
|
|
red: '#cc0000',
|
|
green: '#4e9a06',
|
|
yellow: '#c4a000',
|
|
blue: '#3465a4',
|
|
magenta: '#75507b',
|
|
cyan: '#06989a',
|
|
white: '#d3d7cf',
|
|
brightBlack: '#555753',
|
|
brightRed: '#ef2929',
|
|
brightGreen: '#8ae234',
|
|
brightYellow: '#fce94f',
|
|
brightBlue: '#729fcf',
|
|
brightMagenta: '#ad7fa8',
|
|
brightCyan: '#34e2e2',
|
|
brightWhite: '#eeeeec'
|
|
};
|
|
await ctx.value.page.evaluate(`
|
|
window.term.options.theme = ${JSON.stringify(theme)};
|
|
window.term.options.minimumContrastRatio = 1;
|
|
`);
|
|
await ctx.value.proxy.write(
|
|
`\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
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0x2e, 0x34, 0x36, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [0xcc, 0x00, 0x00, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 1), [0x4e, 0x9a, 0x06, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 4, 1), [0xc4, 0xa0, 0x00, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 5, 1), [0x34, 0x65, 0xa4, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 6, 1), [0x75, 0x50, 0x7b, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 7, 1), [0x06, 0x98, 0x9a, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 8, 1), [0xd3, 0xd7, 0xcf, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 2), [0x55, 0x57, 0x53, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 2), [0xef, 0x29, 0x29, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 2), [0x8a, 0xe2, 0x34, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 4, 2), [0xfc, 0xe9, 0x4f, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 5, 2), [0x72, 0x9f, 0xcf, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 6, 2), [0xad, 0x7f, 0xa8, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 7, 2), [0x34, 0xe2, 0xe2, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 8, 2), [0xee, 0xee, 0xec, 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 pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [46, 52, 54, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [132, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 1), [36, 72, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 4, 1), [72, 59, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 5, 1), [32, 64, 106, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 6, 1), [75, 51, 80, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 7, 1), [0, 71, 72, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 8, 1), [64, 64, 63, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 2), [61, 63, 59, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 2), [125, 19, 19, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 2), [40, 67, 13, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 4, 2), [67, 63, 19, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 5, 2), [45, 65, 87, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 6, 2), [81, 57, 78, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 7, 2), [13, 67, 67, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 8, 2), [64, 64, 64, 255]);
|
|
});
|
|
|
|
test('should enforce half the contrast for dim cells', async () => {
|
|
const theme: ITheme = {
|
|
background: '#ffffff',
|
|
black: '#2e3436',
|
|
red: '#cc0000',
|
|
green: '#4e9a06',
|
|
yellow: '#c4a000',
|
|
blue: '#3465a4',
|
|
magenta: '#75507b',
|
|
cyan: '#06989a',
|
|
white: '#d3d7cf',
|
|
brightBlack: '#555753',
|
|
brightRed: '#ef2929',
|
|
brightGreen: '#8ae234',
|
|
brightYellow: '#fce94f',
|
|
brightBlue: '#729fcf',
|
|
brightMagenta: '#ad7fa8',
|
|
brightCyan: '#34e2e2',
|
|
brightWhite: '#eeeeec'
|
|
};
|
|
await ctx.value.page.evaluate(`
|
|
window.term.options.theme = ${JSON.stringify(theme)};
|
|
window.term.options.minimumContrastRatio = 1;
|
|
`);
|
|
await 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]);
|
|
// 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]);
|
|
});
|
|
});
|
|
|
|
(ctx.skipCanvasExceptions ? test.describe.skip : test.describe)('selectionBackground', async () => {
|
|
test('should resolve the inverse foreground color based on the original background color, not the selection', async () => {
|
|
const theme: ITheme = {
|
|
foreground: '#FF0000',
|
|
background: '#00FF00',
|
|
selectionBackground: '#0000FF'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.write( ` ■\x1b[7m■\x1b[0m`);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 255, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [255, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 1), [0, 255, 0, 255]);
|
|
await ctx.value.proxy.selectAll();
|
|
frameDetails = undefined;
|
|
// Selection only cell needs to be first to ensure renderer has kicked in
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 255, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [255, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 1), [0, 255, 0, 255]);
|
|
});
|
|
});
|
|
|
|
(ctx.skipCanvasExceptions ? test.describe.skip : test.describe)('selectionInactiveBackground', async () => {
|
|
test('should render the the inactive selection when not focused', async () => {
|
|
const theme: ITheme = {
|
|
selectionBackground: '#FF000080',
|
|
selectionInactiveBackground: '#0000FF80'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.focus();
|
|
// Check both the cursor line and another line
|
|
await ctx.value.proxy.writeln('_ ');
|
|
await ctx.value.proxy.write('_ ');
|
|
await ctx.value.proxy.selectAll();
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [128, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [128, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 2), [128, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 2), [128, 0, 0, 255]);
|
|
await ctx.value.page.evaluate(`document.activeElement.blur()`);
|
|
frameDetails = undefined;
|
|
// Selection only cell needs to be first to ensure renderer has kicked in
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 128, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [0, 0, 128, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 2), [0, 0, 128, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 2), [0, 0, 128, 255]);
|
|
});
|
|
});
|
|
|
|
(ctx.skipCanvasExceptions || ctx.skipDomExceptions ? test.describe.skip : test.describe)('selection blending', () => {
|
|
test('background', async () => {
|
|
const theme: ITheme = {
|
|
red: '#CC0000',
|
|
selectionBackground: '#FFFFFF'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.focus();
|
|
await ctx.value.proxy.writeln('\x1b[41m red bg');
|
|
await ctx.value.proxy.writeln('\x1b[7m inverse');
|
|
await ctx.value.proxy.writeln('\x1b[31;7m red fg inverse');
|
|
await ctx.value.proxy.selectAll();
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [230,128,128,255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 2), [255,255,255,255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 3), [230,128,128,255]);
|
|
});
|
|
test('powerline decorative symbols', async () => {
|
|
const theme: ITheme = {
|
|
red: '#CC0000',
|
|
green: '#00CC00',
|
|
selectionBackground: '#FFFFFF'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.focus();
|
|
await ctx.value.proxy.writeln('\u{E0B4} plain\x1b[0m');
|
|
await ctx.value.proxy.writeln('\x1b[31;42m\u{E0B4} red fg green bg\x1b[0m');
|
|
await ctx.value.proxy.writeln('\x1b[32;41m\u{E0B4} green fg red bg\x1b[0m');
|
|
await ctx.value.proxy.writeln('\x1b[31;42;7m\u{E0B4} red fg green bg inverse\x1b[0m');
|
|
await ctx.value.proxy.writeln('\x1b[32;41;7m\u{E0B4} green fg red bg inverse\x1b[0m');
|
|
await ctx.value.proxy.selectAll();
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [255,255,255,255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 2), [230, 128, 128, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 3), [128, 230, 128, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 4), [128, 230, 128, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 5), [230, 128, 128, 255]);
|
|
});
|
|
});
|
|
|
|
test.describe('allowTransparency', async () => {
|
|
test.beforeEach(() => ctx.value.page.evaluate(`term.options.allowTransparency = true`));
|
|
|
|
test('transparent background inverse', async () => {
|
|
const theme: ITheme = {
|
|
background: '#ff000080'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
const data = `\x1b[7m■\x1b[0m`;
|
|
await ctx.value.proxy.write( data);
|
|
// Inverse background should be opaque
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [255, 0, 0, 255]);
|
|
});
|
|
});
|
|
|
|
(ctx.skipCanvasExceptions ? test.describe.skip : test.describe)('selectionForeground', () => {
|
|
test('transparent background inverse', async () => {
|
|
const theme: ITheme = {
|
|
selectionForeground: '#ff0000'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
const data = `\x1b[7m■\x1b[0m`;
|
|
await ctx.value.proxy.write( data);
|
|
await ctx.value.proxy.selectAll();
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [255, 0, 0, 255]);
|
|
});
|
|
});
|
|
|
|
test.describe('decoration color overrides', async () => {
|
|
test('foregroundColor', async () => {
|
|
await ctx.value.page.evaluate(`
|
|
const marker = window.term.registerMarker(-window.term.buffer.active.cursorY);
|
|
window.term.registerDecoration({
|
|
marker,
|
|
foregroundColor: '#ff0000',
|
|
backgroundColor: '#0000ff'
|
|
});
|
|
`);
|
|
const data = `■`;
|
|
await ctx.value.proxy.write( data);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [255, 0, 0, 255]);
|
|
});
|
|
test('foregroundColor should ignore inverse', async () => {
|
|
await ctx.value.page.evaluate(`
|
|
const marker = window.term.registerMarker(-window.term.buffer.active.cursorY);
|
|
window.term.registerDecoration({
|
|
marker,
|
|
foregroundColor: '#ff0000',
|
|
backgroundColor: '#0000ff'
|
|
});
|
|
`);
|
|
const data = `\x1b[7m■\x1b[0m`;
|
|
await ctx.value.proxy.write( data);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [255, 0, 0, 255]);
|
|
});
|
|
test('foregroundColor should ignore inverse (only fg on decoration)', async () => {
|
|
await ctx.value.page.evaluate(`
|
|
const marker = window.term.registerMarker(-window.term.buffer.active.cursorY);
|
|
window.term.registerDecoration({
|
|
marker,
|
|
width: 2,
|
|
foregroundColor: '#ff0000'
|
|
});
|
|
`);
|
|
const data = `\x1b[7m■ \x1b[0m`;
|
|
await ctx.value.proxy.write( data);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [255, 0, 0, 255]); // inverse foreground of '■' should be decoration fg override
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [255, 255, 255, 255]); // inverse background of ' ' should be default foreground
|
|
});
|
|
test('backgroundColor', async () => {
|
|
await ctx.value.page.evaluate(`
|
|
const marker = window.term.registerMarker(-window.term.buffer.active.cursorY);
|
|
window.term.registerDecoration({
|
|
marker,
|
|
foregroundColor: '#ff0000',
|
|
backgroundColor: '#0000ff'
|
|
});
|
|
`);
|
|
const data = ` `;
|
|
await ctx.value.proxy.write( data);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 255, 255]);
|
|
});
|
|
test('backgroundColor should ignore inverse', async () => {
|
|
await ctx.value.page.evaluate(`
|
|
const marker = window.term.registerMarker(-window.term.buffer.active.cursorY);
|
|
window.term.registerDecoration({
|
|
marker,
|
|
foregroundColor: '#ff0000',
|
|
backgroundColor: '#0000ff'
|
|
});
|
|
`);
|
|
const data = `\x1b[7m \x1b[0m`;
|
|
await ctx.value.proxy.write( data);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 255, 255]);
|
|
});
|
|
(ctx.skipCanvasExceptions ? test.skip : test)('backgroundColor should ignore inverse (only bg on decoration)', async () => {
|
|
const data = `\x1b[7m■ \x1b[0m`;
|
|
await ctx.value.proxy.write( data);
|
|
await ctx.value.page.evaluate(`
|
|
const marker = window.term.registerMarker(-window.term.buffer.active.cursorY);
|
|
window.term.registerDecoration({
|
|
marker,
|
|
width: 2,
|
|
backgroundColor: '#0000ff'
|
|
});
|
|
`);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 0, 255]); // inverse foreground of '■' should be default
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [0, 0, 255, 255]); // inverse background of ' ' should be decoration bg override
|
|
});
|
|
});
|
|
|
|
test.describe('regression tests', () => {
|
|
test('#4736: inactive selection background should replace regular cell background color', async () => {
|
|
const theme: ITheme = {
|
|
selectionBackground: '#FF0000',
|
|
selectionInactiveBackground: '#0000FF'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.writeln(' ');
|
|
await ctx.value.proxy.writeln(' O ');
|
|
await ctx.value.proxy.writeln(' ');
|
|
await ctx.value.proxy.focus();
|
|
await ctx.value.proxy.selectAll();
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [255, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [255, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 2), [255, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 3), [255, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 3), [255, 0, 0, 255]);
|
|
await ctx.value.proxy.blur();
|
|
frameDetails = undefined;
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 255, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [0, 0, 255, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 2), [0, 0, 255, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 3), [0, 0, 255, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 3), [0, 0, 255, 255]);
|
|
});
|
|
test('#4758: multiple invisible text characters without SGR change should not be rendered', async () => {
|
|
// 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]);
|
|
});
|
|
test('#4759: minimum contrast ratio should be respected on inverse text', async () => {
|
|
const theme: ITheme = {
|
|
foreground: '#aaaaaa',
|
|
background: '#333333'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.write(`\x1b[7m■■`);
|
|
// Validate before minimumContrastRatio is applied
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [51, 51, 51, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [51, 51, 51, 255]);
|
|
await ctx.value.page.evaluate(`window.term.options.minimumContrastRatio = 10;`);
|
|
frameDetails = undefined;
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [0, 0, 0, 255]);
|
|
});
|
|
(ctx.skipCanvasExceptions ? test.skip : test)('#4759: minimum contrast ratio should be respected on selected inverse text', async () => {
|
|
const theme: ITheme = {
|
|
foreground: '#777777',
|
|
background: '#555555',
|
|
selectionBackground: '#666666' // Slightly more contrast needed for selection
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.write(`\x1b[7m■■`);
|
|
await ctx.value.proxy.selectAll();
|
|
// Validate before minimumContrastRatio is applied
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [85, 85, 85, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [85, 85, 85, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 1), [102, 102, 102, 255]);
|
|
await ctx.value.page.evaluate(`window.term.options.minimumContrastRatio = 10;`);
|
|
await ctx.value.proxy.selectAll();
|
|
frameDetails = undefined;
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [255, 255, 255, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 2, 1), [255, 255, 255, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 3, 1), [102, 102, 102, 255]);
|
|
});
|
|
test('#4773: block cursor should render when the cell is selected', async () => {
|
|
const theme: ITheme = {
|
|
cursor: '#0000FF',
|
|
selectionBackground: '#FF0000'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await ctx.value.proxy.focus();
|
|
await ctx.value.proxy.selectAll();
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 255, 255]);
|
|
});
|
|
test('#4799: cursor should be in the correct position', async () => {
|
|
const theme: ITheme = {
|
|
cursor: '#0000FF'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
for (let index = 0; index < 160; index++) {
|
|
await ctx.value.proxy.writeln(``);
|
|
}
|
|
await ctx.value.proxy.focus();
|
|
await ctx.value.proxy.write('\x1b[A');
|
|
await ctx.value.proxy.write('\x1b[A');
|
|
await ctx.value.proxy.scrollLines(-2);
|
|
const rows = await ctx.value.proxy.rows;
|
|
// block cursor style
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, rows), [0, 0, 255, 255]);
|
|
await ctx.value.proxy.blur();
|
|
frameDetails = undefined;
|
|
// outlink cursor style
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, rows), [0, 0, 0, 255]);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, rows, CellColorPosition.FIRST), [0, 0, 255, 255]);
|
|
});
|
|
});
|
|
}
|
|
|
|
enum CellColorPosition {
|
|
CENTER = 0,
|
|
FIRST = 1
|
|
}
|
|
|
|
/**
|
|
* Injects shared renderer tests where it's required to re-initialize the terminal for each test.
|
|
* This is much slower than just calling `Terminal.reset` but testing some features needs this
|
|
* treatment.
|
|
*/
|
|
export function injectSharedRendererTestsStandalone(ctx: ISharedRendererTestContext): void {
|
|
test.describe('standalone tests', () => {
|
|
test.beforeEach(async () => {
|
|
// Recreate terminal
|
|
await openTerminal(ctx.value);
|
|
ctx.value.page.evaluate(`
|
|
window.term.options.minimumContrastRatio = 1;
|
|
window.term.options.allowTransparency = false;
|
|
window.term.options.theme = undefined;
|
|
`);
|
|
// Clear the cached screenshot before each test
|
|
frameDetails = undefined;
|
|
});
|
|
test.describe('regression tests', () => {
|
|
test('#4790: cursor should not be displayed before focusing', async () => {
|
|
const theme: ITheme = {
|
|
cursor: '#0000FF'
|
|
};
|
|
await ctx.value.page.evaluate(`window.term.options.theme = ${JSON.stringify(theme)};`);
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 0, 255]);
|
|
await ctx.value.proxy.focus();
|
|
frameDetails = undefined;
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 255, 255]);
|
|
await ctx.value.proxy.blur();
|
|
frameDetails = undefined;
|
|
await pollFor(ctx.value.page, () => getCellColor(ctx.value, 1, 1), [0, 0, 0, 255]);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Gets the color of the pixel in the center of a cell.
|
|
* @param ctx The test context.
|
|
* @param col The 1-based column index to get the color for.
|
|
* @param row The 1-based row index to get the color for.
|
|
*/
|
|
function getCellColor(ctx: ITestContext, col: number, row: number, position: CellColorPosition = CellColorPosition.CENTER): MaybeAsync<[red: number, green: number, blue: number, alpha: number]> {
|
|
if (!frameDetails) {
|
|
return getFrameDetails(ctx).then(frameDetails => getCellColorInner(frameDetails, col, row));
|
|
}
|
|
switch (position) {
|
|
case CellColorPosition.CENTER:
|
|
return getCellColorInner(frameDetails, col, row);
|
|
case CellColorPosition.FIRST:
|
|
return getCellColorFirstPoint(frameDetails, col, row);
|
|
}
|
|
}
|
|
|
|
let frameDetails: { cols: number, rows: number, decoded: IImage32 } | undefined = undefined;
|
|
async function getFrameDetails(ctx: ITestContext): Promise<{ cols: number, rows: number, decoded: IImage32 }> {
|
|
const screenshotOptions: LocatorScreenshotOptions | undefined = process.env.DEBUG ? { path: 'out-test/playwright/screenshot.png' } : undefined;
|
|
const buffer = await ctx.page.locator('#terminal-container .xterm-screen').screenshot(screenshotOptions);
|
|
frameDetails = {
|
|
cols: await ctx.proxy.cols,
|
|
rows: await ctx.proxy.rows,
|
|
decoded: (await decodePng(buffer, { force32: true })).image
|
|
};
|
|
return frameDetails;
|
|
}
|
|
|
|
function getCellColorInner(frameDetails: { cols: number, rows: number, decoded: IImage32 }, col: number, row: number): [red: number, green: number, blue: number, alpha: number] {
|
|
const cellSize = {
|
|
width: frameDetails.decoded.width / frameDetails.cols,
|
|
height: frameDetails.decoded.height / frameDetails.rows
|
|
};
|
|
const x = Math.floor((col - 1/* 1- to 0-based index */ + 0.5/* middle of cell */) * cellSize.width);
|
|
const y = Math.floor((row - 1/* 1- to 0-based index */ + 0.5/* middle of cell */) * cellSize.height);
|
|
const i = (y * frameDetails.decoded.width + x) * 4/* 4 channels per pixel */;
|
|
return Array.from(frameDetails.decoded.data.slice(i, i + 4)) as [number, number, number, number];
|
|
}
|
|
|
|
function getCellColorFirstPoint(frameDetails: { cols: number, rows: number, decoded: IImage32 }, col: number, row: number): [red: number, green: number, blue: number, alpha: number] {
|
|
const cellSize = {
|
|
width: frameDetails.decoded.width / frameDetails.cols,
|
|
height: frameDetails.decoded.height / frameDetails.rows
|
|
};
|
|
const x = Math.floor((col - 1/* 1- to 0-based index */) * cellSize.width);
|
|
const y = Math.floor((row - 1/* 1- to 0-based index */) * cellSize.height);
|
|
const i = (y * frameDetails.decoded.width + x) * 4/* 4 channels per pixel */;
|
|
return Array.from(frameDetails.decoded.data.slice(i, i + 4)) as [number, number, number, number];
|
|
}
|
|
|
|
const COLORS_16_TO_255 = [
|
|
'#000000', '#00005f', '#000087', '#0000af', '#0000d7', '#0000ff', '#005f00', '#005f5f', '#005f87', '#005faf', '#005fd7', '#005fff', '#008700', '#00875f', '#008787', '#0087af',
|
|
'#0087d7', '#0087ff', '#00af00', '#00af5f', '#00af87', '#00afaf', '#00afd7', '#00afff', '#00d700', '#00d75f', '#00d787', '#00d7af', '#00d7d7', '#00d7ff', '#00ff00', '#00ff5f',
|
|
'#00ff87', '#00ffaf', '#00ffd7', '#00ffff', '#5f0000', '#5f005f', '#5f0087', '#5f00af', '#5f00d7', '#5f00ff', '#5f5f00', '#5f5f5f', '#5f5f87', '#5f5faf', '#5f5fd7', '#5f5fff',
|
|
'#5f8700', '#5f875f', '#5f8787', '#5f87af', '#5f87d7', '#5f87ff', '#5faf00', '#5faf5f', '#5faf87', '#5fafaf', '#5fafd7', '#5fafff', '#5fd700', '#5fd75f', '#5fd787', '#5fd7af',
|
|
'#5fd7d7', '#5fd7ff', '#5fff00', '#5fff5f', '#5fff87', '#5fffaf', '#5fffd7', '#5fffff', '#870000', '#87005f', '#870087', '#8700af', '#8700d7', '#8700ff', '#875f00', '#875f5f',
|
|
'#875f87', '#875faf', '#875fd7', '#875fff', '#878700', '#87875f', '#878787', '#8787af', '#8787d7', '#8787ff', '#87af00', '#87af5f', '#87af87', '#87afaf', '#87afd7', '#87afff',
|
|
'#87d700', '#87d75f', '#87d787', '#87d7af', '#87d7d7', '#87d7ff', '#87ff00', '#87ff5f', '#87ff87', '#87ffaf', '#87ffd7', '#87ffff', '#af0000', '#af005f', '#af0087', '#af00af',
|
|
'#af00d7', '#af00ff', '#af5f00', '#af5f5f', '#af5f87', '#af5faf', '#af5fd7', '#af5fff', '#af8700', '#af875f', '#af8787', '#af87af', '#af87d7', '#af87ff', '#afaf00', '#afaf5f',
|
|
'#afaf87', '#afafaf', '#afafd7', '#afafff', '#afd700', '#afd75f', '#afd787', '#afd7af', '#afd7d7', '#afd7ff', '#afff00', '#afff5f', '#afff87', '#afffaf', '#afffd7', '#afffff',
|
|
'#d70000', '#d7005f', '#d70087', '#d700af', '#d700d7', '#d700ff', '#d75f00', '#d75f5f', '#d75f87', '#d75faf', '#d75fd7', '#d75fff', '#d78700', '#d7875f', '#d78787', '#d787af',
|
|
'#d787d7', '#d787ff', '#d7af00', '#d7af5f', '#d7af87', '#d7afaf', '#d7afd7', '#d7afff', '#d7d700', '#d7d75f', '#d7d787', '#d7d7af', '#d7d7d7', '#d7d7ff', '#d7ff00', '#d7ff5f',
|
|
'#d7ff87', '#d7ffaf', '#d7ffd7', '#d7ffff', '#ff0000', '#ff005f', '#ff0087', '#ff00af', '#ff00d7', '#ff00ff', '#ff5f00', '#ff5f5f', '#ff5f87', '#ff5faf', '#ff5fd7', '#ff5fff',
|
|
'#ff8700', '#ff875f', '#ff8787', '#ff87af', '#ff87d7', '#ff87ff', '#ffaf00', '#ffaf5f', '#ffaf87', '#ffafaf', '#ffafd7', '#ffafff', '#ffd700', '#ffd75f', '#ffd787', '#ffd7af',
|
|
'#ffd7d7', '#ffd7ff', '#ffff00', '#ffff5f', '#ffff87', '#ffffaf', '#ffffd7', '#ffffff', '#080808', '#121212', '#1c1c1c', '#262626', '#303030', '#3a3a3a', '#444444', '#4e4e4e',
|
|
'#585858', '#626262', '#6c6c6c', '#767676', '#808080', '#8a8a8a', '#949494', '#9e9e9e', '#a8a8a8', '#b2b2b2', '#bcbcbc', '#c6c6c6', '#d0d0d0', '#dadada', '#e4e4e4', '#eeeeee'
|
|
];
|