@badeball/cypress-cucumber-preprocessor
Version:
[](https://github.com/badeball/cypress-cucumber-preprocessor/actions/workflows/build.yml) [ • 38.3 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.retrieveInternalSpecProperties = void 0;
const messages = __importStar(require("@cucumber/messages"));
const tag_expressions_1 = __importDefault(require("@cucumber/tag-expressions"));
const cucumber_expressions_1 = require("@cucumber/cucumber-expressions");
const uuid_1 = require("uuid");
const seedrandom_1 = __importDefault(require("seedrandom"));
const assertions_1 = require("./helpers/assertions");
const data_table_1 = __importDefault(require("./data_table"));
const registry_1 = require("./registry");
const ast_1 = require("./helpers/ast");
const constants_1 = require("./constants");
const cypress_task_definitions_1 = require("./cypress-task-definitions");
const type_guards_1 = require("./helpers/type-guards");
const tag_parser_1 = require("./helpers/tag-parser");
const messages_1 = require("./helpers/messages");
const strings_1 = require("./helpers/strings");
const snippets_1 = require("./helpers/snippets");
const cypress_1 = require("./helpers/cypress");
const environment_1 = require("./helpers/environment");
const sourceReference = {
uri: "not available",
location: { line: 0 },
};
const internalPropertiesReplacementText = "Internal properties of cypress-cucumber-preprocessor omitted from report.";
function retrieveInternalSpecProperties() {
return Cypress.env(constants_1.INTERNAL_SPEC_PROPERTIES);
}
exports.retrieveInternalSpecProperties = retrieveInternalSpecProperties;
function updateInternalSpecProperties(newProperties) {
Object.assign(retrieveInternalSpecProperties(), newProperties);
}
function retrieveInternalSuiteProperties() {
return Cypress.env(constants_1.INTERNAL_SUITE_PROPERTIES);
}
function shouldPropagateMessages(context) {
return context.prettyEnabled || context.messagesEnabled;
}
function taskSpecEnvelopes(context) {
if (shouldPropagateMessages(context)) {
cy.task(cypress_task_definitions_1.TASK_SPEC_ENVELOPES, { messages: context.specEnvelopes }, {
log: false,
});
}
}
function taskTestCaseStarted(context, testCaseStarted) {
if (shouldPropagateMessages(context)) {
cy.task(cypress_task_definitions_1.TASK_TEST_CASE_STARTED, testCaseStarted, {
log: false,
});
}
}
function taskTestCaseFinished(context, testCasefinished) {
if (shouldPropagateMessages(context)) {
cy.task(cypress_task_definitions_1.TASK_TEST_CASE_FINISHED, testCasefinished, {
log: false,
});
}
}
function taskTestStepStarted(context, testStepStarted) {
if (shouldPropagateMessages(context)) {
cy.task(cypress_task_definitions_1.TASK_TEST_STEP_STARTED, testStepStarted, {
log: false,
});
}
}
function taskTestStepFinished(context, testStepfinished, wasLastStep) {
if (shouldPropagateMessages(context)) {
cy.task(cypress_task_definitions_1.TASK_TEST_STEP_FINISHED, Object.assign(Object.assign({}, testStepfinished), { wasLastStep }), {
log: false,
});
}
}
function findPickleById(context, astId) {
return (0, assertions_1.assertAndReturn)(context.pickles.find((pickle) => pickle.astNodeIds && pickle.astNodeIds.includes(astId)), `Expected to find a pickle associated with id = ${astId}`);
}
function collectExampleIds(examples) {
return examples
.map((examples) => {
return (0, assertions_1.assertAndReturn)(examples.tableBody, "Expected to find a table body").map((row) => (0, assertions_1.assertAndReturn)(row.id, "Expected table row to have an id"));
})
.reduce((acum, el) => acum.concat(el), []);
}
function createTestStepId(options) {
const { testStepIds, newId, pickleId, hookIdOrPickleStepId } = options;
const testStepId = newId();
let pickleStepIds;
if (testStepIds.has(pickleId)) {
// See https://github.com/microsoft/TypeScript/issues/9619.
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
pickleStepIds = testStepIds.get(pickleId);
}
else {
pickleStepIds = new Map();
testStepIds.set(pickleId, pickleStepIds);
}
pickleStepIds.set(hookIdOrPickleStepId, testStepId);
return testStepId;
}
function getTestStepId(options) {
const { context, pickleId, hookIdOrPickleStepId } = options;
return (0, assertions_1.assertAndReturn)((0, assertions_1.assertAndReturn)(context.testStepIds.get(pickleId), "Expected to find test step IDs for pickle = " + pickleId).get(hookIdOrPickleStepId), "Expected to find test step ID for hook or pickleStep = " +
hookIdOrPickleStepId);
}
function createStepDescription({ name, tags, }) {
if (name == null && tags == null) {
return;
}
else if (name == null) {
return tags;
}
else if (tags == null) {
return name;
}
else {
return `${name} (${tags})`;
}
}
function isLastEl(col, el) {
return col[col.length - 1] === el;
}
function createFeature(context, feature) {
describe(feature.name || "<unamed feature>", () => {
before(function () {
beforeHandler.call(this, context);
});
beforeEach(function () {
beforeEachHandler.call(this, context);
});
afterEach(function () {
afterEachHandler.call(this, context);
});
if (feature.children) {
for (const child of feature.children) {
if (child.scenario) {
createScenario(context, child.scenario);
}
else if (child.rule) {
createRule(context, child.rule);
}
}
}
});
}
function createRule(context, rule) {
var _a;
const picklesWithinRule = (_a = rule.children) === null || _a === void 0 ? void 0 : _a.map((child) => child.scenario).filter(type_guards_1.notNull).flatMap((scenario) => {
if (scenario.examples.length > 0) {
return collectExampleIds(scenario.examples).map((exampleId) => {
return findPickleById(context, exampleId);
});
}
else {
const scenarioId = (0, assertions_1.assertAndReturn)(scenario.id, "Expected scenario to have an id");
return findPickleById(context, scenarioId);
}
});
if (picklesWithinRule) {
if (context.omitFiltered) {
const matches = picklesWithinRule.filter((pickle) => context.testFilter.evaluate((0, ast_1.collectTagNames)(pickle.tags)));
if (matches.length === 0) {
return;
}
}
}
describe(rule.name || "<unamed rule>", () => {
if (rule.children) {
for (const child of rule.children) {
if (child.scenario) {
createScenario(context, child.scenario);
}
}
}
});
}
function createScenario(context, scenario) {
if (scenario.examples.length > 0) {
const exampleIds = collectExampleIds(scenario.examples);
for (let i = 0; i < exampleIds.length; i++) {
const exampleId = exampleIds[i];
const pickle = findPickleById(context, exampleId);
const baseName = pickle.name || "<unamed scenario>";
const exampleName = `${baseName} (example #${i + 1})`;
createPickle(context, Object.assign(Object.assign({}, pickle), { name: exampleName }));
}
}
else {
const scenarioId = (0, assertions_1.assertAndReturn)(scenario.id, "Expected scenario to have an id");
const pickle = findPickleById(context, scenarioId);
createPickle(context, pickle);
}
}
function createPickle(context, pickle) {
var _a;
const { registry, gherkinDocument, pickles, testFilter } = context;
const testCaseId = pickle.id;
const pickleSteps = (_a = pickle.steps) !== null && _a !== void 0 ? _a : [];
const scenarioName = pickle.name || "<unamed scenario>";
const tags = (0, ast_1.collectTagNames)(pickle.tags);
const beforeHooks = registry.resolveBeforeHooks(tags);
const afterHooks = registry.resolveAfterHooks(tags);
const steps = [
...beforeHooks.map((hook) => ({ hook })),
...pickleSteps.map((pickleStep) => ({ pickleStep })),
...afterHooks.map((hook) => ({ hook })),
];
if (shouldSkipPickle(testFilter, pickle)) {
if (!context.omitFiltered) {
it.skip(scenarioName);
}
return;
}
let attempt = 0;
const internalProperties = {
pickle,
testCaseStartedId: context.newId(),
allSteps: steps,
remainingSteps: [...steps],
toJSON: () => internalPropertiesReplacementText,
};
const internalEnv = {
[constants_1.INTERNAL_SPEC_PROPERTIES]: internalProperties,
};
const suiteOptions = tags
.filter(tag_parser_1.looksLikeOptions)
.map(tag_parser_1.tagToCypressOptions)
.reduce(Object.assign, {});
if (suiteOptions.env) {
Object.assign(suiteOptions.env, internalEnv);
}
else {
suiteOptions.env = internalEnv;
}
it(scenarioName, suiteOptions, function () {
var _a, _b, _c, _d, _e;
const { remainingSteps, testCaseStartedId } = retrieveInternalSpecProperties();
taskTestCaseStarted(context, {
id: testCaseStartedId,
testCaseId,
attempt: attempt++,
timestamp: (0, messages_1.createTimestamp)(),
});
window.testState = {
gherkinDocument,
pickles,
pickle,
};
for (const step of steps) {
if (step.hook) {
const hook = step.hook;
const testStepId = getTestStepId({
context,
pickleId: pickle.id,
hookIdOrPickleStepId: hook.id,
});
cy.then(() => {
delete window.testState.pickleStep;
const start = (0, messages_1.createTimestamp)();
internalProperties.currentStepStartedAt = start;
taskTestStepStarted(context, {
testStepId,
testCaseStartedId,
timestamp: start,
});
return cy.wrap(start, { log: false });
})
.then((start) => {
const options = {
pickle,
gherkinDocument,
testCaseStartedId,
};
(0, cypress_1.runStepWithLogGroup)({
fn: () => registry.runHook(this, hook, options),
keyword: hook.keyword,
text: createStepDescription(hook),
});
return cy.wrap(start, { log: false });
})
.then((start) => {
const end = (0, messages_1.createTimestamp)();
taskTestStepFinished(context, {
testStepId,
testCaseStartedId,
testStepResult: {
status: messages.TestStepResultStatus.PASSED,
duration: (0, messages_1.duration)(start, end),
},
timestamp: end,
}, isLastEl(steps, step));
remainingSteps.shift();
});
}
else if (step.pickleStep) {
const pickleStep = step.pickleStep;
const testStepId = getTestStepId({
context,
pickleId: pickle.id,
hookIdOrPickleStepId: pickleStep.id,
});
const text = (0, assertions_1.assertAndReturn)(pickleStep.text, "Expected pickle step to have a text");
const scenarioStep = (0, assertions_1.assertAndReturn)(context.astIdsMap.get((0, assertions_1.assertAndReturn)((_a = pickleStep.astNodeIds) === null || _a === void 0 ? void 0 : _a[0], "Expected to find at least one astNodeId")), `Expected to find scenario step associated with id = ${(_b = pickleStep.astNodeIds) === null || _b === void 0 ? void 0 : _b[0]}`);
const argument = ((_c = pickleStep.argument) === null || _c === void 0 ? void 0 : _c.dataTable)
? new data_table_1.default(pickleStep.argument.dataTable)
: ((_e = (_d = pickleStep.argument) === null || _d === void 0 ? void 0 : _d.docString) === null || _e === void 0 ? void 0 : _e.content)
? pickleStep.argument.docString.content
: undefined;
cy.then(() => {
window.testState.pickleStep = step.pickleStep;
const start = (0, messages_1.createTimestamp)();
internalProperties.currentStep = { pickleStep };
internalProperties.currentStepStartedAt = start;
taskTestStepStarted(context, {
testStepId,
testCaseStartedId,
timestamp: start,
});
return cy.wrap(start, { log: false });
})
.then((start) => {
const beforeStepHooks = registry.resolveBeforeStepHooks(tags);
const afterStepHooks = registry.resolveAfterStepHooks(tags);
const options = {
pickle,
pickleStep,
gherkinDocument,
testCaseStartedId,
testStepId,
};
const beforeHooksChain = beforeStepHooks.reduce((chain, beforeStepHook) => {
return chain.then(() => (0, cypress_1.runStepWithLogGroup)({
keyword: "BeforeStep",
text: createStepDescription(beforeStepHook),
fn: () => registry.runStepHook(this, beforeStepHook, options),
}));
}, cy.wrap({}, { log: false }));
return beforeHooksChain.then(() => {
try {
return (0, cypress_1.runStepWithLogGroup)({
keyword: (0, assertions_1.assertAndReturn)("keyword" in scenarioStep && scenarioStep.keyword, "Expected to find a keyword in the scenario step"),
argument,
text,
fn: () => registry.runStepDefininition(this, text, argument),
}).then((result) => {
return afterStepHooks
.reduce((chain, afterStepHook) => {
return chain.then(() => (0, cypress_1.runStepWithLogGroup)({
keyword: "AfterStep",
text: createStepDescription(afterStepHook),
fn: () => registry.runStepHook(this, afterStepHook, options),
}));
}, cy.wrap({}, { log: false }))
.then(() => {
return { start, result };
});
});
}
catch (e) {
if (e instanceof registry_1.MissingDefinitionError) {
throw new Error(createMissingStepDefinitionMessage(context, pickleStep, context.registry.parameterTypeRegistry));
}
else {
throw e;
}
}
});
})
.then(({ start, result }) => {
var _a, _b, _c;
const end = (0, messages_1.createTimestamp)();
if (result === "pending" || result === "skipped") {
if (result === "pending") {
taskTestStepFinished(context, {
testStepId,
testCaseStartedId,
testStepResult: {
status: messages.TestStepResultStatus.PENDING,
duration: (0, messages_1.duration)(start, end),
},
timestamp: end,
}, isLastEl(steps, step));
}
else {
taskTestStepFinished(context, {
testStepId,
testCaseStartedId,
testStepResult: {
status: messages.TestStepResultStatus.SKIPPED,
duration: (0, messages_1.duration)(start, end),
},
timestamp: end,
}, isLastEl(steps, step));
}
remainingSteps.shift();
for (const skippedStep of remainingSteps) {
const hookIdOrPickleStepId = (0, assertions_1.assertAndReturn)((_b = (_a = skippedStep.hook) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : (_c = skippedStep.pickleStep) === null || _c === void 0 ? void 0 : _c.id, "Expected a step to either be a hook or a pickleStep");
const testStepId = getTestStepId({
context,
pickleId: pickle.id,
hookIdOrPickleStepId,
});
taskTestStepStarted(context, {
testStepId,
testCaseStartedId,
timestamp: (0, messages_1.createTimestamp)(),
});
taskTestStepFinished(context, {
testStepId,
testCaseStartedId,
testStepResult: {
status: messages.TestStepResultStatus.SKIPPED,
duration: {
seconds: 0,
nanos: 0,
},
},
timestamp: (0, messages_1.createTimestamp)(),
}, isLastEl(remainingSteps, skippedStep));
}
for (let i = 0, count = remainingSteps.length; i < count; i++) {
remainingSteps.pop();
}
cy.then(() => this.skip());
}
else {
taskTestStepFinished(context, {
testStepId,
testCaseStartedId,
testStepResult: {
status: messages.TestStepResultStatus.PASSED,
duration: (0, messages_1.duration)(start, end),
},
timestamp: end,
}, isLastEl(steps, step));
remainingSteps.shift();
}
});
}
}
});
}
function collectTagNamesFromGherkinDocument(gherkinDocument) {
const tagNames = [];
for (const node of (0, ast_1.traverseGherkinDocument)(gherkinDocument)) {
if ("tags" in node) {
tagNames.push(...(0, ast_1.collectTagNames)(node.tags));
}
}
return tagNames;
}
function createTestFilter(gherkinDocument, environment) {
const tagsInDocument = collectTagNamesFromGherkinDocument(gherkinDocument);
if (tagsInDocument.includes("@only") || tagsInDocument.includes("@focus")) {
return (0, tag_expressions_1.default)("@only or @focus");
}
else {
const tags = (0, environment_1.getTags)(environment);
return tags ? (0, tag_expressions_1.default)(tags) : { evaluate: () => true };
}
}
function shouldSkipPickle(testFilter, pickle) {
const tags = (0, ast_1.collectTagNames)(pickle.tags);
return !testFilter.evaluate(tags) || tags.includes("@skip");
}
function beforeHandler(context) {
var _a;
if (!((_a = retrieveInternalSuiteProperties()) === null || _a === void 0 ? void 0 : _a.isEventHandlersAttached)) {
(0, assertions_1.fail)("Missing preprocessor event handlers (this usally means you've not invoked `addCucumberPreprocessorPlugin()` or not returned the config object in `setupNodeEvents()`)");
}
taskSpecEnvelopes(context);
}
function beforeEachHandler(context) {
(0, registry_1.assignRegistry)(context.registry);
}
function afterEachHandler(context) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
(0, registry_1.freeRegistry)();
const properties = retrieveInternalSpecProperties();
const { pickle, testCaseStartedId, currentStepStartedAt, remainingSteps } = properties;
const endTimestamp = (0, messages_1.createTimestamp)();
if (remainingSteps.length > 0) {
if (((_a = this.currentTest) === null || _a === void 0 ? void 0 : _a.state) === "failed") {
const error = (0, assertions_1.assertAndReturn)((_c = (_b = this.currentTest) === null || _b === void 0 ? void 0 : _b.err) === null || _c === void 0 ? void 0 : _c.message, "Expected to find an error message");
if (constants_1.HOOK_FAILURE_EXPR.test(error)) {
return;
}
const failedStep = (0, assertions_1.assertAndReturn)(remainingSteps.shift(), "Expected there to be a remaining step");
const hookIdOrPickleStepId = (0, assertions_1.assertAndReturn)((_e = (_d = failedStep.hook) === null || _d === void 0 ? void 0 : _d.id) !== null && _e !== void 0 ? _e : (_f = failedStep.pickleStep) === null || _f === void 0 ? void 0 : _f.id, "Expected a step to either be a hook or a pickleStep");
const testStepId = getTestStepId({
context,
pickleId: pickle.id,
hookIdOrPickleStepId,
});
const failedTestStepFinished = error.includes("Step implementation missing")
? {
testStepId,
testCaseStartedId,
testStepResult: {
status: messages.TestStepResultStatus.UNDEFINED,
duration: {
seconds: 0,
nanos: 0,
},
},
timestamp: endTimestamp,
}
: {
testStepId,
testCaseStartedId,
testStepResult: {
status: error.includes("Multiple matching step definitions for")
? messages.TestStepResultStatus.AMBIGUOUS
: messages.TestStepResultStatus.FAILED,
message: error,
duration: (0, messages_1.duration)((0, assertions_1.assertAndReturn)(currentStepStartedAt, "Expected there to be a timestamp for current step"), endTimestamp),
},
timestamp: endTimestamp,
};
taskTestStepFinished(context, failedTestStepFinished, remainingSteps.length === 0);
for (const skippedStep of remainingSteps) {
const hookIdOrPickleStepId = (0, assertions_1.assertAndReturn)((_h = (_g = skippedStep.hook) === null || _g === void 0 ? void 0 : _g.id) !== null && _h !== void 0 ? _h : (_j = skippedStep.pickleStep) === null || _j === void 0 ? void 0 : _j.id, "Expected a step to either be a hook or a pickleStep");
const testStepId = getTestStepId({
context,
pickleId: pickle.id,
hookIdOrPickleStepId,
});
taskTestStepStarted(context, {
testStepId,
testCaseStartedId,
timestamp: endTimestamp,
});
taskTestStepFinished(context, {
testStepId,
testCaseStartedId,
testStepResult: {
status: messages.TestStepResultStatus.SKIPPED,
duration: {
seconds: 0,
nanos: 0,
},
},
timestamp: endTimestamp,
}, isLastEl(remainingSteps, skippedStep));
}
}
else if (((_k = this.currentTest) === null || _k === void 0 ? void 0 : _k.state) === "pending") {
if (currentStepStartedAt) {
const skippedStep = (0, assertions_1.assertAndReturn)(remainingSteps.shift(), "Expected there to be a remaining step");
const hookIdOrPickleStepId = (0, assertions_1.assertAndReturn)((_m = (_l = skippedStep.hook) === null || _l === void 0 ? void 0 : _l.id) !== null && _m !== void 0 ? _m : (_o = skippedStep.pickleStep) === null || _o === void 0 ? void 0 : _o.id, "Expected a step to either be a hook or a pickleStep");
const testStepId = getTestStepId({
context,
pickleId: pickle.id,
hookIdOrPickleStepId,
});
taskTestStepFinished(context, {
testStepId,
testCaseStartedId,
testStepResult: {
status: messages.TestStepResultStatus.SKIPPED,
duration: (0, messages_1.duration)(currentStepStartedAt, endTimestamp),
},
timestamp: endTimestamp,
}, remainingSteps.length === 0);
}
for (const remainingStep of remainingSteps) {
const hookIdOrPickleStepId = (0, assertions_1.assertAndReturn)((_q = (_p = remainingStep.hook) === null || _p === void 0 ? void 0 : _p.id) !== null && _q !== void 0 ? _q : (_r = remainingStep.pickleStep) === null || _r === void 0 ? void 0 : _r.id, "Expected a step to either be a hook or a pickleStep");
const testStepId = getTestStepId({
context,
pickleId: pickle.id,
hookIdOrPickleStepId,
});
taskTestStepStarted(context, {
testStepId,
testCaseStartedId,
timestamp: endTimestamp,
});
taskTestStepFinished(context, {
testStepId,
testCaseStartedId,
testStepResult: {
status: messages.TestStepResultStatus.SKIPPED,
duration: {
seconds: 0,
nanos: 0,
},
},
timestamp: endTimestamp,
}, isLastEl(remainingSteps, remainingStep));
}
}
else {
for (const remainingStep of remainingSteps) {
const hookIdOrPickleStepId = (0, assertions_1.assertAndReturn)((_t = (_s = remainingStep.hook) === null || _s === void 0 ? void 0 : _s.id) !== null && _t !== void 0 ? _t : (_u = remainingStep.pickleStep) === null || _u === void 0 ? void 0 : _u.id, "Expected a step to either be a hook or a pickleStep");
const testStepId = getTestStepId({
context,
pickleId: pickle.id,
hookIdOrPickleStepId,
});
taskTestStepStarted(context, {
testStepId,
testCaseStartedId,
timestamp: endTimestamp,
});
taskTestStepFinished(context, {
testStepId,
testCaseStartedId,
testStepResult: {
status: messages.TestStepResultStatus.UNKNOWN,
duration: {
seconds: 0,
nanos: 0,
},
},
timestamp: endTimestamp,
}, isLastEl(remainingSteps, remainingStep));
}
}
}
const currentRetry = (0, assertions_1.assertAndReturn)((_v = this.currentTest) === null || _v === void 0 ? void 0 : _v._currentRetry, "Expected to find an attribute _currentRetry");
const retries = (0, assertions_1.assertAndReturn)((_w = this.currentTest) === null || _w === void 0 ? void 0 : _w._retries, "Expected to find an attribute _retries");
const willBeRetried = ((_x = this.currentTest) === null || _x === void 0 ? void 0 : _x.state) === "failed" ? currentRetry < retries : false;
taskTestCaseFinished(context, {
testCaseStartedId,
timestamp: endTimestamp,
willBeRetried,
});
/**
* Repopulate internal properties in case previous test is retried.
*/
updateInternalSpecProperties({
testCaseStartedId: context.newId(),
remainingSteps: [...properties.allSteps],
});
}
function createTests(registry, seed, source, gherkinDocument, pickles, prettyEnabled, messagesEnabled, omitFiltered, stepDefinitionHints) {
const prng = (0, seedrandom_1.default)(seed.toString());
const newId = () => (0, uuid_1.v4)({
random: Array.from({ length: 16 }, () => Math.floor(prng() * 256)),
});
registry.finalize(newId);
const testFilter = createTestFilter(gherkinDocument, Cypress.env());
const stepDefinitions = registry.stepDefinitions.map((stepDefinition) => {
const type = stepDefinition.expression instanceof cucumber_expressions_1.RegularExpression
? messages.StepDefinitionPatternType.REGULAR_EXPRESSION
: messages.StepDefinitionPatternType.CUCUMBER_EXPRESSION;
return {
id: stepDefinition.id,
pattern: {
type,
source: stepDefinition.expression.source,
},
sourceReference,
};
});
const testStepIds = new Map();
const testCases = pickles
.filter((pickle) => {
return !omitFiltered || !shouldSkipPickle(testFilter, pickle);
})
.map((pickle) => {
const tags = (0, ast_1.collectTagNames)(pickle.tags);
const beforeHooks = registry.resolveBeforeHooks(tags);
const afterHooks = registry.resolveAfterHooks(tags);
const hooksToStep = (hook) => {
return {
id: createTestStepId({
testStepIds,
newId,
pickleId: pickle.id,
hookIdOrPickleStepId: hook.id,
}),
hookId: hook.id,
};
};
const pickleStepToTestStep = (pickleStep) => {
const stepDefinitionIds = registry
.getMatchingStepDefinitions(pickleStep.text)
.map((stepDefinition) => stepDefinition.id);
return {
id: createTestStepId({
testStepIds,
newId,
pickleId: pickle.id,
hookIdOrPickleStepId: pickleStep.id,
}),
pickleStepId: pickleStep.id,
stepDefinitionIds,
};
};
return {
id: pickle.id,
pickleId: pickle.id,
testSteps: [
...beforeHooks.map(hooksToStep),
...pickle.steps.map(pickleStepToTestStep),
...afterHooks.map(hooksToStep),
],
};
});
const specEnvelopes = [];
specEnvelopes.push({
source: {
data: source,
uri: (0, assertions_1.assertAndReturn)(gherkinDocument.uri, "Expected gherkin document to have URI"),
mediaType: messages.SourceMediaType.TEXT_X_CUCUMBER_GHERKIN_PLAIN,
},
});
specEnvelopes.push({
gherkinDocument,
});
for (const pickle of pickles) {
specEnvelopes.push({
pickle,
});
}
for (const hook of registry.hooks) {
specEnvelopes.push({
hook: {
id: hook.id,
name: hook.name,
sourceReference,
},
});
}
for (const stepDefinition of stepDefinitions) {
specEnvelopes.push({
stepDefinition,
});
}
for (const testCase of testCases) {
specEnvelopes.push({
testCase,
});
}
const context = {
registry,
newId,
gherkinDocument,
astIdsMap: (0, ast_1.createAstIdMap)(gherkinDocument),
testStepIds,
pickles,
specEnvelopes,
testFilter,
omitFiltered,
prettyEnabled,
messagesEnabled,
stepDefinitionHints,
};
if (gherkinDocument.feature) {
createFeature(context, gherkinDocument.feature);
}
}
exports.default = createTests;
function strictIsInteractive() {
const isInteractive = Cypress.config("isInteractive");
if (typeof isInteractive === "boolean") {
return isInteractive;
}
throw new Error("Expected to find a Cypress configuration property `isInteractive`, but didn't");
}
function createMissingStepDefinitionMessage(context, pickleStep, parameterTypeRegistry) {
var _a, _b;
const noStepDefinitionPathsTemplate = `
Step implementation missing for "<text>".
We tried searching for files containing step definitions using the following search pattern templates:
<step-definitions>
These templates resolved to the following search patterns:
<step-definition-patterns>
These patterns matched **no files** containing step definitions. This almost certainly means that you have misconfigured \`stepDefinitions\`.
You can implement it using the suggestion(s) below.
<snippets>
`;
const someStepDefinitionPathsTemplate = `
Step implementation missing for "<text>".
We tried searching for files containing step definitions using the following search pattern templates:
<step-definitions>
These templates resolved to the following search patterns:
<step-definition-patterns>
These patterns matched the following files:
<step-definition-paths>
However, none of these files contained a step definition matching "<text>".
You can implement it using the suggestion(s) below.
<snippets>
`;
const { stepDefinitionHints } = context;
const template = stepDefinitionHints.stepDefinitionPaths.length > 0
? someStepDefinitionPathsTemplate
: noStepDefinitionPathsTemplate;
const maybeEscape = (string) => strictIsInteractive() ? string.replaceAll("*", "\\*") : string;
const prettyPrintList = (items) => items.map((item) => " - " + maybeEscape(item)).join("\n");
let parameter = null;
if ((_a = pickleStep.argument) === null || _a === void 0 ? void 0 : _a.dataTable) {
parameter = "dataTable";
}
else if ((_b = pickleStep.argument) === null || _b === void 0 ? void 0 : _b.docString) {
parameter = "docString";
}
const snippets = new cucumber_expressions_1.CucumberExpressionGenerator(() => parameterTypeRegistry.parameterTypes)
.generateExpressions(pickleStep.text)
.map((expression) => (0, snippets_1.generateSnippet)(expression, (0, assertions_1.assertAndReturn)(pickleStep.type, "Expected pickleStep to have a type"), parameter))
.map((snippet) => (0, strings_1.indent)(snippet, { count: 2 }))
.join("\n\n");
return (0, strings_1.stripIndent)(template)
.replaceAll("<text>", pickleStep.text)
.replaceAll("<step-definitions>", prettyPrintList([stepDefinitionHints.stepDefinitions].flat()))
.replaceAll("<step-definition-patterns>", prettyPrintList(stepDefinitionHints.stepDefinitionPatterns))
.replaceAll("<step-definition-paths>", prettyPrintList(stepDefinitionHints.stepDefinitionPaths))
.replaceAll("<snippets>", snippets);
}