/* 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, };