From da3363300c4222f80b3b3e5db11f56119c8aa0f3 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Wed, 18 Sep 2024 15:45:52 +0200 Subject: [PATCH] chore: move Location type from testReporter.d.ts to test.d.ts --- .../class-location.md | 0 packages/playwright/types/test.d.ts | 20 +++++++ packages/playwright/types/testReporter.d.ts | 24 +------- tests/playwright-test/test-step.spec.ts | 59 +++++++++++-------- .../overrides-testReporter.d.ts | 4 +- 5 files changed, 60 insertions(+), 47 deletions(-) rename docs/src/{test-reporter-api => test-api}/class-location.md (100%) diff --git a/docs/src/test-reporter-api/class-location.md b/docs/src/test-api/class-location.md similarity index 100% rename from docs/src/test-reporter-api/class-location.md rename to docs/src/test-api/class-location.md diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index 51a6720a2ecdd..f158baac361f3 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -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), diff --git a/packages/playwright/types/testReporter.d.ts b/packages/playwright/types/testReporter.d.ts index 52073066f0efb..f2a2d62b0ae82 100644 --- a/packages/playwright/types/testReporter.d.ts +++ b/packages/playwright/types/testReporter.d.ts @@ -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}. diff --git a/tests/playwright-test/test-step.spec.ts b/tests/playwright-test/test-step.spec.ts index ad3478b112b12..f0bd8837772a6 100644 --- a/tests/playwright-test/test-step.spec.ts +++ b/tests/playwright-test/test-step.spec.ts @@ -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 ''; 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 `); -}); \ No newline at end of file + + 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); +}); diff --git a/utils/generate_types/overrides-testReporter.d.ts b/utils/generate_types/overrides-testReporter.d.ts index 51eab7e370508..b2e8f0e9e66ad 100644 --- a/utils/generate_types/overrides-testReporter.d.ts +++ b/utils/generate_types/overrides-testReporter.d.ts @@ -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.