Skip to content

Commit

Permalink
feat: env.PLAYWRIGHT_FORCE_TTY to control reporters' tty (#30834)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
dgozman committed May 15, 2024
1 parent 3370f37 commit 89cdf3d
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 31 deletions.
56 changes: 35 additions & 21 deletions packages/playwright/src/reporters/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 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 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;
}

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;
Expand Down
2 changes: 0 additions & 2 deletions packages/playwright/src/reporters/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion tests/playwright-test/reporter-blob.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
14 changes: 7 additions & 7 deletions tests/playwright-test/reporter-list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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' : '✓ ';
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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')
Expand All @@ -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'));

Expand Down Expand Up @@ -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`);
Expand Down

0 comments on commit 89cdf3d

Please sign in to comment.