Skip to content

Commit 5a28f9e

Browse files
authored
feat: Don't ignore skipped features and scenarios when generating the cucumber.json files
* Don't ignore skipped features and scenarios when generating the cucumber.json files * add comment to pending -> skipped in onFail handler closes #288
1 parent 8fe016d commit 5a28f9e

File tree

4 files changed

+86
-71
lines changed

4 files changed

+86
-71
lines changed

lib/createTestFromScenario.js

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,42 @@ const runTest = (scenario, stepsToRun, rowData) => {
3333
Object.assign({}, step, { index })
3434
);
3535

36-
// eslint-disable-next-line func-names
37-
it(scenario.name, function() {
38-
const state = window.testState;
39-
return cy
40-
.then(() => state.onStartScenario(scenario, indexedSteps))
41-
.then(() =>
42-
resolveAndRunBeforeHooks.call(this, scenario.tags, state.feature.name)
43-
)
44-
.then(() =>
45-
indexedSteps.forEach(step => stepTest.call(this, state, step, rowData))
46-
)
47-
.then(() =>
48-
resolveAndRunAfterHooks.call(this, scenario.tags, state.feature.name)
49-
)
50-
.then(() => state.onFinishScenario(scenario));
51-
});
36+
// should we actually run this scenario
37+
// or just mark it as skipped
38+
if (scenario.shouldRun) {
39+
// eslint-disable-next-line func-names
40+
it(scenario.name, function() {
41+
const state = window.testState;
42+
return cy
43+
.then(() => state.onStartScenario(scenario, indexedSteps))
44+
.then(() =>
45+
resolveAndRunBeforeHooks.call(this, scenario.tags, state.feature.name)
46+
)
47+
.then(() =>
48+
indexedSteps.forEach(step =>
49+
stepTest.call(this, state, step, rowData)
50+
)
51+
)
52+
.then(() =>
53+
resolveAndRunAfterHooks.call(this, scenario.tags, state.feature.name)
54+
)
55+
.then(() => state.onFinishScenario(scenario));
56+
});
57+
} else {
58+
// eslint-disable-next-line func-names,prefer-arrow-callback
59+
it(scenario.name, function() {
60+
// register this scenario with the cucumber data collector
61+
// but don't run it
62+
// Tell mocha this is a skipped test so it also shows correctly in Cypress
63+
const state = window.testState;
64+
cy.then(() => state.onStartScenario(scenario, indexedSteps))
65+
.then(() => state.onFinishScenario(scenario))
66+
// eslint-disable-next-line func-names
67+
.then(function() {
68+
return this.skip();
69+
});
70+
});
71+
}
5272
};
5373

5474
const cleanupFilename = s => s.split(".")[0];
@@ -64,7 +84,7 @@ const writeCucumberJsonFile = json => {
6484
};
6585

6686
const createTestFromScenarios = (
67-
scenariosToRun,
87+
allScenarios,
6888
backgroundSection,
6989
testState
7090
) => {
@@ -87,7 +107,7 @@ const createTestFromScenarios = (
87107
Cypress.on("fail", failHandler);
88108
});
89109

90-
scenariosToRun.forEach(section => {
110+
allScenarios.forEach(section => {
91111
if (section.examples) {
92112
section.examples.forEach(example => {
93113
const exampleValues = [];

lib/createTestsFromFeature.js

Lines changed: 27 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,58 +6,37 @@ const createTestsFromFeature = (filePath, spec) => {
66
const testState = new CucumberDataCollector(filePath, spec);
77
const featureTags = testState.feature.tags;
88
const hasEnvTags = !!getEnvTags();
9-
const sectionsWithTags = testState.feature.children.filter(
10-
section => section.tags && section.tags.length
9+
const anyFocused =
10+
testState.feature.children.filter(
11+
section => section.tags && section.tags.find(t => t.name === "@focus")
12+
).length > 0;
13+
const backgroundSection = testState.feature.children.find(
14+
section => section.type === "Background"
15+
);
16+
const allScenarios = testState.feature.children.filter(
17+
section => section.type !== "Background"
1118
);
1219

13-
const sectionsWithTagsExist = sectionsWithTags.length > 0;
14-
15-
let everythingShouldRun = false;
16-
let featureShouldRun = false;
17-
let taggedScenarioShouldRun = false;
18-
let anyFocused = false;
19-
if (hasEnvTags) {
20-
featureShouldRun = shouldProceedCurrentStep(featureTags);
21-
taggedScenarioShouldRun = testState.feature.children.some(
22-
section =>
23-
section.tags &&
24-
section.tags.length &&
25-
shouldProceedCurrentStep(section.tags.concat(featureTags))
26-
);
27-
} else if (!sectionsWithTagsExist) {
28-
everythingShouldRun = true;
29-
} else {
30-
anyFocused = sectionsWithTags.some(section =>
31-
section.tags.find(t => t.name === "@focus")
32-
);
33-
if (anyFocused) {
34-
taggedScenarioShouldRun = true;
20+
const scenariosToRun = allScenarios.filter(section => {
21+
let shouldRun;
22+
// only just run focused if no env tags set
23+
// https://github.com/TheBrainFamily/cypress-cucumber-example#smart-tagging
24+
if (!hasEnvTags && anyFocused) {
25+
shouldRun = section.tags.find(t => t.name === "@focus");
3526
} else {
36-
everythingShouldRun = true;
27+
shouldRun =
28+
!hasEnvTags ||
29+
shouldProceedCurrentStep(section.tags.concat(featureTags)); // Concat handles inheritance of tags from feature
3730
}
38-
}
39-
40-
// eslint-disable-next-line prefer-arrow-callback
41-
if (everythingShouldRun || featureShouldRun || taggedScenarioShouldRun) {
42-
const backgroundSection = testState.feature.children.find(
43-
section => section.type === "Background"
44-
);
45-
const otherSections = testState.feature.children.filter(
46-
section => section.type !== "Background"
47-
);
48-
const scenariosToRun = otherSections.filter(section => {
49-
let shouldRun;
50-
if (anyFocused) {
51-
shouldRun = section.tags.find(t => t.name === "@focus");
52-
} else {
53-
shouldRun =
54-
everythingShouldRun ||
55-
shouldProceedCurrentStep(section.tags.concat(featureTags)); // Concat handles inheritance of tags from feature
56-
}
57-
return shouldRun;
58-
});
59-
createTestFromScenarios(scenariosToRun, backgroundSection, testState);
60-
}
31+
return shouldRun;
32+
});
33+
// create tests for all the scenarios
34+
// but flag only the ones that should be run
35+
scenariosToRun.forEach(section => {
36+
// eslint-disable-next-line no-param-reassign
37+
section.shouldRun = true;
38+
});
39+
createTestFromScenarios(allScenarios, backgroundSection, testState);
6140
};
6241

6342
module.exports = {

lib/cukejson/cucumberDataCollector.js

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,14 @@ class CucumberDataCollector {
7272
status: statuses.UNDEFINED,
7373
duration: this.timeTaken()
7474
};
75+
} else if (err.constructor.name === "Pending") {
76+
// cypress marks skipped mocha tests as pending
77+
// https://github.com/cypress-io/cypress/issues/3092
78+
// don't record this error and mark the step as skipped
79+
this.stepResults[this.currentStep] = {
80+
status: statuses.SKIPPED,
81+
duration: this.timeTaken()
82+
};
7583
} else {
7684
this.stepResults[this.currentStep] = {
7785
status: statuses.FAILED,
@@ -122,9 +130,13 @@ class CucumberDataCollector {
122130
});
123131
};
124132
this.recordScenarioResult = scenario => {
125-
this.runTests[scenario.name].result = this.anyStepsHaveFailed(scenario)
126-
? statuses.FAILED
127-
: statuses.PASSED;
133+
const allSkipped = this.areAllStepsSkipped(scenario.name);
134+
const anyFailed = this.anyStepsHaveFailed(scenario.name);
135+
if (allSkipped) this.runTests[scenario.name].result = statuses.SKIPPED;
136+
else
137+
this.runTests[scenario.name].result = anyFailed
138+
? statuses.FAILED
139+
: statuses.PASSED;
128140
};
129141

130142
this.setStepToPending = step => {
@@ -138,8 +150,11 @@ class CucumberDataCollector {
138150
};
139151
};
140152

141-
this.anyStepsHaveFailed = () =>
142-
Object.values(this.stepResults).find(e => e.status !== statuses.PASSED);
153+
this.areAllStepsSkipped = name =>
154+
this.runTests[name].every(e => e.status === statuses.SKIPPED);
155+
156+
this.anyStepsHaveFailed = name =>
157+
this.runTests[name].find(e => e.status === statuses.FAILED) !== undefined;
143158
}
144159
}
145160

lib/testHelpers/setupTestFramework.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ global.expect = require("chai").expect;
33

44
global.before = jest.fn();
55
global.after = jest.fn();
6+
global.skip = jest.fn();
67

78
window.Cypress = {
89
env: jest.fn(),

0 commit comments

Comments
 (0)