diff --git a/packages/playwright-test/src/testType.ts b/packages/playwright-test/src/testType.ts index 623420c4d4..fd35892382 100644 --- a/packages/playwright-test/src/testType.ts +++ b/packages/playwright-test/src/testType.ts @@ -200,7 +200,7 @@ export class TestTypeImpl { suite._use.push({ fixtures, location }); } - private async _step(location: Location, title: string, body: () => Promise): Promise { + private async _step(location: Location, title: string, body: () => Promise): Promise { const testInfo = currentTestInfo(); if (!testInfo) throw errorWithLocation(location, `test.step() can only be called from a test`); @@ -212,8 +212,9 @@ export class TestTypeImpl { forceNoParent: false }); try { - await body(); + const result = await body(); step.complete({}); + return result; } catch (e) { step.complete({ error: serializeError(e) }); throw e; diff --git a/packages/playwright-test/types/test.d.ts b/packages/playwright-test/types/test.d.ts index 5de024a9ce..b7ac91792a 100644 --- a/packages/playwright-test/types/test.d.ts +++ b/packages/playwright-test/types/test.d.ts @@ -2512,7 +2512,7 @@ export interface TestType Promise): Promise; + step(title: string, body: () => Promise): Promise; /** * `expect` function can be used to create test assertions. Read * [expect library documentation](https://jestjs.io/docs/expect) for more details. diff --git a/tests/playwright-test/test-step.spec.ts b/tests/playwright-test/test-step.spec.ts index d9294e3864..9dc58e32c1 100644 --- a/tests/playwright-test/test-step.spec.ts +++ b/tests/playwright-test/test-step.spec.ts @@ -379,3 +379,25 @@ test('should report custom expect steps', async ({ runInlineTest }) => { }, ]); }); + +test('should return value from step', async ({ runInlineTest }) => { + const result = await runInlineTest({ + 'a.test.ts': ` + const { test } = pwt; + test('steps with return values', async ({ page }) => { + const v1 = await test.step('my step', () => { + return 10; + }); + console.log('v1 = ' + v1); + const v2 = await test.step('my step', async () => { + return new Promise(f => setTimeout(() => f(v1 + 10), 100)); + }); + console.log('v2 = ' + v2); + }); + ` + }, { reporter: '', workers: 1 }); + expect(result.exitCode).toBe(0); + expect(result.passed).toBe(1); + expect(result.output).toContain('v1 = 10'); + expect(result.output).toContain('v2 = 20'); +}); diff --git a/tests/playwright-test/types-2.spec.ts b/tests/playwright-test/types-2.spec.ts index da5fa36986..597437426b 100644 --- a/tests/playwright-test/types-2.spec.ts +++ b/tests/playwright-test/types-2.spec.ts @@ -136,3 +136,26 @@ test('test.extend options should check types', async ({ runTSC }) => { }); expect(result.exitCode).toBe(0); }); + +test('step should inherit return type from its callback ', async ({ runTSC }) => { + const result = await runTSC({ + 'a.spec.ts': ` + const { test } = pwt; + test('my test', async ({ }) => { + // @ts-expect-error + const bad1: string = await test.step('my step', () => { + return 10; + }); + // @ts-expect-error + const bad2: string = await test.step('my step', async () => { + return 10; + }); + const good: string = await test.step('my step', async () => { + return 'foo'; + }); + await test.step('my step', async () => { }); + }); + ` + }); + expect(result.exitCode).toBe(0); +}); diff --git a/utils/generate_types/overrides-test.d.ts b/utils/generate_types/overrides-test.d.ts index da33b45c12..286b0838dc 100644 --- a/utils/generate_types/overrides-test.d.ts +++ b/utils/generate_types/overrides-test.d.ts @@ -150,7 +150,7 @@ export interface TestType Promise | any): void; afterAll(inner: (args: TestArgs & WorkerArgs, testInfo: TestInfo) => Promise | any): void; use(fixtures: Fixtures<{}, {}, TestArgs, WorkerArgs>): void; - step(title: string, body: () => Promise): Promise; + step(title: string, body: () => Promise): Promise; expect: Expect; extend(fixtures: Fixtures): TestType; info(): TestInfo;