Skip to content

Commit

Permalink
Invoke scenario hooks with correct options
Browse files Browse the repository at this point in the history
  • Loading branch information
badeball committed Nov 2, 2023
1 parent f17911a commit 9d2da28
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 5 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ Breaking changes:

- String literal attachments are now base64-encoded in JSON reports, ref. [cucumber/cucumber-js#2261](https://github.com/cucumber/cucumber-js/pull/2261).

Other changes:

- Scenario hooks (`Before(..)` and `After(..)`) are now invoked with an object containing a bunch of relevant data. This is in line with how cucumber-js behaves.

## v18.0.6

- Make the compile output play nicer with ESM, relates to [#1093](https://github.com/badeball/cypress-cucumber-preprocessor/issues/1093).
Expand Down
4 changes: 4 additions & 0 deletions docs/cucumber-basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ Before({ tags: "@foo and @bar" }, function () {
Before({ tags: "@foo or @bar" }, function () {
// This hook will be executed before scenarios tagged with @foo or @bar.
});

Before(function ({ pickle, gherkinDocument, testCaseStartedId }) {
// Scenario hooks are invoked with an object containing a bunch of relevant data.
});
```

# Step hooks
Expand Down
87 changes: 87 additions & 0 deletions features/hooks_argument.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
Feature: hooks argument

Rule: some hooks should be invoked with various arguments

Scenario: Before hook
Given a file named "cypress/e2e/a.feature" with:
"""
Feature: a feature name
Scenario: a scenario name
Given a step
"""
And a file named "cypress/support/step_definitions/steps.js" with:
"""
const { When, Before } = require("@badeball/cypress-cucumber-preprocessor");
When("a step", function() {});
Before(function ({ gherkinDocument, pickle, testCaseStartedId }) {
expect(gherkinDocument.feature.name).to.equal("a feature name");
expect(pickle.name).to.equal("a scenario name");
expect(testCaseStartedId).to.be.a("string");
});
"""
When I run cypress
Then it passes

Scenario: After hook
Given a file named "cypress/e2e/a.feature" with:
"""
Feature: a feature name
Scenario: a scenario name
Given a step
"""
And a file named "cypress/support/step_definitions/steps.js" with:
"""
const { When, Before } = require("@badeball/cypress-cucumber-preprocessor");
When("a step", function() {});
Before(function ({ gherkinDocument, pickle, testCaseStartedId, result, willBeRetried }) {
expect(gherkinDocument.feature.name).to.equal("a feature name");
expect(pickle.name).to.equal("a scenario name");
expect(testCaseStartedId).to.be.a("string");
});
"""
When I run cypress
Then it passes

Scenario: BeforeStep hook
Given a file named "cypress/e2e/a.feature" with:
"""
Feature: a feature name
Scenario: a scenario name
Given a step
"""
And a file named "cypress/support/step_definitions/steps.js" with:
"""
const { When, BeforeStep } = require("@badeball/cypress-cucumber-preprocessor");
When("a step", function() {});
BeforeStep(function ({ pickle, pickleStep, gherkinDocument, testCaseStartedId, testStepId }) {
expect(pickle.name).to.equal("a scenario name");
expect(pickleStep.text).to.equal("a step");
expect(gherkinDocument.feature.name).to.equal("a feature name");
expect(testCaseStartedId).to.be.a("string");
expect(testStepId).to.be.a("string");
});
"""
When I run cypress
Then it passes

Scenario: AfterStep hook
Given a file named "cypress/e2e/a.feature" with:
"""
Feature: a feature name
Scenario: a scenario name
Given a step
"""
And a file named "cypress/support/step_definitions/steps.js" with:
"""
const { When, AfterStep } = require("@badeball/cypress-cucumber-preprocessor");
When("a step", function() {});
AfterStep(function ({ pickle, pickleStep, gherkinDocument, testCaseStartedId, testStepId }) {
expect(pickle.name).to.equal("a scenario name");
expect(pickleStep.text).to.equal("a step");
expect(gherkinDocument.feature.name).to.equal("a feature name");
expect(testCaseStartedId).to.be.a("string");
expect(testStepId).to.be.a("string");
});
"""
When I run cypress
Then it passes
10 changes: 8 additions & 2 deletions lib/browser-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ import { runStepWithLogGroup } from "./helpers/cypress";

import { getTags } from "./helpers/environment";

import { IStepHookParameter } from "./public-member-types";
import { IHookParameter, IStepHookParameter } from "./public-member-types";

type Node = ReturnType<typeof parse>;

Expand Down Expand Up @@ -449,8 +449,14 @@ function createPickle(context: CompositionContext, pickle: messages.Pickle) {
return cy.wrap(start, { log: false });
})
.then((start) => {
const options: IHookParameter = {
pickle,
gherkinDocument,
testCaseStartedId,
};

runStepWithLogGroup({
fn: () => registry.runHook(this, hook),
fn: () => registry.runHook(this, hook, options),
keyword: hook.keyword,
text: hook.tags,
});
Expand Down
8 changes: 7 additions & 1 deletion lib/public-member-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ export interface IParameterTypeDefinition<T, C extends Mocha.Context> {
}

export interface IHookBody {
(this: Mocha.Context): void;
(this: Mocha.Context, options: IHookParameter): void;
}

export interface IHookParameter {
pickle: messages.Pickle;
gherkinDocument: messages.GherkinDocument;
testCaseStartedId: string;
}

export interface IStepHookParameter {
Expand Down
5 changes: 3 additions & 2 deletions lib/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
IStepHookParameter,
IParameterTypeDefinition,
IStepDefinitionBody,
IHookParameter,
} from "./public-member-types";

import {
Expand Down Expand Up @@ -275,8 +276,8 @@ export class Registry {
return this.resolveHooks("After", tags).reverse();
}

public runHook(world: Mocha.Context, hook: IHook) {
return hook.implementation.call(world);
public runHook(world: Mocha.Context, hook: IHook, options: IHookParameter) {
return hook.implementation.call(world, options);
}

public resolveStepHooks(keyword: StepHookKeyword, tags: string[]) {
Expand Down

0 comments on commit 9d2da28

Please sign in to comment.