Skip to content

Commit 8859d0c

Browse files
committed
Create testRunStarted before all, not each
Similarly with testRunFinished. I was a bit too quick in b3bfdea. This fixes #813.
1 parent 905c229 commit 8859d0c

File tree

8 files changed

+146
-51
lines changed

8 files changed

+146
-51
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## Unreleased
6+
7+
- Total execution time is correctly shown in HTML reports, fixes [#813](https://github.com/badeball/cypress-cucumber-preprocessor/issues/813).
8+
59
## v12.1.0
610

711
- Start time and execution time is shown in HTML reports, fixes [#798](https://github.com/badeball/cypress-cucumber-preprocessor/issues/798).

features/issues/813.feature

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# https://github.com/badeball/cypress-cucumber-preprocessor/issues/813
2+
3+
Feature: messages report
4+
Scenario: it should only ever contain one 'testRunStarted' and 'testRunFinished'
5+
Given additional preprocessor configuration
6+
"""
7+
{
8+
"messages": {
9+
"enabled": true
10+
}
11+
}
12+
"""
13+
And a file named "cypress/e2e/a.feature" with:
14+
"""
15+
Feature: a feature
16+
Scenario: a scenario
17+
Given a step
18+
"""
19+
And a file named "cypress/e2e/b.feature" with:
20+
"""
21+
Feature: a feature
22+
Scenario: a scenario
23+
Given a step
24+
"""
25+
And a file named "cypress/support/step_definitions/steps.js" with:
26+
"""
27+
const { Given } = require("@badeball/cypress-cucumber-preprocessor");
28+
Given("a step", function() {})
29+
"""
30+
When I run cypress
31+
Then it passes
32+
And the messages should only contain a single "testRunStarted" and a single "testRunFinished"

features/json_report.feature

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,11 @@ Feature: JSON formatter
296296
"""
297297
When I run cypress
298298
Then it fails
299-
And there should be no JSON output
300299
And the output should contain
301300
"""
302301
Hook failures can't be represented in JSON reports, thus none is created for cypress/e2e/a.feature.
303302
"""
303+
And the JSON report shouldn't contain any specs
304304

305305
Scenario: failing beforeEach hook
306306
Given a file named "cypress/e2e/a.feature" with:
@@ -322,11 +322,11 @@ Feature: JSON formatter
322322
"""
323323
When I run cypress
324324
Then it fails
325-
And there should be no JSON output
326325
And the output should contain
327326
"""
328327
Hook failures can't be represented in JSON reports, thus none is created for cypress/e2e/a.feature.
329328
"""
329+
And the JSON report shouldn't contain any specs
330330

331331
Scenario: failing afterEach hook
332332
Given a file named "cypress/e2e/a.feature" with:
@@ -348,11 +348,11 @@ Feature: JSON formatter
348348
"""
349349
When I run cypress
350350
Then it fails
351-
And there should be no JSON output
352351
And the output should contain
353352
"""
354353
Hook failures can't be represented in JSON reports, thus none is created for cypress/e2e/a.feature.
355354
"""
355+
And the JSON report shouldn't contain any specs
356356

357357
Scenario: failing after hook
358358
Given a file named "cypress/e2e/a.feature" with:
@@ -374,8 +374,8 @@ Feature: JSON formatter
374374
"""
375375
When I run cypress
376376
Then it fails
377-
And there should be no JSON output
378377
And the output should contain
379378
"""
380379
Hook failures can't be represented in JSON reports, thus none is created for cypress/e2e/a.feature.
381380
"""
381+
And the JSON report shouldn't contain any specs

features/step_definitions/json_steps.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,3 +169,17 @@ Then(
169169
assert.strictEqual(actualHeight, expectedDimensions.height);
170170
}
171171
);
172+
173+
Then("the JSON report shouldn't contain any specs", async function () {
174+
const absolutejsonPath = path.join(this.tmpDir, "cucumber-report.json");
175+
176+
const jsonFile = await fs.readFile(absolutejsonPath);
177+
178+
const actualJsonOutput = JSON.parse(jsonFile.toString());
179+
180+
if (actualJsonOutput.length > 0) {
181+
throw new Error(
182+
`Expected to find zero specs, but found ${actualJsonOutput.length}`
183+
);
184+
}
185+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { Then } from "@cucumber/cucumber";
2+
import path from "path";
3+
import { promises as fs } from "fs";
4+
5+
Then(
6+
"the messages should only contain a single {string} and a single {string}",
7+
async function (a, b) {
8+
const absoluteMessagesPath = path.join(
9+
this.tmpDir,
10+
"cucumber-messages.ndjson"
11+
);
12+
13+
const messages = (await fs.readFile(absoluteMessagesPath))
14+
.toString()
15+
.trim()
16+
.split("\n")
17+
.map((string) => JSON.parse(string));
18+
19+
const aCount = messages.filter((m) => m[a]).length;
20+
const bCount = messages.filter((m) => m[b]).length;
21+
22+
if (aCount !== 1) {
23+
throw new Error(`Expected to find a single "${a}", but found ${aCount}`);
24+
}
25+
26+
if (bCount !== 1) {
27+
throw new Error(`Expected to find a single "${b}", but found ${bCount}`);
28+
}
29+
}
30+
);

lib/add-cucumber-preprocessor-plugin.ts

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ import { getTags } from "./environment-helpers";
4141

4242
import { ensureIsAbsolute } from "./helpers";
4343

44+
import { createTimestamp } from "./messages-helpers";
45+
4446
/**
4547
* Work-around for the fact that some Cypress versions pre v10 were missing this property in their types.
4648
*/
@@ -84,12 +86,26 @@ export async function beforeRunHandler(config: Cypress.PluginConfigOptions) {
8486
);
8587

8688
await fs.rm(messagesPath, { force: true });
89+
90+
const testRunStarted: messages.Envelope = {
91+
testRunStarted: {
92+
timestamp: createTimestamp(),
93+
},
94+
};
95+
96+
await fs.mkdir(path.dirname(messagesPath), { recursive: true });
97+
98+
await fs.writeFile(messagesPath, JSON.stringify(testRunStarted) + "\n");
8799
}
88100

89101
export async function afterRunHandler(config: Cypress.PluginConfigOptions) {
90102
const preprocessor = await resolve(config, config.env, "/");
91103

92-
if (!preprocessor.json.enabled && !preprocessor.html.enabled) {
104+
if (
105+
!preprocessor.messages.enabled &&
106+
!preprocessor.json.enabled &&
107+
!preprocessor.html.enabled
108+
) {
93109
return;
94110
}
95111

@@ -104,6 +120,22 @@ export async function afterRunHandler(config: Cypress.PluginConfigOptions) {
104120
return;
105121
}
106122

123+
if (preprocessor.messages.enabled) {
124+
const testRunFinished: messages.Envelope = {
125+
testRunFinished: {
126+
/**
127+
* We're missing a "success" attribute here, but cucumber-js doesn't output it, so I won't.
128+
* Mostly because I don't want to look into the semantics of it right now.
129+
*/
130+
timestamp: createTimestamp(),
131+
} as messages.TestRunFinished,
132+
};
133+
134+
await fs.writeFile(messagesPath, JSON.stringify(testRunFinished) + "\n", {
135+
flag: "a",
136+
});
137+
}
138+
107139
if (preprocessor.json.enabled) {
108140
const jsonPath = ensureIsAbsolute(
109141
config.projectRoot,
@@ -213,8 +245,6 @@ export async function afterSpecHandler(
213245
)
214246
);
215247
} else {
216-
await fs.mkdir(path.dirname(messagesPath), { recursive: true });
217-
218248
await fs.writeFile(
219249
messagesPath,
220250
currentSpecMessages.map((message) => JSON.stringify(message)).join("\n") +

lib/create-tests.ts

Lines changed: 2 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import { notNull } from "./type-guards";
3333

3434
import { looksLikeOptions, tagToCypressOptions } from "./tag-parser";
3535

36+
import { createTimestamp, duration } from "./messages-helpers";
37+
3638
declare global {
3739
namespace globalThis {
3840
var __cypress_cucumber_preprocessor_dont_use_this: true | undefined;
@@ -115,34 +117,6 @@ function collectExampleIds(examples: readonly messages.Examples[]) {
115117
.reduce((acum, el) => acum.concat(el), []);
116118
}
117119

118-
type StrictTimestamp = {
119-
seconds: number;
120-
nanos: number;
121-
};
122-
123-
function createTimestamp(): StrictTimestamp {
124-
const now = new Date().getTime();
125-
126-
const seconds = Math.floor(now / 1000);
127-
128-
const nanos = (now - seconds * 1000) * 1000000;
129-
130-
return {
131-
seconds,
132-
nanos,
133-
};
134-
}
135-
136-
function duration(
137-
start: StrictTimestamp,
138-
end: StrictTimestamp
139-
): StrictTimestamp {
140-
return {
141-
seconds: end.seconds - start.seconds,
142-
nanos: end.nanos - start.nanos,
143-
};
144-
}
145-
146120
function minIndent(content: string) {
147121
const match = content.match(/^[ \t]*(?=\S)/gm);
148122

@@ -677,12 +651,6 @@ export default function createTests(
677651
});
678652
}
679653

680-
messages.push({
681-
testRunStarted: {
682-
timestamp: createTimestamp(),
683-
},
684-
});
685-
686654
const tagsInDocument = collectTagNamesFromGherkinDocument(gherkinDocument);
687655

688656
const testFilter =
@@ -836,16 +804,6 @@ export default function createTests(
836804
});
837805

838806
after(function () {
839-
messages.push({
840-
testRunFinished: {
841-
/**
842-
* We're missing a "success" attribute here, but cucumber-js doesn't output it, so I won't.
843-
* Mostly because I don't want to look into the semantics of it right now.
844-
*/
845-
timestamp: createTimestamp(),
846-
} as messages.TestRunFinished,
847-
});
848-
849807
if (messagesEnabled) {
850808
cy.task(TASK_APPEND_MESSAGES, messages, { log: false });
851809
}

lib/messages-helpers.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
export type StrictTimestamp = {
2+
seconds: number;
3+
nanos: number;
4+
};
5+
6+
export function createTimestamp(): StrictTimestamp {
7+
const now = new Date().getTime();
8+
9+
const seconds = Math.floor(now / 1000);
10+
11+
const nanos = (now - seconds * 1000) * 1000000;
12+
13+
return {
14+
seconds,
15+
nanos,
16+
};
17+
}
18+
19+
export function duration(
20+
start: StrictTimestamp,
21+
end: StrictTimestamp
22+
): StrictTimestamp {
23+
return {
24+
seconds: end.seconds - start.seconds,
25+
nanos: end.nanos - start.nanos,
26+
};
27+
}

0 commit comments

Comments
 (0)