chore: do not use ansi outsite of TTY (#27979)
Fixes https://github.com/microsoft/playwright/issues/27891
This commit is contained in:
parent
b9aaa38d3b
commit
cb14de7a5b
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { colors, ms as milliseconds, parseStackTraceLine } from 'playwright-core/lib/utilsBundle';
|
import { colors as realColors, ms as milliseconds, parseStackTraceLine } from 'playwright-core/lib/utilsBundle';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import type { FullConfig, TestCase, Suite, TestResult, TestError, FullResult, TestStep, Location } from '../../types/testReporter';
|
import type { FullConfig, TestCase, Suite, TestResult, TestError, FullResult, TestStep, Location } from '../../types/testReporter';
|
||||||
import type { SuitePrivate } from '../../types/reporterPrivate';
|
import type { SuitePrivate } from '../../types/reporterPrivate';
|
||||||
|
|
@ -45,6 +45,28 @@ type TestSummary = {
|
||||||
fatalErrors: TestError[];
|
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 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,
|
||||||
|
};
|
||||||
|
|
||||||
export class BaseReporter implements ReporterV2 {
|
export class BaseReporter implements ReporterV2 {
|
||||||
config!: FullConfig;
|
config!: FullConfig;
|
||||||
suite!: Suite;
|
suite!: Suite;
|
||||||
|
|
@ -52,13 +74,11 @@ export class BaseReporter implements ReporterV2 {
|
||||||
result!: FullResult;
|
result!: FullResult;
|
||||||
private fileDurations = new Map<string, number>();
|
private fileDurations = new Map<string, number>();
|
||||||
private _omitFailures: boolean;
|
private _omitFailures: boolean;
|
||||||
private readonly _ttyWidthForTest: number;
|
|
||||||
private _fatalErrors: TestError[] = [];
|
private _fatalErrors: TestError[] = [];
|
||||||
private _failureCount: number = 0;
|
private _failureCount: number = 0;
|
||||||
|
|
||||||
constructor(options: { omitFailures?: boolean } = {}) {
|
constructor(options: { omitFailures?: boolean } = {}) {
|
||||||
this._omitFailures = options.omitFailures || false;
|
this._omitFailures = options.omitFailures || false;
|
||||||
this._ttyWidthForTest = parseInt(process.env.PWTEST_TTY_WIDTH || '', 10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
version(): 'v2' {
|
version(): 'v2' {
|
||||||
|
|
@ -128,12 +148,7 @@ export class BaseReporter implements ReporterV2 {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected ttyWidth() {
|
|
||||||
return this._ttyWidthForTest || process.stdout.columns || 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fitToScreen(line: string, prefix?: string): string {
|
protected fitToScreen(line: string, prefix?: string): string {
|
||||||
const ttyWidth = this.ttyWidth();
|
|
||||||
if (!ttyWidth) {
|
if (!ttyWidth) {
|
||||||
// Guard against the case where we cannot determine available width.
|
// Guard against the case where we cannot determine available width.
|
||||||
return line;
|
return line;
|
||||||
|
|
@ -473,7 +488,7 @@ export function formatError(error: TestError, highlightCode: boolean): ErrorDeta
|
||||||
export function separator(text: string = ''): string {
|
export function separator(text: string = ''): string {
|
||||||
if (text)
|
if (text)
|
||||||
text += ' ';
|
text += ' ';
|
||||||
const columns = Math.min(100, process.stdout?.columns || 100);
|
const columns = Math.min(100, ttyWidth || 100);
|
||||||
return text + colors.dim('─'.repeat(Math.max(0, columns - text.length)));
|
return text + colors.dim('─'.repeat(Math.max(0, columns - text.length)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { colors } from 'playwright-core/lib/utilsBundle';
|
import { colors, BaseReporter, formatError } from './base';
|
||||||
import { BaseReporter, formatError } from './base';
|
|
||||||
import type { FullResult, TestCase, TestResult, Suite, TestError } from '../../types/testReporter';
|
import type { FullResult, TestCase, TestResult, Suite, TestError } from '../../types/testReporter';
|
||||||
|
|
||||||
class DotReporter extends BaseReporter {
|
class DotReporter extends BaseReporter {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { colors, open } from 'playwright-core/lib/utilsBundle';
|
import { open } from 'playwright-core/lib/utilsBundle';
|
||||||
import { MultiMap, getPackageManagerExecCommand } from 'playwright-core/lib/utils';
|
import { MultiMap, getPackageManagerExecCommand } from 'playwright-core/lib/utils';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
@ -25,7 +25,7 @@ import { codeFrameColumns } from '../transform/babelBundle';
|
||||||
import type { FullResult, FullConfig, Location, Suite, TestCase as TestCasePublic, TestResult as TestResultPublic, TestStep as TestStepPublic, TestError } from '../../types/testReporter';
|
import type { FullResult, FullConfig, Location, Suite, TestCase as TestCasePublic, TestResult as TestResultPublic, TestStep as TestStepPublic, TestError } from '../../types/testReporter';
|
||||||
import type { SuitePrivate } from '../../types/reporterPrivate';
|
import type { SuitePrivate } from '../../types/reporterPrivate';
|
||||||
import { HttpServer, assert, calculateSha1, copyFileAndMakeWritable, gracefullyProcessExitDoNotHang, removeFolders, sanitizeForFilePath } from 'playwright-core/lib/utils';
|
import { HttpServer, assert, calculateSha1, copyFileAndMakeWritable, gracefullyProcessExitDoNotHang, removeFolders, sanitizeForFilePath } from 'playwright-core/lib/utils';
|
||||||
import { formatError, formatResultFailure, stripAnsiEscapes } from './base';
|
import { colors, formatError, formatResultFailure, stripAnsiEscapes } from './base';
|
||||||
import { resolveReporterOutputPath } from '../util';
|
import { resolveReporterOutputPath } from '../util';
|
||||||
import type { Metadata } from '../../types/test';
|
import type { Metadata } from '../../types/test';
|
||||||
import type { ZipFile } from 'playwright-core/lib/zipBundle';
|
import type { ZipFile } from 'playwright-core/lib/zipBundle';
|
||||||
|
|
|
||||||
|
|
@ -15,11 +15,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { colors } from 'playwright-core/lib/utilsBundle';
|
|
||||||
import { codeFrameColumns } from '../transform/babelBundle';
|
import { codeFrameColumns } from '../transform/babelBundle';
|
||||||
import type { FullConfig, TestCase, TestError, TestResult, FullResult, TestStep } from '../../types/testReporter';
|
import type { FullConfig, TestCase, TestError, TestResult, FullResult, TestStep } from '../../types/testReporter';
|
||||||
import { Suite } from '../common/test';
|
import { Suite } from '../common/test';
|
||||||
import { prepareErrorStack, relativeFilePath } from './base';
|
import { colors, prepareErrorStack, relativeFilePath } from './base';
|
||||||
import type { ReporterV2 } from './reporterV2';
|
import type { ReporterV2 } from './reporterV2';
|
||||||
import { monotonicTime } from 'playwright-core/lib/utils';
|
import { monotonicTime } from 'playwright-core/lib/utils';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,7 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { colors } from 'playwright-core/lib/utilsBundle';
|
import { colors, BaseReporter, formatError, formatFailure, formatTestTitle } from './base';
|
||||||
import { BaseReporter, formatError, formatFailure, formatTestTitle } from './base';
|
|
||||||
import type { TestCase, Suite, TestResult, FullResult, TestStep, TestError } from '../../types/testReporter';
|
import type { TestCase, Suite, TestResult, FullResult, TestStep, TestError } from '../../types/testReporter';
|
||||||
|
|
||||||
class LineReporter extends BaseReporter {
|
class LineReporter extends BaseReporter {
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { colors, ms as milliseconds } from 'playwright-core/lib/utilsBundle';
|
import { ms as milliseconds } from 'playwright-core/lib/utilsBundle';
|
||||||
import { BaseReporter, formatError, formatTestTitle, stepSuffix, stripAnsiEscapes } from './base';
|
import { colors, BaseReporter, formatError, formatTestTitle, isTTY, stepSuffix, stripAnsiEscapes, ttyWidth } from './base';
|
||||||
import type { FullResult, Suite, TestCase, TestError, TestResult, TestStep } from '../../types/testReporter';
|
import type { FullResult, Suite, TestCase, TestError, TestResult, TestStep } from '../../types/testReporter';
|
||||||
|
|
||||||
// Allow it in the Visual Studio Code Terminal and the new Windows Terminal
|
// Allow it in the Visual Studio Code Terminal and the new Windows Terminal
|
||||||
|
|
@ -31,13 +31,11 @@ class ListReporter extends BaseReporter {
|
||||||
private _resultIndex = new Map<TestResult, string>();
|
private _resultIndex = new Map<TestResult, string>();
|
||||||
private _stepIndex = new Map<TestStep, string>();
|
private _stepIndex = new Map<TestStep, string>();
|
||||||
private _needNewLine = false;
|
private _needNewLine = false;
|
||||||
private readonly _liveTerminal: string | boolean | undefined;
|
|
||||||
private _printSteps: boolean;
|
private _printSteps: boolean;
|
||||||
|
|
||||||
constructor(options: { omitFailures?: boolean, printSteps?: boolean } = {}) {
|
constructor(options: { omitFailures?: boolean, printSteps?: boolean } = {}) {
|
||||||
super(options);
|
super(options);
|
||||||
this._printSteps = options.printSteps || !!process.env.PW_TEST_DEBUG_REPORTERS_PRINT_STEPS;
|
this._printSteps = isTTY && (options.printSteps || !!process.env.PW_TEST_DEBUG_REPORTERS_PRINT_STEPS);
|
||||||
this._liveTerminal = process.stdout.isTTY || !!process.env.PWTEST_TTY_WIDTH;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override printsToStdio() {
|
override printsToStdio() {
|
||||||
|
|
@ -55,16 +53,15 @@ class ListReporter extends BaseReporter {
|
||||||
|
|
||||||
override onTestBegin(test: TestCase, result: TestResult) {
|
override onTestBegin(test: TestCase, result: TestResult) {
|
||||||
super.onTestBegin(test, result);
|
super.onTestBegin(test, result);
|
||||||
if (this._liveTerminal)
|
if (!isTTY)
|
||||||
this._maybeWriteNewLine();
|
return;
|
||||||
this._resultIndex.set(result, String(this._resultIndex.size + 1));
|
this._maybeWriteNewLine();
|
||||||
if (this._liveTerminal) {
|
const index = String(this._resultIndex.size + 1);
|
||||||
this._testRows.set(test, this._lastRow);
|
this._resultIndex.set(result, index);
|
||||||
const index = this._resultIndex.get(result)!;
|
this._testRows.set(test, this._lastRow);
|
||||||
const prefix = this._testPrefix(index, '');
|
const prefix = this._testPrefix(index, '');
|
||||||
const line = colors.dim(formatTestTitle(this.config, test)) + this._retrySuffix(result);
|
const line = colors.dim(formatTestTitle(this.config, test)) + this._retrySuffix(result);
|
||||||
this._appendLine(line, prefix);
|
this._appendLine(line, prefix);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override onStdOut(chunk: string | Buffer, test?: TestCase, result?: TestResult) {
|
override onStdOut(chunk: string | Buffer, test?: TestCase, result?: TestResult) {
|
||||||
|
|
@ -81,9 +78,9 @@ class ListReporter extends BaseReporter {
|
||||||
super.onStepBegin(test, result, step);
|
super.onStepBegin(test, result, step);
|
||||||
if (step.category !== 'test.step')
|
if (step.category !== 'test.step')
|
||||||
return;
|
return;
|
||||||
const testIndex = this._resultIndex.get(result)!;
|
const testIndex = this._resultIndex.get(result) || '';
|
||||||
if (!this._printSteps) {
|
if (!this._printSteps) {
|
||||||
if (this._liveTerminal)
|
if (isTTY)
|
||||||
this._updateLine(this._testRows.get(test)!, colors.dim(formatTestTitle(this.config, test, step)) + this._retrySuffix(result), this._testPrefix(testIndex, ''));
|
this._updateLine(this._testRows.get(test)!, colors.dim(formatTestTitle(this.config, test, step)) + this._retrySuffix(result), this._testPrefix(testIndex, ''));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -93,9 +90,8 @@ class ListReporter extends BaseReporter {
|
||||||
const stepIndex = `${testIndex}.${ordinal}`;
|
const stepIndex = `${testIndex}.${ordinal}`;
|
||||||
this._stepIndex.set(step, stepIndex);
|
this._stepIndex.set(step, stepIndex);
|
||||||
|
|
||||||
if (this._liveTerminal)
|
if (isTTY) {
|
||||||
this._maybeWriteNewLine();
|
this._maybeWriteNewLine();
|
||||||
if (this._liveTerminal) {
|
|
||||||
this._stepRows.set(step, this._lastRow);
|
this._stepRows.set(step, this._lastRow);
|
||||||
const prefix = this._testPrefix(stepIndex, '');
|
const prefix = this._testPrefix(stepIndex, '');
|
||||||
const line = test.title + colors.dim(stepSuffix(step));
|
const line = test.title + colors.dim(stepSuffix(step));
|
||||||
|
|
@ -108,9 +104,9 @@ class ListReporter extends BaseReporter {
|
||||||
if (step.category !== 'test.step')
|
if (step.category !== 'test.step')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const testIndex = this._resultIndex.get(result)!;
|
const testIndex = this._resultIndex.get(result) || '';
|
||||||
if (!this._printSteps) {
|
if (!this._printSteps) {
|
||||||
if (this._liveTerminal)
|
if (isTTY)
|
||||||
this._updateLine(this._testRows.get(test)!, colors.dim(formatTestTitle(this.config, test, step.parent)) + this._retrySuffix(result), this._testPrefix(testIndex, ''));
|
this._updateLine(this._testRows.get(test)!, colors.dim(formatTestTitle(this.config, test, step.parent)) + this._retrySuffix(result), this._testPrefix(testIndex, ''));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -137,8 +133,7 @@ class ListReporter extends BaseReporter {
|
||||||
|
|
||||||
private _updateLineCountAndNewLineFlagForOutput(text: string) {
|
private _updateLineCountAndNewLineFlagForOutput(text: string) {
|
||||||
this._needNewLine = text[text.length - 1] !== '\n';
|
this._needNewLine = text[text.length - 1] !== '\n';
|
||||||
const ttyWidth = this.ttyWidth();
|
if (!ttyWidth)
|
||||||
if (!this._liveTerminal || ttyWidth === 0)
|
|
||||||
return;
|
return;
|
||||||
for (const ch of text) {
|
for (const ch of text) {
|
||||||
if (ch === '\n') {
|
if (ch === '\n') {
|
||||||
|
|
@ -168,7 +163,15 @@ class ListReporter extends BaseReporter {
|
||||||
const title = formatTestTitle(this.config, test);
|
const title = formatTestTitle(this.config, test);
|
||||||
let prefix = '';
|
let prefix = '';
|
||||||
let text = '';
|
let text = '';
|
||||||
const index = this._resultIndex.get(result)!;
|
|
||||||
|
// In TTY mode test index is incremented in onTestStart
|
||||||
|
// and in non-TTY mode it is incremented onTestEnd.
|
||||||
|
let index = this._resultIndex.get(result);
|
||||||
|
if (!index) {
|
||||||
|
index = String(this._resultIndex.size + 1);
|
||||||
|
this._resultIndex.set(result, index);
|
||||||
|
}
|
||||||
|
|
||||||
if (result.status === 'skipped') {
|
if (result.status === 'skipped') {
|
||||||
prefix = this._testPrefix(index, colors.green('-'));
|
prefix = this._testPrefix(index, colors.green('-'));
|
||||||
// Do not show duration for skipped.
|
// Do not show duration for skipped.
|
||||||
|
|
@ -189,7 +192,7 @@ class ListReporter extends BaseReporter {
|
||||||
}
|
}
|
||||||
|
|
||||||
private _updateOrAppendLine(row: number, text: string, prefix: string) {
|
private _updateOrAppendLine(row: number, text: string, prefix: string) {
|
||||||
if (this._liveTerminal) {
|
if (isTTY) {
|
||||||
this._updateLine(row, text, prefix);
|
this._updateLine(row, text, prefix);
|
||||||
} else {
|
} else {
|
||||||
this._maybeWriteNewLine();
|
this._maybeWriteNewLine();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue