cypress-xray-plugin
Version:
A Cypress plugin for uploading test results to Xray (test management for Jira)
243 lines (238 loc) • 11.2 kB
JavaScript
;
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 () {
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 __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.resetPlugin = resetPlugin;
exports.configureXrayPlugin = configureXrayPlugin;
exports.syncFeatureFile = syncFeatureFile;
const path_1 = __importDefault(require("path"));
const context_1 = __importStar(require("./context"));
const tasks_1 = require("./cypress/tasks");
const after_run_1 = __importDefault(require("./hooks/after/after-run"));
const file_preprocessor_1 = __importDefault(require("./hooks/preprocessor/file-preprocessor"));
const dedent_1 = require("./util/dedent");
const executable_graph_1 = require("./util/graph/executable-graph");
const graph_logger_1 = require("./util/graph/logging/graph-logger");
const help_1 = require("./util/help");
const logging_1 = require("./util/logging");
let canShowInitializationWarning = true;
/**
* Resets the plugin including its context.
*/
function resetPlugin() {
context_1.default.setGlobalContext(undefined);
canShowInitializationWarning = true;
}
/**
* Configures the plugin. The plugin will check all environment variables passed in
* {@link Cypress.PluginConfigOptions.env | `config.env`} and merge them with those specified in
* `options`. Environment variables always override values specified in `options`.
*
* Note: This method will register upload hooks under the following Cypress events:
* - `after:run`
* - `on:screenshot`
* - `task`
*
* Consider using [`cypress-on-fix`](https://github.com/bahmutov/cypress-on-fix) if you have these
* hooks registered to prevent the plugin from replacing them.
*
* @param on - the Cypress event registration functon
* @param config - the Cypress configuration
* @param options - the plugin options
*
* @see https://qytera-gmbh.github.io/projects/cypress-xray-plugin/section/guides/uploadTestResults/#setup
*/
async function configureXrayPlugin(on, config, options) {
var _a;
canShowInitializationWarning = false;
// Resolve these before all other options for correct enabledness.
const pluginOptions = context_1.default.initPluginOptions(config.env, options.plugin);
if (!pluginOptions.enabled) {
logging_1.LOG.message("info", "Plugin disabled. Skipping further configuration.");
// Tasks must always be registered in case users forget to comment out imported commands.
registerDefaultTasks(on);
return;
}
// We should be using config.isInteractive here, but cannot currently because of a bug.
// See: https://github.com/cypress-io/cypress/issues/20789
if (!config.isTextTerminal) {
pluginOptions.enabled = false;
logging_1.LOG.message("info", "Interactive mode detected, disabling plugin.");
// Tasks must always be registered in case users forget to comment out imported commands.
registerDefaultTasks(on);
return;
}
// Init logging before all other configurations because they might require an initialized
// logging module.
if (!path_1.default.isAbsolute(pluginOptions.logDirectory)) {
// Cypress might change process.cwd(), so we need to query the root directory.
// See: https://github.com/cypress-io/cypress/issues/22689
pluginOptions.logDirectory = path_1.default.resolve(config.projectRoot, pluginOptions.logDirectory);
}
logging_1.LOG.configure({
debug: pluginOptions.debug,
logDirectory: pluginOptions.logDirectory,
logger: pluginOptions.logger,
});
const internalOptions = {
cucumber: await context_1.default.initCucumberOptions(config, options.cucumber),
http: options.http,
jira: context_1.default.initJiraOptions(config.env, options.jira),
plugin: pluginOptions,
xray: context_1.default.initXrayOptions(config.env, options.xray),
};
const httpClients = context_1.default.initHttpClients(internalOptions.plugin, internalOptions.http);
const logger = new logging_1.CapturingLogger();
const context = new context_1.PluginContext(await context_1.default.initClients(internalOptions.jira, internalOptions.xray, config.env, httpClients), internalOptions, config, new context_1.SimpleEvidenceCollection(), new context_1.SimpleIterationParameterCollection(), new context_1.SimpleScreenshotCollection(), new executable_graph_1.ExecutableGraph(), logger);
context_1.default.setGlobalContext(context);
const cypressTaskListener = new tasks_1.CypressTaskListener(internalOptions.jira.projectKey, context, context, logger);
if ((_a = options.plugin) === null || _a === void 0 ? void 0 : _a.listener) {
await options.plugin.listener({
on: context.getEventEmitter().on.bind(context.getEventEmitter()),
});
}
on("task", {
["cypress-xray-plugin:task:iteration:definition"]: (args) => {
return cypressTaskListener["cypress-xray-plugin:task:iteration:definition"](args);
},
["cypress-xray-plugin:task:request"]: (args) => {
if (internalOptions.xray.uploadRequests) {
return cypressTaskListener["cypress-xray-plugin:task:request"](args);
}
return args.request;
},
["cypress-xray-plugin:task:response"]: (args) => {
if (internalOptions.xray.uploadRequests) {
return cypressTaskListener["cypress-xray-plugin:task:response"](args);
}
return args.response;
},
});
on("after:screenshot", (screenshot) => {
context.addScreenshot(screenshot);
});
on("after:run", async (results) => {
if (context.getOptions().xray.uploadResults) {
if ("status" in results && results.status === "failed") {
const failedResult = results;
logging_1.LOG.message("error", (0, dedent_1.dedent)(`
Skipping results upload: Failed to run ${failedResult.failures.toString()} tests.
${failedResult.message}
`));
}
else {
await after_run_1.default.addUploadCommands(results, context.getCypressOptions().projectRoot, context.getOptions(), context.getClients(), context, context, context, context.getEventEmitter(), context.getGraph(), logger);
}
}
else {
logging_1.LOG.message("info", "Skipping results upload: Plugin is configured to not upload test results.");
}
try {
await context.getGraph().execute();
}
finally {
new graph_logger_1.ChainingCommandGraphLogger(logger).logGraph(context.getGraph());
const messages = logger.getMessages();
messages.forEach(([level, text]) => {
if (["debug", "info", "notice"].includes(level)) {
logging_1.LOG.message(level, text);
}
});
if (messages.some(([level]) => level === "warning" || level === "error")) {
logging_1.LOG.message("warning", "Encountered problems during plugin execution!");
messages
.filter(([level]) => level === "warning")
.forEach(([level, text]) => {
logging_1.LOG.message(level, text);
});
messages
.filter(([level]) => level === "error")
.forEach(([level, text]) => {
logging_1.LOG.message(level, text);
});
}
logger.getFileLogErrorMessages().forEach(([error, filename]) => {
logging_1.LOG.logErrorToFile(error, filename);
});
logger.getFileLogMessages().forEach(([data, filename]) => {
logging_1.LOG.logToFile(data, filename);
});
}
});
}
/**
* Attempts to synchronize the Cucumber feature file with Xray. If the filename does not end with
* the configured {@link https://qytera-gmbh.github.io/projects/cypress-xray-plugin/section/configuration/cucumber/#featurefileextension | feature file extension},
* this method will not upload anything to Xray.
*
* @param file - the Cypress file object
* @returns the unmodified file's path
*/
function syncFeatureFile(file) {
const context = context_1.default.getGlobalContext();
if (!context) {
if (canShowInitializationWarning) {
logging_1.LOG.message("warning", (0, dedent_1.dedent)(`
${file.filePath}
Skipping file:preprocessor hook: Plugin misconfigured: configureXrayPlugin() was not called.
Make sure your project is set up correctly: ${help_1.HELP.plugin.configuration.introduction}
`));
}
return file.filePath;
}
if (!context.getOptions().plugin.enabled) {
logging_1.LOG.message("info", (0, dedent_1.dedent)(`
${file.filePath}
Plugin disabled. Skipping feature file synchronization.
`));
return file.filePath;
}
const cucumberOptions = context.getOptions().cucumber;
if (cucumberOptions &&
file.filePath.endsWith(cucumberOptions.featureFileExtension) &&
cucumberOptions.uploadFeatures) {
file_preprocessor_1.default.addSynchronizationCommands(file, context.getOptions(), context.getClients(), context.getGraph(), context.getLogger());
}
return file.filePath;
}
function registerDefaultTasks(on) {
on("task", {
["cypress-xray-plugin:task:iteration:definition"]: (args) => args.parameters,
["cypress-xray-plugin:task:request"]: (args) => args.request,
["cypress-xray-plugin:task:response"]: (args) => args.response,
});
}