vitalets/playwright-bdd

Question: Custom fixtures in `Cucumber-style steps`

rraffi opened this issue · 3 comments

Is there a way to define a custom fixture and pass it to the Given, When, Then steps?

I do understand that:

As per https://vitalets.github.io/playwright-bdd/#/writing-steps/cucumber-style:

  • step definitions receive only step parameters, don't receive custom fixtures as a first parameter

This is what I'm trying to achieve:

// Cucumber-Style Mode
 
// fixture.ts

type BaseFixtures = {
    myWorld: MyWorld;
    testData: TestData; // a simple-custom test data fixture that holds different properties shareable between steps

}

export const test = base.extend<BaseFixtures>({
    myWorld: async ({ page }, use, testInfo) => {
        const myWorld = new MyWorld(page, testInfo);
        await use(myWorld);
    },

    testData: async ({}, use) => {
        const testData = TestData.init; // initialize test data
        await use(testData);
        TestData.reset(); // reset test data
    }
});

export const { Given, When, Then } = createBdd(test, { worldFixture: 'myWorld' })

// steps.ts

Given('I am logged in as user {string}', async function ({ testData}, userName: string) {   // `testData` is unrecognized
    testData.userName = userName;
    this.navigateToFoo();
});

My current project setup:

❯ npx bddgen env
Playwright-bdd environment info:

platform: darwin
node: v22.2.0
playwright-bdd: v7.0.0-0
@playwright/test: v1.45.1
node:internal/modules/cjs/loader:1189
  throw err;
  ^

Error: Cannot find module '@cucumber/cucumber/package.json'
Require stack:
- /bdd-project/node_modules/playwright-bdd/dist/utils/index.js
- /bdd-project/node_modules/playwright-bdd/dist/playwright/utils.js
- /bdd-project/node_modules/playwright-bdd/dist/gen/formatter.js
- /bdd-project/node_modules/playwright-bdd/dist/gen/testFile.js
- /bdd-project/node_modules/playwright-bdd/dist/gen/index.js
- /bdd-project/node_modules/playwright-bdd/dist/cli/commands/test.js
- /bdd-project/node_modules/playwright-bdd/dist/cli/index.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1186:15)
    at Function.resolve (node:internal/modules/helpers:133:19)
    at resolvePackageRoot (/bdd-project/node_modules/playwright-bdd/dist/utils/index.js:46:37)
    at getPackageVersion (/bdd-project/node_modules/playwright-bdd/dist/utils/index.js:51:25)
    at showPackageVersion (/bdd-project/node_modules/playwright-bdd/dist/cli/commands/env.js:24:51)
    at Command.<anonymous> (/bdd-project/node_modules/playwright-bdd/dist/cli/commands/env.js:20:5)
    at Command.listener [as _actionHandler] (/bdd-project/node_modules/playwright-bdd/node_modules/commander/lib/command.js:542:17)
    at /bdd-project/node_modules/playwright-bdd/node_modules/commander/lib/command.js:1502:14
    at Command._chainOrCall (/bdd-project/node_modules/playwright-bdd/node_modules/commander/lib/command.js:1386:12)
    at Command._parseCommand (/bdd-project/node_modules/playwright-bdd/node_modules/commander/lib/command.js:1501:27) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/bdd-project/node_modules/playwright-bdd/dist/utils/index.js',
    '/bdd-project/node_modules/playwright-bdd/dist/playwright/utils.js',
    '/bdd-project/node_modules/playwright-bdd/dist/gen/formatter.js',
    '/bdd-project/node_modules/playwright-bdd/dist/gen/testFile.js',
    '/bdd-project/node_modules/playwright-bdd/dist/gen/index.js',
    '/bdd-project/node_modules/playwright-bdd/dist/cli/commands/test.js',
    '/bdd-project/node_modules/playwright-bdd/dist/cli/index.js'
  ]
}

Node.js v22.2.0

I tried the this.useFixture(fixtureName) recommendation in https://vitalets.github.io/playwright-bdd/#/writing-steps/cucumber-style-legacy?id=custom-fixtures, but useFixture wasn't recognized. I'm on "playwright-bdd": "^7.2.2" now.

CleanShot 2024-08-20 at 15 51 36

Yes, since v7 you can pass custom fixtures to steps via world object:

type MyWorld = {
   testData: TestData;  // a simple-custom test data fixture that holds different properties shareable between steps
  // any other props of world
}

type BaseFixtures = {
    myWorld: MyWorld;
}

export const test = base.extend<BaseFixtures>({
    myWorld: async ({ page, testData }, use, testInfo) => {
        const myWorld = new MyWorld(page, testInfo, testData);
        await use(myWorld);
    },

    testData: async ({}, use) => {
        const testData = TestData.init; // initialize test data
        await use(testData);
        TestData.reset(); // reset test data
    }
});

And in steps:

Given('I am logged in as user {string}', async function (userName: string) {  
    this.testData.userName = userName;
    this.navigateToFoo();
});

Will add this example to documentation 👍

Documented custom fixtures in cucumber-style steps: https://vitalets.github.io/playwright-bdd/#/writing-steps/cucumber-style?id=provide-custom-fixtures
Feel free to re-open in case of any issues.