@badeball/cypress-cucumber-preprocessor
Version:
[](https://github.com/badeball/cypress-cucumber-preprocessor/actions/workflows/build.yml) [ || (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 () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.retrieveInternalSpecProperties = retrieveInternalSpecProperties;
exports.default = createTests;
const cucumber_expressions_1 = require("@cucumber/cucumber-expressions");
const messages = __importStar(require("@cucumber/messages"));
const tag_expressions_1 = __importDefault(require("@cucumber/tag-expressions"));
const seedrandom_1 = __importDefault(require("seedrandom"));
const uuid_1 = require("uuid");
const constants_1 = require("./constants");
const cypress_task_definitions_1 = require("./cypress-task-definitions");
const data_table_1 = __importDefault(require("./data_table"));
const assertions_1 = require("./helpers/assertions");
const ast_1 = require("./helpers/ast");
const cypress_1 = require("./helpers/cypress");
const environment_1 = require("./helpers/environment");
const messages_1 = require("./helpers/messages");
const options_1 = require("./helpers/options");
const snippets_1 = require("./helpers/snippets");
const strings_1 = require("./helpers/strings");
const tag_parser_1 = require("./helpers/tag-parser");
const type_guards_1 = require("./helpers/type-guards");
const registry_1 = require("./registry");
function getSourceReferenceFromPosition(position) {
if (position) {
return {
uri: position.source,
location: { line: position.line, column: position.column },
};
}
else {
return {
uri: "not available",
location: { line: 0, column: 0 },
};
}
}
function convertReturnValueToTestStepResultStatus(retval) {
if (retval === "skipped") {
return messages.TestStepResultStatus.SKIPPED;
}
else if (retval === "pending") {
return messages.TestStepResultStatus.PENDING;
}
else {
return messages.TestStepResultStatus.PASSED;
}
}
const internalPropertiesReplacementText = "Internal properties of cypress-cucumber-preprocessor omitted from report.";
const noopFn = () => { };
function retrieveInternalSpecProperties() {
return Cypress.env(constants_1.INTERNAL_SPEC_PROPERTIES);
}
function updateInternalSpecProperties(newProperties) {
Object.assign(retrieveInternalSpecProperties(), newProperties);
}
function retrieveInternalSuiteProperties() {
return Cypress.env(constants_1.INTERNAL_SUITE_PROPERTIES);
}
function taskSpecEnvelopes(context) {
if (context.isTrackingState) {
cy.task(cypress_task_definitions_1.TASK_SPEC_ENVELOPES, { messages: context.specEnvelopes }, {
log: false,
});
}
}
function taskTestCaseStarted(context, testCaseStarted) {
if (context.isTrackingState) {
cy.task(cypress_task_definitions_1.TASK_TEST_CASE_STARTED, testCaseStarted, {
log: false,
});
}
}
function taskTestCaseFinished(context, testCasefinished) {
if (context.isTrackingState) {
cy.task(cypress_task_definitions_1.TASK_TEST_CASE_FINISHED, testCasefinished, {
log: false,
});
}
}
function taskTestStepStarted(context, testStepStarted) {
if (context.isTrackingState) {
cy.task(cypress_task_definitions_1.TASK_TEST_STEP_STARTED, testStepStarted, {
log: false,
});
}
}
function taskTestStepFinished(context, testStepfinished) {
if (context.isTrackingState) {
cy.task(cypress_task_definitions_1.TASK_TEST_STEP_FINISHED, testStepfinished, {
log: false,
});
}
}
function taskRunHookStarted(context, testRunHookStarted) {
if (context.isTrackingState) {
cy.task(cypress_task_definitions_1.TASK_TEST_RUN_HOOK_STARTED, testRunHookStarted, {
log: false,
});
}
}
function taskRunHookFinished(context, testRunHookFinished) {
if (context.isTrackingState) {
cy.task(cypress_task_definitions_1.TASK_TEST_RUN_HOOK_FINISHED, testRunHookFinished, {
log: false,
});
}
}
function taskFrontEndTrackingError(error) {
var _a;
cy.task(cypress_task_definitions_1.TASK_FRONTEND_TRACKING_ERROR, ((_a = error.stack) !== null && _a !== void 0 ? _a : error.message), {
log: true,
});
}
function taskSuggestion(context, suggestion) {
if (context.isTrackingState) {
return cy.task(cypress_task_definitions_1.TASK_SUGGESTION, suggestion, {
log: false,
});
}
else {
return cy.wrap({}, { log: false });
}
}
function emitSkippedPickle(context, pickle) {
var _a;
const { registry } = context;
const testCaseId = pickle.id;
const pickleSteps = (_a = pickle.steps) !== null && _a !== void 0 ? _a : [];
const tags = (0, ast_1.collectTagNames)(pickle.tags);
const beforeHooks = registry.resolveBeforeHooks(tags);
const afterHooks = registry.resolveAfterHooks(tags);
const testCaseStartedId = context.newId();
const timestamp = (0, messages_1.createTimestamp)();
const steps = [
...beforeHooks,
...pickleSteps,
...afterHooks,
];
taskTestCaseStarted(context, {
id: testCaseStartedId,
testCaseId,
attempt: 0,
timestamp,
});
for (const step of steps) {
const testStepId = getTestStepId({
context,
pickleId: pickle.id,
hookIdOrPickleStepId: step.id,
});
taskTestStepStarted(context, {
testStepId,
testCaseStartedId,
timestamp,
});
taskTestStepFinished(context, {
testStepId,
testCaseStartedId,
testStepResult: {
status: messages.TestStepResultStatus.SKIPPED,
duration: {
seconds: 0,
nanos: 0,
},
},
timestamp,
});
}
taskTestCaseFinished(context, {
testCaseStartedId,
timestamp,
willBeRetried: false,
});
}
function findPickleById(context, astId) {
return (0, assertions_1.ensure)(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.ensure)(examples.tableBody, "Expected to find a table body").map((row) => (0, assertions_1.ensure)(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.
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.ensure)((0, assertions_1.ensure)(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 createFeature(context, feature) {
var _a;
const suiteOptions = Object.fromEntries((0, options_1.tagsToOptions)(feature.tags).filter(options_1.isExclusivelySuiteConfiguration));
const mochaGlobals = (_a = globalThis["__cypress_cucumber_preprocessor_mocha_dont_use_this"]) !== null && _a !== void 0 ? _a : globalThis;
describe(feature.name || "<unamed feature>", suiteOptions, () => {
mochaGlobals.before(function () {
beforeHandler.call(this, context);
});
mochaGlobals.beforeEach(function () {
beforeEachHandler.call(this, context);
});
mochaGlobals.after(function () {
afterHandler.call(this, context);
});
mochaGlobals.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.ensure)(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;
}
}
}
const suiteOptions = Object.fromEntries((0, options_1.tagsToOptions)(rule.tags).filter(options_1.isExclusivelySuiteConfiguration));
describe(rule.name || "<unamed rule>", suiteOptions, () => {
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.ensure)(scenario.id, "Expected scenario to have an id");
const pickle = findPickleById(context, scenarioId);
createPickle(context, pickle);
}
}
function createPickle(context, pickle) {
var _a, _b, _c;
const { registry, gherkinDocument, pickles, testFilter, dryRun } = 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 scenario = (0, assertions_1.ensure)(context.astIdsMap.get((0, assertions_1.ensure)((_b = pickle.astNodeIds) === null || _b === void 0 ? void 0 : _b[0], "Expected to find at least one astNodeId")), `Expected to find scenario associated with id = ${(_c = pickle.astNodeIds) === null || _c === void 0 ? void 0 : _c[0]}`);
(0, assertions_1.assert)("tags" in scenario, "Expected a scenario to have a tags property");
(0, assertions_1.assert)("examples" in scenario, "Expected a scenario to have a examples property");
const testSpecificOptions = (0, options_1.tagsToOptions)([
...scenario.tags,
...scenario.examples.flatMap((example) => example.tags),
]);
for (const entry of testSpecificOptions) {
if ((0, options_1.isExclusivelySuiteConfiguration)(entry)) {
throw new Error(`The \`${entry[0]}\` configuration can only be overridden from a suite-level override (in Cucumber-terms this means on a Feature or Rule).`);
}
}
const inheritedTestOptions = Object.fromEntries(tags
.filter(tag_parser_1.looksLikeOptions)
.map(tag_parser_1.tagToCypressOptions)
.filter(options_1.isNotExclusivelySuiteConfiguration));
if (inheritedTestOptions.env) {
Object.assign(inheritedTestOptions.env, internalEnv);
}
else {
inheritedTestOptions.env = internalEnv;
}
it(scenarioName, inheritedTestOptions, function () {
var _a, _b, _c, _d, _e;
/**
* This must always be true, otherwise something is off.
*/
(0, assertions_1.assert)(context.includedPickles[0].id === pickle.id, "Included pickle stack is unsynchronized");
const { remainingSteps, testCaseStartedId } = retrieveInternalSpecProperties();
taskTestCaseStarted(context, {
id: testCaseStartedId,
testCaseId,
attempt: attempt++,
timestamp: (0, messages_1.createTimestamp)(),
});
window.testState = {
gherkinDocument,
pickles,
pickle,
};
const onAfterStep = (options) => {
var _a, _b, _c;
const { testStepId, testStepResult } = options;
const end = (0, messages_1.createTimestamp)();
if (testStepResult.status === messages.TestStepResultStatus.PENDING ||
testStepResult.status === messages.TestStepResultStatus.SKIPPED) {
taskTestStepFinished(context, {
testStepId,
testCaseStartedId,
testStepResult,
timestamp: end,
});
remainingSteps.shift();
for (const skippedStep of remainingSteps) {
const hookIdOrPickleStepId = (0, assertions_1.ensure)((_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)(),
});
}
for (let i = 0, count = remainingSteps.length; i < count; i++) {
remainingSteps.pop();
}
cy.then(() => this.skip());
}
else {
taskTestStepFinished(context, {
testStepId,
testCaseStartedId,
testStepResult,
timestamp: (0, messages_1.createTimestamp)(),
});
remainingSteps.shift();
}
};
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,
};
return (0, cypress_1.runStepWithLogGroup)({
fn: dryRun
? noopFn
: () => registry.runCaseHook(this, hook, options),
keyword: hook.keyword,
text: createStepDescription(hook),
})
.then(convertReturnValueToTestStepResultStatus)
.then((status) => {
return { start, status };
});
})
.then(({ start, status }) => onAfterStep({
testStepResult: {
status,
duration: (0, messages_1.duration)(start, (0, messages_1.createTimestamp)()),
},
testStepId,
}));
}
else if (step.pickleStep) {
const pickleStep = step.pickleStep;
const testStepId = getTestStepId({
context,
pickleId: pickle.id,
hookIdOrPickleStepId: pickleStep.id,
});
const text = (0, assertions_1.ensure)(pickleStep.text, "Expected pickle step to have a text");
const scenarioStep = (0, assertions_1.ensure)(context.astIdsMap.get((0, assertions_1.ensure)((_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((results) => {
const start = (0, messages_1.createTimestamp)();
return (0, cypress_1.runStepWithLogGroup)({
keyword: "BeforeStep",
text: createStepDescription(beforeStepHook),
fn: dryRun
? noopFn
: () => registry.runStepHook(this, beforeStepHook, options),
})
.then(convertReturnValueToTestStepResultStatus)
.then((status) => results.concat({
status,
duration: (0, messages_1.duration)(start, (0, messages_1.createTimestamp)()),
}));
});
}, cy.wrap([], { log: false }));
const afterStepHooksChain = () => afterStepHooks.reduce((chain, afterStepHook) => {
return chain.then((results) => {
const start = (0, messages_1.createTimestamp)();
return (0, cypress_1.runStepWithLogGroup)({
keyword: "AfterStep",
text: createStepDescription(afterStepHook),
fn: dryRun
? noopFn
: () => registry.runStepHook(this, afterStepHook, options),
})
.then(convertReturnValueToTestStepResultStatus)
.then((status) => results.concat({
status,
duration: (0, messages_1.duration)(start, (0, messages_1.createTimestamp)()),
}));
});
}, cy.wrap([], {
log: false,
}));
return beforeHooksChain()
.then((beforeStepHookResults) => {
return (0, cypress_1.runStepWithLogGroup)({
keyword: (0, assertions_1.ensure)("keyword" in scenarioStep && scenarioStep.keyword, "Expected to find a keyword in the scenario step"),
argument,
text,
fn: () => {
var _a, _b;
try {
return registry.runStepDefinition(this, text, dryRun, argument);
}
catch (e) {
if (e instanceof registry_1.MissingDefinitionError ||
e instanceof registry_1.MultipleDefinitionsError) {
this.test._retries = this.test._currentRetry;
}
if (e instanceof registry_1.MissingDefinitionError) {
let parameterType = null;
if ((_a = pickleStep.argument) === null || _a === void 0 ? void 0 : _a.dataTable) {
parameterType = "dataTable";
}
else if ((_b = pickleStep.argument) === null || _b === void 0 ? void 0 : _b.docString) {
parameterType = "docString";
}
const snippets = new cucumber_expressions_1.CucumberExpressionGenerator(() => context.registry.parameterTypeRegistry
.parameterTypes)
.generateExpressions(pickleStep.text)
.map((expression) => (0, snippets_1.generateSnippet)(expression, (0, assertions_1.ensure)(pickleStep.type, "Expected pickleStep to have a type"), parameterType));
return taskSuggestion(context, {
id: context.newId(),
pickleStepId: pickleStep.id,
snippets: snippets.map((code) => {
return {
language: "javascript",
code,
};
}),
}).then(() => {
throw new Error(createMissingStepDefinitionMessage(context, pickleStep, snippets));
});
}
else {
throw e;
}
}
},
})
.then(convertReturnValueToTestStepResultStatus)
.then((status) => {
const testStepResult = {
status,
duration: (0, messages_1.duration)(start, (0, messages_1.createTimestamp)()),
};
return {
beforeStepHookResults,
testStepResult,
};
});
})
.then(({ beforeStepHookResults, testStepResult }) => {
return afterStepHooksChain().then((afterStepHookResults) => {
return messages.getWorstTestStepResult([
...beforeStepHookResults,
testStepResult,
...afterStepHookResults,
]);
});
});
})
.then((testStepResult) => onAfterStep({ testStepResult, testStepId }));
}
}
});
}
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 usually means you've not invoked `addCucumberPreprocessorPlugin()` or not returned the config object in `setupNodeEvents()`)");
}
const { registry } = context;
taskSpecEnvelopes(context);
registry.resolveBeforeAllHooks().reduce((chain, hook) => {
return chain.then(() => {
const testRunHookStartedId = context.newId();
const start = (0, messages_1.createTimestamp)();
taskRunHookStarted(context, {
id: testRunHookStartedId,
hookId: hook.id,
testRunStartedId: (0, assertions_1.ensure)(Cypress.env("testRunStartedId"), "Expected to find a testRunStartedId"),
timestamp: start,
});
(0, cypress_1.runStepWithLogGroup)({
fn: context.dryRun ? noopFn : () => registry.runRunHook(this, hook),
keyword: "BeforeAll",
}).then(() => {
taskRunHookFinished(context, {
testRunHookStartedId,
timestamp: (0, messages_1.createTimestamp)(),
result: {
duration: (0, messages_1.duration)(start, (0, messages_1.createTimestamp)()),
status: messages.TestStepResultStatus.PASSED,
},
});
});
});
}, cy.wrap({}, { log: false }));
while (context.includedPickles.length > 0 &&
context.includedPickles[0].willBekipped) {
emitSkippedPickle(context, context.includedPickles.shift());
}
}
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;
(0, registry_1.freeRegistry)();
const properties = retrieveInternalSpecProperties();
const { pickle, testCaseStartedId, currentStepStartedAt, remainingSteps } = properties;
const endTimestamp = (0, messages_1.createTimestamp)();
if (remainingSteps.length > 0) {
try {
if (((_a = this.currentTest) === null || _a === void 0 ? void 0 : _a.state) === "failed") {
const error = (0, assertions_1.ensure)((_b = this.currentTest) === null || _b === void 0 ? void 0 : _b.err, "Expected to find an error");
const message = (0, assertions_1.ensure)(error.message, "Expected to find an error message");
if (constants_1.EACH_HOOK_FAILURE_EXPR.test(message) ||
constants_1.ALL_HOOK_FAILURE_EXPR.test(message)) {
return;
}
const failedStep = (0, assertions_1.ensure)(remainingSteps.shift(), "Expected there to be a remaining step");
const hookIdOrPickleStepId = (0, assertions_1.ensure)((_d = (_c = failedStep.hook) === null || _c === void 0 ? void 0 : _c.id) !== null && _d !== void 0 ? _d : (_e = failedStep.pickleStep) === null || _e === void 0 ? void 0 : _e.id, "Expected a step to either be a hook or a pickleStep");
const testStepId = getTestStepId({
context,
pickleId: pickle.id,
hookIdOrPickleStepId,
});
const wasUndefinedStepDefinition = message.includes("Step implementation missing");
const failedTestStepFinished = wasUndefinedStepDefinition
? {
testStepId,
testCaseStartedId,
testStepResult: {
status: messages.TestStepResultStatus.UNDEFINED,
duration: {
seconds: 0,
nanos: 0,
},
},
timestamp: endTimestamp,
}
: {
testStepId,
testCaseStartedId,
testStepResult: Object.assign(Object.assign({}, (message.includes("Multiple matching step definitions for")
? {
status: messages.TestStepResultStatus.AMBIGUOUS,
}
: {
status: messages.TestStepResultStatus.FAILED,
exception: { type: error.name || "Error", message },
message,
})), { duration: (0, messages_1.duration)((0, assertions_1.ensure)(currentStepStartedAt, "Expected there to be a timestamp for current step"), endTimestamp) }),
timestamp: endTimestamp,
};
taskTestStepFinished(context, failedTestStepFinished);
for (const skippedStep of remainingSteps) {
const hookIdOrPickleStepId = (0, assertions_1.ensure)((_g = (_f = skippedStep.hook) === null || _f === void 0 ? void 0 : _f.id) !== null && _g !== void 0 ? _g : (_h = skippedStep.pickleStep) === null || _h === void 0 ? void 0 : _h.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,
});
}
}
else if (((_j = this.currentTest) === null || _j === void 0 ? void 0 : _j.state) === "pending") {
if (currentStepStartedAt) {
const skippedStep = (0, assertions_1.ensure)(remainingSteps.shift(), "Expected there to be a remaining step");
const hookIdOrPickleStepId = (0, assertions_1.ensure)((_l = (_k = skippedStep.hook) === null || _k === void 0 ? void 0 : _k.id) !== null && _l !== void 0 ? _l : (_m = skippedStep.pickleStep) === null || _m === void 0 ? void 0 : _m.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,
});
}
for (const remainingStep of remainingSteps) {
const hookIdOrPickleStepId = (0, assertions_1.ensure)((_p = (_o = remainingStep.hook) === null || _o === void 0 ? void 0 : _o.id) !== null && _p !== void 0 ? _p : (_q = remainingStep.pickleStep) === null || _q === void 0 ? void 0 : _q.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,
});
}
}
else {
for (const remainingStep of remainingSteps) {
const hookIdOrPickleStepId = (0, assertions_1.ensure)((_s = (_r = remainingStep.hook) === null || _r === void 0 ? void 0 : _r.id) !== null && _s !== void 0 ? _s : (_t = remainingStep.pickleStep) === null || _t === void 0 ? void 0 : _t.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,
});
}
}
}
catch (e) {
if (e instanceof assertions_1.CypressCucumberAssertionError &&
context.isTrackingState &&
context.softErrors) {
taskFrontEndTrackingError(e);
}
else {
throw e;
}
}
}
const currentRetry = (0, assertions_1.ensure)((_u = this.currentTest) === null || _u === void 0 ? void 0 : _u._currentRetry, "Expected to find an attribute _currentRetry");
const retries = (0, assertions_1.ensure)((_v = this.currentTest) === null || _v === void 0 ? void 0 : _v._retries, "Expected to find an attribute _retries");
const willBeRetried = ((_w = this.currentTest) === null || _w === void 0 ? void 0 : _w.state) === "failed" ? currentRetry < retries : false;
taskTestCaseFinished(context, {
testCaseStartedId,
timestamp: endTimestamp,
willBeRetried,
});
/**
* Repopulate internal properties in case previous test is retried.
*/
if (willBeRetried) {
updateInternalSpecProperties({
testCaseStartedId: context.newId(),
remainingSteps: [...properties.allSteps],
});
}
else {
context.includedPickles.shift();
while (context.includedPickles.length > 0 &&
context.includedPickles[0].willBekipped) {
emitSkippedPickle(context, context.includedPickles.shift());
}
}
}
function afterHandler(context) {
const { registry } = context;
registry.resolveAfterAllHooks().reduce((chain, hook) => {
return chain.then(() => {
const testRunHookStartedId = context.newId();
const start = (0, messages_1.createTimestamp)();
taskRunHookStarted(context, {
id: testRunHookStartedId,
hookId: hook.id,
testRunStartedId: (0, assertions_1.ensure)(Cypress.env("testRunStartedId"), "Expected to find a testRunStartedId"),
timestamp: start,
});
(0, cypress_1.runStepWithLogGroup)({
fn: context.dryRun ? noopFn : () => registry.runRunHook(this, hook),
keyword: "AfterAll",
}).then(() => {
taskRunHookFinished(context, {
testRunHookStartedId,
timestamp: (0, messages_1.createTimestamp)(),
result: {
duration: (0, messages_1.duration)(start, (0, messages_1.createTimestamp)()),
status: messages.TestStepResultStatus.PASSED,
},
});
});
});
}, cy.wrap({}, { log: false }));
}
function createTests(registry, seed, source, gherkinDocument, pickles, isTrackingState, softErrors, omitFiltered, stepDefinitionHints, dryRun) {
const prng = (0, seedrandom_1.default)(seed.toString());
const newId = () => (0, uuid_1.v4)({
random: Uint8Array.of(...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: getSourceReferenceFromPosition(stepDefinition.position),
lexicalOrder: stepDefinition.lexicalOrder,
};
});
const runHooks = registry.runHooks.map((runHook) => {
return {
id: runHook.id,
sourceReference: getSourceReferenceFromPosition(runHook.position),
type: runHook.keyword === "BeforeAll"
? messages.HookType.BEFORE_TEST_RUN
: messages.HookType.AFTER_TEST_RUN,
lexicalOrder: runHook.lexicalOrder,
};
});
const testStepIds = new Map();
const includedPickles = pickles.filter((pickle) => {
return !omitFiltered || !shouldSkipPickle(testFilter, pickle);
});
const testCases = includedPickles.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 stepDefinitions = registry.getMatchingStepDefinitions(pickleStep.text);
return {
id: createTestStepId({
testStepIds,
newId,
pickleId: pickle.id,
hookIdOrPickleStepId: pickleStep.id,
}),
pickleStepId: pickleStep.id,
stepDefinitionIds: stepDefinitions.map((stepDefinition) => stepDefinition.id),
stepMatchArgumentsLists: stepDefinitions.map((stepDefinition) => {
const result = stepDefinition.expression.match(pickleStep.text);
return {
stepMatchArguments: (result !== null && result !== void 0 ? result : []).map((arg) => {
return {
group: mapArgumentGroup(arg.group),
parameterTypeName: arg.parameterType.name,
};
}),
};
}),
};
};
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.ensure)(gherkinDocument.uri, "Expected gherkin document to have URI"),
mediaType: messages.SourceMediaType.TEXT_X_CUCUMBER_GHERKIN_PLAIN,
},
});
specEnvelopes.push({
gherkinDocument,
});
for (const pickle of includedPickles) {
specEnvelopes.push({
pickle,
});
}
const parameterTypes = Array.from(registry.parameterTypeRegistry.parameterTypes)
.filter((parameterType) => !parameterType.builtin)
.map((parameterType) => {
return {
id: newId(),
name: parameterType.name,
preferForRegularExpressionMatch: parameterType.preferForRegexpMatch,
regularExpressions: parameterType.regexpStrings,
useForSnippets: parameterType.useForSnippets,
sourceReference: getSourceReferenceFromPosition(),
lexicalOrder: (0, assertions_1.ensure)(registry.parameterTypeOrdering.get(parameterType), "Expected parameter type to have a lexical order"),
};
});
const caseHooks = registry.caseHooks.map((hook) => {
return {
id: hook.id,
name: hook.name,
sourceReference: getSourceReferenceFromPosition(hook.position),
tagExpression: hook.tags,
type: hook.keyword === "Before"
? messages.HookType.BEFORE_TEST_CASE
: messages.HookType.AFTER_TEST_CASE,
lexicalOrder: hook.lexicalOrder,
};
});
const userCode = [
...stepDefinitions.map((stepDefinition) => {
return { stepDefinition };
}),
...runHooks.map((runHook) => {
return { runHook };
}),
...caseHooks.map((caseHook) => {
return { caseHook };
}),
...parameterTypes.map((parameterType) => {
return { parameterType };
}),
];
userCode.sort((a, b) => {
const userCodeA = a.stepDefinition || a.runHook || a.caseHook || a.parameterType;
const userCodeB = b.stepDefinition || b.runHook || b.caseHook || b.parameterType;
return userCodeA.lexicalOrder - userCodeB.lexicalOrder;
});
const omit = (obj, key) => {
const _a = obj, _b = key, _omitted = _a[_b], rest = __rest(_a, [typeof _b === "symbol" ? _b : _b + ""]);
return rest;
};
for (const userCodeEl of userCode) {
const { stepDefinition, runHook, caseHook, parameterType } = userCodeEl;
if (stepDefinition) {
specEnvelopes.push({
stepDefinition: omit(stepDefinition, "lexicalOrder"),
});
}
else if (runHook) {
specEnvelopes.push({
hook: omit(runHook, "lexicalOrder"),
});
}
else if (caseHook) {
s