vite, return types, etc.

This commit is contained in:
Yury Semikhatsky 2024-04-02 15:06:59 -07:00
parent 1c1a0d9783
commit a44dd67bea
8 changed files with 502 additions and 510 deletions

View file

@ -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) };
}

View file

@ -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<string, any> } | null> {
export async function buildBundle(config: FullConfig, configDir: string, suite: Suite): Promise<{ buildInfo: BuildInfo, viteConfig: Record<string, any> } | null> {
const { registerSourceFile, frameworkPluginFactory } = frameworkConfig(config);
{
// Detect a running dev server and use it if available.

View file

@ -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<ComponentDirs | null> {
export async function resolveDirs(configDir: string, config: FullConfig): Promise<ComponentDirs | null> {
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<Plugin>) | undefined, supportJsxInJs: boolean) {
export async function createConfig(dirs: ComponentDirs, config: FullConfig, frameworkPluginFactory: (() => Promise<Plugin>) | 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<Plugin> } {
export function frameworkConfig(config: FullConfig): { registerSourceFile: string, frameworkPluginFactory?: () => Promise<Plugin> } {
return (config as any)['@playwright/experimental-ct-core'];
}

View file

@ -46,7 +46,7 @@ export class FullConfigInternal {
readonly configCLIOverrides: ConfigCLIOverrides;
readonly ignoreSnapshots: boolean;
readonly preserveOutputDir: boolean;
readonly webServers: NonNullable<ConfigInWorker['webServer']>[];
readonly webServers: NonNullable<FullConfig['webServer']>[];
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<ConfigInWorker['webServer']>;
this.config.webServer = webServers;
this.webServers = [webServers];
} else {
this.webServers = [];

View file

@ -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();
}
}

View file

@ -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,

View file

@ -1272,485 +1272,6 @@ export interface ConfigInWorker<TestArgs = {}, WorkerArgs = {}> {
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<void>;
/**
* 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>): 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>): 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<TestInfoError>;
/**
* 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<string>;
/**
* 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<string>;
/**
* 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<void>;
/**
* 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>): 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>): 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<TestInfoError>;
/**
* 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<string>;
/**
* 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<string>;
/**
* 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`..

View file

@ -101,16 +101,6 @@ export interface ConfigInWorker<TestArgs = {}, WorkerArgs = {}> {
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;