diff --git a/docs/src/test-api/class-test.md b/docs/src/test-api/class-test.md index 05a3275eed..fb86014004 100644 --- a/docs/src/test-api/class-test.md +++ b/docs/src/test-api/class-test.md @@ -350,6 +350,41 @@ test('runs second', async ({ page }) => {}); +## method: Test.describe.fixme +* since: v1.25 + +Declares a test group similarly to [`method: Test.describe#1`]. Tests in this group are maked as "fixme" and will not be executed. + +```js tab=js-js +test.describe.fixme('broken tests', () => { + test('example', async ({ page }) => { + // This test will not run + }); +}); +``` + +```js tab=js-ts +test.describe.fixme('broken tests', () => { + test('example', async ({ page }) => { + // This test will not run + }); +}); +``` + +### param: Test.describe.fixme.title +* since: v1.25 +- `title` <[string]> + +Group title. + +### param: Test.describe.fixme.callback +* since: v1.25 +- `callback` <[function]> + +A callback that is run immediately when calling [`method: Test.describe.fixme`]. Any tests added in this callback will belong to the group, and will not be run. + + + ## method: Test.describe.only * since: v1.10 diff --git a/packages/playwright-test/src/testType.ts b/packages/playwright-test/src/testType.ts index aa9ba2a73f..623420c4d4 100644 --- a/packages/playwright-test/src/testType.ts +++ b/packages/playwright-test/src/testType.ts @@ -37,6 +37,7 @@ export class TestTypeImpl { test.describe = wrapFunctionWithLocation(this._describe.bind(this, 'default')); test.describe.only = wrapFunctionWithLocation(this._describe.bind(this, 'only')); test.describe.configure = wrapFunctionWithLocation(this._configure.bind(this)); + test.describe.fixme = wrapFunctionWithLocation(this._describe.bind(this, 'fixme')); test.describe.parallel = wrapFunctionWithLocation(this._describe.bind(this, 'parallel')); test.describe.parallel.only = wrapFunctionWithLocation(this._describe.bind(this, 'parallel.only')); test.describe.serial = wrapFunctionWithLocation(this._describe.bind(this, 'serial')); @@ -98,7 +99,7 @@ export class TestTypeImpl { } } - private _describe(type: 'default' | 'only' | 'serial' | 'serial.only' | 'parallel' | 'parallel.only' | 'skip', location: Location, title: string | Function, fn?: Function) { + private _describe(type: 'default' | 'only' | 'serial' | 'serial.only' | 'parallel' | 'parallel.only' | 'skip' | 'fixme', location: Location, title: string | Function, fn?: Function) { throwIfRunningInsideJest(); const suite = this._ensureCurrentSuite(location, 'test.describe()'); @@ -118,9 +119,9 @@ export class TestTypeImpl { child._parallelMode = 'serial'; if (type === 'parallel' || type === 'parallel.only') child._parallelMode = 'parallel'; - if (type === 'skip') { + if (type === 'skip' || type === 'fixme') { child._skipped = true; - child._annotations.push({ type: 'skip' }); + child._annotations.push({ type }); } for (let parent: Suite | undefined = suite; parent; parent = parent.parent) { diff --git a/packages/playwright-test/types/test.d.ts b/packages/playwright-test/types/test.d.ts index e5f30330a9..5de024a9ce 100644 --- a/packages/playwright-test/types/test.d.ts +++ b/packages/playwright-test/types/test.d.ts @@ -1899,6 +1899,24 @@ export interface TestType { + * test('example', async ({ page }) => { + * // This test will not run + * }); + * }); + * ``` + * + * @param title Group title. + * @param callback A callback that is run immediately when calling [test.describe.fixme(title, callback)](https://playwright.dev/docs/api/class-test#test-describe-fixme). Any tests added + * in this callback will belong to the group, and will not be run. + */ + fixme: SuiteFunction; + /** * Declares a group of tests that should always be run serially. If one of the tests fails, all subsequent tests are * skipped. All tests in a group are retried together. * diff --git a/tests/playwright-test/basic.spec.ts b/tests/playwright-test/basic.spec.ts index e5ad390082..799c7fce02 100644 --- a/tests/playwright-test/basic.spec.ts +++ b/tests/playwright-test/basic.spec.ts @@ -470,3 +470,29 @@ test('should support describe.skip', async ({ runInlineTest }) => { expect(result.skipped).toBe(3); expect(result.output).toContain('heytest4'); }); + +test('should support describe.fixme', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'nested-skip.spec.js': ` + const { test } = pwt; + test.describe.fixme('skipped', () => { + test.describe('nested', () => { + test('test1', () => {}); + }); + test('test2', () => {}); + }); + test.describe('not skipped', () => { + test.describe.fixme('skipped', () => { + test('test4', () => {}); + }); + test('test4', () => { + console.log('heytest4'); + }); + }); + ` + }); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + expect(result.skipped).toBe(3); + expect(result.output).toContain('heytest4'); +}); diff --git a/tests/playwright-test/types-2.spec.ts b/tests/playwright-test/types-2.spec.ts index 6fa4892a03..da5fa36986 100644 --- a/tests/playwright-test/types-2.spec.ts +++ b/tests/playwright-test/types-2.spec.ts @@ -40,6 +40,7 @@ test('basics should work', async ({ runTSC }) => { test.describe.serial('suite', () => {}); test.describe.serial.only('suite', () => {}); test.describe.skip('suite', () => {}); + test.describe.fixme('suite', () => {}); // @ts-expect-error test.foo(); ` diff --git a/utils/generate_types/overrides-test.d.ts b/utils/generate_types/overrides-test.d.ts index 9b8c09bfd1..da33b45c12 100644 --- a/utils/generate_types/overrides-test.d.ts +++ b/utils/generate_types/overrides-test.d.ts @@ -121,6 +121,7 @@ export interface TestType