Skip to content

Commit ba4dc23

Browse files
committed
Adding BeforeAll and AfterAll hooks
1 parent ad66c3d commit ba4dc23

File tree

7 files changed

+141
-13
lines changed

7 files changed

+141
-13
lines changed

features/issues/758.feature

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,30 @@
11
# https://github.com/badeball/cypress-cucumber-preprocessor/issues/758
22

3-
Feature: visualizing hook with filter
4-
Scenario: visualizing hook with filter
3+
Feature: beforeAll and afterAll hooks
4+
@fav
5+
Scenario: beforeAll and afterAll hooks
56
Given a file named "cypress/e2e/a.feature" with:
67
"""
7-
@foo
88
Feature: a feature x
9-
Scenario: a scenario a
9+
Scenario: a scenario b
1010
Given a step
1111
12-
Feature: a feature x
13-
Scenario: a scenario b
14-
Given a step
12+
@foo
13+
Scenario: a scenario c
14+
Given a step
1515
"""
1616
And a file named "cypress/support/step_definitions/steps.js" with:
1717
"""
1818
const { BeforeAll, AfterAll, Given } = require("@badeball/cypress-cucumber-preprocessor");
19-
BeforeAll(() => {})
19+
let counter = 0
20+
BeforeAll(() => {
21+
expect(counter++, "Expect counter to be 0").to.equal(0)
22+
})
2023
Given("a step", function() {
2124
})
22-
AfterAll(() => {})
25+
AfterAll(() => {
26+
expect(counter++, "Expect counter to be 1").to.equal(1)
27+
})
2328
"""
2429
When I run cypress
2530
Then it passes

lib/browser-runtime.ts

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import DataTable from "./data_table";
1818

1919
import {
2020
assignRegistry,
21-
freeRegistry,
21+
freeRegistry, getRegistry,
2222
IHook,
2323
MissingDefinitionError,
2424
Registry,
@@ -268,12 +268,17 @@ function createFeature(context: CompositionContext, feature: messages.Feature) {
268268
describe(feature.name || "<unamed feature>", () => {
269269
before(function () {
270270
beforeHandler.call(this, context);
271+
beforeAllHandler.call(this, context);
271272
});
272273

273274
beforeEach(function () {
274275
beforeEachHandler.call(this, context);
275276
});
276277

278+
after(function () {
279+
afterAllHandler.call(this, context);
280+
});
281+
277282
afterEach(function () {
278283
afterEachHandler.call(this, context);
279284
});
@@ -715,6 +720,31 @@ function beforeHandler(context: CompositionContext) {
715720
taskSpecEnvelopes(context);
716721
}
717722

723+
function beforeAllHandler(this: Mocha.Context, context: CompositionContext) {
724+
const { registry } = context;
725+
let beforeAllHooks = registry.resolveBeforeAllHooks();
726+
for(const beforeAllHook of beforeAllHooks) {
727+
if (beforeAllHook) {
728+
const hook = beforeAllHook;
729+
cy.then(() => {
730+
const start = createTimestamp();
731+
return cy.wrap(start, { log: false });
732+
})
733+
.then((start) => {
734+
runStepWithLogGroup({
735+
fn: () => registry.runHook(this, hook),
736+
keyword: "BeforeAll"
737+
});
738+
739+
return cy.wrap(start, { log: false });
740+
})
741+
.then((start) => {
742+
const end = createTimestamp();
743+
});
744+
}
745+
}
746+
}
747+
718748
function beforeEachHandler(context: CompositionContext) {
719749
assignRegistry(context.registry);
720750
}
@@ -946,6 +976,30 @@ function afterEachHandler(this: Mocha.Context, context: CompositionContext) {
946976
});
947977
}
948978

979+
function afterAllHandler(this: Mocha.Context, context: CompositionContext) {
980+
const { registry } = context;
981+
let afterAllHooks = registry.resolveAfterAllHooks();
982+
for(const afterAllHook of afterAllHooks) {
983+
if (afterAllHook) {
984+
const hook = afterAllHook;
985+
cy.then(() => {
986+
const start = createTimestamp();
987+
return cy.wrap(start, { log: false });
988+
})
989+
.then((start) => {
990+
runStepWithLogGroup({
991+
fn: () => registry.runHook(this, hook),
992+
keyword: "AfterAll"
993+
});
994+
995+
return cy.wrap(start, { log: false });
996+
})
997+
.then((start) => {
998+
const end = createTimestamp();
999+
});
1000+
}
1001+
}
1002+
}
9491003
export default function createTests(
9501004
registry: Registry,
9511005
seed: number,
@@ -999,7 +1053,8 @@ export default function createTests(
9991053
const tags = collectTagNames(pickle.tags);
10001054
const beforeHooks = registry.resolveBeforeHooks(tags);
10011055
const afterHooks = registry.resolveAfterHooks(tags);
1002-
1056+
const beforeAllHooks = registry.resolveBeforeAllHooks();
1057+
const afterAllHooks = registry.resolveAfterAllHooks();
10031058
const hooksToStep = (hook: IHook): messages.TestStep => {
10041059
return {
10051060
id: createTestStepId({
@@ -1035,9 +1090,11 @@ export default function createTests(
10351090
id: pickle.id,
10361091
pickleId: pickle.id,
10371092
testSteps: [
1093+
...beforeAllHooks.map(hooksToStep),
10381094
...beforeHooks.map(hooksToStep),
10391095
...pickle.steps.map(pickleStepToTestStep),
10401096
...afterHooks.map(hooksToStep),
1097+
...afterAllHooks.map(hooksToStep)
10411098
],
10421099
};
10431100
});

lib/entrypoint-browser.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,28 @@ function defineAfterStep(
126126
}
127127
}
128128

129+
function defineBeforeAll(fn: IHookBody): void;
130+
function defineBeforeAll(
131+
maybeFn?: IHookBody
132+
) {
133+
if (typeof maybeFn === "function") {
134+
getRegistry().defineBeforeAll(maybeFn);
135+
} else {
136+
throw new Error("Unexpected argument for BeforeAll hook");
137+
}
138+
}
139+
140+
function defineAfterAll(fn: IHookBody): void;
141+
function defineAfterAll(
142+
maybeFn?: IHookBody
143+
) {
144+
if (typeof maybeFn === "function") {
145+
getRegistry().defineAfterAll(maybeFn);
146+
} else {
147+
throw new Error("Unexpected argument for AfterAll hook");
148+
}
149+
}
150+
129151
function createStringAttachment(
130152
data: string,
131153
mediaType: string,
@@ -205,6 +227,8 @@ export {
205227
defineAfter as After,
206228
defineBeforeStep as BeforeStep,
207229
defineAfterStep as AfterStep,
230+
defineBeforeAll as BeforeAll,
231+
defineAfterAll as AfterAll
208232
};
209233

210234
/**

lib/entrypoint-node.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,20 @@ export function AfterStep(
118118
throw createUnimplemented();
119119
}
120120

121+
export function BeforeAll(fn: IStepHookBody): void;
122+
export function BeforeAll(
123+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
124+
maybeFn?: IStepHookBody
125+
) {
126+
throw createUnimplemented();
127+
}
128+
129+
export function AfterAll(fn: IStepHookBody): void;
130+
export function AfterAll(
131+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
132+
maybeFn?: IStepHookBody
133+
) {
134+
throw createUnimplemented();
135+
}
136+
121137
export { default as DataTable } from "./data_table";

lib/registry.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ export class MissingDefinitionError extends CypressCucumberError {}
4040

4141
export class MultipleDefinitionsError extends CypressCucumberError {}
4242

43-
export type ScenarioHookKeyword = "Before" | "After";
43+
export type ScenarioHookKeyword = "Before" | "After" | "BeforeAll" | "AfterAll";
4444

4545
export type StepHookKeyword = "BeforeStep" | "AfterStep";
4646

@@ -97,7 +97,6 @@ export class Registry {
9797
this.runStepDefininition = this.runStepDefininition.bind(this);
9898
this.defineParameterType = this.defineParameterType.bind(this);
9999
this.defineBefore = this.defineBefore.bind(this);
100-
this.defineAfter = this.defineAfter.bind(this);
101100

102101
this.parameterTypeRegistry = new ParameterTypeRegistry();
103102
}
@@ -204,6 +203,14 @@ export class Registry {
204203
this.defineStepHook("AfterStep", options, fn);
205204
}
206205

206+
public defineBeforeAll(fn: IHookBody) {
207+
this.defineHook("BeforeAll", {}, fn);
208+
}
209+
210+
public defineAfterAll(fn: IHookBody) {
211+
this.defineHook("AfterAll", {}, fn);
212+
}
213+
207214
public getMatchingStepDefinitions(text: string) {
208215
return this.stepDefinitions.filter((stepDefinition) =>
209216
stepDefinition.expression.match(text)
@@ -293,6 +300,13 @@ export class Registry {
293300
return this.resolveStepHooks("AfterStep", tags);
294301
}
295302

303+
public resolveBeforeAllHooks() {
304+
return this.resolveHooks("BeforeAll", []);
305+
}
306+
307+
public resolveAfterAllHooks() {
308+
return this.resolveHooks("AfterAll", []);
309+
}
296310
public runStepHook(
297311
world: Mocha.Context,
298312
hook: IStepHook,

test-d/entrypoint-browser.test-d.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import {
2525
After,
2626
BeforeStep,
2727
AfterStep,
28+
BeforeAll,
29+
AfterAll,
2830
DataTable,
2931
} from "../lib/entrypoint-browser";
3032

@@ -138,6 +140,10 @@ defineParameterType({
138140
},
139141
});
140142

143+
BeforeAll(function () {
144+
expectType<Mocha.Context>(this);
145+
});
146+
141147
Before(function () {
142148
expectType<Mocha.Context>(this);
143149
});
@@ -162,6 +168,10 @@ After({ tags: "foo" }, function () {
162168
expectType<Mocha.Context>(this);
163169
});
164170

171+
AfterAll(function () {
172+
expectType<Mocha.Context>(this);
173+
});
174+
165175
BeforeStep(function ({
166176
pickle,
167177
pickleStep,

test-d/entrypoint-node.test-d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import {
2525
After,
2626
BeforeStep,
2727
AfterStep,
28+
BeforeAll,
29+
AfterAll,
2830
DataTable,
2931
} from "../lib/entrypoint-node";
3032

0 commit comments

Comments
 (0)