Skip to content

Commit

Permalink
feat: cleanup and improvement for the significantly faster testrun fo…
Browse files Browse the repository at this point in the history
…r all tests

closes #189
  • Loading branch information
lgandecki committed Aug 24, 2019
1 parent 3bd07a5 commit 217b9be
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 67 deletions.
3 changes: 3 additions & 0 deletions circle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ jobs:
- run:
name: run tests
command: npm test
- run:
name: slow test run, for sanity
command: npm run test:each
- run:
name: release
command: npm run semantic-release || true
Empty file.
6 changes: 3 additions & 3 deletions cypress/integration/AndAndButSteps.feature
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
Feature: Using And and but
Scenario: With an And everything is find
Feature: Using And and But
Scenario: With an And everything is fine
Given I do something
And Something else
Then I happily work

Scenario: With a But also the step definition
Scenario: With a But
Given I dont do something
And it is sunday
Then I stream on twitch
Expand Down
5 changes: 0 additions & 5 deletions cypress/integration/UsingAnd.feature

This file was deleted.

15 changes: 0 additions & 15 deletions cypress/support/step_definitions/usingAnd.js

This file was deleted.

24 changes: 24 additions & 0 deletions lib/cucumberTemplate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
exports.cucumberTemplate = `
const {
resolveAndRunStepDefinition,
defineParameterType,
given,
when,
then,
and,
but,
Before,
After,
defineStep
} = require("cypress-cucumber-preprocessor/lib/resolveStepDefinition");
const Given = (window.Given = window.given = given);
const When = (window.When = window.when = when);
const Then = (window.Then = window.then = then);
const And = (window.And = window.and = and);
const But = (window.But = window.but = but);
window.defineParameterType = defineParameterType;
window.defineStep = defineStep;
const {
createTestsFromFeature
} = require("cypress-cucumber-preprocessor/lib/createTestsFromFeature");
`;
52 changes: 33 additions & 19 deletions lib/featuresLoader.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
/* eslint-disable no-eval */
const glob = require("glob");
const path = require("path");
const fs = require("fs");
const { Parser } = require("gherkin");
const log = require("debug")("cypress:cucumber");

const { getStepDefinitionsPaths } = require("./getStepDefinitionsPaths");
const { cucumberTemplate } = require("./cucumberTemplate");
const { getCucumberJsonConfig } = require("./getCucumberJsonConfig");

// This is the template for the file that we will send back to cypress instead of the text of a
// feature file
const createCucumber = (specs, toRequire) =>
const createCucumber = (specs, toRequire, cucumberJson) =>
`
const {resolveAndRunStepDefinition, defineParameterType, given, when, then, and, but, defineStep} = require('cypress-cucumber-preprocessor/lib/resolveStepDefinition');
const Given = window.Given = window.given = given;
const When = window.When = window.when = when;
const Then = window.Then = window.then = then;
const And = window.And = window.and = and;
const But = window.But = window.but = but;
window.defineParameterType = defineParameterType;
window.defineStep = defineStep;
const { createTestsFromFeature } = require('cypress-cucumber-preprocessor/lib/createTestsFromFeature');
${eval(toRequire).join("\n")}
const {Parser, Compiler} = require('gherkin');
${cucumberTemplate}
window.cucumberJson = ${JSON.stringify(cucumberJson)};
${toRequire.join("\n")}
${specs
.map(spec => `createTestsFromFeature(new Parser().parse(\`${spec}\`))`)
.map(
({ spec, filePath, name }) =>
`
describe(\`${name}\`, function() {
createTestsFromFeature('${filePath}', \`${spec}\`);
})
`
)
.join("\n")}
`;

Expand All @@ -46,9 +49,20 @@ module.exports = function(_, filePath) {
)
];

const specs = features.map(featurePath =>
fs.readFileSync(featurePath).toString()
);
const specs = features
.map(featurePath => ({
spec: fs.readFileSync(featurePath).toString(),
filePath: path.basename(featurePath)
}))
.map(feature =>
Object.assign({}, feature, {
name: new Parser().parse(feature.spec.toString()).feature.name
})
);

return createCucumber(specs, stepDefinitionsToRequire);
return createCucumber(
specs,
stepDefinitionsToRequire,
getCucumberJsonConfig()
);
};
15 changes: 15 additions & 0 deletions lib/getCucumberJsonConfig.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
const cosmiconfig = require("cosmiconfig");
const log = require("debug")("cypress:cucumber");

exports.getCucumberJsonConfig = () => {
const explorer = cosmiconfig("cypress-cucumber-preprocessor", { sync: true });
const loaded = explorer.load();

const cucumberJson =
loaded && loaded.config && loaded.config.cucumberJson
? loaded.config.cucumberJson
: { generate: false };
log("cucumber.json", JSON.stringify(cucumberJson));

return cucumberJson;
};
32 changes: 8 additions & 24 deletions lib/loader.js
Original file line number Diff line number Diff line change
@@ -1,49 +1,33 @@
/* eslint-disable no-eval */
const log = require("debug")("cypress:cucumber");
const path = require("path");
const cosmiconfig = require("cosmiconfig");
const { Parser } = require("gherkin");
const { getStepDefinitionsPaths } = require("./getStepDefinitionsPaths");

const { cucumberTemplate } = require("./cucumberTemplate");
const { getCucumberJsonConfig } = require("./getCucumberJsonConfig");
// This is the template for the file that we will send back to cypress instead of the text of a
// feature file
const createCucumber = (filePath, cucumberJson, spec, toRequire, name) =>
`
const {resolveAndRunStepDefinition, defineParameterType, given, when, then, and, but, Before, After, defineStep} = require('cypress-cucumber-preprocessor/lib/resolveStepDefinition');
const Given = window.Given = window.given = given;
const When = window.When = window.when = when;
const Then = window.Then = window.then = then;
const And = window.And = window.and = and;
const But = window.But = window.but = but;
window.defineParameterType = defineParameterType;
window.defineStep = defineStep;
window.cucumberJson = ${JSON.stringify(cucumberJson)};
const { createTestsFromFeature } = require('cypress-cucumber-preprocessor/lib/createTestsFromFeature');
${cucumberTemplate}
describe(\`${name}\`, function() {
${eval(toRequire).join("\n")}
window.cucumberJson = ${JSON.stringify(cucumberJson)};
describe('${name}', function() {
${toRequire.join("\n")}
createTestsFromFeature('${filePath}', \`${spec}\`);
});
`;

// eslint-disable-next-line func-names
module.exports = function(spec, filePath = this.resourcePath) {
const explorer = cosmiconfig("cypress-cucumber-preprocessor", { sync: true });
const loaded = explorer.load();
const cucumberJson =
loaded && loaded.config && loaded.config.cucumberJson
? loaded.config.cucumberJson
: { generate: false };

log("compiling", spec);
log("cucumber.json", JSON.stringify(cucumberJson));
const stepDefinitionsToRequire = getStepDefinitionsPaths(filePath).map(
sdPath => `require('${sdPath}')`
);

const { name } = new Parser().parse(spec.toString()).feature;
return createCucumber(
path.basename(filePath),
cucumberJson,
getCucumberJsonConfig(),
spec,
stepDefinitionsToRequire,
name
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"description": "Run gherkin-syntaxed specs with cypress.io",
"main": "lib/index.js",
"scripts": {
"test": "eslint . && jest && cypress run",
"test": "eslint . && jest && npm run test:all",
"test:all": "cypress run --spec \"**/*.features\"",
"test:each": "cypress run --spec \"**/*.feature\"",
"test:debug": "jest && DEBUG=cypress:* cypress open\n",
"fixStyle": "eslint . --fix",
"semantic-release": "semantic-release"
Expand Down

0 comments on commit 217b9be

Please sign in to comment.