UNPKG

cumulocity-cypress

Version:
282 lines (275 loc) 9.52 kB
#!/usr/bin/env node 'use strict'; var cypress = require('cypress'); var path = require('path'); var fs = require('fs'); var _ = require('lodash'); var yargs = require('yargs/yargs'); var helpers = require('yargs/helpers'); var dotenv = require('dotenv'); var c8yscrn_helper = require('./helper.js'); var debug = require('debug'); var util = require('../util-CJ8J1x_Y.js'); require('yaml'); require('../ajv-qt7Q2OLe.js'); require('semver'); require('ajv'); require('ajv-formats'); require('ajv/lib/refs/json-schema-draft-06.json'); function _interopNamespaceDefault(e) { var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n.default = e; return Object.freeze(n); } var path__namespace = /*#__PURE__*/_interopNamespaceDefault(path); var fs__namespace = /*#__PURE__*/_interopNamespaceDefault(fs); const log = debug("c8y:scrn:startup"); const logEnv = debug("c8y:scrn:env"); (async () => { try { const args = getConfigFromArgs(); if (!args.config) { throw new Error("No config file provided. Use --config option to provide the config file."); } const resolvedCypressConfig = c8yscrn_helper.resolveConfigOptions(args); let baseUrl = c8yscrn_helper.resolveBaseUrl(args); const yamlFile = path__namespace.resolve(process.cwd(), args.config); if (args.init === true) { if (!fs__namespace.existsSync(yamlFile)) { fs__namespace.writeFileSync(yamlFile, c8yscrn_helper.createInitConfig(baseUrl ?? "http://localhost:8080"), "utf8"); log(`Config file ${yamlFile} created.`); } else { throw new Error(`Config file ${yamlFile} already exists.`); } return; } if (!fs__namespace.existsSync(yamlFile)) { log(`Config file ${yamlFile} does not exist.`); throw new Error(`Config file ${yamlFile} does not exist.`); } const tags = (args.tags ?? []).join(","); log(`Running with tags: ${tags}`); const envs = { ...(dotenv.config().parsed ?? {}), ...(dotenv.config({ path: ".c8yscrn" }).parsed ?? {}), ...(tags.length > 0 ? { grepTags: tags } : {}), ..._.pickBy(process.env, (value, key) => key.startsWith("C8Y_") || key.endsWith("_username") || key.endsWith("_password")), }; logEnv(util.sanitizeStringifiedObject(JSON.stringify(envs, null, 2))); // we need to read config here to get some config values const configData = c8yscrn_helper.loadConfigFile(yamlFile); if (configData == null) { throw new Error(`Config file ${yamlFile} is empty.`); } baseUrl = baseUrl ?? configData.baseUrl ?? "http://localhost:8080"; resolvedCypressConfig.config.e2e.baseUrl = baseUrl; log(`Using baseUrl ${baseUrl}`); const screenshotsFolder = resolvedCypressConfig.config.e2e.screenshotsFolder; log(`Using screenshots folder ${screenshotsFolder}`); const cypressConfigFile = resolvedCypressConfig.configFile; log(`Using cypress config file ${cypressConfigFile}`); const browser = resolvedCypressConfig.browser; log(`Using browser ${browser}`); const browserLaunchArgs = process.env[`C8Y_${browser.toUpperCase()}_LAUNCH_ARGS`] ?? process.env.C8Y_BROWSER_LAUNCH_ARGS ?? ""; if (args.highlight === false) { log(`Disabling highlights in screenshots`); } const diffFolder = args.diffFolder != null ? c8yscrn_helper.resolveScreenshotFolder(args.diffFolder) : undefined; const failureFolder = args.failureFolder != null ? c8yscrn_helper.resolveScreenshotFolder(args.failureFolder) : undefined; let diffOptions = undefined; if (args.diff === true) { diffOptions = { ...{ antialiasing: true, noFailOnFsErrors: true, reduceRamUsage: true, }, ...(configData.global?.diff ?? {}), targetFolder: diffFolder, skipMove: args.diffSkip, }; } // https://docs.cypress.io/guides/guides/module-api const config = { ...resolvedCypressConfig, ...{ env: { ...envs, ...{ _c8yscrnHighlight: args.highlight, _c8yscrnCli: true, _c8yscrnConfigFile: yamlFile, _c8yscrnyaml: configData, _c8yscrnBrowserLaunchArgs: browserLaunchArgs, _c8yscrnDiffOptions: diffOptions, _c8yscrnFailureFolder: failureFolder, }, }, }, }; if (args.open === true) { await cypress.open(config); } else { const result = await cypress.run(config); if (isFailedRunResult(result)) { console.error(result.message); process.exit(result.failures); } else { process.exit(result.totalFailed); } } } catch (error) { console.error(error.message); process.exit(1); } })(); function isFailedRunResult(result) { return "status" in result && result.status === "failed"; } function getConfigFromArgs() { const result = yargs(helpers.hideBin(process.argv)) .usage("Usage: $0 [options]") .scriptName("c8yscrn") .command("run", "Run workflows in headless mode", (yargs) => { return runOptions(sharedOptions(yargs)); }) .command("open", "Run workflows in Cypress open mode", (yargs) => { return runOptions(sharedOptions(yargs)).options("open", { type: "boolean", default: true, hidden: true, }); }) .command("init", "Initialize and create a new config file", (yargs) => { return sharedOptions(yargs).options("init", { type: "boolean", default: true, hidden: true, }); }) .help() .wrap(100) .parseSync(); const filteredResult = Object.fromEntries(Object.entries(result).filter(([, value]) => value !== undefined)); return filteredResult; } function sharedOptions(yargs) { return yargs .option("config", { alias: "c", type: "string", requiresArg: true, description: "The yaml config file", default: "c8yscrn.config.yaml", }) .option("baseUrl", { alias: "u", type: "string", requiresArg: true, description: "The Cumulocity base url", }); } function runOptions(yargs) { return yargs .option("folder", { alias: "f", type: "string", requiresArg: true, description: "The target folder for the screenshots", }) .option("failureFolder", { alias: "e", type: "string", requiresArg: true, description: "The target folder for failure screenshots", }) .option("skipFailure", { type: "boolean", requiresArg: false, description: "Disable failure screenshots", default: false, }) .option("clear", { type: "boolean", requiresArg: false, description: "Clear the target folder and remove all data", default: false, }) .option("browser", { alias: "b", type: "string", requiresArg: true, default: "chrome", description: "Browser to use", }) .option("quiet", { type: "boolean", default: true, requiresArg: true, hidden: true, }) .option("diff", { type: "boolean", default: false, requiresArg: false, description: "Enable image diffing", }) .option("diffFolder", { type: "string", requiresArg: true, description: "Optional target folder for the diff images", }) .option("diffSkip", { type: "boolean", default: true, requiresArg: false, description: "Skip screenshots without difference", }) .option("highlight", { type: "boolean", alias: "h", default: true, requiresArg: true, description: "Enable or disable highlights in screenshots", }) .option("tags", { alias: "t", type: "array", requiresArg: true, description: "Run only screenshot workflows with the given tags", coerce: (arg) => { const result = []; (Array.isArray(arg) ? arg : [arg]).forEach((tag) => { const t = tag?.split(","); if (t != null) { result.push(...t); } }); return result; }, }); } exports.getConfigFromArgs = getConfigFromArgs;