diff --git a/src/generate/file.ts b/src/generate/file.ts index ccbd479b..08b8ac3c 100644 --- a/src/generate/file.ts +++ b/src/generate/file.ts @@ -307,10 +307,12 @@ export class TestFile { }); }); + this.hooks.getWorldFixtureNames().forEach((name) => worldFixtureNames.add(name)); + if (worldFixtureNames.size > 1) { throw new Error( [ - `All steps in a feature file should have the same worldFixture.`, + `All steps and hooks in a feature file should have the same worldFixture.`, `Found fixtures: ${[...worldFixtureNames].join(', ')}`, `File: ${this.featureUri}`, ].join('\n'), diff --git a/src/generate/hooks.ts b/src/generate/hooks.ts index c6fcf96b..464ce3a1 100644 --- a/src/generate/hooks.ts +++ b/src/generate/hooks.ts @@ -60,6 +60,13 @@ export class TestFileHooks { ]); } + getWorldFixtureNames() { + return new Set([ + ...this.before.getWorldFixtureNames(), // prettier-ignore + ...this.after.getWorldFixtureNames(), + ]); + } + render() { const lines = [ ...this.beforeAll.render(), // prettier-ignore @@ -96,6 +103,10 @@ class TestFileScenarioHooks { getFixtureNames() { return getScenarioHooksFixtureNames([...this.hooks]); } + + getWorldFixtureNames() { + return new Set([...this.hooks].map((hook) => hook.worldFixture).filter(toBoolean)); + } } class TestFileWorkerHooks { diff --git a/src/hooks/scenario.ts b/src/hooks/scenario.ts index 54cfed16..97c106c0 100644 --- a/src/hooks/scenario.ts +++ b/src/hooks/scenario.ts @@ -37,6 +37,7 @@ type ScenarioHook = { location: PlaywrightLocation; customTest?: TestTypeCommon; defaultTags?: string; + worldFixture?: string; }; /** @@ -64,7 +65,7 @@ export function scenarioHookFactory< TestFixtures extends KeyValue, WorkerFixtures extends KeyValue, World, ->(type: ScenarioHookType, { customTest, defaultTags }: HookConstructorOptions) { +>(type: ScenarioHookType, { customTest, defaultTags, worldFixture }: HookConstructorOptions) { type AllFixtures = TestFixtures & WorkerFixtures; type Args = ScenarioHookDefinitionArgs; @@ -77,6 +78,7 @@ export function scenarioHookFactory< location: getLocationByOffset(3), customTest, defaultTags, + worldFixture, }); }; } diff --git a/test/world-ambiguos/only-steps/fixtures.ts b/test/world-ambiguos/only-steps/fixtures.ts index 22f46acd..d83e270b 100644 --- a/test/world-ambiguos/only-steps/fixtures.ts +++ b/test/world-ambiguos/only-steps/fixtures.ts @@ -2,4 +2,5 @@ import { test as base } from 'playwright-bdd'; export const test = base.extend<{ world1: string; world2: string }>({ world1: async ({}, use) => use('world1'), + world2: async ({}, use) => use('world2'), }); diff --git a/test/world-ambiguos/playwright.config.ts b/test/world-ambiguos/playwright.config.ts index be2082f0..ecef407d 100644 --- a/test/world-ambiguos/playwright.config.ts +++ b/test/world-ambiguos/playwright.config.ts @@ -2,7 +2,7 @@ import { defineConfig } from '@playwright/test'; import { defineBddConfig } from 'playwright-bdd'; const testDir = defineBddConfig({ - featuresRoot: 'only-steps', + featuresRoot: process.env.FEATURES_ROOT!, }); export default defineConfig({ diff --git a/test/world-ambiguos/scenario-hooks/fixtures.ts b/test/world-ambiguos/scenario-hooks/fixtures.ts new file mode 100644 index 00000000..d83e270b --- /dev/null +++ b/test/world-ambiguos/scenario-hooks/fixtures.ts @@ -0,0 +1,6 @@ +import { test as base } from 'playwright-bdd'; + +export const test = base.extend<{ world1: string; world2: string }>({ + world1: async ({}, use) => use('world1'), + world2: async ({}, use) => use('world2'), +}); diff --git a/test/world-ambiguos/scenario-hooks/hooks.ts b/test/world-ambiguos/scenario-hooks/hooks.ts new file mode 100644 index 00000000..0fc6350f --- /dev/null +++ b/test/world-ambiguos/scenario-hooks/hooks.ts @@ -0,0 +1,6 @@ +import { createBdd } from 'playwright-bdd'; +import { test } from './fixtures'; + +const { Before } = createBdd(test, { worldFixture: 'world2' }); + +Before(async function () {}); diff --git a/test/world-ambiguos/scenario-hooks/sample.feature b/test/world-ambiguos/scenario-hooks/sample.feature new file mode 100644 index 00000000..d9e098d4 --- /dev/null +++ b/test/world-ambiguos/scenario-hooks/sample.feature @@ -0,0 +1,4 @@ +Feature: feature + + Scenario: scenario + Given step with world1 diff --git a/test/world-ambiguos/scenario-hooks/steps.ts b/test/world-ambiguos/scenario-hooks/steps.ts new file mode 100644 index 00000000..7dcc5734 --- /dev/null +++ b/test/world-ambiguos/scenario-hooks/steps.ts @@ -0,0 +1,6 @@ +import { createBdd } from 'playwright-bdd'; +import { test } from './fixtures'; + +const { Given } = createBdd(test, { worldFixture: 'world1' }); + +Given('step with world1', async function () {}); diff --git a/test/world-ambiguos/test.mjs b/test/world-ambiguos/test.mjs index 361132fc..479a23a6 100644 --- a/test/world-ambiguos/test.mjs +++ b/test/world-ambiguos/test.mjs @@ -2,9 +2,24 @@ import { test, TestDir, execPlaywrightTestWithError } from '../_helpers/index.mj const testDir = new TestDir(import.meta); -test(testDir.name, () => { - execPlaywrightTestWithError(testDir.name, [ - 'All steps in a feature file should have the same worldFixture', - 'Found fixtures: world1, world2', - ]); +test(`${testDir.name} (only-steps)`, () => { + execPlaywrightTestWithError( + testDir.name, + [ + 'All steps and hooks in a feature file should have the same worldFixture', + 'Found fixtures: world1, world2', + ], + { env: { FEATURES_ROOT: 'only-steps' } }, + ); +}); + +test(`${testDir.name} (scenario-hooks)`, () => { + execPlaywrightTestWithError( + testDir.name, + [ + 'All steps and hooks in a feature file should have the same worldFixture', + 'Found fixtures: world1, world2', + ], + { env: { FEATURES_ROOT: 'scenario-hooks' } }, + ); });