diff --git a/packages/playwright-ct-core/src/cliOverrides.ts b/packages/playwright-ct-core/src/cliOverrides.ts index 5aa0f6c640..aaa456427c 100644 --- a/packages/playwright-ct-core/src/cliOverrides.ts +++ b/packages/playwright-ct-core/src/cliOverrides.ts @@ -19,17 +19,16 @@ import { removeFolder } from 'playwright/lib/program'; import { affectedTestFiles, cacheDir } from 'playwright/lib/transform/compilationCache'; import { buildBundle } from './vitePlugin'; import { resolveDirs } from './viteUtils'; -import type { Suite } from 'playwright/lib/common/test'; -import type { ConfigInWorker } from 'playwright/test'; +import type { FullConfig, Suite } from 'playwright/types/testReporter'; -export async function clearCacheCommand(config: ConfigInWorker, configDir: string) { +export async function clearCacheCommand(config: FullConfig, configDir: string) { const dirs = await resolveDirs(configDir, config); if (dirs) await removeFolder(dirs.outDir); await removeFolder(cacheDir); } -export async function findRelatedTestFilesCommand(files: string[], config: ConfigInWorker, configDir: string, suite: Suite) { +export async function findRelatedTestFilesCommand(files: string[], config: FullConfig, configDir: string, suite: Suite) { await buildBundle(config, configDir, suite); return { testFiles: affectedTestFiles(files) }; } diff --git a/packages/playwright-ct-core/src/vitePlugin.ts b/packages/playwright-ct-core/src/vitePlugin.ts index 43dc0f90ca..26964e079b 100644 --- a/packages/playwright-ct-core/src/vitePlugin.ts +++ b/packages/playwright-ct-core/src/vitePlugin.ts @@ -22,8 +22,7 @@ import { assert, calculateSha1, getPlaywrightVersion, isURLAvailable } from 'pla import { debug } from 'playwright-core/lib/utilsBundle'; import { internalDependenciesForTestFile, setExternalDependencies } from 'playwright/lib/transform/compilationCache'; import { stoppable } from 'playwright/lib/utilsBundle'; -import type { ConfigInWorker } from 'playwright/test'; -import type { Suite } from 'playwright/types/testReporter'; +import type { FullConfig, Suite } from 'playwright/types/testReporter'; import type { PluginContext } from 'rollup'; import type { Plugin, ResolveFn, ResolvedConfig } from 'vite'; import type { TestRunnerPlugin } from '../../playwright/src/plugins'; @@ -40,11 +39,11 @@ const playwrightVersion = getPlaywrightVersion(); export function createPlugin(): TestRunnerPlugin { let configDir: string; - let config: ConfigInWorker; + let config: FullConfig; return { name: 'playwright-vite-plugin', - setup: async (configObject: ConfigInWorker, configDirectory: string) => { + setup: async (configObject: FullConfig, configDirectory: string) => { config = configObject; configDir = configDirectory; }, @@ -88,7 +87,7 @@ type BuildInfo = { } }; -export async function buildBundle(config: ConfigInWorker, configDir: string, suite: Suite): Promise<{ buildInfo: BuildInfo, viteConfig: Record } | null> { +export async function buildBundle(config: FullConfig, configDir: string, suite: Suite): Promise<{ buildInfo: BuildInfo, viteConfig: Record } | null> { const { registerSourceFile, frameworkPluginFactory } = frameworkConfig(config); { // Detect a running dev server and use it if available. diff --git a/packages/playwright-ct-core/src/viteUtils.ts b/packages/playwright-ct-core/src/viteUtils.ts index 840816c648..505301c48e 100644 --- a/packages/playwright-ct-core/src/viteUtils.ts +++ b/packages/playwright-ct-core/src/viteUtils.ts @@ -18,7 +18,8 @@ import fs from 'fs'; import path from 'path'; import { debug } from 'playwright-core/lib/utilsBundle'; import { getUserData } from 'playwright/lib/transform/compilationCache'; -import type { PlaywrightTestConfig as BasePlaywrightTestConfig, ConfigInWorker } from 'playwright/test'; +import type { PlaywrightTestConfig as BasePlaywrightTestConfig } from 'playwright/types/test'; +import type { FullConfig } from 'playwright/types/testReporter'; import type { InlineConfig, Plugin, TransformResult, UserConfig } from 'vite'; import type { ImportInfo } from './tsxTransform'; import { resolveHook } from 'playwright/lib/transform/transform'; @@ -39,7 +40,7 @@ export type ComponentDirs = { templateDir: string; }; -export async function resolveDirs(configDir: string, config: ConfigInWorker): Promise { +export async function resolveDirs(configDir: string, config: FullConfig): Promise { const use = config.projects[0].use as CtConfig; // FIXME: use build plugin to determine html location to resolve this. // TemplateDir must be relative, otherwise we can't move the final index.html into its target location post-build. @@ -56,7 +57,7 @@ export async function resolveDirs(configDir: string, config: ConfigInWorker): Pr }; } -export function resolveEndpoint(config: ConfigInWorker) { +export function resolveEndpoint(config: FullConfig) { const use = config.projects[0].use as CtConfig; const baseURL = new URL(use.baseURL || 'http://localhost'); return { @@ -66,7 +67,7 @@ export function resolveEndpoint(config: ConfigInWorker) { }; } -export async function createConfig(dirs: ComponentDirs, config: ConfigInWorker, frameworkPluginFactory: (() => Promise) | undefined, supportJsxInJs: boolean) { +export async function createConfig(dirs: ComponentDirs, config: FullConfig, frameworkPluginFactory: (() => Promise) | undefined, supportJsxInJs: boolean) { // We are going to have 3 config files: // - the defaults that user config overrides (baseConfig) // - the user config (userConfig) @@ -193,6 +194,6 @@ export function transformIndexFile(id: string, content: string, templateDir: str }; } -export function frameworkConfig(config: ConfigInWorker): { registerSourceFile: string, frameworkPluginFactory?: () => Promise } { +export function frameworkConfig(config: FullConfig): { registerSourceFile: string, frameworkPluginFactory?: () => Promise } { return (config as any)['@playwright/experimental-ct-core']; } diff --git a/packages/playwright/src/common/config.ts b/packages/playwright/src/common/config.ts index ab5e6ca805..4e202e382f 100644 --- a/packages/playwright/src/common/config.ts +++ b/packages/playwright/src/common/config.ts @@ -46,7 +46,7 @@ export class FullConfigInternal { readonly configCLIOverrides: ConfigCLIOverrides; readonly ignoreSnapshots: boolean; readonly preserveOutputDir: boolean; - readonly webServers: NonNullable[]; + readonly webServers: NonNullable[]; readonly plugins: TestRunnerPluginRegistration[]; readonly projects: FullProjectInternal[] = []; cliArgs: string[] = []; @@ -123,7 +123,7 @@ export class FullConfigInternal { this.config.webServer = null; this.webServers = webServers; } else if (webServers) { // legacy singleton mode - this.config.webServer = webServers as NonNullable; + this.config.webServer = webServers; this.webServers = [webServers]; } else { this.webServers = []; diff --git a/packages/playwright/src/common/test.ts b/packages/playwright/src/common/test.ts index 21cdb55d9c..5f22f8fe3b 100644 --- a/packages/playwright/src/common/test.ts +++ b/packages/playwright/src/common/test.ts @@ -19,8 +19,7 @@ import type * as reporterTypes from '../../types/testReporter'; import type { TestTypeImpl } from './testType'; import { rootTestType } from './testType'; import type { Annotation, FixturesWithLocation, FullProjectInternal } from './config'; -import type { ProjectInWorker } from '../../types/test'; -import type { Location } from '../../types/testReporter'; +import type { Location, FullProject } from '../../types/testReporter'; class Base { title: string; @@ -238,7 +237,7 @@ export class Suite extends Base { return suite; } - project(): ProjectInWorker | undefined { + project(): FullProject | undefined { return this._fullProject?.project || this.parent?.project(); } } diff --git a/packages/playwright/src/isomorphic/teleReceiver.ts b/packages/playwright/src/isomorphic/teleReceiver.ts index 57b1376e9b..5b23b4a7b3 100644 --- a/packages/playwright/src/isomorphic/teleReceiver.ts +++ b/packages/playwright/src/isomorphic/teleReceiver.ts @@ -15,7 +15,7 @@ */ import type { Annotation } from '../common/config'; -import type { ProjectInWorker, Metadata } from '../../types/test'; +import type { Metadata } from '../../types/test'; import type * as reporterTypes from '../../types/testReporter'; import type { ReporterV2 } from '../reporters/reporterV2'; @@ -590,7 +590,7 @@ class TeleTestResult implements reporterTypes.TestResult { } } -export type TeleFullProject = ProjectInWorker; +export type TeleFullProject = reporterTypes.FullProject; export const baseFullConfig: reporterTypes.FullConfig = { forbidOnly: false, diff --git a/packages/playwright/types/test.d.ts b/packages/playwright/types/test.d.ts index ae59ca6dd3..0e93e1ea2a 100644 --- a/packages/playwright/types/test.d.ts +++ b/packages/playwright/types/test.d.ts @@ -1272,485 +1272,6 @@ export interface ConfigInWorker { export type TestStatus = 'passed' | 'failed' | 'timedOut' | 'skipped' | 'interrupted'; -/** - * `WorkerInfo` contains information about the worker that is running tests and is available to worker-scoped - * fixtures. `WorkerInfo` is a subset of {@link TestInfo} that is available in many other places. - */ -export interface WorkerInfo { - /** - * Processed configuration from the [configuration file](https://playwright.dev/docs/test-configuration). - */ - config: ConfigInWorker; - /** - * Processed project configuration from the [configuration file](https://playwright.dev/docs/test-configuration). - */ - project: ProjectInWorker; - /** - * The index of the worker between `0` and `workers - 1`. It is guaranteed that workers running at the same time have - * a different `parallelIndex`. When a worker is restarted, for example after a failure, the new worker process has - * the same `parallelIndex`. - * - * Also available as `process.env.TEST_PARALLEL_INDEX`. Learn more about - * [parallelism and sharding](https://playwright.dev/docs/test-parallel) with Playwright Test. - */ - parallelIndex: number; - - /** - * The unique index of the worker process that is running the test. When a worker is restarted, for example after a - * failure, the new worker process gets a new unique `workerIndex`. - * - * Also available as `process.env.TEST_WORKER_INDEX`. Learn more about [parallelism and sharding](https://playwright.dev/docs/test-parallel) - * with Playwright Test. - */ - workerIndex: 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), - * [test.afterEach([title, hookFunction])](https://playwright.dev/docs/api/class-test#test-after-each), - * [test.beforeAll([title, hookFunction])](https://playwright.dev/docs/api/class-test#test-before-all) and - * [test.afterAll([title, hookFunction])](https://playwright.dev/docs/api/class-test#test-after-all) hooks, and - * test-scoped fixtures. `TestInfo` provides utilities to control test execution: attach files, update test timeout, - * determine which test is currently running and whether it was retried, etc. - * - * ```js - * import { test, expect } from '@playwright/test'; - * - * test('basic test', async ({ page }, testInfo) => { - * expect(testInfo.title).toBe('basic test'); - * await page.screenshot(testInfo.outputPath('screenshot.png')); - * }); - * ``` - * - */ -export interface TestInfo { - /** - * Processed configuration from the [configuration file](https://playwright.dev/docs/test-configuration). - */ - config: ConfigInWorker; - /** - * Processed project configuration from the [configuration file](https://playwright.dev/docs/test-configuration). - */ - project: ProjectInWorker; - /** - * Attach a value or a file from disk to the current test. Some reporters show test attachments. Either `path` or - * `body` must be specified, but not both. - * - * For example, you can attach a screenshot to the test: - * - * ```js - * import { test, expect } from '@playwright/test'; - * - * test('basic test', async ({ page }, testInfo) => { - * await page.goto('https://playwright.dev'); - * const screenshot = await page.screenshot(); - * await testInfo.attach('screenshot', { body: screenshot, contentType: 'image/png' }); - * }); - * ``` - * - * Or you can attach files returned by your APIs: - * - * ```js - * import { test, expect } from '@playwright/test'; - * import { download } from './my-custom-helpers'; - * - * test('basic test', async ({}, testInfo) => { - * const tmpPath = await download('a'); - * await testInfo.attach('downloaded', { path: tmpPath }); - * }); - * ``` - * - * **NOTE** [testInfo.attach(name[, options])](https://playwright.dev/docs/api/class-testinfo#test-info-attach) - * automatically takes care of copying attached files to a location that is accessible to reporters. You can safely - * remove the attachment after awaiting the attach call. - * @param name Attachment name. The name will also be sanitized and used as the prefix of file name when saving to disk. - * @param options - */ - attach(name: string, options?: { - /** - * Attachment body. Mutually exclusive with `path`. - */ - body?: string|Buffer; - - /** - * Content type of this attachment to properly present in the report, for example `'application/json'` or - * `'image/png'`. If omitted, content type is inferred based on the `path`, or defaults to `text/plain` for [string] - * attachments and `application/octet-stream` for [Buffer] attachments. - */ - contentType?: string; - - /** - * Path on the filesystem to the attached file. Mutually exclusive with `body`. - */ - path?: string; - }): Promise; - - /** - * Marks the currently running test as "should fail". Playwright Test runs this test and ensures that it is actually - * failing. This is useful for documentation purposes to acknowledge that some functionality is broken until it is - * fixed. This is similar to - * [test.fail([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-fail). - */ - fail(): void; - - /** - * Conditionally mark the currently running test as "should fail" with an optional description. This is similar to - * [test.fail([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-fail). - * @param condition Test is marked as "should fail" when the condition is `true`. - * @param description Optional description that will be reflected in a test report. - */ - fail(condition: boolean, description?: string): void; - - /** - * Mark a test as "fixme", with the intention to fix it. Test is immediately aborted. This is similar to - * [test.fixme([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-fixme). - */ - fixme(): void; - - /** - * Conditionally mark the currently running test as "fixme" with an optional description. This is similar to - * [test.fixme([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-fixme). - * @param condition Test is marked as "fixme" when the condition is `true`. - * @param description Optional description that will be reflected in a test report. - */ - fixme(condition: boolean, description?: string): void; - - /** - * Returns a path inside the [testInfo.outputDir](https://playwright.dev/docs/api/class-testinfo#test-info-output-dir) - * where the test can safely put a temporary file. Guarantees that tests running in parallel will not interfere with - * each other. - * - * ```js - * import { test, expect } from '@playwright/test'; - * import fs from 'fs'; - * - * test('example test', async ({}, testInfo) => { - * const file = testInfo.outputPath('dir', 'temporary-file.txt'); - * await fs.promises.writeFile(file, 'Put some data to the dir/temporary-file.txt', 'utf8'); - * }); - * ``` - * - * > Note that `pathSegments` accepts path segments to the test output directory such as - * `testInfo.outputPath('relative', 'path', 'to', 'output')`. - * > However, this path must stay within the - * [testInfo.outputDir](https://playwright.dev/docs/api/class-testinfo#test-info-output-dir) directory for each test - * (i.e. `test-results/a-test-title`), otherwise it will throw. - * @param pathSegments Path segments to append at the end of the resulting path. - */ - outputPath(...pathSegments: ReadonlyArray): string; - - /** - * Changes the timeout for the currently running test. Zero means no timeout. Learn more about - * [various timeouts](https://playwright.dev/docs/test-timeouts). - * - * Timeout is usually specified in the [configuration file](https://playwright.dev/docs/test-configuration), but it could be useful to - * change the timeout in certain scenarios: - * - * ```js - * import { test, expect } from '@playwright/test'; - * - * test.beforeEach(async ({ page }, testInfo) => { - * // Extend timeout for all tests running this hook by 30 seconds. - * testInfo.setTimeout(testInfo.timeout + 30000); - * }); - * ``` - * - * @param timeout Timeout in milliseconds. - */ - setTimeout(timeout: number): void; - - /** - * Unconditionally skip the currently running test. Test is immediately aborted. This is similar to - * [test.skip([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-skip). - */ - skip(): void; - - /** - * Conditionally skips the currently running test with an optional description. This is similar to - * [test.skip([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-skip). - * @param condition A skip condition. Test is skipped when the condition is `true`. - * @param description Optional description that will be reflected in a test report. - */ - skip(condition: boolean, description?: string): void; - - /** - * Marks the currently running test as "slow", giving it triple the default timeout. This is similar to - * [test.slow([condition, callback, description])](https://playwright.dev/docs/api/class-test#test-slow). - */ - slow(): void; - - /** - * Conditionally mark the currently running test as "slow" with an optional description, giving it triple the default - * timeout. This is similar to - * [test.slow([condition, callback, description])](https://playwright.dev/docs/api/class-test#test-slow). - * @param condition Test is marked as "slow" when the condition is `true`. - * @param description Optional description that will be reflected in a test report. - */ - slow(condition: boolean, description?: string): void; - - /** - * Returns a path to a snapshot file with the given `pathSegments`. Learn more about - * [snapshots](https://playwright.dev/docs/test-snapshots). - * - * > Note that `pathSegments` accepts path segments to the snapshot file such as `testInfo.snapshotPath('relative', - * 'path', 'to', 'snapshot.png')`. - * > However, this path must stay within the snapshots directory for each test file (i.e. `a.spec.js-snapshots`), - * otherwise it will throw. - * @param pathSegments The name of the snapshot or the path segments to define the snapshot file path. Snapshots with the same name in the - * same test file are expected to be the same. - */ - snapshotPath(...pathSegments: ReadonlyArray): string; - - /** - * The list of annotations applicable to the current test. Includes annotations from the test, annotations from all - * [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) groups the - * test belongs to and file-level annotations for the test file. - * - * Learn more about [test annotations](https://playwright.dev/docs/test-annotations). - */ - annotations: Array<{ - /** - * Annotation type, for example `'skip'` or `'fail'`. - */ - type: string; - - /** - * Optional description. - */ - description?: string; - }>; - - /** - * The list of files or buffers attached to the current test. Some reporters show test attachments. - * - * To add an attachment, use - * [testInfo.attach(name[, options])](https://playwright.dev/docs/api/class-testinfo#test-info-attach) instead of - * directly pushing onto this array. - */ - attachments: Array<{ - /** - * Attachment name. - */ - name: string; - - /** - * Content type of this attachment to properly present in the report, for example `'application/json'` or - * `'image/png'`. - */ - contentType: string; - - /** - * Optional path on the filesystem to the attached file. - */ - path?: string; - - /** - * Optional attachment body used instead of a file. - */ - body?: Buffer; - }>; - - /** - * Column number where the currently running test is declared. - */ - column: number; - - /** - * The number of milliseconds the test took to finish. Always zero before the test finishes, either successfully or - * not. Can be used in - * [test.afterEach([title, hookFunction])](https://playwright.dev/docs/api/class-test#test-after-each) hook. - */ - duration: number; - - /** - * First error thrown during test execution, if any. This is equal to the first element in - * [testInfo.errors](https://playwright.dev/docs/api/class-testinfo#test-info-errors). - */ - error?: TestInfoError; - - /** - * Errors thrown during test execution, if any. - */ - errors: Array; - - /** - * Expected status for the currently running test. This is usually `'passed'`, except for a few cases: - * - `'skipped'` for skipped tests, e.g. with - * [test.skip([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-skip); - * - `'failed'` for tests marked as failed with - * [test.fail([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-fail). - * - * Expected status is usually compared with the actual - * [testInfo.status](https://playwright.dev/docs/api/class-testinfo#test-info-status): - * - * ```js - * import { test, expect } from '@playwright/test'; - * - * test.afterEach(async ({}, testInfo) => { - * if (testInfo.status !== testInfo.expectedStatus) - * console.log(`${testInfo.title} did not run as expected!`); - * }); - * ``` - * - */ - expectedStatus: "passed"|"failed"|"timedOut"|"skipped"|"interrupted"; - - /** - * Absolute path to a file where the currently running test is declared. - */ - file: string; - - /** - * Test function as passed to `test(title, testFunction)`. - */ - fn: Function; - - /** - * Line number where the currently running test is declared. - */ - line: number; - - /** - * Absolute path to the output directory for this specific test run. Each test run gets its own directory so they - * cannot conflict. - */ - outputDir: string; - - /** - * The index of the worker between `0` and `workers - 1`. It is guaranteed that workers running at the same time have - * a different `parallelIndex`. When a worker is restarted, for example after a failure, the new worker process has - * the same `parallelIndex`. - * - * Also available as `process.env.TEST_PARALLEL_INDEX`. Learn more about - * [parallelism and sharding](https://playwright.dev/docs/test-parallel) with Playwright Test. - */ - parallelIndex: number; - - /** - * Specifies a unique repeat index when running in "repeat each" mode. This mode is enabled by passing `--repeat-each` - * to the [command line](https://playwright.dev/docs/test-cli). - */ - repeatEachIndex: number; - - /** - * Specifies the retry number when the test is retried after a failure. The first test run has - * [testInfo.retry](https://playwright.dev/docs/api/class-testinfo#test-info-retry) equal to zero, the first retry has - * it equal to one, and so on. Learn more about [retries](https://playwright.dev/docs/test-retries#retries). - * - * ```js - * import { test, expect } from '@playwright/test'; - * - * test.beforeEach(async ({}, testInfo) => { - * // You can access testInfo.retry in any hook or fixture. - * if (testInfo.retry > 0) - * console.log(`Retrying!`); - * }); - * - * test('my test', async ({ page }, testInfo) => { - * // Here we clear some server-side state when retrying. - * if (testInfo.retry) - * await cleanSomeCachesOnTheServer(); - * // ... - * }); - * ``` - * - */ - retry: number; - - /** - * Absolute path to the snapshot output directory for this specific test. Each test suite gets its own directory so - * they cannot conflict. - * - * This property does not account for the - * [testProject.snapshotPathTemplate](https://playwright.dev/docs/api/class-testproject#test-project-snapshot-path-template) - * configuration. - */ - snapshotDir: string; - - /** - * **NOTE** Use of [testInfo.snapshotSuffix](https://playwright.dev/docs/api/class-testinfo#test-info-snapshot-suffix) - * is discouraged. Please use - * [testConfig.snapshotPathTemplate](https://playwright.dev/docs/api/class-testconfig#test-config-snapshot-path-template) - * to configure snapshot paths. - * - * Suffix used to differentiate snapshots between multiple test configurations. For example, if snapshots depend on - * the platform, you can set `testInfo.snapshotSuffix` equal to `process.platform`. In this case - * `expect(value).toMatchSnapshot(snapshotName)` will use different snapshots depending on the platform. Learn more - * about [snapshots](https://playwright.dev/docs/test-snapshots). - */ - snapshotSuffix: string; - - /** - * Actual status for the currently running test. Available after the test has finished in - * [test.afterEach([title, hookFunction])](https://playwright.dev/docs/api/class-test#test-after-each) hook and - * fixtures. - * - * Status is usually compared with the - * [testInfo.expectedStatus](https://playwright.dev/docs/api/class-testinfo#test-info-expected-status): - * - * ```js - * import { test, expect } from '@playwright/test'; - * - * test.afterEach(async ({}, testInfo) => { - * if (testInfo.status !== testInfo.expectedStatus) - * console.log(`${testInfo.title} did not run as expected!`); - * }); - * ``` - * - */ - status?: "passed"|"failed"|"timedOut"|"skipped"|"interrupted"; - - /** - * Tags that apply to the test. Learn more about [tags](https://playwright.dev/docs/test-annotations#tag-tests). - * - * Note that any changes made to this list while the test is running will not be visible to test reporters. - */ - tags: Array; - - /** - * Test id matching the test case id in the reporter API. - */ - testId: string; - - /** - * Timeout in milliseconds for the currently running test. Zero means no timeout. Learn more about - * [various timeouts](https://playwright.dev/docs/test-timeouts). - * - * Timeout is usually specified in the [configuration file](https://playwright.dev/docs/test-configuration) - * - * ```js - * import { test, expect } from '@playwright/test'; - * - * test.beforeEach(async ({ page }, testInfo) => { - * // Extend timeout for all tests running this hook by 30 seconds. - * testInfo.setTimeout(testInfo.timeout + 30000); - * }); - * ``` - * - */ - timeout: number; - - /** - * The title of the currently running test as passed to `test(title, testFunction)`. - */ - title: string; - - /** - * The full title path starting with the project. - */ - titlePath: Array; - - /** - * The unique index of the worker process that is running the test. When a worker is restarted, for example after a - * failure, the new worker process gets a new unique `workerIndex`. - * - * Also available as `process.env.TEST_WORKER_INDEX`. Learn more about [parallelism and sharding](https://playwright.dev/docs/test-parallel) - * with Playwright Test. - */ - workerIndex: number; -} - type TestDetailsAnnotation = { type: string; description?: string; @@ -7780,6 +7301,454 @@ interface SnapshotAssertions { }): void; } +/** + * `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), + * [test.afterEach([title, hookFunction])](https://playwright.dev/docs/api/class-test#test-after-each), + * [test.beforeAll([title, hookFunction])](https://playwright.dev/docs/api/class-test#test-before-all) and + * [test.afterAll([title, hookFunction])](https://playwright.dev/docs/api/class-test#test-after-all) hooks, and + * test-scoped fixtures. `TestInfo` provides utilities to control test execution: attach files, update test timeout, + * determine which test is currently running and whether it was retried, etc. + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test('basic test', async ({ page }, testInfo) => { + * expect(testInfo.title).toBe('basic test'); + * await page.screenshot(testInfo.outputPath('screenshot.png')); + * }); + * ``` + * + */ +export interface TestInfo { + /** + * Attach a value or a file from disk to the current test. Some reporters show test attachments. Either `path` or + * `body` must be specified, but not both. + * + * For example, you can attach a screenshot to the test: + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test('basic test', async ({ page }, testInfo) => { + * await page.goto('https://playwright.dev'); + * const screenshot = await page.screenshot(); + * await testInfo.attach('screenshot', { body: screenshot, contentType: 'image/png' }); + * }); + * ``` + * + * Or you can attach files returned by your APIs: + * + * ```js + * import { test, expect } from '@playwright/test'; + * import { download } from './my-custom-helpers'; + * + * test('basic test', async ({}, testInfo) => { + * const tmpPath = await download('a'); + * await testInfo.attach('downloaded', { path: tmpPath }); + * }); + * ``` + * + * **NOTE** [testInfo.attach(name[, options])](https://playwright.dev/docs/api/class-testinfo#test-info-attach) + * automatically takes care of copying attached files to a location that is accessible to reporters. You can safely + * remove the attachment after awaiting the attach call. + * @param name Attachment name. The name will also be sanitized and used as the prefix of file name when saving to disk. + * @param options + */ + attach(name: string, options?: { + /** + * Attachment body. Mutually exclusive with `path`. + */ + body?: string|Buffer; + + /** + * Content type of this attachment to properly present in the report, for example `'application/json'` or + * `'image/png'`. If omitted, content type is inferred based on the `path`, or defaults to `text/plain` for [string] + * attachments and `application/octet-stream` for [Buffer] attachments. + */ + contentType?: string; + + /** + * Path on the filesystem to the attached file. Mutually exclusive with `body`. + */ + path?: string; + }): Promise; + + /** + * Marks the currently running test as "should fail". Playwright Test runs this test and ensures that it is actually + * failing. This is useful for documentation purposes to acknowledge that some functionality is broken until it is + * fixed. This is similar to + * [test.fail([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-fail). + */ + fail(): void; + + /** + * Conditionally mark the currently running test as "should fail" with an optional description. This is similar to + * [test.fail([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-fail). + * @param condition Test is marked as "should fail" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ + fail(condition: boolean, description?: string): void; + + /** + * Mark a test as "fixme", with the intention to fix it. Test is immediately aborted. This is similar to + * [test.fixme([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-fixme). + */ + fixme(): void; + + /** + * Conditionally mark the currently running test as "fixme" with an optional description. This is similar to + * [test.fixme([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-fixme). + * @param condition Test is marked as "fixme" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ + fixme(condition: boolean, description?: string): void; + + /** + * Returns a path inside the [testInfo.outputDir](https://playwright.dev/docs/api/class-testinfo#test-info-output-dir) + * where the test can safely put a temporary file. Guarantees that tests running in parallel will not interfere with + * each other. + * + * ```js + * import { test, expect } from '@playwright/test'; + * import fs from 'fs'; + * + * test('example test', async ({}, testInfo) => { + * const file = testInfo.outputPath('dir', 'temporary-file.txt'); + * await fs.promises.writeFile(file, 'Put some data to the dir/temporary-file.txt', 'utf8'); + * }); + * ``` + * + * > Note that `pathSegments` accepts path segments to the test output directory such as + * `testInfo.outputPath('relative', 'path', 'to', 'output')`. + * > However, this path must stay within the + * [testInfo.outputDir](https://playwright.dev/docs/api/class-testinfo#test-info-output-dir) directory for each test + * (i.e. `test-results/a-test-title`), otherwise it will throw. + * @param pathSegments Path segments to append at the end of the resulting path. + */ + outputPath(...pathSegments: ReadonlyArray): string; + + /** + * Changes the timeout for the currently running test. Zero means no timeout. Learn more about + * [various timeouts](https://playwright.dev/docs/test-timeouts). + * + * Timeout is usually specified in the [configuration file](https://playwright.dev/docs/test-configuration), but it could be useful to + * change the timeout in certain scenarios: + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test.beforeEach(async ({ page }, testInfo) => { + * // Extend timeout for all tests running this hook by 30 seconds. + * testInfo.setTimeout(testInfo.timeout + 30000); + * }); + * ``` + * + * @param timeout Timeout in milliseconds. + */ + setTimeout(timeout: number): void; + + /** + * Unconditionally skip the currently running test. Test is immediately aborted. This is similar to + * [test.skip([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-skip). + */ + skip(): void; + + /** + * Conditionally skips the currently running test with an optional description. This is similar to + * [test.skip([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-skip). + * @param condition A skip condition. Test is skipped when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ + skip(condition: boolean, description?: string): void; + + /** + * Marks the currently running test as "slow", giving it triple the default timeout. This is similar to + * [test.slow([condition, callback, description])](https://playwright.dev/docs/api/class-test#test-slow). + */ + slow(): void; + + /** + * Conditionally mark the currently running test as "slow" with an optional description, giving it triple the default + * timeout. This is similar to + * [test.slow([condition, callback, description])](https://playwright.dev/docs/api/class-test#test-slow). + * @param condition Test is marked as "slow" when the condition is `true`. + * @param description Optional description that will be reflected in a test report. + */ + slow(condition: boolean, description?: string): void; + + /** + * Returns a path to a snapshot file with the given `pathSegments`. Learn more about + * [snapshots](https://playwright.dev/docs/test-snapshots). + * + * > Note that `pathSegments` accepts path segments to the snapshot file such as `testInfo.snapshotPath('relative', + * 'path', 'to', 'snapshot.png')`. + * > However, this path must stay within the snapshots directory for each test file (i.e. `a.spec.js-snapshots`), + * otherwise it will throw. + * @param pathSegments The name of the snapshot or the path segments to define the snapshot file path. Snapshots with the same name in the + * same test file are expected to be the same. + */ + snapshotPath(...pathSegments: ReadonlyArray): string; + + /** + * The list of annotations applicable to the current test. Includes annotations from the test, annotations from all + * [test.describe([title, details, callback])](https://playwright.dev/docs/api/class-test#test-describe) groups the + * test belongs to and file-level annotations for the test file. + * + * Learn more about [test annotations](https://playwright.dev/docs/test-annotations). + */ + annotations: Array<{ + /** + * Annotation type, for example `'skip'` or `'fail'`. + */ + type: string; + + /** + * Optional description. + */ + description?: string; + }>; + + /** + * The list of files or buffers attached to the current test. Some reporters show test attachments. + * + * To add an attachment, use + * [testInfo.attach(name[, options])](https://playwright.dev/docs/api/class-testinfo#test-info-attach) instead of + * directly pushing onto this array. + */ + attachments: Array<{ + /** + * Attachment name. + */ + name: string; + + /** + * Content type of this attachment to properly present in the report, for example `'application/json'` or + * `'image/png'`. + */ + contentType: string; + + /** + * Optional path on the filesystem to the attached file. + */ + path?: string; + + /** + * Optional attachment body used instead of a file. + */ + body?: Buffer; + }>; + + /** + * Column number where the currently running test is declared. + */ + column: number; + + /** + * Processed configuration from the [configuration file](https://playwright.dev/docs/test-configuration). + */ + config: ConfigInWorker; + + /** + * The number of milliseconds the test took to finish. Always zero before the test finishes, either successfully or + * not. Can be used in + * [test.afterEach([title, hookFunction])](https://playwright.dev/docs/api/class-test#test-after-each) hook. + */ + duration: number; + + /** + * First error thrown during test execution, if any. This is equal to the first element in + * [testInfo.errors](https://playwright.dev/docs/api/class-testinfo#test-info-errors). + */ + error?: TestInfoError; + + /** + * Errors thrown during test execution, if any. + */ + errors: Array; + + /** + * Expected status for the currently running test. This is usually `'passed'`, except for a few cases: + * - `'skipped'` for skipped tests, e.g. with + * [test.skip([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-skip); + * - `'failed'` for tests marked as failed with + * [test.fail([title, details, body, condition, callback, description])](https://playwright.dev/docs/api/class-test#test-fail). + * + * Expected status is usually compared with the actual + * [testInfo.status](https://playwright.dev/docs/api/class-testinfo#test-info-status): + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test.afterEach(async ({}, testInfo) => { + * if (testInfo.status !== testInfo.expectedStatus) + * console.log(`${testInfo.title} did not run as expected!`); + * }); + * ``` + * + */ + expectedStatus: "passed"|"failed"|"timedOut"|"skipped"|"interrupted"; + + /** + * Absolute path to a file where the currently running test is declared. + */ + file: string; + + /** + * Test function as passed to `test(title, testFunction)`. + */ + fn: Function; + + /** + * Line number where the currently running test is declared. + */ + line: number; + + /** + * Absolute path to the output directory for this specific test run. Each test run gets its own directory so they + * cannot conflict. + */ + outputDir: string; + + /** + * The index of the worker between `0` and `workers - 1`. It is guaranteed that workers running at the same time have + * a different `parallelIndex`. When a worker is restarted, for example after a failure, the new worker process has + * the same `parallelIndex`. + * + * Also available as `process.env.TEST_PARALLEL_INDEX`. Learn more about + * [parallelism and sharding](https://playwright.dev/docs/test-parallel) with Playwright Test. + */ + parallelIndex: number; + + /** + * Processed project configuration from the [configuration file](https://playwright.dev/docs/test-configuration). + */ + project: ProjectInWorker; + + /** + * Specifies a unique repeat index when running in "repeat each" mode. This mode is enabled by passing `--repeat-each` + * to the [command line](https://playwright.dev/docs/test-cli). + */ + repeatEachIndex: number; + + /** + * Specifies the retry number when the test is retried after a failure. The first test run has + * [testInfo.retry](https://playwright.dev/docs/api/class-testinfo#test-info-retry) equal to zero, the first retry has + * it equal to one, and so on. Learn more about [retries](https://playwright.dev/docs/test-retries#retries). + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test.beforeEach(async ({}, testInfo) => { + * // You can access testInfo.retry in any hook or fixture. + * if (testInfo.retry > 0) + * console.log(`Retrying!`); + * }); + * + * test('my test', async ({ page }, testInfo) => { + * // Here we clear some server-side state when retrying. + * if (testInfo.retry) + * await cleanSomeCachesOnTheServer(); + * // ... + * }); + * ``` + * + */ + retry: number; + + /** + * Absolute path to the snapshot output directory for this specific test. Each test suite gets its own directory so + * they cannot conflict. + * + * This property does not account for the + * [testProject.snapshotPathTemplate](https://playwright.dev/docs/api/class-testproject#test-project-snapshot-path-template) + * configuration. + */ + snapshotDir: string; + + /** + * **NOTE** Use of [testInfo.snapshotSuffix](https://playwright.dev/docs/api/class-testinfo#test-info-snapshot-suffix) + * is discouraged. Please use + * [testConfig.snapshotPathTemplate](https://playwright.dev/docs/api/class-testconfig#test-config-snapshot-path-template) + * to configure snapshot paths. + * + * Suffix used to differentiate snapshots between multiple test configurations. For example, if snapshots depend on + * the platform, you can set `testInfo.snapshotSuffix` equal to `process.platform`. In this case + * `expect(value).toMatchSnapshot(snapshotName)` will use different snapshots depending on the platform. Learn more + * about [snapshots](https://playwright.dev/docs/test-snapshots). + */ + snapshotSuffix: string; + + /** + * Actual status for the currently running test. Available after the test has finished in + * [test.afterEach([title, hookFunction])](https://playwright.dev/docs/api/class-test#test-after-each) hook and + * fixtures. + * + * Status is usually compared with the + * [testInfo.expectedStatus](https://playwright.dev/docs/api/class-testinfo#test-info-expected-status): + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test.afterEach(async ({}, testInfo) => { + * if (testInfo.status !== testInfo.expectedStatus) + * console.log(`${testInfo.title} did not run as expected!`); + * }); + * ``` + * + */ + status?: "passed"|"failed"|"timedOut"|"skipped"|"interrupted"; + + /** + * Tags that apply to the test. Learn more about [tags](https://playwright.dev/docs/test-annotations#tag-tests). + * + * Note that any changes made to this list while the test is running will not be visible to test reporters. + */ + tags: Array; + + /** + * Test id matching the test case id in the reporter API. + */ + testId: string; + + /** + * Timeout in milliseconds for the currently running test. Zero means no timeout. Learn more about + * [various timeouts](https://playwright.dev/docs/test-timeouts). + * + * Timeout is usually specified in the [configuration file](https://playwright.dev/docs/test-configuration) + * + * ```js + * import { test, expect } from '@playwright/test'; + * + * test.beforeEach(async ({ page }, testInfo) => { + * // Extend timeout for all tests running this hook by 30 seconds. + * testInfo.setTimeout(testInfo.timeout + 30000); + * }); + * ``` + * + */ + timeout: number; + + /** + * The title of the currently running test as passed to `test(title, testFunction)`. + */ + title: string; + + /** + * The full title path starting with the project. + */ + titlePath: Array; + + /** + * The unique index of the worker process that is running the test. When a worker is restarted, for example after a + * failure, the new worker process gets a new unique `workerIndex`. + * + * Also available as `process.env.TEST_WORKER_INDEX`. Learn more about [parallelism and sharding](https://playwright.dev/docs/test-parallel) + * with Playwright Test. + */ + workerIndex: number; +} + /** * Information about an error thrown during test execution. */ @@ -8329,6 +8298,41 @@ interface TestProject { timeout?: number; } +/** + * `WorkerInfo` contains information about the worker that is running tests and is available to worker-scoped + * fixtures. `WorkerInfo` is a subset of {@link TestInfo} that is available in many other places. + */ +export interface WorkerInfo { + /** + * Processed configuration from the [configuration file](https://playwright.dev/docs/test-configuration). + */ + config: ConfigInWorker; + + /** + * The index of the worker between `0` and `workers - 1`. It is guaranteed that workers running at the same time have + * a different `parallelIndex`. When a worker is restarted, for example after a failure, the new worker process has + * the same `parallelIndex`. + * + * Also available as `process.env.TEST_PARALLEL_INDEX`. Learn more about + * [parallelism and sharding](https://playwright.dev/docs/test-parallel) with Playwright Test. + */ + parallelIndex: number; + + /** + * Processed project configuration from the [configuration file](https://playwright.dev/docs/test-configuration). + */ + project: ProjectInWorker; + + /** + * The unique index of the worker process that is running the test. When a worker is restarted, for example after a + * failure, the new worker process gets a new unique `workerIndex`. + * + * Also available as `process.env.TEST_WORKER_INDEX`. Learn more about [parallelism and sharding](https://playwright.dev/docs/test-parallel) + * with Playwright Test. + */ + workerIndex: number; +} + interface TestConfigWebServer { /** * Shell command to start. For example `npm run start`.. diff --git a/utils/generate_types/overrides-test.d.ts b/utils/generate_types/overrides-test.d.ts index 860461fc61..fe07d9cc07 100644 --- a/utils/generate_types/overrides-test.d.ts +++ b/utils/generate_types/overrides-test.d.ts @@ -101,16 +101,6 @@ export interface ConfigInWorker { export type TestStatus = 'passed' | 'failed' | 'timedOut' | 'skipped' | 'interrupted'; -export interface WorkerInfo { - config: ConfigInWorker; - project: ProjectInWorker; -} - -export interface TestInfo { - config: ConfigInWorker; - project: ProjectInWorker; -} - type TestDetailsAnnotation = { type: string; description?: string;