diff --git a/docs/src/puppeteer-js.md b/docs/src/puppeteer-js.md index a74272421dd54..7b31c2d0cdc23 100644 --- a/docs/src/puppeteer-js.md +++ b/docs/src/puppeteer-js.md @@ -137,7 +137,7 @@ test.describe('Playwright homepage', () => { 1. Each Playwright Test file has explicit import of the `test` and `expect` functions 1. Test function is marked with `async` 1. Playwright Test is given a `page` as one of its parameters. This is one of the many [useful fixtures](./api/class-fixtures) in Playwright Test. -Playwright Test creates an isolated [Page] object for each test. However, if you'd like to reuse a single [Page] object between multiple tests, you can create your own in [`method: Test.beforeAll`] and close it in [`method: Test.afterAll`]. +Playwright Test creates an isolated [Page] object for each test. However, if you'd like to reuse a single [Page] object between multiple tests, you can create your own in [`method: Test.beforeAll#1`] and close it in [`method: Test.afterAll#1`]. 1. Locator creation with [`method: Page.locator`] is one of the few methods that is sync. 1. Use [assertions](./test-assertions) to verify the state instead of `page.$eval()`. diff --git a/docs/src/test-api/class-test.md b/docs/src/test-api/class-test.md index 82afec4a401c4..f4af86db496c7 100644 --- a/docs/src/test-api/class-test.md +++ b/docs/src/test-api/class-test.md @@ -44,7 +44,7 @@ Test function that takes one or two arguments: an object with fixtures and optio -## method: Test.afterAll +## method: Test.afterAll#1 * since: v1.10 Declares an `afterAll` hook that is executed once per worker after all tests. @@ -64,15 +64,42 @@ test.afterAll(async () => { }); ``` -### param: Test.afterAll.hookFunction +### param: Test.afterAll#1.hookFunction * since: v1.10 - `hookFunction` <[function]\([Fixtures], [TestInfo]\)> Hook function that takes one or two arguments: an object with worker fixtures and optional [TestInfo]. +## method: Test.afterAll#2 +* since: v1.38 -## method: Test.afterEach +Declares an `afterAll` hook with a title that is executed once per worker after all tests. + +**Usage** + +```js +test.afterAll('Teardown', async () => { + console.log('Done with tests'); + // ... +}); +``` + +### param: Test.afterAll#2.title +* since: v1.38 +- `title` <[string]> + +Hook title. + +### param: Test.afterAll#2.hookFunction +* since: v1.38 +- `hookFunction` <[function]\([Fixtures], [TestInfo]\)> + +Hook function that takes one or two arguments: an object with worker fixtures and optional [TestInfo]. + + + +## method: Test.afterEach#1 * since: v1.10 Declares an `afterEach` hook that is executed after each test. @@ -100,14 +127,50 @@ test('my test', async ({ page }) => { }); ``` -### param: Test.afterEach.hookFunction +### param: Test.afterEach#1.hookFunction * since: v1.10 - `hookFunction` <[function]\([Fixtures], [TestInfo]\)> Hook function that takes one or two arguments: an object with fixtures and optional [TestInfo]. -## method: Test.beforeAll +## method: Test.afterEach#2 +* since: v1.38 + +Declares an `afterEach` hook with a title that is executed after each test. + +**Usage** + +```js title="example.spec.ts" +import { test, expect } from '@playwright/test'; + +test.afterEach('Status check', async ({ page }, testInfo) => { + console.log(`Finished ${testInfo.title} with status ${testInfo.status}`); + + if (testInfo.status !== testInfo.expectedStatus) + console.log(`Did not run as expected, ended up at ${page.url()}`); +}); + +test('my test', async ({ page }) => { + // ... +}); +``` + +### param: Test.afterEach#2.title +* since: v1.38 +- `title` <[string]> + +Hook title. + +### param: Test.afterEach#2.hookFunction +* since: v1.38 +- `hookFunction` <[function]\([Fixtures], [TestInfo]\)> + +Hook function that takes one or two arguments: an object with fixtures and optional [TestInfo]. + + + +## method: Test.beforeAll#1 * since: v1.10 Declares a `beforeAll` hook that is executed once per worker process before all tests. @@ -118,7 +181,7 @@ When called in the scope of a test file, runs before all tests in the file. When Note that worker process is restarted on test failures, and `beforeAll` hook runs again in the new worker. Learn more about [workers and failures](../test-retries.md). -You can use [`method: Test.afterAll`] to teardown any resources set up in `beforeAll`. +You can use [`method: Test.afterAll#1`] to teardown any resources set up in `beforeAll`. **Usage** @@ -138,15 +201,47 @@ test('my test', async ({ page }) => { }); ``` -### param: Test.beforeAll.hookFunction +### param: Test.beforeAll#1.hookFunction * since: v1.10 - `hookFunction` <[function]\([Fixtures], [TestInfo]\)> Hook function that takes one or two arguments: an object with worker fixtures and optional [TestInfo]. +## method: Test.beforeAll#2 +* since: v1.38 + +Declares a `beforeAll` hook with a title that is executed once per worker process before all tests. -## method: Test.beforeEach +**Usage** + +```js title="example.spec.ts" +import { test, expect } from '@playwright/test'; + +test.beforeAll('Setup', async () => { + console.log('Before tests'); +}); + +test('my test', async ({ page }) => { + // ... +}); +``` + +### param: Test.beforeAll#2.title +* since: v1.38 +- `title` <[string]> + +Hook title. + +### param: Test.beforeAll#2.hookFunction +* since: v1.38 +- `hookFunction` <[function]\([Fixtures], [TestInfo]\)> + +Hook function that takes one or two arguments: an object with worker fixtures and optional [TestInfo]. + + + +## method: Test.beforeEach#1 * since: v1.10 Declares a `beforeEach` hook that is executed before each test. @@ -157,7 +252,7 @@ When called in the scope of a test file, runs before each test in the file. When You can access all the same [Fixtures] as the test function itself, and also the [TestInfo] object that gives a lot of useful information. For example, you can navigate the page before starting the test. -You can use [`method: Test.afterEach`] to teardown any resources set up in `beforeEach`. +You can use [`method: Test.afterEach#1`] to teardown any resources set up in `beforeEach`. **Usage** @@ -174,13 +269,45 @@ test('my test', async ({ page }) => { }); ``` -### param: Test.beforeEach.hookFunction +### param: Test.beforeEach#1.hookFunction * since: v1.10 - `hookFunction` <[function]\([Fixtures], [TestInfo]\)> Hook function that takes one or two arguments: an object with fixtures and optional [TestInfo]. +## method: Test.beforeEach#2 +* since: v1.38 + +Declares a `beforeEach` hook with a title that is executed before each test. + +**Usage** + +```js title="example.spec.ts" +import { test, expect } from '@playwright/test'; + +test.beforeEach('Open start URL', async ({ page }, testInfo) => { + console.log(`Running ${testInfo.title}`); + await page.goto('https://my.start.url/'); +}); + +test('my test', async ({ page }) => { + expect(page.url()).toBe('https://my.start.url/'); +}); +``` + +### param: Test.beforeEach#2.title +* since: v1.38 +- `title` <[string]> + +Hook title. + +### param: Test.beforeEach#2.hookFunction +* since: v1.38 +- `hookFunction` <[function]\([Fixtures], [TestInfo]\)> + +Hook function that takes one or two arguments: an object with fixtures and optional [TestInfo]. + ## method: Test.describe#1 @@ -1057,7 +1184,7 @@ test('skip in WebKit', async ({ page, browserName }) => { }); ``` -Skip from [`method: Test.beforeEach`] hook: +Skip from [`method: Test.beforeEach#1`] hook: ```js import { test, expect } from '@playwright/test'; diff --git a/docs/src/test-api/class-testinfo.md b/docs/src/test-api/class-testinfo.md index cfbc9cb4becbd..b8b492efbc06f 100644 --- a/docs/src/test-api/class-testinfo.md +++ b/docs/src/test-api/class-testinfo.md @@ -2,7 +2,7 @@ * since: v1.10 * langs: js -`TestInfo` contains information about currently running test. It is available to test functions, [`method: Test.beforeEach`], [`method: Test.afterEach`], [`method: Test.beforeAll`] and [`method: Test.afterAll`] 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. +`TestInfo` contains information about currently running test. It is available to test functions, [`method: Test.beforeEach#1`], [`method: Test.afterEach#1`], [`method: Test.beforeAll#1`] and [`method: Test.afterAll#1`] 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'; @@ -115,7 +115,7 @@ Processed configuration from the [configuration file](../test-configuration.md). * since: v1.10 - type: <[int]> -The number of milliseconds the test took to finish. Always zero before the test finishes, either successfully or not. Can be used in [`method: Test.afterEach`] hook. +The number of milliseconds the test took to finish. Always zero before the test finishes, either successfully or not. Can be used in [`method: Test.afterEach#1`] hook. ## property: TestInfo.error @@ -403,7 +403,7 @@ Suffix used to differentiate snapshots between multiple test configurations. For * since: v1.10 - type: ?<[TestStatus]<"passed"|"failed"|"timedOut"|"skipped"|"interrupted">> -Actual status for the currently running test. Available after the test has finished in [`method: Test.afterEach`] hook and fixtures. +Actual status for the currently running test. Available after the test has finished in [`method: Test.afterEach#1`] hook and fixtures. Status is usually compared with the [`property: TestInfo.expectedStatus`]: diff --git a/docs/src/test-retries-js.md b/docs/src/test-retries-js.md index d5dca35d04516..92ec79ca88664 100644 --- a/docs/src/test-retries-js.md +++ b/docs/src/test-retries-js.md @@ -161,7 +161,7 @@ It is usually better to make your tests isolated, so they can be efficiently run ## Reuse single page between tests -Playwright Test creates an isolated [Page] object for each test. However, if you'd like to reuse a single [Page] object between multiple tests, you can create your own in [`method: Test.beforeAll`] and close it in [`method: Test.afterAll`]. +Playwright Test creates an isolated [Page] object for each test. However, if you'd like to reuse a single [Page] object between multiple tests, you can create your own in [`method: Test.beforeAll#1`] and close it in [`method: Test.afterAll#1`]. ```js tab=js-js title="example.spec.js" // @ts-check diff --git a/packages/playwright-test/src/common/test.ts b/packages/playwright-test/src/common/test.ts index 3e0d125a3a44c..aadcc89781c22 100644 --- a/packages/playwright-test/src/common/test.ts +++ b/packages/playwright-test/src/common/test.ts @@ -45,7 +45,7 @@ export class Suite extends Base implements SuitePrivate { parent?: Suite; _use: FixturesWithLocation[] = []; _entries: (Suite | TestCase)[] = []; - _hooks: { type: 'beforeEach' | 'afterEach' | 'beforeAll' | 'afterAll', fn: Function, location: Location }[] = []; + _hooks: { type: 'beforeEach' | 'afterEach' | 'beforeAll' | 'afterAll', fn: Function, title: string, location: Location }[] = []; _timeout: number | undefined; _retries: number | undefined; _staticAnnotations: Annotation[] = []; @@ -187,7 +187,7 @@ export class Suite extends Base implements SuitePrivate { staticAnnotations: this._staticAnnotations.slice(), modifiers: this._modifiers.slice(), parallelMode: this._parallelMode, - hooks: this._hooks.map(h => ({ type: h.type, location: h.location })), + hooks: this._hooks.map(h => ({ type: h.type, location: h.location, title: h.title })), fileId: this._fileId, }; } @@ -202,7 +202,7 @@ export class Suite extends Base implements SuitePrivate { suite._staticAnnotations = data.staticAnnotations; suite._modifiers = data.modifiers; suite._parallelMode = data.parallelMode; - suite._hooks = data.hooks.map((h: any) => ({ type: h.type, location: h.location, fn: () => { } })); + suite._hooks = data.hooks.map((h: any) => ({ type: h.type, location: h.location, title: h.title, fn: () => { } })); suite._fileId = data.fileId; return suite; } diff --git a/packages/playwright-test/src/common/testType.ts b/packages/playwright-test/src/common/testType.ts index 86e2174a3f84b..05fcb54a04ed1 100644 --- a/packages/playwright-test/src/common/testType.ts +++ b/packages/playwright-test/src/common/testType.ts @@ -134,11 +134,16 @@ export class TestTypeImpl { setCurrentlyLoadingFileSuite(suite); } - private _hook(name: 'beforeEach' | 'afterEach' | 'beforeAll' | 'afterAll', location: Location, fn: Function) { + private _hook(name: 'beforeEach' | 'afterEach' | 'beforeAll' | 'afterAll', location: Location, title: string | Function, fn?: Function) { const suite = this._currentSuite(location, `test.${name}()`); if (!suite) return; - suite._hooks.push({ type: name, fn, location }); + if (typeof title === 'function') { + fn = title; + title = `${name} hook`; + } + + suite._hooks.push({ type: name, fn: fn!, title, location }); } private _configure(location: Location, options: { mode?: 'default' | 'parallel' | 'serial', retries?: number, timeout?: number }) { diff --git a/packages/playwright-test/src/worker/workerMain.ts b/packages/playwright-test/src/worker/workerMain.ts index b6b520ea7c2f9..01937843cfb5a 100644 --- a/packages/playwright-test/src/worker/workerMain.ts +++ b/packages/playwright-test/src/worker/workerMain.ts @@ -528,7 +528,7 @@ export class WorkerMain extends ProcessRunner { testInfo._timeoutManager.setCurrentRunnable({ type: 'beforeAll', location: hook.location, slot: timeSlot }); await testInfo._runAsStep({ category: 'hook', - title: `${hook.type} hook`, + title: `${hook.title}`, location: hook.location, }, async () => { try { @@ -564,7 +564,7 @@ export class WorkerMain extends ProcessRunner { testInfo._timeoutManager.setCurrentRunnable({ type: 'afterAll', location: hook.location, slot: timeSlot }); await testInfo._runAsStep({ category: 'hook', - title: `${hook.type} hook`, + title: `${hook.title}`, location: hook.location, }, async () => { try { @@ -590,7 +590,7 @@ export class WorkerMain extends ProcessRunner { testInfo._timeoutManager.setCurrentRunnable({ type, location: hook.location, slot: timeSlot }); await testInfo._runAsStep({ category: 'hook', - title: `${hook.type} hook`, + title: `${hook.title}`, location: hook.location, }, () => this._fixtureRunner.resolveParametersAndRunFunction(hook.fn, testInfo, 'test')); } catch (e) { diff --git a/packages/playwright-test/types/test.d.ts b/packages/playwright-test/types/test.d.ts index 4baff0fb68188..ea7eff81c5476 100644 --- a/packages/playwright-test/types/test.d.ts +++ b/packages/playwright-test/types/test.d.ts @@ -1900,10 +1900,10 @@ export interface WorkerInfo { /** * `TestInfo` contains information about currently running test. It is available to test functions, - * [test.beforeEach(hookFunction)](https://playwright.dev/docs/api/class-test#test-before-each), - * [test.afterEach(hookFunction)](https://playwright.dev/docs/api/class-test#test-after-each), - * [test.beforeAll(hookFunction)](https://playwright.dev/docs/api/class-test#test-before-all) and - * [test.afterAll(hookFunction)](https://playwright.dev/docs/api/class-test#test-after-all) hooks, and test-scoped + * [test.beforeEach(hookFunction)](https://playwright.dev/docs/api/class-test#test-before-each-1), + * [test.afterEach(hookFunction)](https://playwright.dev/docs/api/class-test#test-after-each-1), + * [test.beforeAll(hookFunction)](https://playwright.dev/docs/api/class-test#test-before-all-1) and + * [test.afterAll(hookFunction)](https://playwright.dev/docs/api/class-test#test-after-all-1) 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. * @@ -2150,7 +2150,7 @@ export interface TestInfo { /** * 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(hookFunction)](https://playwright.dev/docs/api/class-test#test-after-each) + * not. Can be used in [test.afterEach(hookFunction)](https://playwright.dev/docs/api/class-test#test-after-each-1) * hook. */ duration: number; @@ -2274,7 +2274,7 @@ export interface TestInfo { /** * Actual status for the currently running test. Available after the test has finished in - * [test.afterEach(hookFunction)](https://playwright.dev/docs/api/class-test#test-after-each) hook and fixtures. + * [test.afterEach(hookFunction)](https://playwright.dev/docs/api/class-test#test-after-each-1) hook and fixtures. * * Status is usually compared with the * [testInfo.expectedStatus](https://playwright.dev/docs/api/class-testinfo#test-info-expected-status): @@ -2746,7 +2746,7 @@ export interface TestType Promise | any): void; + /** + * Declares a `beforeEach` hook with a title that is executed before each test. + * + * **Usage** + * + * ```js + * // example.spec.ts + * import { test, expect } from '@playwright/test'; + * + * test.beforeEach('Open start URL', async ({ page }, testInfo) => { + * console.log(`Running ${testInfo.title}`); + * await page.goto('https://my.start.url/'); + * }); + * + * test('my test', async ({ page }) => { + * expect(page.url()).toBe('https://my.start.url/'); + * }); + * ``` + * + * @param title Hook title. + * @param hookFunction Hook function that takes one or two arguments: an object with fixtures and optional {@link TestInfo}. + */ + beforeEach(title: string, inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; /** * Declares an `afterEach` hook that is executed after each test. * @@ -3126,6 +3149,31 @@ export interface TestType Promise | any): void; + /** + * Declares an `afterEach` hook with a title that is executed after each test. + * + * **Usage** + * + * ```js + * // example.spec.ts + * import { test, expect } from '@playwright/test'; + * + * test.afterEach('Status check', async ({ page }, testInfo) => { + * console.log(`Finished ${testInfo.title} with status ${testInfo.status}`); + * + * if (testInfo.status !== testInfo.expectedStatus) + * console.log(`Did not run as expected, ended up at ${page.url()}`); + * }); + * + * test('my test', async ({ page }) => { + * // ... + * }); + * ``` + * + * @param title Hook title. + * @param hookFunction Hook function that takes one or two arguments: an object with fixtures and optional {@link TestInfo}. + */ + afterEach(title: string, inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; /** * Declares a `beforeAll` hook that is executed once per worker process before all tests. * @@ -3138,7 +3186,7 @@ export interface TestType Promise | any): void; + /** + * Declares a `beforeAll` hook with a title that is executed once per worker process before all tests. + * + * **Usage** + * + * ```js + * // example.spec.ts + * import { test, expect } from '@playwright/test'; + * + * test.beforeAll('Setup', async () => { + * console.log('Before tests'); + * }); + * + * test('my test', async ({ page }) => { + * // ... + * }); + * ``` + * + * @param title Hook title. + * @param hookFunction Hook function that takes one or two arguments: an object with worker fixtures and optional {@link TestInfo}. + */ + beforeAll(title: string, inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; /** * Declares an `afterAll` hook that is executed once per worker after all tests. * @@ -3187,6 +3257,22 @@ export interface TestType Promise | any): void; + /** + * Declares an `afterAll` hook with a title that is executed once per worker after all tests. + * + * **Usage** + * + * ```js + * test.afterAll('Teardown', async () => { + * console.log('Done with tests'); + * // ... + * }); + * ``` + * + * @param title Hook title. + * @param hookFunction Hook function that takes one or two arguments: an object with worker fixtures and optional {@link TestInfo}. + */ + afterAll(title: string, inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; /** * Specifies options or fixtures to use in a single test file or a * [test.describe(title, callback)](https://playwright.dev/docs/api/class-test#test-describe-1) group. Most useful to diff --git a/tests/playwright-test/reporter-html.spec.ts b/tests/playwright-test/reporter-html.spec.ts index dfc82e8af38f8..91a7a394ac57a 100644 --- a/tests/playwright-test/reporter-html.spec.ts +++ b/tests/playwright-test/reporter-html.spec.ts @@ -2063,6 +2063,122 @@ for (const useIntermediateMergeReport of [false, true] as const) { await expect(page.getByText('failed title')).not.toBeVisible(); await expect(page.getByText('passes title')).toBeVisible(); }); + + test('should properly display beforeEach with and without title', async ({ runInlineTest, showReport, page }) => { + const result = await runInlineTest({ + 'a.test.js': ` + const { test, expect } = require('@playwright/test'); + test.beforeEach('titled hook', () => { + console.log('titled hook'); + }); + test.beforeEach(() => { + console.log('anonymous hook'); + }); + test('titles', async ({}) => { + expect(1).toBe(1); + }); + `, + }, { reporter: 'dot,html' }, { PW_TEST_HTML_REPORT_OPEN: 'never' }); + + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + + await showReport(); + await page.click('text=titles'); + + await page.click('text=Before Hooks'); + await expect(page.locator('.tree-item:has-text("Before Hooks") .tree-item')).toContainText([ + /titled hook/, + /beforeEach hook/, + ]); + }); + + test('should properly display beforeAll with and without title', async ({ runInlineTest, showReport, page }) => { + const result = await runInlineTest({ + 'a.test.js': ` + const { test, expect } = require('@playwright/test'); + test.beforeAll('titled hook', () => { + console.log('titled hook'); + }); + test.beforeAll(() => { + console.log('anonymous hook'); + }); + test('titles', async ({}) => { + expect(1).toBe(1); + }); + `, + }, { reporter: 'dot,html' }, { PW_TEST_HTML_REPORT_OPEN: 'never' }); + + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + + await showReport(); + await page.click('text=titles'); + + await page.click('text=Before Hooks'); + await expect(page.locator('.tree-item:has-text("Before Hooks") .tree-item')).toContainText([ + /titled hook/, + /beforeAll hook/, + ]); + }); + + test('should properly display afterEach with and without title', async ({ runInlineTest, showReport, page }) => { + const result = await runInlineTest({ + 'a.test.js': ` + const { test, expect } = require('@playwright/test'); + test.afterEach('titled hook', () => { + console.log('titled hook'); + }); + test.afterEach(() => { + console.log('anonymous hook'); + }); + test('titles', async ({}) => { + expect(1).toBe(1); + }); + `, + }, { reporter: 'dot,html' }, { PW_TEST_HTML_REPORT_OPEN: 'never' }); + + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + + await showReport(); + await page.click('text=titles'); + + await page.click('text=After Hooks'); + await expect(page.locator('.tree-item:has-text("After Hooks") .tree-item')).toContainText([ + /titled hook/, + /afterEach hook/, + ]); + }); + + test('should properly display afterAll with and without title', async ({ runInlineTest, showReport, page }) => { + const result = await runInlineTest({ + 'a.test.js': ` + const { test, expect } = require('@playwright/test'); + test.afterAll('titled hook', () => { + console.log('titled hook'); + }); + test.afterAll(() => { + console.log('anonymous hook'); + }); + test('titles', async ({}) => { + expect(1).toBe(1); + }); + `, + }, { reporter: 'dot,html' }, { PW_TEST_HTML_REPORT_OPEN: 'never' }); + + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + + await showReport(); + await page.click('text=titles'); + + await page.click('text=After Hooks'); + await expect(page.locator('.tree-item:has-text("After Hooks") .tree-item')).toContainText([ + /titled hook/, + /afterAll hook/, + ]); + }); }); } diff --git a/utils/generate_types/overrides-test.d.ts b/utils/generate_types/overrides-test.d.ts index 0b199d03570b9..de88ed4f5f224 100644 --- a/utils/generate_types/overrides-test.d.ts +++ b/utils/generate_types/overrides-test.d.ts @@ -149,9 +149,13 @@ export interface TestType boolean, description?: string): void; setTimeout(timeout: number): void; beforeEach(inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; + beforeEach(title: string, inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; afterEach(inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; + afterEach(title: string, inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; beforeAll(inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; + beforeAll(title: string, inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; afterAll(inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; + afterAll(title: string, inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; use(fixtures: Fixtures<{}, {}, TestArgs, WorkerArgs>): void; step(title: string, body: () => T | Promise): Promise; expect: Expect;