Skip to content

Commit

Permalink
feat: Don't ignore skipped features and scenarios when generating the…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
jcundill authored Jun 1, 2020
1 parent 8fe016d commit 5a28f9e
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 71 deletions.
56 changes: 38 additions & 18 deletions lib/createTestFromScenario.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,42 @@ const runTest = (scenario, stepsToRun, rowData) => {
Object.assign({}, step, { index })
);

// eslint-disable-next-line func-names
it(scenario.name, function() {
const state = window.testState;
return cy
.then(() => state.onStartScenario(scenario, indexedSteps))
.then(() =>
resolveAndRunBeforeHooks.call(this, scenario.tags, state.feature.name)
)
.then(() =>
indexedSteps.forEach(step => stepTest.call(this, state, step, rowData))
)
.then(() =>
resolveAndRunAfterHooks.call(this, scenario.tags, state.feature.name)
)
.then(() => state.onFinishScenario(scenario));
});
// should we actually run this scenario
// or just mark it as skipped
if (scenario.shouldRun) {
// eslint-disable-next-line func-names
it(scenario.name, function() {
const state = window.testState;
return cy
.then(() => state.onStartScenario(scenario, indexedSteps))
.then(() =>
resolveAndRunBeforeHooks.call(this, scenario.tags, state.feature.name)
)
.then(() =>
indexedSteps.forEach(step =>
stepTest.call(this, state, step, rowData)
)
)
.then(() =>
resolveAndRunAfterHooks.call(this, scenario.tags, state.feature.name)
)
.then(() => state.onFinishScenario(scenario));
});
} else {
// eslint-disable-next-line func-names,prefer-arrow-callback
it(scenario.name, function() {
// register this scenario with the cucumber data collector
// but don't run it
// Tell mocha this is a skipped test so it also shows correctly in Cypress
const state = window.testState;
cy.then(() => state.onStartScenario(scenario, indexedSteps))
.then(() => state.onFinishScenario(scenario))
// eslint-disable-next-line func-names
.then(function() {
return this.skip();
});
});
}
};

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

const createTestFromScenarios = (
scenariosToRun,
allScenarios,
backgroundSection,
testState
) => {
Expand All @@ -87,7 +107,7 @@ const createTestFromScenarios = (
Cypress.on("fail", failHandler);
});

scenariosToRun.forEach(section => {
allScenarios.forEach(section => {
if (section.examples) {
section.examples.forEach(example => {
const exampleValues = [];
Expand Down
75 changes: 27 additions & 48 deletions lib/createTestsFromFeature.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,58 +6,37 @@ const createTestsFromFeature = (filePath, spec) => {
const testState = new CucumberDataCollector(filePath, spec);
const featureTags = testState.feature.tags;
const hasEnvTags = !!getEnvTags();
const sectionsWithTags = testState.feature.children.filter(
section => section.tags && section.tags.length
const anyFocused =
testState.feature.children.filter(
section => section.tags && section.tags.find(t => t.name === "@focus")
).length > 0;
const backgroundSection = testState.feature.children.find(
section => section.type === "Background"
);
const allScenarios = testState.feature.children.filter(
section => section.type !== "Background"
);

const sectionsWithTagsExist = sectionsWithTags.length > 0;

let everythingShouldRun = false;
let featureShouldRun = false;
let taggedScenarioShouldRun = false;
let anyFocused = false;
if (hasEnvTags) {
featureShouldRun = shouldProceedCurrentStep(featureTags);
taggedScenarioShouldRun = testState.feature.children.some(
section =>
section.tags &&
section.tags.length &&
shouldProceedCurrentStep(section.tags.concat(featureTags))
);
} else if (!sectionsWithTagsExist) {
everythingShouldRun = true;
} else {
anyFocused = sectionsWithTags.some(section =>
section.tags.find(t => t.name === "@focus")
);
if (anyFocused) {
taggedScenarioShouldRun = true;
const scenariosToRun = allScenarios.filter(section => {
let shouldRun;
// only just run focused if no env tags set
// https:/TheBrainFamily/cypress-cucumber-example#smart-tagging
if (!hasEnvTags && anyFocused) {
shouldRun = section.tags.find(t => t.name === "@focus");
} else {
everythingShouldRun = true;
shouldRun =
!hasEnvTags ||
shouldProceedCurrentStep(section.tags.concat(featureTags)); // Concat handles inheritance of tags from feature
}
}

// eslint-disable-next-line prefer-arrow-callback
if (everythingShouldRun || featureShouldRun || taggedScenarioShouldRun) {
const backgroundSection = testState.feature.children.find(
section => section.type === "Background"
);
const otherSections = testState.feature.children.filter(
section => section.type !== "Background"
);
const scenariosToRun = otherSections.filter(section => {
let shouldRun;
if (anyFocused) {
shouldRun = section.tags.find(t => t.name === "@focus");
} else {
shouldRun =
everythingShouldRun ||
shouldProceedCurrentStep(section.tags.concat(featureTags)); // Concat handles inheritance of tags from feature
}
return shouldRun;
});
createTestFromScenarios(scenariosToRun, backgroundSection, testState);
}
return shouldRun;
});
// create tests for all the scenarios
// but flag only the ones that should be run
scenariosToRun.forEach(section => {
// eslint-disable-next-line no-param-reassign
section.shouldRun = true;
});
createTestFromScenarios(allScenarios, backgroundSection, testState);
};

module.exports = {
Expand Down
25 changes: 20 additions & 5 deletions lib/cukejson/cucumberDataCollector.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ class CucumberDataCollector {
status: statuses.UNDEFINED,
duration: this.timeTaken()
};
} else if (err.constructor.name === "Pending") {
// cypress marks skipped mocha tests as pending
// https:/cypress-io/cypress/issues/3092
// don't record this error and mark the step as skipped
this.stepResults[this.currentStep] = {
status: statuses.SKIPPED,
duration: this.timeTaken()
};
} else {
this.stepResults[this.currentStep] = {
status: statuses.FAILED,
Expand Down Expand Up @@ -122,9 +130,13 @@ class CucumberDataCollector {
});
};
this.recordScenarioResult = scenario => {
this.runTests[scenario.name].result = this.anyStepsHaveFailed(scenario)
? statuses.FAILED
: statuses.PASSED;
const allSkipped = this.areAllStepsSkipped(scenario.name);
const anyFailed = this.anyStepsHaveFailed(scenario.name);
if (allSkipped) this.runTests[scenario.name].result = statuses.SKIPPED;
else
this.runTests[scenario.name].result = anyFailed
? statuses.FAILED
: statuses.PASSED;
};

this.setStepToPending = step => {
Expand All @@ -138,8 +150,11 @@ class CucumberDataCollector {
};
};

this.anyStepsHaveFailed = () =>
Object.values(this.stepResults).find(e => e.status !== statuses.PASSED);
this.areAllStepsSkipped = name =>
this.runTests[name].every(e => e.status === statuses.SKIPPED);

this.anyStepsHaveFailed = name =>
this.runTests[name].find(e => e.status === statuses.FAILED) !== undefined;
}
}

Expand Down
1 change: 1 addition & 0 deletions lib/testHelpers/setupTestFramework.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ global.expect = require("chai").expect;

global.before = jest.fn();
global.after = jest.fn();
global.skip = jest.fn();

window.Cypress = {
env: jest.fn(),
Expand Down

0 comments on commit 5a28f9e

Please sign in to comment.