mirror of
https://github.com/microsoft/playwright.git
synced 2024-09-11 20:37:54 +03:00
feat: env.PLAYWRIGHT_FORCE_TTY to control reporters' tty (#30834)
Previously, terminal reporters consulted `process.stdout.isTTY`. Now it is possible to control the tty behavior: - `PLAYWRIGHT_FORCE_TTY=0` or `PLAYWRIGHT_FORCE_TTY=false` to disable TTY; - `PLAYWRIGHT_FORCE_TTY=1` or `PLAYWRIGHT_FORCE_TTY=true` to enable TTY, defaults to 100 columns when real columns are unavailable; - `PLAYWRIGHT_FORCE_TTY=<number>` to force enable TTY and set the columns. Fixes #29422.
This commit is contained in:
parent
3370f37e7b
commit
89cdf3d56e
@ -45,27 +45,41 @@ type TestSummary = {
|
||||
fatalErrors: TestError[];
|
||||
};
|
||||
|
||||
export const isTTY = !!process.env.PWTEST_TTY_WIDTH || process.stdout.isTTY;
|
||||
export const ttyWidth = process.env.PWTEST_TTY_WIDTH ? parseInt(process.env.PWTEST_TTY_WIDTH, 10) : process.stdout.columns || 0;
|
||||
let useColors = isTTY;
|
||||
if (process.env.DEBUG_COLORS === '0'
|
||||
|| process.env.DEBUG_COLORS === 'false'
|
||||
|| process.env.FORCE_COLOR === '0'
|
||||
|| process.env.FORCE_COLOR === 'false')
|
||||
useColors = false;
|
||||
else if (process.env.DEBUG_COLORS || process.env.FORCE_COLOR)
|
||||
useColors = true;
|
||||
export const { isTTY, ttyWidth, colors } = (() => {
|
||||
let isTTY = !!process.stdout.isTTY;
|
||||
let ttyWidth = process.stdout.columns || 0;
|
||||
if (process.env.PLAYWRIGHT_FORCE_TTY === 'false' || process.env.PLAYWRIGHT_FORCE_TTY === '0') {
|
||||
isTTY = false;
|
||||
ttyWidth = 0;
|
||||
} else if (process.env.PLAYWRIGHT_FORCE_TTY === 'true' || process.env.PLAYWRIGHT_FORCE_TTY === '1') {
|
||||
isTTY = true;
|
||||
ttyWidth = process.stdout.columns || 100;
|
||||
} else if (process.env.PLAYWRIGHT_FORCE_TTY) {
|
||||
isTTY = true;
|
||||
ttyWidth = +process.env.PLAYWRIGHT_FORCE_TTY;
|
||||
if (isNaN(ttyWidth))
|
||||
ttyWidth = 100;
|
||||
}
|
||||
|
||||
export const colors = useColors ? realColors : {
|
||||
bold: (t: string) => t,
|
||||
cyan: (t: string) => t,
|
||||
dim: (t: string) => t,
|
||||
gray: (t: string) => t,
|
||||
green: (t: string) => t,
|
||||
red: (t: string) => t,
|
||||
yellow: (t: string) => t,
|
||||
enabled: false,
|
||||
};
|
||||
let useColors = isTTY;
|
||||
if (process.env.DEBUG_COLORS === '0' || process.env.DEBUG_COLORS === 'false' ||
|
||||
process.env.FORCE_COLOR === '0' || process.env.FORCE_COLOR === 'false')
|
||||
useColors = false;
|
||||
else if (process.env.DEBUG_COLORS || process.env.FORCE_COLOR)
|
||||
useColors = true;
|
||||
|
||||
const colors = useColors ? realColors : {
|
||||
bold: (t: string) => t,
|
||||
cyan: (t: string) => t,
|
||||
dim: (t: string) => t,
|
||||
gray: (t: string) => t,
|
||||
green: (t: string) => t,
|
||||
red: (t: string) => t,
|
||||
yellow: (t: string) => t,
|
||||
enabled: false,
|
||||
};
|
||||
return { isTTY, ttyWidth, colors };
|
||||
})();
|
||||
|
||||
export class BaseReporter implements ReporterV2 {
|
||||
config!: FullConfig;
|
||||
|
@ -229,8 +229,6 @@ class ListReporter extends BaseReporter {
|
||||
// Go down if needed.
|
||||
if (row !== this._lastRow)
|
||||
process.stdout.write(`\u001B[${this._lastRow - row}E`);
|
||||
if (process.env.PWTEST_TTY_WIDTH)
|
||||
process.stdout.write('\n'); // For testing.
|
||||
}
|
||||
|
||||
private _testPrefix(index: string, statusMark: string) {
|
||||
|
@ -441,7 +441,7 @@ test('merge into list report by default', async ({ runInlineTest, mergeReports }
|
||||
const reportFiles = await fs.promises.readdir(reportDir);
|
||||
reportFiles.sort();
|
||||
expect(reportFiles).toEqual(['report-1.zip', 'report-2.zip', 'report-3.zip']);
|
||||
const { exitCode, output } = await mergeReports(reportDir, { PW_TEST_DEBUG_REPORTERS: '1', PW_TEST_DEBUG_REPORTERS_PRINT_STEPS: '1', PWTEST_TTY_WIDTH: '80' }, { additionalArgs: ['--reporter', 'list'] });
|
||||
const { exitCode, output } = await mergeReports(reportDir, { PW_TEST_DEBUG_REPORTERS: '1', PW_TEST_DEBUG_REPORTERS_PRINT_STEPS: '1', PLAYWRIGHT_FORCE_TTY: '80' }, { additionalArgs: ['--reporter', 'list'] });
|
||||
expect(exitCode).toBe(0);
|
||||
|
||||
const text = stripAnsi(output);
|
||||
|
@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { test, expect } from './playwright-test-fixtures';
|
||||
import { test, expect, stripAnsi } from './playwright-test-fixtures';
|
||||
|
||||
const DOES_NOT_SUPPORT_UTF8_IN_TERMINAL = process.platform === 'win32' && process.env.TERM_PROGRAM !== 'vscode' && !process.env.WT_SESSION;
|
||||
const POSITIVE_STATUS_MARK = DOES_NOT_SUPPORT_UTF8_IN_TERMINAL ? 'ok' : '✓ ';
|
||||
@ -70,7 +70,7 @@ for (const useIntermediateMergeReport of [false, true] as const) {
|
||||
});
|
||||
});
|
||||
`,
|
||||
}, { reporter: 'list' }, { PW_TEST_DEBUG_REPORTERS: '1', PW_TEST_DEBUG_REPORTERS_PRINT_STEPS: '1', PWTEST_TTY_WIDTH: '80' });
|
||||
}, { reporter: 'list' }, { PW_TEST_DEBUG_REPORTERS: '1', PW_TEST_DEBUG_REPORTERS_PRINT_STEPS: '1', PLAYWRIGHT_FORCE_TTY: '80' });
|
||||
const text = result.output;
|
||||
const lines = text.split('\n').filter(l => l.match(/^\d :/)).map(l => l.replace(/[.\d]+m?s/, 'Xms'));
|
||||
lines.pop(); // Remove last item that contains [v] and time in ms.
|
||||
@ -105,7 +105,7 @@ for (const useIntermediateMergeReport of [false, true] as const) {
|
||||
await test.step('inner 2.2', async () => {});
|
||||
});
|
||||
});`,
|
||||
}, { reporter: 'list' }, { PW_TEST_DEBUG_REPORTERS: '1', PWTEST_TTY_WIDTH: '80' });
|
||||
}, { reporter: 'list' }, { PW_TEST_DEBUG_REPORTERS: '1', PLAYWRIGHT_FORCE_TTY: '80' });
|
||||
const text = result.output;
|
||||
const lines = text.split('\n').filter(l => l.match(/^\d :/)).map(l => l.replace(/[.\d]+m?s/, 'Xms'));
|
||||
lines.pop(); // Remove last item that contains [v] and time in ms.
|
||||
@ -135,7 +135,7 @@ for (const useIntermediateMergeReport of [false, true] as const) {
|
||||
console.log('a'.repeat(80) + 'b'.repeat(20));
|
||||
});
|
||||
`,
|
||||
}, { reporter: 'list' }, { PWTEST_TTY_WIDTH: TTY_WIDTH + '' });
|
||||
}, { reporter: 'list' }, { PLAYWRIGHT_FORCE_TTY: TTY_WIDTH + '' });
|
||||
|
||||
const renderedText = simpleAnsiRenderer(result.rawOutput, TTY_WIDTH);
|
||||
if (process.platform === 'win32')
|
||||
@ -154,7 +154,7 @@ for (const useIntermediateMergeReport of [false, true] as const) {
|
||||
expect(testInfo.retry).toBe(1);
|
||||
});
|
||||
`,
|
||||
}, { reporter: 'list', retries: '1' }, { PW_TEST_DEBUG_REPORTERS: '1', PWTEST_TTY_WIDTH: '80' });
|
||||
}, { reporter: 'list', retries: '1' }, { PW_TEST_DEBUG_REPORTERS: '1', PLAYWRIGHT_FORCE_TTY: '80' });
|
||||
const text = result.output;
|
||||
const lines = text.split('\n').filter(l => l.startsWith('0 :') || l.startsWith('1 :')).map(l => l.replace(/\d+(\.\d+)?m?s/, 'XXms'));
|
||||
|
||||
@ -185,10 +185,10 @@ for (const useIntermediateMergeReport of [false, true] as const) {
|
||||
test.skip('skipped very long name', async () => {
|
||||
});
|
||||
`,
|
||||
}, { reporter: 'list', retries: 0 }, { PWTEST_TTY_WIDTH: '50' });
|
||||
}, { reporter: 'list', retries: 0 }, { PLAYWRIGHT_FORCE_TTY: '50' });
|
||||
expect(result.exitCode).toBe(1);
|
||||
|
||||
const lines = result.output.split('\n').slice(3, 11);
|
||||
const lines = result.rawOutput.split('\n').map(line => line.split('\x1B[22m\x1B[1E')).flat().map(line => stripAnsi(line)).filter(line => line.trim()).slice(1, 9);
|
||||
expect(lines.every(line => line.length <= 50)).toBe(true);
|
||||
|
||||
expect(lines[0]).toBe(` 1 …a.test.ts:3:15 › failure in very long name`);
|
||||
|
Loading…
Reference in New Issue
Block a user