chore: move Location type from testReporter.d.ts to test.d.ts (#32687)

This commit is contained in:
Max Schmitt 2024-09-18 16:57:11 +02:00 committed by GitHub
parent ddd43d0f20
commit 523ec83cad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 60 additions and 47 deletions

View File

@ -7772,6 +7772,26 @@ interface SnapshotAssertions {
}): void;
}
/**
* Represents a location in the source code where [TestCase] or [Suite] is defined.
*/
export interface Location {
/**
* Column number in the source file.
*/
column: number;
/**
* Path to the source file.
*/
file: string;
/**
* Line number in the source file.
*/
line: number;
}
/**
* `TestInfo` contains information about currently running test. It is available to test functions,
* [test.beforeEach([title, hookFunction])](https://playwright.dev/docs/api/class-test#test-before-each),

View File

@ -15,8 +15,8 @@
* limitations under the License.
*/
import type { TestStatus, Metadata, PlaywrightTestOptions, PlaywrightWorkerOptions, ReporterDescription, FullConfig, FullProject } from './test';
export type { FullConfig, FullProject, TestStatus } from './test';
import type { TestStatus, Metadata, PlaywrightTestOptions, PlaywrightWorkerOptions, ReporterDescription, FullConfig, FullProject, Location } from './test';
export type { FullConfig, FullProject, TestStatus, Location } from './test';
/**
* Result of the full test run.
@ -319,26 +319,6 @@ export type JSONReportSTDIOEntry = { text: string } | { buffer: string };
export {};
/**
* Represents a location in the source code where {@link TestCase} or {@link Suite} is defined.
*/
export interface Location {
/**
* Column number in the source file.
*/
column: number;
/**
* Path to the source file.
*/
file: string;
/**
* Line number in the source file.
*/
line: number;
}
/**
* `Suite` is a group of tests. All tests in Playwright Test form the following hierarchy:
* - Root suite has a child suite for each {@link FullProject}.

View File

@ -17,37 +17,41 @@
import { test, expect, stripAnsi } from './playwright-test-fixtures';
const stepIndentReporter = `
import { FullConfig, Location, Reporter, Suite, TestStep } from '@playwright/test/reporter';
import * as path from 'path';
function formatPrefix(str) {
function formatPrefix(str: string) {
return str.padEnd(10, ' ') + '|';
}
function formatLocation(location) {
function formatLocation(location?: Location) {
if (!location)
throw new Error('Location is missing');
return ' @ ' + path.basename(location.file) + ':' + location.line;
}
function formatStack(indent, stack) {
stack = stack.split('\\n').filter(s => s.startsWith(' at '));
function formatStack(indent: string, rawStack: string) {
let stack = rawStack.split('\\n').filter(s => s.startsWith(' at '));
stack = stack.map(s => {
const match = /^( at.* )\\(?([^ )]+)\\)?/.exec(s);
let location = match[2];
let location = match![2];
location = location.substring(location.lastIndexOf(path.sep) + 1);
return ' at ' + location;
});
return indent + stack.join('\\n' + indent);
}
class Reporter {
export default class MyReporter implements Reporter {
printErrorLocation: boolean;
skipErrorMessage: boolean;
suite!: Suite;
constructor(options) {
constructor(options: { printErrorLocation: boolean, skipErrorMessage: boolean }) {
this.printErrorLocation = options.printErrorLocation;
this.skipErrorMessage = options.skipErrorMessage;
}
trimError(message) {
trimError(message: string) {
if (this.skipErrorMessage)
return '<error message>';
const lines = message.split('\\n');
@ -59,24 +63,24 @@ class Reporter {
}
// For easier debugging.
onStdOut(data) {
onStdOut(data: string|Buffer) {
process.stdout.write(data.toString());
}
// For easier debugging.
onStdErr(data) {
onStdErr(data: string|Buffer) {
process.stderr.write(data.toString());
}
printStep(step, indent) {
printStep(step: TestStep, indent: string) {
let location = '';
if (step.location)
location = formatLocation(step.location);
console.log(formatPrefix(step.category) + indent + step.title + location);
if (step.error) {
const errorLocation = this.printErrorLocation ? formatLocation(step.error.location) : '';
console.log(formatPrefix(step.category) + indent + '↪ error: ' + this.trimError(step.error.message) + errorLocation);
console.log(formatPrefix(step.category) + indent + '↪ error: ' + this.trimError(step.error.message!) + errorLocation);
if (this.printErrorLocation)
console.log(formatStack(formatPrefix(step.category) + indent, step.error.stack));
console.log(formatStack(formatPrefix(step.category) + indent, step.error.stack!));
}
indent += ' ';
for (const child of step.steps)
@ -94,9 +98,9 @@ class Reporter {
this.printStep(step, '');
for (const error of result.errors) {
const errorLocation = this.printErrorLocation ? formatLocation(error.location) : '';
console.log(formatPrefix('') + this.trimError(error.message) + errorLocation);
console.log(formatPrefix('') + this.trimError(error.message!) + errorLocation);
if (this.printErrorLocation)
console.log(formatStack(formatPrefix(''), error.stack));
console.log(formatStack(formatPrefix(''), error.stack!));
}
}
}
@ -104,7 +108,6 @@ class Reporter {
processSuite(this.suite);
}
}
module.exports = Reporter;
`;
test('should report api step hierarchy', async ({ runInlineTest }) => {
@ -1247,14 +1250,14 @@ fixture | fixture: context
`);
});
test('test location to test.step', async ({ runInlineTest }) => {
test('should allow passing location to test.step', async ({ runInlineTest, runTSC }) => {
const result = await runInlineTest({
'reporter.ts': stepIndentReporter,
'helper.ts': `
import { test } from '@playwright/test';
import { Location, TestType } from '@playwright/test';
export async function dummyStep(test, title, action, location) {
return await test.step(title, action, { location });
export async function dummyStep(test: TestType<{}, {}>, title: string, action: () => void, location: Location) {
await test.step(title, action, { location });
}
export function getCustomLocation() {
@ -1272,8 +1275,7 @@ test('test location to test.step', async ({ runInlineTest }) => {
test('custom location test', async () => {
const location = getCustomLocation();
await dummyStep(test, 'Perform a dummy step', async () => {
}, location);
await dummyStep(test, 'Perform a dummy step', async () => {}, location);
});
`
}, { reporter: '', workers: 1 });
@ -1284,4 +1286,15 @@ hook |Before Hooks
test.step |Perform a dummy step @ dummy-file.ts:123
hook |After Hooks
`);
});
const { exitCode } = await runTSC({
'a.test.ts': `
import { test, expect } from '@playwright/test';
test('should work', async () => {
const location = { file: 'dummy-file.ts', line: 123, column: 45 };
await test.step('step1', () => {}, { location });
});
`
});
expect(exitCode).toBe(0);
});

View File

@ -14,8 +14,8 @@
* limitations under the License.
*/
import type { TestStatus, Metadata, PlaywrightTestOptions, PlaywrightWorkerOptions, ReporterDescription, FullConfig, FullProject } from './test';
export type { FullConfig, FullProject, TestStatus } from './test';
import type { TestStatus, Metadata, PlaywrightTestOptions, PlaywrightWorkerOptions, ReporterDescription, FullConfig, FullProject, Location } from './test';
export type { FullConfig, FullProject, TestStatus, Location } from './test';
/**
* Result of the full test run.