refactor(Cypress): add nodemodules
This commit is contained in:
191
node_modules/cypress-cucumber-preprocessor/lib/createTestFromScenario.js
generated
vendored
Normal file
191
node_modules/cypress-cucumber-preprocessor/lib/createTestFromScenario.js
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
/* eslint-disable prefer-template */
|
||||
const statuses = require("cucumber/lib/status").default;
|
||||
const {
|
||||
resolveStepDefinition,
|
||||
resolveAndRunStepDefinition,
|
||||
resolveAndRunBeforeHooks,
|
||||
resolveAndRunAfterHooks,
|
||||
} = require("./resolveStepDefinition");
|
||||
const { generateCucumberJson } = require("./cukejson/generateCucumberJson");
|
||||
const { shouldProceedCurrentStep, getEnvTags } = require("./tagsHelper");
|
||||
|
||||
const replaceParameterTags = (rowData, text) =>
|
||||
Object.keys(rowData).reduce(
|
||||
(value, key) => value.replace(new RegExp(`<${key}>`, "g"), rowData[key]),
|
||||
text
|
||||
);
|
||||
|
||||
// eslint-disable-next-line func-names
|
||||
const stepTest = function (state, stepDetails, exampleRowData) {
|
||||
const step = resolveStepDefinition.call(
|
||||
this,
|
||||
stepDetails,
|
||||
state.feature.name
|
||||
);
|
||||
cy.then(() => state.onStartStep(stepDetails))
|
||||
.then((step && step.config) || {}, () =>
|
||||
resolveAndRunStepDefinition.call(
|
||||
this,
|
||||
stepDetails,
|
||||
replaceParameterTags,
|
||||
exampleRowData,
|
||||
state.feature.name
|
||||
)
|
||||
)
|
||||
.then(() => state.onFinishStep(stepDetails, statuses.PASSED));
|
||||
};
|
||||
|
||||
const runTest = (scenario, stepsToRun, rowData) => {
|
||||
const indexedSteps = stepsToRun.map((step, index) => ({ ...step, index }));
|
||||
|
||||
// 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(() => 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];
|
||||
|
||||
const writeCucumberJsonFile = (json) => {
|
||||
const outputFolder =
|
||||
window.cucumberJson.outputFolder || "cypress/cucumber-json";
|
||||
const outputPrefix = window.cucumberJson.filePrefix || "";
|
||||
const outputSuffix = window.cucumberJson.fileSuffix || ".cucumber";
|
||||
const fileName = json[0] ? cleanupFilename(json[0].uri) : "empty";
|
||||
const outFile = `${outputFolder}/${outputPrefix}${fileName}${outputSuffix}.json`;
|
||||
cy.writeFile(outFile, json, { log: false });
|
||||
};
|
||||
|
||||
const createTestFromScenarios = (
|
||||
allScenarios,
|
||||
backgroundSection,
|
||||
testState
|
||||
) => {
|
||||
// eslint-disable-next-line func-names, prefer-arrow-callback
|
||||
before(function () {
|
||||
cy.then(() => testState.onStartTest());
|
||||
});
|
||||
|
||||
// ctx is cleared between each 'it'
|
||||
// eslint-disable-next-line func-names, prefer-arrow-callback
|
||||
beforeEach(function () {
|
||||
window.testState = testState;
|
||||
|
||||
const failHandler = (_, err) => {
|
||||
testState.onFail(err);
|
||||
};
|
||||
|
||||
Cypress.mocha.getRunner().on("fail", failHandler);
|
||||
});
|
||||
|
||||
allScenarios.forEach((section) => {
|
||||
if (section.examples) {
|
||||
const hasEnvTags = !!getEnvTags();
|
||||
section.examples.forEach((example) => {
|
||||
const exampleValues = [];
|
||||
const exampleLocations = [];
|
||||
const shouldRunExamples =
|
||||
!hasEnvTags ||
|
||||
shouldProceedCurrentStep(example.tags.concat(section.tags));
|
||||
|
||||
example.tableBody.forEach((row, rowIndex) => {
|
||||
exampleLocations[rowIndex] = row.location;
|
||||
example.tableHeader.cells.forEach((header, headerIndex) => {
|
||||
exampleValues[rowIndex] = {
|
||||
...exampleValues[rowIndex],
|
||||
[header.value]: row.cells[headerIndex].value,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
exampleValues.forEach((rowData, index) => {
|
||||
// eslint-disable-next-line prefer-arrow-callback
|
||||
const scenarioName = replaceParameterTags(rowData, section.name);
|
||||
const uniqueScenarioName = `${scenarioName} (example #${index + 1})`;
|
||||
const exampleSteps = section.steps.map((step) => {
|
||||
const newStep = { ...step };
|
||||
newStep.text = replaceParameterTags(rowData, newStep.text);
|
||||
return newStep;
|
||||
});
|
||||
|
||||
const stepsToRun = backgroundSection
|
||||
? backgroundSection.steps.concat(exampleSteps)
|
||||
: exampleSteps;
|
||||
|
||||
const scenarioExample = {
|
||||
...section,
|
||||
// tags on scenario's should be inherited by examples (https://cucumber.io/docs/cucumber/api/#tags)
|
||||
tags: example.tags.concat(section.tags),
|
||||
shouldRun: shouldRunExamples,
|
||||
name: uniqueScenarioName,
|
||||
example: exampleLocations[index],
|
||||
};
|
||||
|
||||
runTest.call(this, scenarioExample, stepsToRun, rowData);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
const stepsToRun = backgroundSection
|
||||
? backgroundSection.steps.concat(section.steps)
|
||||
: section.steps;
|
||||
|
||||
runTest.call(this, section, stepsToRun);
|
||||
}
|
||||
});
|
||||
|
||||
// eslint-disable-next-line func-names, prefer-arrow-callback
|
||||
after(function () {
|
||||
cy.then(() => testState.onFinishTest()).then(() => {
|
||||
if (window.cucumberJson && window.cucumberJson.generate) {
|
||||
const json = generateCucumberJson(testState);
|
||||
writeCucumberJsonFile(json);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// eslint-disable-next-line func-names, prefer-arrow-callback
|
||||
afterEach(function () {
|
||||
if (testState.currentScenario && testState.currentScenario.shouldRun) {
|
||||
cy.then(() =>
|
||||
resolveAndRunAfterHooks.call(
|
||||
this,
|
||||
testState.currentScenario.tags,
|
||||
testState.feature.name
|
||||
)
|
||||
);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
createTestFromScenarios,
|
||||
};
|
48
node_modules/cypress-cucumber-preprocessor/lib/createTestsFromFeature.js
generated
vendored
Normal file
48
node_modules/cypress-cucumber-preprocessor/lib/createTestsFromFeature.js
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
const { CucumberDataCollector } = require("./cukejson/cucumberDataCollector");
|
||||
const { createTestFromScenarios } = require("./createTestFromScenario");
|
||||
const { shouldProceedCurrentStep, getEnvTags } = require("./tagsHelper");
|
||||
|
||||
const createTestsFromFeature = (filePath, spec) => {
|
||||
const testState = new CucumberDataCollector(filePath, spec);
|
||||
const featureTags = testState.feature.tags;
|
||||
const hasEnvTags = !!getEnvTags();
|
||||
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"
|
||||
);
|
||||
|
||||
// tags on features should be inherited by scenario's (https://cucumber.io/docs/cucumber/api/#tags)
|
||||
allScenarios.forEach((section) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
section.tags = section.tags.concat(featureTags);
|
||||
});
|
||||
|
||||
const scenariosToRun = allScenarios.filter((section) => {
|
||||
let shouldRun;
|
||||
// only just run focused if no env tags set
|
||||
// https://github.com/TheBrainFamily/cypress-cucumber-example#smart-tagging
|
||||
if (!hasEnvTags && anyFocused) {
|
||||
shouldRun = section.tags.find((t) => t.name === "@focus");
|
||||
} else {
|
||||
shouldRun = !hasEnvTags || shouldProceedCurrentStep(section.tags);
|
||||
}
|
||||
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 = {
|
||||
createTestsFromFeature,
|
||||
};
|
36
node_modules/cypress-cucumber-preprocessor/lib/cucumberTemplate.js
generated
vendored
Normal file
36
node_modules/cypress-cucumber-preprocessor/lib/cucumberTemplate.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
const path = require("path");
|
||||
const os = require("os");
|
||||
|
||||
const getPathFor = (file) => {
|
||||
if (os.platform() === "win32") {
|
||||
return path
|
||||
.join(__dirname.replace(/\\/g, "\\\\"), file)
|
||||
.replace(/\\/g, "\\\\");
|
||||
}
|
||||
return `${__dirname}/${file}`;
|
||||
};
|
||||
|
||||
exports.cucumberTemplate = `
|
||||
const {
|
||||
resolveAndRunStepDefinition,
|
||||
defineParameterType,
|
||||
Given,
|
||||
When,
|
||||
Then,
|
||||
And,
|
||||
But,
|
||||
Before,
|
||||
After,
|
||||
defineStep
|
||||
} = require("${getPathFor("resolveStepDefinition")}");
|
||||
window.Given = Given;
|
||||
window.When = When;
|
||||
window.Then = Then;
|
||||
window.And = And;
|
||||
window.But = But;
|
||||
window.defineParameterType = defineParameterType;
|
||||
window.defineStep = defineStep;
|
||||
const {
|
||||
createTestsFromFeature
|
||||
} = require("${getPathFor("createTestsFromFeature")}");
|
||||
`;
|
165
node_modules/cypress-cucumber-preprocessor/lib/cukejson/cucumberDataCollector.js
generated
vendored
Normal file
165
node_modules/cypress-cucumber-preprocessor/lib/cukejson/cucumberDataCollector.js
generated
vendored
Normal file
@@ -0,0 +1,165 @@
|
||||
const { Parser } = require("gherkin");
|
||||
const statuses = require("cucumber/lib/status").default;
|
||||
|
||||
class CucumberDataCollector {
|
||||
constructor(uri, spec) {
|
||||
this.feature = new Parser().parse(spec.toString()).feature;
|
||||
this.scenarioSteps = {};
|
||||
this.runScenarios = {};
|
||||
this.runTests = {};
|
||||
this.stepResults = {};
|
||||
this.testError = null;
|
||||
this.uri = uri;
|
||||
this.spec = spec;
|
||||
|
||||
this.currentScenario = null;
|
||||
this.currentStep = 0;
|
||||
|
||||
this.timer = Date.now();
|
||||
|
||||
this.logStep = (step) => {
|
||||
Cypress.log({
|
||||
name: "step",
|
||||
displayName: step.keyword,
|
||||
message: `**${step.text}**`,
|
||||
consoleProps: () => ({ feature: this.uri, step }),
|
||||
});
|
||||
};
|
||||
|
||||
this.onStartTest = () => {};
|
||||
|
||||
this.onFinishTest = () => {
|
||||
if (this.testError) {
|
||||
this.attachErrorToFailingStep();
|
||||
}
|
||||
};
|
||||
|
||||
this.onStartScenario = (scenario, stepsToRun) => {
|
||||
this.currentScenario = scenario;
|
||||
this.currentStep = 0;
|
||||
this.stepResults = {};
|
||||
this.scenarioSteps[scenario.name] = stepsToRun;
|
||||
this.testError = null;
|
||||
|
||||
stepsToRun.forEach((step) => {
|
||||
this.stepResults[step.index] = { status: statuses.PENDING };
|
||||
});
|
||||
this.runScenarios[scenario.name] = scenario;
|
||||
};
|
||||
|
||||
this.onFinishScenario = (scenario) => {
|
||||
this.markStillPendingStepsAsSkipped(scenario);
|
||||
this.recordScenarioResult(scenario);
|
||||
};
|
||||
|
||||
this.onStartStep = (step) => {
|
||||
this.currentStep = step.index;
|
||||
this.setStepToPending(step);
|
||||
this.logStep(step);
|
||||
};
|
||||
|
||||
this.onFinishStep = (step, result) => {
|
||||
this.recordStepResult(step, result);
|
||||
};
|
||||
|
||||
this.onFail = (err) => {
|
||||
this.testError = err;
|
||||
if (
|
||||
err.message &&
|
||||
err.message.indexOf("Step implementation missing for") > -1
|
||||
) {
|
||||
this.stepResults[this.currentStep] = {
|
||||
status: statuses.UNDEFINED,
|
||||
duration: this.timeTaken(),
|
||||
};
|
||||
} else if (err.constructor.name === "Pending") {
|
||||
// cypress marks skipped mocha tests as pending
|
||||
// https://github.com/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,
|
||||
duration: this.timeTaken(),
|
||||
exception: this.testError,
|
||||
};
|
||||
}
|
||||
this.onFinishScenario(this.currentScenario);
|
||||
};
|
||||
|
||||
this.timeTaken = () => {
|
||||
const now = Date.now();
|
||||
const duration = now - this.timer;
|
||||
this.timer = now;
|
||||
return duration;
|
||||
};
|
||||
|
||||
this.formatTestCase = (scenario) => {
|
||||
const line = scenario.example
|
||||
? scenario.example.line
|
||||
: scenario.location.line;
|
||||
return {
|
||||
sourceLocation: { uri, line },
|
||||
};
|
||||
};
|
||||
|
||||
this.attachErrorToFailingStep = () => {
|
||||
Object.keys(this.runTests).forEach((test) => {
|
||||
const stepResults = this.runTests[test];
|
||||
Object.keys(stepResults).forEach((stepIdx) => {
|
||||
const stepResult = stepResults[stepIdx];
|
||||
if (stepResult.result === statuses.FAILED) {
|
||||
stepResult.exception = this.testError;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
this.markStillPendingStepsAsSkipped = (scenario) => {
|
||||
this.runTests[scenario.name] = Object.keys(this.stepResults).map(
|
||||
(key) => {
|
||||
const result = this.stepResults[key];
|
||||
return {
|
||||
...result,
|
||||
status:
|
||||
result.status === statuses.PENDING
|
||||
? statuses.SKIPPED
|
||||
: result.status,
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
this.recordScenarioResult = (scenario) => {
|
||||
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) => {
|
||||
this.stepResults[step.index] = { status: statuses.PENDING };
|
||||
};
|
||||
|
||||
this.recordStepResult = (step, result) => {
|
||||
this.stepResults[step.index] = {
|
||||
status: result,
|
||||
duration: this.timeTaken(),
|
||||
};
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { CucumberDataCollector };
|
160
node_modules/cypress-cucumber-preprocessor/lib/cukejson/cucumberDataCollector.test.js
generated
vendored
Normal file
160
node_modules/cypress-cucumber-preprocessor/lib/cukejson/cucumberDataCollector.test.js
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
const fs = require("fs");
|
||||
const statuses = require("cucumber/lib/status").default;
|
||||
const { CucumberDataCollector } = require("./cucumberDataCollector");
|
||||
const { generateCucumberJson } = require("./generateCucumberJson");
|
||||
|
||||
window.cucumberJson = { generate: true };
|
||||
|
||||
const assertCucumberJson = (json, expectedResults) => {
|
||||
expect(json).to.have.length(1);
|
||||
expect(json[0].keyword).to.eql("Feature");
|
||||
expect(json[0].name).to.eql("Being a plugin");
|
||||
expect(json[0].elements).to.have.length(1);
|
||||
expect(json[0].elements[0].keyword).to.eql("Scenario");
|
||||
expect(json[0].elements[0].name).to.eql("Basic example");
|
||||
expect(json[0].elements[0].steps).to.have.length(3);
|
||||
expect(json[0].elements[0].steps[0].keyword).to.equal("Given ");
|
||||
expect(json[0].elements[0].steps[0].name).to.equal(
|
||||
"a feature and a matching step definition file"
|
||||
);
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
expect(json[0].elements[0].steps[0].result).to.be.not.null;
|
||||
expect(json[0].elements[0].steps[0].result.status).to.eql(expectedResults[0]);
|
||||
expect(json[0].elements[0].steps[1].keyword).to.equal("When ");
|
||||
expect(json[0].elements[0].steps[1].name).to.equal("I run cypress tests");
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
expect(json[0].elements[0].steps[1].result).to.be.not.null;
|
||||
expect(json[0].elements[0].steps[1].result.status).to.eql(expectedResults[1]);
|
||||
expect(json[0].elements[0].steps[2].keyword).to.equal("Then ");
|
||||
expect(json[0].elements[0].steps[2].name).to.equal("they run properly");
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
expect(json[0].elements[0].steps[2].result).to.be.not.null;
|
||||
expect(json[0].elements[0].steps[2].result.status).to.eql(expectedResults[2]);
|
||||
};
|
||||
describe("Cucumber Data Collector", () => {
|
||||
const scenario = {
|
||||
type: "Scenario",
|
||||
tags: [],
|
||||
location: { line: 7, column: 3 },
|
||||
keyword: "Scenario",
|
||||
name: "Basic example",
|
||||
steps: [
|
||||
{
|
||||
type: "Step",
|
||||
location: { line: 8, column: 5 },
|
||||
keyword: "Given ",
|
||||
text: "a feature and a matching step definition file",
|
||||
},
|
||||
{
|
||||
type: "Step",
|
||||
location: { line: 9, column: 5 },
|
||||
keyword: "When ",
|
||||
text: "I run cypress tests",
|
||||
},
|
||||
{
|
||||
type: "Step",
|
||||
location: { line: 10, column: 5 },
|
||||
keyword: "Then ",
|
||||
text: "they run properly",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
const stepsToRun = [
|
||||
{
|
||||
type: "Step",
|
||||
location: { line: 8, column: 5 },
|
||||
keyword: "Given ",
|
||||
text: "a feature and a matching step definition file",
|
||||
index: 0,
|
||||
},
|
||||
{
|
||||
type: "Step",
|
||||
location: { line: 9, column: 5 },
|
||||
keyword: "When ",
|
||||
text: "I run cypress tests",
|
||||
index: 1,
|
||||
},
|
||||
{
|
||||
type: "Step",
|
||||
location: { line: 10, column: 5 },
|
||||
keyword: "Then ",
|
||||
text: "they run properly",
|
||||
index: 2,
|
||||
},
|
||||
];
|
||||
|
||||
beforeEach(() => {
|
||||
const filePath = "./cypress/integration/Plugin.feature";
|
||||
const spec = fs.readFileSync(filePath);
|
||||
this.testState = new CucumberDataCollector(filePath, spec);
|
||||
this.testState.onStartTest();
|
||||
});
|
||||
|
||||
it("runs", () => {
|
||||
this.testState.onFinishTest();
|
||||
const json = generateCucumberJson(this.testState);
|
||||
expect(json).to.have.length(0);
|
||||
});
|
||||
|
||||
it("records pending scenarios", () => {
|
||||
this.testState.onStartScenario(scenario, stepsToRun);
|
||||
this.testState.onFinishScenario(scenario);
|
||||
this.testState.onFinishTest();
|
||||
const json = generateCucumberJson(this.testState);
|
||||
assertCucumberJson(json, [
|
||||
statuses.SKIPPED,
|
||||
statuses.SKIPPED,
|
||||
statuses.SKIPPED,
|
||||
]);
|
||||
});
|
||||
it("records passed scenarios", () => {
|
||||
this.testState.onStartScenario(scenario, stepsToRun);
|
||||
this.testState.onStartStep(stepsToRun[0]);
|
||||
this.testState.onFinishStep(stepsToRun[0], statuses.PASSED);
|
||||
this.testState.onStartStep(stepsToRun[1]);
|
||||
this.testState.onFinishStep(stepsToRun[1], statuses.PASSED);
|
||||
this.testState.onStartStep(stepsToRun[2]);
|
||||
this.testState.onFinishStep(stepsToRun[2], statuses.PASSED);
|
||||
this.testState.onFinishScenario(scenario);
|
||||
this.testState.onFinishTest();
|
||||
const json = generateCucumberJson(this.testState);
|
||||
assertCucumberJson(json, [
|
||||
statuses.PASSED,
|
||||
statuses.PASSED,
|
||||
statuses.PASSED,
|
||||
]);
|
||||
});
|
||||
|
||||
it("records failed scenarios", () => {
|
||||
this.testState.onStartScenario(scenario, stepsToRun);
|
||||
this.testState.onStartStep(stepsToRun[0]);
|
||||
this.testState.onFinishStep(stepsToRun[0], statuses.PASSED);
|
||||
this.testState.onStartStep(stepsToRun[1]);
|
||||
this.testState.onFinishStep(stepsToRun[1], statuses.FAILED);
|
||||
this.testState.onFinishScenario(scenario);
|
||||
this.testState.onFinishTest();
|
||||
const json = generateCucumberJson(this.testState);
|
||||
assertCucumberJson(json, [
|
||||
statuses.PASSED,
|
||||
statuses.FAILED,
|
||||
statuses.SKIPPED,
|
||||
]);
|
||||
});
|
||||
|
||||
it("handles missing steps", () => {
|
||||
this.testState.onStartScenario(scenario, stepsToRun);
|
||||
this.testState.onStartStep(stepsToRun[0]);
|
||||
this.testState.onFinishStep(stepsToRun[0], statuses.PASSED);
|
||||
this.testState.onStartStep(stepsToRun[1]);
|
||||
this.testState.onFinishStep(stepsToRun[1], statuses.UNDEFINED);
|
||||
this.testState.onFinishScenario(scenario);
|
||||
this.testState.onFinishTest();
|
||||
const json = generateCucumberJson(this.testState);
|
||||
assertCucumberJson(json, [
|
||||
statuses.PASSED,
|
||||
statuses.UNDEFINED,
|
||||
statuses.SKIPPED,
|
||||
]);
|
||||
});
|
||||
});
|
72
node_modules/cypress-cucumber-preprocessor/lib/cukejson/generateCucumberJson.js
generated
vendored
Normal file
72
node_modules/cypress-cucumber-preprocessor/lib/cukejson/generateCucumberJson.js
generated
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
const { EventEmitter } = require("events");
|
||||
const { generateEvents } = require("gherkin");
|
||||
const JsonFormatter = require("cucumber/lib/formatter/json_formatter").default;
|
||||
const formatterHelpers = require("cucumber/lib/formatter/helpers");
|
||||
|
||||
function generateCucumberJson(state) {
|
||||
let output = "";
|
||||
const logFn = (data) => {
|
||||
output += data;
|
||||
};
|
||||
|
||||
const eventBroadcaster = new EventEmitter();
|
||||
|
||||
function storePickle({ pickle, uri }) {
|
||||
eventBroadcaster.emit("pickle-accepted", { pickle, uri });
|
||||
}
|
||||
|
||||
eventBroadcaster.on("pickle", storePickle);
|
||||
|
||||
// eslint-disable-next-line no-new
|
||||
new JsonFormatter({
|
||||
eventBroadcaster,
|
||||
eventDataCollector: new formatterHelpers.EventDataCollector(
|
||||
eventBroadcaster
|
||||
),
|
||||
log: logFn,
|
||||
});
|
||||
|
||||
// Start feeding the recorded test run into the JsonFormatter
|
||||
|
||||
// Feed in the static test structure
|
||||
generateEvents(state.spec.toString(), state.uri).forEach((event) => {
|
||||
eventBroadcaster.emit(event.type, event);
|
||||
});
|
||||
|
||||
// Feed in the results from the recorded scenarios and steps
|
||||
Object.keys(state.runTests).forEach((test) => {
|
||||
const scenario = state.runScenarios[test];
|
||||
const stepResults = state.runTests[test];
|
||||
const stepsToRun = state.scenarioSteps[test];
|
||||
const steps = stepsToRun.map((step) => ({
|
||||
sourceLocation: { uri: state.uri, line: step.location.line },
|
||||
}));
|
||||
eventBroadcaster.emit("test-case-prepared", {
|
||||
sourceLocation: state.formatTestCase(scenario).sourceLocation,
|
||||
steps,
|
||||
});
|
||||
stepResults.forEach((stepResult, stepIdx) => {
|
||||
eventBroadcaster.emit("test-step-prepared", {
|
||||
index: stepIdx,
|
||||
testCase: state.formatTestCase(scenario),
|
||||
});
|
||||
eventBroadcaster.emit("test-step-finished", {
|
||||
index: stepIdx,
|
||||
testCase: state.formatTestCase(scenario),
|
||||
result: stepResult,
|
||||
});
|
||||
if (stepResult.attachment) {
|
||||
eventBroadcaster.emit("test-step-attachment", stepResult.attachment);
|
||||
}
|
||||
});
|
||||
eventBroadcaster.emit("test-case-finished", {
|
||||
sourceLocation: state.formatTestCase(scenario).sourceLocation,
|
||||
result: state.runTests[scenario.name].result,
|
||||
});
|
||||
});
|
||||
eventBroadcaster.emit("test-run-finished", {});
|
||||
|
||||
return JSON.parse(output);
|
||||
}
|
||||
|
||||
module.exports = { generateCucumberJson };
|
0
node_modules/cypress-cucumber-preprocessor/lib/cypressExecutionInstance.js
generated
vendored
Normal file
0
node_modules/cypress-cucumber-preprocessor/lib/cypressExecutionInstance.js
generated
vendored
Normal file
59
node_modules/cypress-cucumber-preprocessor/lib/cypressTagsHelpers.js
generated
vendored
Normal file
59
node_modules/cypress-cucumber-preprocessor/lib/cypressTagsHelpers.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
const minimist = require("minimist");
|
||||
const dargs = require("dargs");
|
||||
|
||||
const minimistConfig = {
|
||||
alias: { g: "glob" },
|
||||
string: ["g"],
|
||||
};
|
||||
|
||||
function stripCLIArguments(argsToRemove = []) {
|
||||
const command = process.argv[2];
|
||||
const userOptions = process.argv.slice(3);
|
||||
|
||||
const minimistArgs = minimist(userOptions);
|
||||
const argsAndAliasesToExclude =
|
||||
argsToRemove.length > 0
|
||||
? Object.entries(minimistConfig.alias)
|
||||
.map(([key, value]) => [key, value].flat())
|
||||
.filter((aliasedOption) =>
|
||||
aliasedOption.some((option) => argsToRemove.includes(option))
|
||||
)
|
||||
.flat()
|
||||
: [];
|
||||
|
||||
return [
|
||||
command,
|
||||
...dargs(minimistArgs, {
|
||||
excludes: [...new Set([...argsAndAliasesToExclude, ...argsToRemove])],
|
||||
useEquals: false,
|
||||
}),
|
||||
];
|
||||
}
|
||||
/**
|
||||
* Users will be expected to pass args by --glob/-g to avoid issues related to commas in those parameters.
|
||||
*/
|
||||
function parseArgsOrDefault(argPrefix, defaultValue) {
|
||||
const matchedArg = process.argv
|
||||
.slice(2)
|
||||
.find((arg) => arg.includes(`${argPrefix}=`));
|
||||
|
||||
// Cypress requires env vars to be passed as comma separated list
|
||||
// otherwise it only accepts the last provided variable,
|
||||
// the way we replace here accomodates for that.
|
||||
const argValue = matchedArg
|
||||
? matchedArg.replace(new RegExp(`.*${argPrefix}=`), "").replace(/,.*/, "")
|
||||
: "";
|
||||
|
||||
return argValue !== "" ? argValue : defaultValue;
|
||||
}
|
||||
|
||||
function getGlobArg() {
|
||||
const args = minimist(process.argv.slice(2), minimistConfig);
|
||||
return args.g || parseArgsOrDefault("GLOB", false);
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
stripCLIArguments,
|
||||
parseArgsOrDefault,
|
||||
getGlobArg,
|
||||
};
|
82
node_modules/cypress-cucumber-preprocessor/lib/cypressTagsHelpers.test.js
generated
vendored
Normal file
82
node_modules/cypress-cucumber-preprocessor/lib/cypressTagsHelpers.test.js
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
const { stripCLIArguments, getGlobArg } = require("./cypressTagsHelpers");
|
||||
|
||||
const processArgv = process.argv;
|
||||
|
||||
describe("stripCLIArguments function should return correct args array", () => {
|
||||
beforeEach(() => {
|
||||
process.argv = ["path/to/node", "path/to/file", "run"];
|
||||
});
|
||||
|
||||
test("when only target option is present", () => {
|
||||
process.argv.push(...["-g", "cypress/integration/**/*.feature"]);
|
||||
expect(stripCLIArguments(["g"])).to.eql(["run"]);
|
||||
});
|
||||
|
||||
test("when target option is a word", () => {
|
||||
process.argv.push(...["--glob", "cypress/integration/**/*.feature"]);
|
||||
expect(stripCLIArguments(["glob"])).to.eql(["run"]);
|
||||
});
|
||||
|
||||
test("when option doesn't have a value tied to it", () => {
|
||||
process.argv.push(...["-g"]);
|
||||
expect(stripCLIArguments(["g"])).to.eql(["run"]);
|
||||
});
|
||||
|
||||
test("when there are multiple options but only one is target for removal", () => {
|
||||
process.argv.push(...["-g", "-t"]);
|
||||
expect(stripCLIArguments(["g"])).to.eql(["run", "-t"]);
|
||||
});
|
||||
|
||||
test("when there are multiple options to remove", () => {
|
||||
process.argv.push(...["-g", "-t", "cypress tags string"]);
|
||||
expect(stripCLIArguments(["g", "t"])).to.eql(["run"]);
|
||||
});
|
||||
|
||||
test("when option is coupled with other ones like -tg", () => {
|
||||
process.argv.push(...["-tg", "cypress/integration/**/*.feature"]);
|
||||
expect(stripCLIArguments(["t"])).to.eql([
|
||||
"run",
|
||||
"-g",
|
||||
"cypress/integration/**/*.feature",
|
||||
]);
|
||||
});
|
||||
|
||||
test("when option is coupled with other ones like -gt where t has a value", () => {
|
||||
process.argv.push(...["-gt", "cypress tags string"]);
|
||||
expect(stripCLIArguments(["t"])).to.eql(["run", "-g"]);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.argv = processArgv;
|
||||
});
|
||||
});
|
||||
|
||||
describe("getGlobArg function should return", () => {
|
||||
beforeEach(() => {
|
||||
process.argv = ["path/to/node", "path/to/file", "run"];
|
||||
});
|
||||
|
||||
test("glob pattern when using -g or --glob option", () => {
|
||||
process.argv.push(...["-g", "cypress/integration/**/*.feature"]);
|
||||
expect(getGlobArg()).to.equal("cypress/integration/**/*.feature");
|
||||
});
|
||||
|
||||
test("glob pattern containing commas when using -g option", () => {
|
||||
process.argv.push(...["-g", "cypress/integration/**/1,2*.feature"]);
|
||||
expect(getGlobArg()).to.equal("cypress/integration/**/1,2*.feature");
|
||||
});
|
||||
|
||||
test("glob pattern containing braced sections when using -g option", () => {
|
||||
process.argv.push(...["-g", "cypress/integration/**/{1,2}*.feature"]);
|
||||
expect(getGlobArg()).to.equal("cypress/integration/**/{1,2}*.feature");
|
||||
});
|
||||
|
||||
test("glob pattern when using env variables GLOB=", () => {
|
||||
process.argv.push(...["-e", "GLOB=cypress/integration/**/*.feature"]);
|
||||
expect(getGlobArg()).to.equal("cypress/integration/**/*.feature");
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
process.argv = processArgv;
|
||||
});
|
||||
});
|
123
node_modules/cypress-cucumber-preprocessor/lib/featuresLoader.js
generated
vendored
Normal file
123
node_modules/cypress-cucumber-preprocessor/lib/featuresLoader.js
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
const glob = require("glob");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const { Parser } = require("gherkin");
|
||||
const log = require("debug")("cypress:cucumber");
|
||||
const jsStringEscape = require("js-string-escape");
|
||||
|
||||
const { getStepDefinitionsPaths } = require("./getStepDefinitionsPaths");
|
||||
const { cucumberTemplate } = require("./cucumberTemplate");
|
||||
const { getCucumberJsonConfig } = require("./getCucumberJsonConfig");
|
||||
const {
|
||||
isNonGlobalStepDefinitionsMode,
|
||||
} = require("./isNonGlobalStepDefinitionsMode");
|
||||
|
||||
const createCucumber = (
|
||||
specs,
|
||||
globalToRequire,
|
||||
nonGlobalToRequire,
|
||||
cucumberJson
|
||||
) =>
|
||||
`
|
||||
${cucumberTemplate}
|
||||
window.cucumberJson = ${JSON.stringify(cucumberJson)};
|
||||
|
||||
var moduleCache = arguments[5];
|
||||
|
||||
function clearFromCache(moduleId, instance){
|
||||
if(isWebpack()){
|
||||
delete require.cache[moduleId];
|
||||
} else {
|
||||
clearFromCacheBrowserify(instance);
|
||||
}
|
||||
}
|
||||
|
||||
function isWebpack(){
|
||||
return !!require.cache
|
||||
}
|
||||
|
||||
// Stolen from https://github.com/browserify/browserify/issues/1444
|
||||
function clearFromCacheBrowserify(instance) {
|
||||
for(const key in moduleCache)
|
||||
{
|
||||
if(moduleCache[key].exports == instance)
|
||||
{
|
||||
delete moduleCache[key];
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new Error("could not clear instance from browserify module cache");
|
||||
}
|
||||
|
||||
${globalToRequire.join("\n")}
|
||||
|
||||
${specs
|
||||
.map(
|
||||
({ spec, filePath, name }) => `
|
||||
describe(\`${name}\`, function() {
|
||||
window.currentFeatureName = \`${name}\`
|
||||
${
|
||||
nonGlobalToRequire &&
|
||||
nonGlobalToRequire
|
||||
.find((fileSteps) => fileSteps[filePath])
|
||||
[filePath].join("\n")
|
||||
}
|
||||
|
||||
createTestsFromFeature('${path.basename(filePath)}', '${jsStringEscape(
|
||||
spec
|
||||
)}');
|
||||
})
|
||||
`
|
||||
)
|
||||
.join("\n")}
|
||||
`;
|
||||
|
||||
// eslint-disable-next-line func-names
|
||||
module.exports = function (_, filePath = this.resourcePath) {
|
||||
log("compiling", filePath);
|
||||
|
||||
const features = glob.sync(`${path.dirname(filePath)}/**/*.feature`);
|
||||
|
||||
let globalStepDefinitionsToRequire = [];
|
||||
let nonGlobalStepDefinitionsToRequire;
|
||||
|
||||
if (isNonGlobalStepDefinitionsMode()) {
|
||||
nonGlobalStepDefinitionsToRequire = features.map((featurePath) => ({
|
||||
[featurePath]: getStepDefinitionsPaths(featurePath).map(
|
||||
(sdPath) =>
|
||||
`clearFromCache(require.resolve && require.resolve('${sdPath}'), require('${sdPath}'))`
|
||||
),
|
||||
}));
|
||||
} else {
|
||||
globalStepDefinitionsToRequire = [
|
||||
...new Set(
|
||||
features.reduce(
|
||||
(requires) =>
|
||||
requires.concat(
|
||||
getStepDefinitionsPaths(filePath).map(
|
||||
(sdPath) => `require('${sdPath}')`
|
||||
)
|
||||
),
|
||||
[]
|
||||
)
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
const specs = features
|
||||
.map((featurePath) => ({
|
||||
spec: fs.readFileSync(featurePath).toString(),
|
||||
filePath: featurePath,
|
||||
}))
|
||||
.map((feature) => ({
|
||||
...feature,
|
||||
name: new Parser().parse(feature.spec.toString()).feature.name,
|
||||
}));
|
||||
|
||||
return createCucumber(
|
||||
specs,
|
||||
globalStepDefinitionsToRequire,
|
||||
nonGlobalStepDefinitionsToRequire,
|
||||
getCucumberJsonConfig()
|
||||
);
|
||||
};
|
15
node_modules/cypress-cucumber-preprocessor/lib/getConfig.js
generated
vendored
Normal file
15
node_modules/cypress-cucumber-preprocessor/lib/getConfig.js
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
const cosmiconfig = require("cosmiconfig");
|
||||
|
||||
let explorer;
|
||||
|
||||
exports.getConfig = () => {
|
||||
if (!explorer) {
|
||||
explorer = cosmiconfig("cypress-cucumber-preprocessor", {
|
||||
sync: true,
|
||||
rcExtensions: true,
|
||||
});
|
||||
}
|
||||
|
||||
const loaded = explorer.load();
|
||||
return loaded && loaded.config;
|
||||
};
|
11
node_modules/cypress-cucumber-preprocessor/lib/getCucumberJsonConfig.js
generated
vendored
Normal file
11
node_modules/cypress-cucumber-preprocessor/lib/getCucumberJsonConfig.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
const log = require("debug")("cypress:cucumber");
|
||||
const { getConfig } = require("./getConfig");
|
||||
|
||||
exports.getCucumberJsonConfig = () => {
|
||||
const config = getConfig();
|
||||
const cucumberJson =
|
||||
config && config.cucumberJson ? config.cucumberJson : { generate: false };
|
||||
log("cucumber.json", JSON.stringify(cucumberJson));
|
||||
|
||||
return cucumberJson;
|
||||
};
|
6
node_modules/cypress-cucumber-preprocessor/lib/getStepDefinitionPathsFrom.js
generated
vendored
Normal file
6
node_modules/cypress-cucumber-preprocessor/lib/getStepDefinitionPathsFrom.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
getStepDefinitionPathsFrom: (filePath) =>
|
||||
filePath.replace(path.extname(filePath), ""),
|
||||
};
|
7
node_modules/cypress-cucumber-preprocessor/lib/getStepDefinitionPathsFrom.test.js
generated
vendored
Normal file
7
node_modules/cypress-cucumber-preprocessor/lib/getStepDefinitionPathsFrom.test.js
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
const { getStepDefinitionPathsFrom } = require("./getStepDefinitionPathsFrom");
|
||||
|
||||
test("getStepDefinitionPathsFrom", () => {
|
||||
expect(
|
||||
getStepDefinitionPathsFrom("/home/lgandecki/someComplex_.feature")
|
||||
).equal("/home/lgandecki/someComplex_");
|
||||
});
|
40
node_modules/cypress-cucumber-preprocessor/lib/getStepDefinitionsPaths.js
generated
vendored
Normal file
40
node_modules/cypress-cucumber-preprocessor/lib/getStepDefinitionsPaths.js
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
const path = require("path");
|
||||
const glob = require("glob");
|
||||
const process = require("process");
|
||||
const { getConfig } = require("./getConfig");
|
||||
const stepDefinitionPath = require("./stepDefinitionPath.js");
|
||||
const { getStepDefinitionPathsFrom } = require("./getStepDefinitionPathsFrom");
|
||||
|
||||
const getStepDefinitionsPaths = (filePath) => {
|
||||
const appRoot = process.cwd();
|
||||
let paths = [];
|
||||
const config = getConfig();
|
||||
if (config && config.nonGlobalStepDefinitions) {
|
||||
let nonGlobalPath = getStepDefinitionPathsFrom(filePath);
|
||||
let commonPath = config.commonPath || `${stepDefinitionPath()}/common/`;
|
||||
|
||||
if (config.commonPath) {
|
||||
commonPath = `${path.resolve(appRoot, commonPath)}/`;
|
||||
}
|
||||
|
||||
if (config.nonGlobalStepBaseDir) {
|
||||
const stepBase = `${appRoot}/${config.nonGlobalStepBaseDir}`;
|
||||
nonGlobalPath = nonGlobalPath.replace(stepDefinitionPath(), stepBase);
|
||||
commonPath = `${stepBase}/${config.commonPath || "common/"}`;
|
||||
}
|
||||
|
||||
const nonGlobalPattern = `${nonGlobalPath}/**/*.+(js|ts|tsx)`;
|
||||
|
||||
const commonDefinitionsPattern = `${commonPath}**/*.+(js|ts|tsx)`;
|
||||
paths = paths.concat(
|
||||
glob.sync(nonGlobalPattern),
|
||||
glob.sync(commonDefinitionsPattern)
|
||||
);
|
||||
} else {
|
||||
const pattern = `${stepDefinitionPath()}/**/*.+(js|ts|tsx)`;
|
||||
paths = paths.concat(glob.sync(pattern));
|
||||
}
|
||||
return paths;
|
||||
};
|
||||
|
||||
module.exports = { getStepDefinitionsPaths };
|
99
node_modules/cypress-cucumber-preprocessor/lib/getStepDefinitionsPaths.test.js
generated
vendored
Normal file
99
node_modules/cypress-cucumber-preprocessor/lib/getStepDefinitionsPaths.test.js
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// file.only
|
||||
/* eslint-disable global-require */
|
||||
jest.mock("./stepDefinitionPath.js", () => () => "stepDefinitionPath");
|
||||
jest.mock("glob", () => ({
|
||||
sync(pattern) {
|
||||
return pattern;
|
||||
},
|
||||
}));
|
||||
|
||||
let getConfig;
|
||||
|
||||
describe("getStepDefinitionsPaths", () => {
|
||||
beforeEach(() => {
|
||||
jest.resetModules();
|
||||
({ getConfig } = require("./getConfig"));
|
||||
jest.unmock("path");
|
||||
jest.mock("./getConfig");
|
||||
});
|
||||
it("should return the default common folder", () => {
|
||||
getConfig.mockReturnValue({
|
||||
nonGlobalStepDefinitions: true,
|
||||
});
|
||||
|
||||
const { getStepDefinitionsPaths } = require("./getStepDefinitionsPaths");
|
||||
|
||||
const actual = getStepDefinitionsPaths("/path");
|
||||
const expected = "stepDefinitionPath/common/**/*.+(js|ts|tsx)";
|
||||
expect(actual).to.include(expected);
|
||||
});
|
||||
|
||||
it("should return the common folder defined by the developer", () => {
|
||||
jest.spyOn(process, "cwd").mockImplementation(() => "/cwd/");
|
||||
|
||||
getConfig.mockReturnValue({
|
||||
nonGlobalStepDefinitions: true,
|
||||
commonPath: "myPath/",
|
||||
});
|
||||
|
||||
const { getStepDefinitionsPaths } = require("./getStepDefinitionsPaths");
|
||||
|
||||
const actual = getStepDefinitionsPaths("/path");
|
||||
const expected = "/cwd/myPath/**/*.+(js|ts|tsx)";
|
||||
expect(actual).to.include(expected);
|
||||
});
|
||||
it("should return the default non global step definition pattern", () => {
|
||||
getConfig.mockReturnValue({
|
||||
nonGlobalStepDefinitions: true,
|
||||
});
|
||||
// eslint-disable-next-line global-require
|
||||
const { getStepDefinitionsPaths } = require("./getStepDefinitionsPaths");
|
||||
const path = "stepDefinitionPath/test.feature";
|
||||
const actual = getStepDefinitionsPaths(path);
|
||||
const expected = "stepDefinitionPath/test/**/*.+(js|ts|tsx)";
|
||||
|
||||
expect(actual).to.include(expected);
|
||||
});
|
||||
|
||||
describe("nonGlobalStepBaseDir is defined", () => {
|
||||
const path = "stepDefinitionPath/test.feature";
|
||||
const config = {
|
||||
nonGlobalStepDefinitions: true,
|
||||
nonGlobalStepBaseDir: "nonGlobalStepBaseDir",
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
jest.spyOn(process, "cwd").mockImplementation(() => "cwd");
|
||||
});
|
||||
|
||||
it("should return the overriden non global step definition pattern and default common folder", () => {
|
||||
getConfig.mockReturnValue(config);
|
||||
|
||||
const { getStepDefinitionsPaths } = require("./getStepDefinitionsPaths");
|
||||
const actual = getStepDefinitionsPaths(path);
|
||||
|
||||
const expectedNonGlobalDefinitionPattern =
|
||||
"cwd/nonGlobalStepBaseDir/test/**/*.+(js|ts|tsx)";
|
||||
const expectedCommonPath =
|
||||
"cwd/nonGlobalStepBaseDir/common/**/*.+(js|ts|tsx)";
|
||||
|
||||
expect(actual).to.include(expectedNonGlobalDefinitionPattern);
|
||||
expect(actual).to.include(expectedCommonPath);
|
||||
expect(actual).to.not.include(
|
||||
"stepDefinitionPath/test/**/*.+(js|ts|tsx)"
|
||||
);
|
||||
});
|
||||
|
||||
it("should return common folder defined by the dev and based on nonGlobalStepBaseDir", () => {
|
||||
getConfig.mockReturnValue({ ...config, commonPath: "commonPath/" });
|
||||
|
||||
const { getStepDefinitionsPaths } = require("./getStepDefinitionsPaths");
|
||||
const actual = getStepDefinitionsPaths(path);
|
||||
|
||||
const expectedCommonPath =
|
||||
"cwd/nonGlobalStepBaseDir/commonPath/**/*.+(js|ts|tsx)";
|
||||
|
||||
expect(actual).to.include(expectedCommonPath);
|
||||
});
|
||||
});
|
||||
});
|
27
node_modules/cypress-cucumber-preprocessor/lib/hookRegistry.js
generated
vendored
Normal file
27
node_modules/cypress-cucumber-preprocessor/lib/hookRegistry.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
const { shouldProceedCurrentStep } = require("./tagsHelper");
|
||||
|
||||
class HookRegistry {
|
||||
constructor() {
|
||||
this.definitions = [];
|
||||
this.runtime = {};
|
||||
|
||||
this.runtime = (tags, implementation) => {
|
||||
this.definitions.push({
|
||||
tags,
|
||||
implementation,
|
||||
featureName: window.currentFeatureName || "___GLOBAL_EXECUTION___",
|
||||
});
|
||||
};
|
||||
|
||||
this.resolve = (scenarioTags, runningFeatureName) =>
|
||||
this.definitions.filter(
|
||||
({ tags, featureName }) =>
|
||||
(!tags ||
|
||||
tags.length === 0 ||
|
||||
shouldProceedCurrentStep(scenarioTags, tags)) &&
|
||||
(runningFeatureName === featureName ||
|
||||
featureName === "___GLOBAL_EXECUTION___")
|
||||
);
|
||||
}
|
||||
}
|
||||
exports.HookRegistry = HookRegistry;
|
97
node_modules/cypress-cucumber-preprocessor/lib/index.js
generated
vendored
Normal file
97
node_modules/cypress-cucumber-preprocessor/lib/index.js
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
/* eslint-disable no-eval */
|
||||
const fs = require("fs");
|
||||
const through = require("through");
|
||||
const browserify = require("@cypress/browserify-preprocessor");
|
||||
const log = require("debug")("cypress:cucumber");
|
||||
const chokidar = require("chokidar");
|
||||
const compile = require("./loader.js");
|
||||
const compileFeatures = require("./featuresLoader.js");
|
||||
const stepDefinitionPath = require("./stepDefinitionPath.js");
|
||||
|
||||
const transform = (file) => {
|
||||
let data = "";
|
||||
|
||||
function write(buf) {
|
||||
data += buf;
|
||||
}
|
||||
|
||||
function end() {
|
||||
if (file.match(".features$")) {
|
||||
log("compiling features ", file);
|
||||
this.queue(compileFeatures(data, file));
|
||||
} else if (file.match(".feature$")) {
|
||||
log("compiling feature ", file);
|
||||
this.queue(compile(data, file));
|
||||
} else {
|
||||
this.queue(data);
|
||||
}
|
||||
this.queue(null);
|
||||
}
|
||||
|
||||
return through(write, end);
|
||||
};
|
||||
|
||||
const touch = (filename) => {
|
||||
fs.utimesSync(filename, new Date(), new Date());
|
||||
};
|
||||
|
||||
let watcher;
|
||||
|
||||
// Include our transform in Browserify options
|
||||
const wrapOptions = (options) => {
|
||||
let wrappedTransform;
|
||||
if (
|
||||
!options.browserifyOptions ||
|
||||
!Array.isArray(options.browserifyOptions.transform)
|
||||
) {
|
||||
wrappedTransform = [transform];
|
||||
} else if (!options.browserifyOptions.transform.includes(transform)) {
|
||||
wrappedTransform = [transform, ...options.browserifyOptions.transform];
|
||||
} else {
|
||||
wrappedTransform = options.browserifyOptions.transform;
|
||||
}
|
||||
|
||||
return {
|
||||
...options,
|
||||
browserifyOptions: {
|
||||
...(options.browserifyOptions || {}),
|
||||
transform: wrappedTransform,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const preprocessor = (options = browserify.defaultOptions) => {
|
||||
if (typeof options !== "object") {
|
||||
throw new Error("Preprocessor options must be an object");
|
||||
}
|
||||
|
||||
const wrappedOptions = wrapOptions(options);
|
||||
|
||||
return async (file) => {
|
||||
if (file.shouldWatch) {
|
||||
if (watcher) {
|
||||
watcher.close();
|
||||
}
|
||||
watcher = chokidar
|
||||
.watch(
|
||||
[
|
||||
`${stepDefinitionPath()}*.js`,
|
||||
`${stepDefinitionPath()}*.ts`,
|
||||
`${stepDefinitionPath()}*.tsx`,
|
||||
],
|
||||
{
|
||||
ignoreInitial: true,
|
||||
}
|
||||
)
|
||||
.on("all", () => {
|
||||
touch(file.filePath);
|
||||
});
|
||||
}
|
||||
return browserify(wrappedOptions)(file);
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
default: preprocessor,
|
||||
transform,
|
||||
};
|
98
node_modules/cypress-cucumber-preprocessor/lib/index.test.js
generated
vendored
Normal file
98
node_modules/cypress-cucumber-preprocessor/lib/index.test.js
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
const browserify = require("@cypress/browserify-preprocessor");
|
||||
const { default: preprocessor, transform } = require(".");
|
||||
|
||||
jest.mock("@cypress/browserify-preprocessor");
|
||||
const { defaultOptions } = jest.requireActual(
|
||||
"@cypress/browserify-preprocessor"
|
||||
);
|
||||
|
||||
describe("Preprocessor", () => {
|
||||
beforeEach(() => {
|
||||
browserify.defaultOptions = defaultOptions;
|
||||
browserify.mockReturnValue(() => {});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
browserify.mockClear();
|
||||
});
|
||||
|
||||
it("should use Cypress browserify options by default", async () => {
|
||||
await preprocessor()({ shouldWatch: false });
|
||||
|
||||
global.jestExpect(browserify).toHaveBeenCalledWith({
|
||||
...defaultOptions,
|
||||
browserifyOptions: {
|
||||
...defaultOptions.browserifyOptions,
|
||||
transform: [transform, ...defaultOptions.browserifyOptions.transform],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should add transform when other transforms are defined in options", async () => {
|
||||
await preprocessor({
|
||||
browserifyOptions: {
|
||||
transform: ["babelify"],
|
||||
},
|
||||
})({ shouldWatch: false });
|
||||
|
||||
global.jestExpect(browserify).toHaveBeenCalledWith({
|
||||
browserifyOptions: {
|
||||
transform: [transform, "babelify"],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should preserve transforms in options when our transform is already included", async () => {
|
||||
const options = {
|
||||
browserifyOptions: {
|
||||
extensions: ["js", "ts"],
|
||||
plugins: [["tsify"]],
|
||||
transform: ["aliasify", transform, "babelify"],
|
||||
},
|
||||
};
|
||||
|
||||
await preprocessor(options)({ shouldWatch: false });
|
||||
|
||||
global.jestExpect(browserify).toHaveBeenCalledWith(options);
|
||||
});
|
||||
|
||||
it("should add our transform when no other transforms are defined in options", async () => {
|
||||
const options = {
|
||||
browserifyOptions: {
|
||||
extensions: ["js", "ts"],
|
||||
plugins: [["tsify"]],
|
||||
},
|
||||
};
|
||||
|
||||
await preprocessor(options)({ shouldWatch: false });
|
||||
|
||||
global.jestExpect(browserify).toHaveBeenCalledWith({
|
||||
...options,
|
||||
browserifyOptions: {
|
||||
...options.browserifyOptions,
|
||||
transform: [transform],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should add our transform when browserifyOptions property is not passed to options", async () => {
|
||||
const options = { unsupported: true };
|
||||
|
||||
await preprocessor(options)({ shouldWatch: false });
|
||||
|
||||
global.jestExpect(browserify).toHaveBeenCalledWith({
|
||||
...options,
|
||||
browserifyOptions: {
|
||||
transform: [transform],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it("should fail gracefully when options is not an object", () => {
|
||||
const err = new Error("Preprocessor options must be an object");
|
||||
|
||||
global.jestExpect(() => preprocessor("options")).toThrow(err);
|
||||
global.jestExpect(() => preprocessor(1)).toThrow(err);
|
||||
global.jestExpect(() => preprocessor(false)).toThrow(err);
|
||||
});
|
||||
});
|
6
node_modules/cypress-cucumber-preprocessor/lib/isNonGlobalStepDefinitionsMode.js
generated
vendored
Normal file
6
node_modules/cypress-cucumber-preprocessor/lib/isNonGlobalStepDefinitionsMode.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
const { getConfig } = require("./getConfig");
|
||||
|
||||
exports.isNonGlobalStepDefinitionsMode = () => {
|
||||
const config = getConfig();
|
||||
return config && config.nonGlobalStepDefinitions;
|
||||
};
|
37
node_modules/cypress-cucumber-preprocessor/lib/loader.js
generated
vendored
Normal file
37
node_modules/cypress-cucumber-preprocessor/lib/loader.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
const log = require("debug")("cypress:cucumber");
|
||||
const path = require("path");
|
||||
const { Parser } = require("gherkin");
|
||||
const jsStringEscape = require("js-string-escape");
|
||||
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) =>
|
||||
`
|
||||
${cucumberTemplate}
|
||||
|
||||
window.cucumberJson = ${JSON.stringify(cucumberJson)};
|
||||
describe(\`${name}\`, function() {
|
||||
${toRequire.join("\n")}
|
||||
createTestsFromFeature('${filePath}', '${jsStringEscape(spec)}');
|
||||
});
|
||||
`;
|
||||
|
||||
// eslint-disable-next-line func-names
|
||||
module.exports = function (spec, filePath = this.resourcePath) {
|
||||
log("compiling", spec);
|
||||
const stepDefinitionsToRequire = getStepDefinitionsPaths(filePath).map(
|
||||
(sdPath) => `require('${sdPath}')`
|
||||
);
|
||||
|
||||
const { name } = new Parser().parse(spec.toString()).feature;
|
||||
return createCucumber(
|
||||
path.basename(filePath),
|
||||
getCucumberJsonConfig(),
|
||||
spec,
|
||||
stepDefinitionsToRequire,
|
||||
name
|
||||
);
|
||||
};
|
228
node_modules/cypress-cucumber-preprocessor/lib/resolveStepDefinition.js
generated
vendored
Normal file
228
node_modules/cypress-cucumber-preprocessor/lib/resolveStepDefinition.js
generated
vendored
Normal file
@@ -0,0 +1,228 @@
|
||||
const DataTable = require("cucumber/lib/models/data_table").default;
|
||||
const {
|
||||
defineParameterType,
|
||||
} = require("cucumber/lib/support_code_library_builder/define_helpers");
|
||||
const {
|
||||
CucumberExpression,
|
||||
RegularExpression,
|
||||
ParameterTypeRegistry,
|
||||
} = require("cucumber-expressions");
|
||||
|
||||
const { HookRegistry } = require("./hookRegistry");
|
||||
|
||||
class StepDefinitionRegistry {
|
||||
constructor() {
|
||||
this.definitions = {};
|
||||
this.runtime = {};
|
||||
this.options = {
|
||||
parameterTypeRegistry: new ParameterTypeRegistry(),
|
||||
};
|
||||
|
||||
this.definitions = [];
|
||||
this.runtime = (...args) => {
|
||||
let matcher;
|
||||
let config;
|
||||
let implementation;
|
||||
if (args.length > 2) {
|
||||
[matcher, config, implementation] = args;
|
||||
} else {
|
||||
[matcher, implementation] = args;
|
||||
}
|
||||
let expression;
|
||||
if (matcher instanceof RegExp) {
|
||||
expression = new RegularExpression(
|
||||
matcher,
|
||||
this.options.parameterTypeRegistry
|
||||
);
|
||||
} else {
|
||||
expression = new CucumberExpression(
|
||||
matcher,
|
||||
this.options.parameterTypeRegistry
|
||||
);
|
||||
}
|
||||
|
||||
this.definitions.push({
|
||||
implementation,
|
||||
expression,
|
||||
config,
|
||||
featureName: window.currentFeatureName || "___GLOBAL_EXECUTION___",
|
||||
});
|
||||
};
|
||||
|
||||
this.resolve = (type, text, runningFeatureName) =>
|
||||
this.definitions.filter(
|
||||
({ expression, featureName }) =>
|
||||
expression.match(text) &&
|
||||
(runningFeatureName === featureName ||
|
||||
featureName === "___GLOBAL_EXECUTION___")
|
||||
)[0];
|
||||
}
|
||||
}
|
||||
|
||||
const stepDefinitionRegistry = new StepDefinitionRegistry();
|
||||
const beforeHookRegistry = new HookRegistry();
|
||||
const afterHookRegistry = new HookRegistry();
|
||||
|
||||
function resolveStepDefinition(step, featureName) {
|
||||
const stepDefinition = stepDefinitionRegistry.resolve(
|
||||
step.keyword.toLowerCase().trim(),
|
||||
step.text,
|
||||
featureName
|
||||
);
|
||||
return stepDefinition || {};
|
||||
}
|
||||
|
||||
function storeTemplateRowsOnArgumentIfNotPresent(argument) {
|
||||
return !argument.templateRows
|
||||
? { ...argument, templateRows: argument.rows }
|
||||
: argument;
|
||||
}
|
||||
|
||||
function applyExampleData(argument, exampleRowData, replaceParameterTags) {
|
||||
const argumentWithTemplateRows = storeTemplateRowsOnArgumentIfNotPresent(
|
||||
argument
|
||||
);
|
||||
|
||||
const scenarioDataTableRows = argumentWithTemplateRows.templateRows.map(
|
||||
(tr) => {
|
||||
if (!(tr && tr.type === "TableRow")) {
|
||||
return tr;
|
||||
}
|
||||
const cells = {
|
||||
cells: tr.cells.map((c) => {
|
||||
const value = {
|
||||
value: replaceParameterTags(exampleRowData, c.value),
|
||||
};
|
||||
return { ...c, ...value };
|
||||
}),
|
||||
};
|
||||
return { ...tr, ...cells };
|
||||
}
|
||||
);
|
||||
return { ...argumentWithTemplateRows, rows: scenarioDataTableRows };
|
||||
}
|
||||
|
||||
function resolveStepArgument(argument, exampleRowData, replaceParameterTags) {
|
||||
if (!argument) {
|
||||
return argument;
|
||||
}
|
||||
if (argument.type === "DataTable") {
|
||||
if (!exampleRowData) {
|
||||
return new DataTable(argument);
|
||||
}
|
||||
const argumentWithAppliedExampleData = applyExampleData(
|
||||
argument,
|
||||
exampleRowData,
|
||||
replaceParameterTags
|
||||
);
|
||||
|
||||
return new DataTable(argumentWithAppliedExampleData);
|
||||
}
|
||||
if (argument.type === "DocString") {
|
||||
if (exampleRowData) {
|
||||
return replaceParameterTags(exampleRowData, argument.content);
|
||||
}
|
||||
return argument.content;
|
||||
}
|
||||
|
||||
return argument;
|
||||
}
|
||||
|
||||
function resolveAndRunHooks(hookRegistry, scenarioTags, featureName) {
|
||||
return window.Cypress.Promise.each(
|
||||
hookRegistry.resolve(scenarioTags, featureName),
|
||||
({ implementation }) => implementation.call(this)
|
||||
);
|
||||
}
|
||||
|
||||
function parseHookArgs(args) {
|
||||
if (args.length === 2) {
|
||||
if (typeof args[0] !== "object" || typeof args[0].tags !== "string") {
|
||||
throw new Error(
|
||||
"Hook definitions with two arguments should have an object containing tags (string) as the first argument."
|
||||
);
|
||||
}
|
||||
if (typeof args[1] !== "function") {
|
||||
throw new Error(
|
||||
"Hook definitions with two arguments must have a function as the second argument."
|
||||
);
|
||||
}
|
||||
return {
|
||||
tags: args[0].tags,
|
||||
implementation: args[1],
|
||||
};
|
||||
}
|
||||
if (typeof args[0] !== "function") {
|
||||
throw new Error(
|
||||
"Hook definitions with one argument must have a function as the first argument."
|
||||
);
|
||||
}
|
||||
return {
|
||||
implementation: args[0],
|
||||
};
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
resolveStepDefinition(step, featureName) {
|
||||
return resolveStepDefinition(step, featureName);
|
||||
},
|
||||
resolveAndRunBeforeHooks(scenarioTags, featureName) {
|
||||
return resolveAndRunHooks(beforeHookRegistry, scenarioTags, featureName);
|
||||
},
|
||||
resolveAndRunAfterHooks(scenarioTags, featureName) {
|
||||
return resolveAndRunHooks(afterHookRegistry, scenarioTags, featureName);
|
||||
},
|
||||
// eslint-disable-next-line func-names
|
||||
resolveAndRunStepDefinition(
|
||||
step,
|
||||
replaceParameterTags,
|
||||
exampleRowData,
|
||||
featureName
|
||||
) {
|
||||
const { expression, implementation } = resolveStepDefinition(
|
||||
step,
|
||||
featureName
|
||||
);
|
||||
const stepText = step.text;
|
||||
if (expression && implementation) {
|
||||
const argument = resolveStepArgument(
|
||||
step.argument,
|
||||
exampleRowData,
|
||||
replaceParameterTags
|
||||
);
|
||||
return implementation.call(
|
||||
this,
|
||||
...expression.match(stepText).map((match) => match.getValue()),
|
||||
argument
|
||||
);
|
||||
}
|
||||
throw new Error(`Step implementation missing for: ${stepText}`);
|
||||
},
|
||||
Given: (...args) => {
|
||||
stepDefinitionRegistry.runtime(...args);
|
||||
},
|
||||
When: (...args) => {
|
||||
stepDefinitionRegistry.runtime(...args);
|
||||
},
|
||||
Then: (...args) => {
|
||||
stepDefinitionRegistry.runtime(...args);
|
||||
},
|
||||
And: (...args) => {
|
||||
stepDefinitionRegistry.runtime(...args);
|
||||
},
|
||||
But: (...args) => {
|
||||
stepDefinitionRegistry.runtime(...args);
|
||||
},
|
||||
Before: (...args) => {
|
||||
const { tags, implementation } = parseHookArgs(args);
|
||||
beforeHookRegistry.runtime(tags, implementation);
|
||||
},
|
||||
After: (...args) => {
|
||||
const { tags, implementation } = parseHookArgs(args);
|
||||
afterHookRegistry.runtime(tags, implementation);
|
||||
},
|
||||
defineStep: (expression, implementation) => {
|
||||
stepDefinitionRegistry.runtime(expression, implementation);
|
||||
},
|
||||
defineParameterType: defineParameterType(stepDefinitionRegistry),
|
||||
};
|
87
node_modules/cypress-cucumber-preprocessor/lib/resolveStepDefinition.test.js
generated
vendored
Normal file
87
node_modules/cypress-cucumber-preprocessor/lib/resolveStepDefinition.test.js
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
/* eslint-disable global-require */
|
||||
|
||||
const {
|
||||
resolveFeatureFromFile,
|
||||
} = require("./testHelpers/resolveFeatureFromFile");
|
||||
|
||||
describe("Scenario Outline", () => {
|
||||
require("../cypress/support/step_definitions/scenario_outline_integer");
|
||||
require("../cypress/support/step_definitions/scenario_outline_string");
|
||||
require("../cypress/support/step_definitions/scenario_outline_data_table");
|
||||
require("../cypress/support/step_definitions/scenario_outline_multiple_vars");
|
||||
resolveFeatureFromFile("./cypress/integration/ScenarioOutline.feature");
|
||||
});
|
||||
|
||||
describe("DocString", () => {
|
||||
require("../cypress/support/step_definitions/docString");
|
||||
resolveFeatureFromFile("./cypress/integration/DocString.feature");
|
||||
});
|
||||
|
||||
describe("Data table", () => {
|
||||
require("../cypress/support/step_definitions/dataTable");
|
||||
resolveFeatureFromFile("./cypress/integration/DataTable.feature");
|
||||
});
|
||||
|
||||
describe("Basic example", () => {
|
||||
require("../cypress/support/step_definitions/basic");
|
||||
resolveFeatureFromFile("./cypress/integration/Plugin.feature");
|
||||
});
|
||||
|
||||
describe("Background section", () => {
|
||||
require("../cypress/support/step_definitions/backgroundSection");
|
||||
resolveFeatureFromFile("./cypress/integration/BackgroundSection.feature");
|
||||
});
|
||||
|
||||
describe("Regexp", () => {
|
||||
require("../cypress/support/step_definitions/regexp");
|
||||
resolveFeatureFromFile("./cypress/integration/RegularExpressions.feature");
|
||||
});
|
||||
|
||||
describe("Custom Parameter Types", () => {
|
||||
require("../cypress/support/step_definitions/customParameterTypes");
|
||||
resolveFeatureFromFile("./cypress/integration/CustomParameterTypes.feature");
|
||||
});
|
||||
|
||||
describe("Tags implementation", () => {
|
||||
require("../cypress/support/step_definitions/tags_implementation");
|
||||
resolveFeatureFromFile("./cypress/integration/TagsImplementation.feature");
|
||||
});
|
||||
|
||||
describe("Tags with env TAGS set", () => {
|
||||
window.Cypress = {
|
||||
...window.Cypress,
|
||||
env: () => "@test-tag and not @ignore-tag",
|
||||
};
|
||||
require("../cypress/support/step_definitions/tags_implementation_with_env_set");
|
||||
resolveFeatureFromFile(
|
||||
"./cypress/integration/TagsImplementationWithEnvSet.feature"
|
||||
);
|
||||
|
||||
resolveFeatureFromFile(
|
||||
"./cypress/integration/TagsImplementationWithEnvSetScenarioLevel.feature"
|
||||
);
|
||||
});
|
||||
|
||||
describe("Smart tagging", () => {
|
||||
window.Cypress = {
|
||||
...window.Cypress,
|
||||
env: () => "",
|
||||
};
|
||||
require("../cypress/support/step_definitions/smart_tagging");
|
||||
resolveFeatureFromFile("./cypress/integration/SmartTagging.feature");
|
||||
});
|
||||
|
||||
describe("And and But", () => {
|
||||
require("../cypress/support/step_definitions/and_and_but_steps");
|
||||
resolveFeatureFromFile("./cypress/integration/AndAndButSteps.feature");
|
||||
});
|
||||
|
||||
describe("defineStep", () => {
|
||||
require("../cypress/support/step_definitions/usingDefineSteps");
|
||||
resolveFeatureFromFile("./cypress/integration/DefineStep.feature");
|
||||
});
|
||||
|
||||
describe("Before and After", () => {
|
||||
require("../cypress/support/step_definitions/before_and_after_steps");
|
||||
resolveFeatureFromFile("./cypress/integration/BeforeAndAfterSteps.feature");
|
||||
});
|
32
node_modules/cypress-cucumber-preprocessor/lib/stepDefinitionPath.js
generated
vendored
Normal file
32
node_modules/cypress-cucumber-preprocessor/lib/stepDefinitionPath.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const { getConfig } = require("./getConfig");
|
||||
|
||||
module.exports = () => {
|
||||
const appRoot = process.cwd();
|
||||
const config = getConfig();
|
||||
if (config) {
|
||||
// left for backward compability, but we need the consistency with other configuration options
|
||||
const confStepDefinitions = config.step_definitions
|
||||
? config.step_definitions
|
||||
: config.stepDefinitions;
|
||||
|
||||
if (config.nonGlobalStepDefinitions) {
|
||||
const relativePath =
|
||||
confStepDefinitions || `cypress${path.sep}integration`;
|
||||
const stepsPath = path.resolve(appRoot, relativePath);
|
||||
|
||||
if (!fs.existsSync(stepsPath)) {
|
||||
throw new Error(
|
||||
`We've tried to resolve your step definitions at ${relativePath}, but that doesn't seem to exist. As of version 2.0.0 it's required to set step_definitions in your cypress-cucumber-preprocessor configuration. Look for nonGlobalStepDefinitions and add stepDefinitions right next to it. It should match your cypress configuration has set for integrationFolder. We no longer rely on getting information from that file as it was unreliable and problematic across Linux/MacOS/Windows especially since the config file could have been passed as an argument to cypress.`
|
||||
);
|
||||
}
|
||||
return stepsPath;
|
||||
}
|
||||
if (confStepDefinitions) {
|
||||
return path.resolve(appRoot, confStepDefinitions);
|
||||
}
|
||||
}
|
||||
|
||||
return `${appRoot}/cypress/support/step_definitions`;
|
||||
};
|
92
node_modules/cypress-cucumber-preprocessor/lib/stepDefinitionPath.test.js
generated
vendored
Normal file
92
node_modules/cypress-cucumber-preprocessor/lib/stepDefinitionPath.test.js
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
const fs = require("fs");
|
||||
const { sep } = require("path");
|
||||
const { getConfig } = require("./getConfig");
|
||||
const stepDefinitionPath = require("./stepDefinitionPath");
|
||||
|
||||
jest.mock("./getConfig");
|
||||
jest.mock("fs", () => ({
|
||||
existsSync: jest.fn(),
|
||||
}));
|
||||
|
||||
const defaultNonGlobalStepDefinitionsPath = `cypress${sep}integration`;
|
||||
|
||||
describe("load path from step definitions", () => {
|
||||
beforeEach(() => {
|
||||
getConfig.mockReset();
|
||||
fs.existsSync.mockReset();
|
||||
});
|
||||
|
||||
test("Should throw an error if nonGlobalStepDefinitions and stepDefinitions are not set and the default is wrong", () => {
|
||||
getConfig.mockReturnValue({
|
||||
nonGlobalStepDefinitions: true,
|
||||
});
|
||||
fs.existsSync.mockReturnValue(false);
|
||||
|
||||
const errorMessage = `We've tried to resolve your step definitions at ${defaultNonGlobalStepDefinitionsPath}, but that doesn't seem to exist. As of version 2.0.0 it's required to set step_definitions in your cypress-cucumber-preprocessor configuration. Look for nonGlobalStepDefinitions and add stepDefinitions right next to it. It should match your cypress configuration has set for integrationFolder. We no longer rely on getting information from that file as it was unreliable and problematic across Linux/MacOS/Windows especially since the config file could have been passed as an argument to cypress.`;
|
||||
expect(stepDefinitionPath).throw(errorMessage);
|
||||
});
|
||||
|
||||
test("Should throw an error if nonGlobalStepDefinitions and stepDefinitions are set but the folder doesn't exist", () => {
|
||||
const stepDefinitions = "cypress/stepDefinitions";
|
||||
getConfig.mockReturnValue({
|
||||
nonGlobalStepDefinitions: true,
|
||||
stepDefinitions,
|
||||
});
|
||||
fs.existsSync.mockReturnValue(false);
|
||||
|
||||
const errorMessage = `We've tried to resolve your step definitions at ${stepDefinitions}, but that doesn't seem to exist. As of version 2.0.0 it's required to set step_definitions in your cypress-cucumber-preprocessor configuration. Look for nonGlobalStepDefinitions and add stepDefinitions right next to it. It should match your cypress configuration has set for integrationFolder. We no longer rely on getting information from that file as it was unreliable and problematic across Linux/MacOS/Windows especially since the config file could have been passed as an argument to cypress.`;
|
||||
expect(stepDefinitionPath).throw(errorMessage);
|
||||
});
|
||||
|
||||
test("should use the default stepDefinitions path for nonGlobalStepDefinitions", () => {
|
||||
const appRoot = process.cwd();
|
||||
getConfig.mockReturnValue({
|
||||
nonGlobalStepDefinitions: true,
|
||||
});
|
||||
fs.existsSync.mockReturnValue(true);
|
||||
|
||||
expect(stepDefinitionPath()).to.equal(
|
||||
`${appRoot}${sep}${defaultNonGlobalStepDefinitionsPath}`
|
||||
);
|
||||
});
|
||||
|
||||
test("should use the stepDefinitions path for nonGlobalStepDefinitions", () => {
|
||||
const appRoot = process.cwd();
|
||||
getConfig.mockReturnValue({
|
||||
step_definitions: "./e2e/support/step-definitions",
|
||||
});
|
||||
|
||||
expect(stepDefinitionPath()).to.equal(
|
||||
`${appRoot}${sep}e2e${sep}support${sep}step-definitions`
|
||||
);
|
||||
});
|
||||
|
||||
test("should use the stepDefinitions path", () => {
|
||||
const appRoot = process.cwd();
|
||||
getConfig.mockReturnValue({
|
||||
step_definitions: "./e2e/support/step-definitions",
|
||||
});
|
||||
|
||||
expect(stepDefinitionPath()).to.equal(
|
||||
`${appRoot}${sep}e2e${sep}support${sep}step-definitions`
|
||||
);
|
||||
});
|
||||
|
||||
test("should return default path if stepDefinition are not configured and nonGlobalStepDefinitions are not set", () => {
|
||||
const appRoot = process.cwd();
|
||||
expect(stepDefinitionPath()).to.equal(
|
||||
`${appRoot}/cypress/support/step_definitions`
|
||||
);
|
||||
});
|
||||
|
||||
test("should allow the backward compatible use of step_definitions in cosmiconfig", () => {
|
||||
const appRoot = process.cwd();
|
||||
getConfig.mockReturnValue({
|
||||
step_definitions: "./e2e/support/step-definitions",
|
||||
});
|
||||
|
||||
expect(stepDefinitionPath()).to.equal(
|
||||
`${appRoot}${sep}e2e${sep}support${sep}step-definitions`
|
||||
);
|
||||
});
|
||||
});
|
23
node_modules/cypress-cucumber-preprocessor/lib/tagsHelper.js
generated
vendored
Normal file
23
node_modules/cypress-cucumber-preprocessor/lib/tagsHelper.js
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
const { TagExpressionParser } = require("cucumber-tag-expressions");
|
||||
|
||||
function getEnvTags() {
|
||||
return Cypress.env("TAGS") || "";
|
||||
}
|
||||
|
||||
function shouldProceedCurrentStep(tags = [], envTags = getEnvTags()) {
|
||||
const parser = new TagExpressionParser();
|
||||
try {
|
||||
const expressionNode = parser.parse(envTags);
|
||||
const mappedTags = tags.map((tag) => tag.name);
|
||||
return expressionNode.evaluate(mappedTags);
|
||||
} catch (e) {
|
||||
/* eslint-disable-next-line no-console */
|
||||
console.log(`Error parsing tags: '${envTags}'. Message: ${e.message}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
shouldProceedCurrentStep,
|
||||
getEnvTags,
|
||||
};
|
14
node_modules/cypress-cucumber-preprocessor/lib/tagsInheritance.test.js
generated
vendored
Normal file
14
node_modules/cypress-cucumber-preprocessor/lib/tagsInheritance.test.js
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
/* eslint-disable global-require */
|
||||
const {
|
||||
resolveFeatureFromFile,
|
||||
} = require("./testHelpers/resolveFeatureFromFile");
|
||||
|
||||
describe("Tags inheritance", () => {
|
||||
window.Cypress = {
|
||||
...window.Cypress,
|
||||
env: () => "@inherited-tag and @own-tag",
|
||||
};
|
||||
|
||||
require("../cypress/support/step_definitions/tags_implementation_with_env_set");
|
||||
resolveFeatureFromFile("./cypress/integration/TagsInheritance.feature");
|
||||
});
|
13
node_modules/cypress-cucumber-preprocessor/lib/testHelpers/resolveFeatureFromFile.js
generated
vendored
Normal file
13
node_modules/cypress-cucumber-preprocessor/lib/testHelpers/resolveFeatureFromFile.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/* eslint-disable global-require */
|
||||
const fs = require("fs");
|
||||
|
||||
const { createTestsFromFeature } = require("../createTestsFromFeature");
|
||||
|
||||
const resolveFeatureFromFile = (featureFile) => {
|
||||
const spec = fs.readFileSync(featureFile);
|
||||
createTestsFromFeature(featureFile, spec);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
resolveFeatureFromFile,
|
||||
};
|
68
node_modules/cypress-cucumber-preprocessor/lib/testHelpers/setupTestFramework.js
generated
vendored
Normal file
68
node_modules/cypress-cucumber-preprocessor/lib/testHelpers/setupTestFramework.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
global.jestExpect = global.expect;
|
||||
global.expect = require("chai").expect;
|
||||
|
||||
global.before = jest.fn();
|
||||
global.after = jest.fn();
|
||||
global.skip = jest.fn();
|
||||
|
||||
window.Cypress = {
|
||||
env: jest.fn(),
|
||||
on: jest.fn(),
|
||||
off: jest.fn(),
|
||||
log: jest.fn(),
|
||||
mocha: {
|
||||
getRunner: () => {
|
||||
return {
|
||||
on: jest.fn(),
|
||||
};
|
||||
},
|
||||
},
|
||||
Promise: { each: (iterator, iteree) => iterator.map(iteree) },
|
||||
};
|
||||
|
||||
const {
|
||||
defineParameterType,
|
||||
defineStep,
|
||||
When,
|
||||
Then,
|
||||
Given,
|
||||
And,
|
||||
But,
|
||||
Before,
|
||||
After,
|
||||
} = require("../resolveStepDefinition");
|
||||
|
||||
const mockedThen = (funcOrConfig, func) => {
|
||||
if (typeof funcOrConfig === "object") {
|
||||
func();
|
||||
} else {
|
||||
funcOrConfig();
|
||||
}
|
||||
return { then: mockedThen };
|
||||
};
|
||||
|
||||
const mockedPromise = (func) => {
|
||||
func();
|
||||
return { then: mockedThen };
|
||||
};
|
||||
|
||||
window.defineParameterType = defineParameterType;
|
||||
window.When = When;
|
||||
window.Then = Then;
|
||||
window.Given = Given;
|
||||
window.And = And;
|
||||
window.But = But;
|
||||
window.Before = Before;
|
||||
window.After = After;
|
||||
window.defineStep = defineStep;
|
||||
window.cy = {
|
||||
log: jest.fn(),
|
||||
logStep: mockedPromise,
|
||||
startScenario: mockedPromise,
|
||||
finishScenario: mockedPromise,
|
||||
startStep: mockedPromise,
|
||||
finishStep: mockedPromise,
|
||||
finishTest: mockedPromise,
|
||||
then: mockedThen,
|
||||
end: mockedPromise,
|
||||
};
|
Reference in New Issue
Block a user