UNPKG

@nx/cypress

Version:

The Nx Plugin for Cypress contains executors and generators allowing your workspace to use the powerful Cypress integration testing capabilities.

135 lines (134 loc) 4.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = cypressExecutor; const devkit_1 = require("@nx/devkit"); const fs_1 = require("fs"); const path_1 = require("path"); const ct_helpers_1 = require("../../utils/ct-helpers"); const start_dev_server_1 = require("../../utils/start-dev-server"); const Cypress = require('cypress'); // @NOTE: Importing via ES6 messes the whole test dependencies. async function cypressExecutor(options, context) { options = normalizeOptions(options, context); // this is used by cypress component testing presets to build the executor contexts with the correct configuration options. process.env.NX_CYPRESS_TARGET_CONFIGURATION = context.configurationName; let success; const generatorInstance = (0, start_dev_server_1.startDevServer)(options, context); for await (const devServerValues of generatorInstance) { try { success = await runCypress(devServerValues.baseUrl, { ...options, portLockFilePath: devServerValues.portLockFilePath, }); if (!options.watch) { generatorInstance.return(); break; } } catch (e) { devkit_1.logger.error(e.message); success = false; if (!options.watch) break; } } return { success }; } function normalizeOptions(options, context) { options.env = options.env || {}; options.testingType ??= 'e2e'; if (options.testingType === 'component') { const project = context?.projectGraph?.nodes?.[context.projectName]; if (project?.data?.root) { options.ctTailwindPath = (0, ct_helpers_1.getTempTailwindPath)(context); } } return options; } /** * @whatItDoes Initialize the Cypress test runner with the provided project configuration. * By default, Cypress will run tests from the CLI without the GUI and provide directly the results in the console output. * If `watch` is `true`: Open Cypress in the interactive GUI to interact directly with the application. */ async function runCypress(baseUrl, opts) { // Cypress expects the folder where a cypress config is present const projectFolderPath = (0, path_1.dirname)(opts.cypressConfig); const options = { project: projectFolderPath, configFile: (0, path_1.basename)(opts.cypressConfig), }; // If not, will use the `baseUrl` normally from `cypress.json` if (baseUrl) { options.config = { baseUrl }; } if (opts.browser) { options.browser = opts.browser; } if (opts.env) { options.env = { ...options.env, ...opts.env, }; } if (opts.spec) { options.spec = opts.spec; } options.tag = opts.tag; options.exit = opts.exit; options.headed = opts.headed; options.runnerUi = opts.runnerUi; if (opts.headless) { options.headless = opts.headless; } options.record = opts.record; options.key = opts.key; options.parallel = opts.parallel; options.ciBuildId = opts.ciBuildId?.toString(); options.group = opts.group; // renamed in cy 10 options.config ??= {}; options.config[opts.testingType] = { excludeSpecPattern: opts.ignoreTestFiles, }; if (opts.reporter) { options.reporter = opts.reporter; } if (opts.reporterOptions) { options.reporterOptions = opts.reporterOptions; } if (opts.quiet) { options.quiet = opts.quiet; } if (opts.autoCancelAfterFailures !== undefined) { options.autoCancelAfterFailures = opts.autoCancelAfterFailures; } options.testingType = opts.testingType; const result = await (opts.watch ? Cypress.open(options) : Cypress.run(options)); cleanupTmpFile(opts.ctTailwindPath); cleanupTmpFile(opts.portLockFilePath); if (process.env.NX_VERBOSE_LOGGING === 'true' && opts.portLockFilePath) { (0, fs_1.readdirSync)((0, path_1.dirname)(opts.portLockFilePath)).forEach((f) => { if (f.endsWith('.txt')) { devkit_1.logger.debug(`Lock file ${f} still present`); } }); } /** * `cypress.open` is returning `0` and is not of the same type as `cypress.run`. * `cypress.open` is the graphical UI, so it will be obvious to know what wasn't * working. Forcing the build to success when `cypress.open` is used. */ return !result.totalFailed && !result.failures; } function cleanupTmpFile(path) { try { if (path && (0, fs_1.existsSync)(path)) { (0, fs_1.unlinkSync)(path); } return true; } catch (err) { return false; } }