playwright-bdd
Version:
BDD Testing with Playwright runner
108 lines • 5.55 kB
JavaScript
;
/**
* Class to invoke step in playwright runner.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.BddStepInvoker = void 0;
const getLocationInFile_1 = require("../playwright/getLocationInFile");
const DataTable_1 = require("../cucumber/DataTable");
const bddTestFixturesAuto_1 = require("./bddTestFixturesAuto");
const runStepWithLocation_1 = require("../playwright/runStepWithLocation");
const finder_1 = require("../steps/finder");
const step_1 = require("../hooks/step");
class BddStepInvoker {
constructor(bddContext, world) {
this.bddContext = bddContext;
this.world = world;
this.stepFinder = new finder_1.StepFinder(bddContext.config);
}
/**
* Invokes particular step.
* See: https://github.com/cucumber/cucumber-js/blob/main/src/runtime/test_case_runner.ts#L299
*/
async invoke(stepText, // step text without keyword
argument, providedFixtures) {
this.bddContext.stepIndex++;
this.bddContext.step.title = stepText;
const stepTextWithKeyword = this.getBddStepData().textWithKeyword;
const matchedDefinition = this.findStepDefinition(stepText, stepTextWithKeyword);
// Get location of step call in generated test file.
// This call must be exactly here to have correct call stack (before async calls)
const location = (0, getLocationInFile_1.getLocationInFile)(this.bddContext.testInfo.file);
const stepParameters = await this.getStepParameters(matchedDefinition, stepText, argument || undefined);
const stepHookFixtures = this.getStepHookFixtures(providedFixtures || {});
const stepFixtures = this.getStepFixtures(providedFixtures || {});
await (0, runStepWithLocation_1.runStepWithLocation)(this.bddContext.test, stepTextWithKeyword, location, async () => {
// Although pw-style does not expect usage of world / this in steps,
// some projects request it for better migration process from cucumber.
// Here, for pw-style we pass empty object as world.
// See: https://github.com/vitalets/playwright-bdd/issues/208
await this.runBeforeStepHooks(stepHookFixtures);
const result = await matchedDefinition.definition.fn.call(this.world, stepFixtures, ...stepParameters);
await this.runAfterStepHooks(stepHookFixtures);
return result;
});
}
async runBeforeStepHooks(stepHookFixtures) {
const beforeHooksToRun = (0, step_1.getStepHooksToRun)('beforeStep', this.bddContext.tags);
await (0, step_1.runStepHooks)(beforeHooksToRun, this.world, stepHookFixtures);
}
async runAfterStepHooks(stepHookFixtures) {
const afterHooksToRun = (0, step_1.getStepHooksToRun)('afterStep', this.bddContext.tags);
afterHooksToRun.reverse();
await (0, step_1.runStepHooks)(afterHooksToRun, this.world, stepHookFixtures);
}
findStepDefinition(stepText, stepTextWithKeyword) {
const { keywordType, gherkinStepLine } = this.getBddStepData();
const stepDefinitions = this.stepFinder.findDefinitions(keywordType, stepText, this.bddContext.tags);
const firstFoundDefinition = stepDefinitions[0];
if (firstFoundDefinition && stepDefinitions.length === 1)
return firstFoundDefinition;
const fullStepLocation = `${this.bddContext.featureUri}:${gherkinStepLine}`;
if (stepDefinitions.length === 0) {
// todo: better error?
throw new Error(`Missing step: ${stepTextWithKeyword}`);
}
const message = (0, finder_1.formatDuplicateStepsMessage)(stepDefinitions, stepTextWithKeyword, fullStepLocation);
throw new Error(message);
}
async getStepParameters(matchedDefinition, world, argument) {
const parameters = await matchedDefinition.getMatchedParameters(world);
if (argument?.dataTable) {
parameters.push(new DataTable_1.DataTable(argument.dataTable));
}
else if (argument?.docString) {
parameters.push(argument.docString.content);
}
// todo: handle invalid code length
// see: https://github.com/cucumber/cucumber-js/blob/main/src/models/step_definition.ts#L25
return parameters;
}
getStepFixtures(providedFixtures) {
const { pomFixtureName } = this.getBddStepData();
if (pomFixtureName) {
// for decorator steps keep only one fixture - POM instance.
const pomFixture = providedFixtures[pomFixtureName];
if (!pomFixture)
throw new Error(`POM fixture not provided: ${pomFixtureName}`);
providedFixtures = { [pomFixtureName]: pomFixture };
}
return Object.assign({}, providedFixtures, (0, bddTestFixturesAuto_1.getBddAutoInjectFixtures)(this.bddContext));
}
getStepHookFixtures(providedFixtures) {
return Object.assign({}, providedFixtures, (0, bddTestFixturesAuto_1.getBddAutoInjectFixtures)(this.bddContext));
}
getBddStepData() {
const { stepIndex, bddTestData } = this.bddContext;
const bddStepData = bddTestData.steps[stepIndex];
if (!bddStepData) {
throw new Error([
`bddStepData not found for step index: ${stepIndex}.`,
`Steps: ${JSON.stringify(bddTestData.steps)}`,
].join(' '));
}
return bddStepData;
}
}
exports.BddStepInvoker = BddStepInvoker;
//# sourceMappingURL=bddStepInvoker.js.map