From d8db785c0a70a6ee2259cbc5707da152b540d1d6 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Fri, 11 Feb 2022 08:33:56 -0800 Subject: [PATCH] fix(reporters): correctly handle missing stdout.columns (#12016) When columns are not available, do not trim the output. --- packages/playwright-test/src/dispatcher.ts | 2 +- packages/playwright-test/src/reporters/base.ts | 11 ++++++++--- packages/playwright-test/src/reporters/line.ts | 6 +++--- packages/playwright-test/src/reporters/list.ts | 13 +++---------- tests/playwright-test/reporter-line.spec.ts | 16 ++++++++++++++++ 5 files changed, 31 insertions(+), 17 deletions(-) diff --git a/packages/playwright-test/src/dispatcher.ts b/packages/playwright-test/src/dispatcher.ts index dcb1806a36..10cef1dbea 100644 --- a/packages/playwright-test/src/dispatcher.ts +++ b/packages/playwright-test/src/dispatcher.ts @@ -478,7 +478,7 @@ class Worker extends EventEmitter { detached: false, env: { FORCE_COLOR: '1', - DEBUG_COLORS: process.stdout.isTTY ? '1' : '0', + DEBUG_COLORS: '1', TEST_WORKER_INDEX: String(this.workerIndex), TEST_PARALLEL_INDEX: String(this.parallelIndex), ...process.env diff --git a/packages/playwright-test/src/reporters/base.ts b/packages/playwright-test/src/reporters/base.ts index cdfda403e9..0888fd40b1 100644 --- a/packages/playwright-test/src/reporters/base.ts +++ b/packages/playwright-test/src/reporters/base.ts @@ -107,8 +107,13 @@ export class BaseReporter implements Reporter { this.result = result; } - protected ttyWidth() { - return this._ttyWidthForTest || (process.env.PWTEST_SKIP_TEST_OUTPUT ? 80 : process.stdout.columns || 0); + protected fitToScreen(line: string, suffix?: string): string { + const ttyWidth = this._ttyWidthForTest || (process.env.PWTEST_SKIP_TEST_OUTPUT ? 80 : process.stdout.columns || 0); + if (!ttyWidth) { + // Guard against the case where we cannot determine available width. + return line; + } + return fitToWidth(line, ttyWidth, suffix); } protected generateStartingMessage() { @@ -431,7 +436,7 @@ export function stripAnsiEscapes(str: string): string { } // Leaves enough space for the "suffix" to also fit. -export function fitToScreen(line: string, width: number, suffix?: string): string { +function fitToWidth(line: string, width: number, suffix?: string): string { const suffixLength = suffix ? stripAnsiEscapes(suffix).length : 0; width -= suffixLength; if (line.length <= width) diff --git a/packages/playwright-test/src/reporters/line.ts b/packages/playwright-test/src/reporters/line.ts index 5c907d3e0e..d3c8971459 100644 --- a/packages/playwright-test/src/reporters/line.ts +++ b/packages/playwright-test/src/reporters/line.ts @@ -15,7 +15,7 @@ */ import colors from 'colors/safe'; -import { BaseReporter, fitToScreen, formatFailure, formatTestTitle } from './base'; +import { BaseReporter, formatFailure, formatTestTitle } from './base'; import { FullConfig, TestCase, Suite, TestResult, FullResult } from '../../types/testReporter'; class LineReporter extends BaseReporter { @@ -51,7 +51,7 @@ class LineReporter extends BaseReporter { if (test && this._lastTest !== test) { // Write new header for the output. const title = colors.gray(formatTestTitle(this.config, test)); - stream.write(fitToScreen(title, this.ttyWidth()) + `\n`); + stream.write(this.fitToScreen(title) + `\n`); this._lastTest = test; } @@ -69,7 +69,7 @@ class LineReporter extends BaseReporter { if (process.env.PWTEST_SKIP_TEST_OUTPUT) process.stdout.write(`${title + suffix}\n`); else - process.stdout.write(`\u001B[1A\u001B[2K${fitToScreen(title, this.ttyWidth(), suffix) + colors.yellow(suffix)}\n`); + process.stdout.write(`\u001B[1A\u001B[2K${this.fitToScreen(title, suffix) + colors.yellow(suffix)}\n`); if (!this.willRetry(test) && (test.outcome() === 'flaky' || test.outcome() === 'unexpected')) { if (!process.env.PWTEST_SKIP_TEST_OUTPUT) diff --git a/packages/playwright-test/src/reporters/list.ts b/packages/playwright-test/src/reporters/list.ts index 20e4d7dfcb..553a07df49 100644 --- a/packages/playwright-test/src/reporters/list.ts +++ b/packages/playwright-test/src/reporters/list.ts @@ -17,7 +17,7 @@ /* eslint-disable no-console */ import colors from 'colors/safe'; import milliseconds from 'ms'; -import { BaseReporter, fitToScreen, formatTestTitle } from './base'; +import { BaseReporter, formatTestTitle } from './base'; import { FullConfig, FullResult, Suite, TestCase, TestResult, TestStep } from '../../types/testReporter'; // Allow it in the Visual Studio Code Terminal and the new Windows Terminal @@ -55,7 +55,7 @@ class ListReporter extends BaseReporter { } const line = ' ' + colors.gray(formatTestTitle(this.config, test)); const suffix = this._retrySuffix(result); - process.stdout.write(this._fitToScreen(line, suffix) + suffix + '\n'); + process.stdout.write(this.fitToScreen(line, suffix) + suffix + '\n'); } this._testRows.set(test, this._lastRow++); } @@ -142,7 +142,7 @@ class ListReporter extends BaseReporter { process.stdout.write(`\u001B[${this._lastRow - testRow}A`); // Erase line, go to the start process.stdout.write('\u001B[2K\u001B[0G'); - process.stdout.write(this._fitToScreen(line, suffix) + suffix); + process.stdout.write(this.fitToScreen(line, suffix) + suffix); // Go down if needed. if (testRow !== this._lastRow) process.stdout.write(`\u001B[${this._lastRow - testRow}E`); @@ -152,13 +152,6 @@ class ListReporter extends BaseReporter { return (result.retry ? colors.yellow(` (retry #${result.retry})`) : ''); } - private _fitToScreen(line: string, suffix?: string): string { - const ttyWidth = this.ttyWidth(); - if (!ttyWidth) - return line; - return fitToScreen(line, ttyWidth, suffix); - } - private _updateTestLineForTest(test: TestCase, line: string, suffix: string) { const testRow = this._testRows.get(test)!; process.stdout.write(testRow + ' : ' + line + suffix + '\n'); diff --git a/tests/playwright-test/reporter-line.spec.ts b/tests/playwright-test/reporter-line.spec.ts index 4f56b39119..8febdb5d04 100644 --- a/tests/playwright-test/reporter-line.spec.ts +++ b/tests/playwright-test/reporter-line.spec.ts @@ -66,3 +66,19 @@ test('should print flaky failures', async ({ runInlineTest }) => { expect(result.flaky).toBe(1); expect(stripAnsi(result.output)).toContain('expect(testInfo.retry).toBe(1)'); }); + +test('should work without tty', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.test.js': ` + const { test } = pwt; + test('one', async ({}) => { + expect(1).toBe(0); + }); + `, + }, { reporter: 'line' }, { PWTEST_TTY_WIDTH: '0', PWTEST_SKIP_TEST_OUTPUT: undefined }); + const text = stripAnsi(result.output); + expect(text).toContain('[1/1] a.test.js:6:7 › one'); + expect(text).toContain('1 failed'); + expect(text).toContain('1) a.test'); + expect(result.exitCode).toBe(1); +});