UNPKG

@nx/cypress

Version:

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

199 lines (198 loc) • 9.13 kB
"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 () { 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; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.CYPRESS_CONFIG_FILE_NAME_PATTERN = void 0; exports.addDefaultE2EConfig = addDefaultE2EConfig; exports.addDefaultCTConfig = addDefaultCTConfig; exports.addMountDefinition = addMountDefinition; exports.getProjectCypressConfigPath = getProjectCypressConfigPath; exports.resolveCypressConfigObject = resolveCypressConfigObject; const devkit_1 = require("@nx/devkit"); const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript"); exports.CYPRESS_CONFIG_FILE_NAME_PATTERN = 'cypress.config.{js,ts,mjs,cjs}'; const TS_QUERY_COMMON_JS_EXPORT_SELECTOR = 'BinaryExpression:has(Identifier[name="module"]):has(Identifier[name="exports"])'; const TS_QUERY_EXPORT_CONFIG_PREFIX = `:matches(ExportAssignment, ${TS_QUERY_COMMON_JS_EXPORT_SELECTOR}) `; async function addDefaultE2EConfig(cyConfigContents, options, baseUrl) { if (!cyConfigContents) { throw new Error('The passed in cypress config file is empty!'); } const { tsquery } = await Promise.resolve().then(() => __importStar(require('@phenomnomnominal/tsquery'))); const isCommonJS = tsquery.query(cyConfigContents, TS_QUERY_COMMON_JS_EXPORT_SELECTOR).length > 0; const testingTypeConfig = tsquery.query(cyConfigContents, `${TS_QUERY_EXPORT_CONFIG_PREFIX} PropertyAssignment:has(Identifier[name="e2e"])`); let updatedConfigContents = cyConfigContents; if (testingTypeConfig.length === 0) { const configValue = `nxE2EPreset(__filename, ${JSON.stringify(options, null, 2) .split('\n') .join('\n ')})`; updatedConfigContents = tsquery.replace(cyConfigContents, `${TS_QUERY_EXPORT_CONFIG_PREFIX} ObjectLiteralExpression:first-child`, (node) => { let baseUrlContents = baseUrl ? `,\n baseUrl: '${baseUrl}'` : ''; if (node.properties.length > 0) { return `{ ${node.properties.map((p) => p.getText()).join(',\n')}, e2e: { ...${configValue}${baseUrlContents} } }`; } return `{ e2e: { ...${configValue}${baseUrlContents} } }`; }); return isCommonJS ? `const { nxE2EPreset } = require('@nx/cypress/plugins/cypress-preset'); ${updatedConfigContents}` : `import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset'; ${updatedConfigContents}`; } return updatedConfigContents; } /** * Adds the nxComponentTestingPreset to the cypress config file * Make sure after calling this the correct import statement is addeda * to bring in the nxComponentTestingPreset function **/ async function addDefaultCTConfig(cyConfigContents, options = {}) { if (!cyConfigContents) { throw new Error('The passed in cypress config file is empty!'); } const { tsquery } = await Promise.resolve().then(() => __importStar(require('@phenomnomnominal/tsquery'))); const testingTypeConfig = tsquery.query(cyConfigContents, `${TS_QUERY_EXPORT_CONFIG_PREFIX} PropertyAssignment:has(Identifier[name="component"])`); let updatedConfigContents = cyConfigContents; if (testingTypeConfig.length === 0) { let configValue = 'nxComponentTestingPreset(__filename)'; if (options) { if (options.bundler !== 'vite') { // vite is the default bundler, so we don't need to set it delete options.bundler; } if (Object.keys(options).length) { configValue = `nxComponentTestingPreset(__filename, ${JSON.stringify(options)})`; } } updatedConfigContents = tsquery.replace(cyConfigContents, `${TS_QUERY_EXPORT_CONFIG_PREFIX} ObjectLiteralExpression:first-child`, (node) => { if (node.properties.length > 0) { return `{ ${node.properties.map((p) => p.getText()).join(',\n')}, component: ${configValue} }`; } return `{ component: ${configValue} }`; }); } return updatedConfigContents; } /** * Adds the mount command for Cypress * Make sure after calling this the correct import statement is added * to bring in the correct mount from cypress. **/ async function addMountDefinition(cmpCommandFileContents) { if (!cmpCommandFileContents) { throw new Error('The passed in cypress component file is empty!'); } const { tsquery } = await Promise.resolve().then(() => __importStar(require('@phenomnomnominal/tsquery'))); const hasMountCommand = tsquery.query(cmpCommandFileContents, 'CallExpression StringLiteral[value="mount"]')?.length > 0; if (hasMountCommand) { return cmpCommandFileContents; } const mountCommand = `Cypress.Commands.add('mount', mount);`; const updatedInterface = tsquery.replace(cmpCommandFileContents, 'InterfaceDeclaration', (node) => { return `interface ${node.name.getText()}${node.typeParameters ? `<${node.typeParameters.map((p) => p.getText()).join(', ')}>` : ''} { ${node.members.map((m) => m.getText()).join('\n ')} mount: typeof mount; }`; }); return `${updatedInterface}\n${mountCommand}`; } function getProjectCypressConfigPath(tree, projectRoot) { const cypressConfigPaths = (0, devkit_1.glob)(tree, [ (0, devkit_1.joinPathFragments)(projectRoot, exports.CYPRESS_CONFIG_FILE_NAME_PATTERN), ]); if (cypressConfigPaths.length === 0) { throw new Error(`Could not find a cypress config file in ${projectRoot}.`); } return cypressConfigPaths[0]; } function resolveCypressConfigObject(cypressConfigContents) { const ts = (0, ensure_typescript_1.ensureTypescript)(); const { tsquery } = (require('@phenomnomnominal/tsquery')); const sourceFile = tsquery.ast(cypressConfigContents); const exportDefaultStatement = sourceFile.statements.find((statement) => ts.isExportAssignment(statement)); if (exportDefaultStatement) { return resolveCypressConfigObjectFromExportExpression(exportDefaultStatement.expression, sourceFile); } const moduleExportsStatement = sourceFile.statements.find((statement) => ts.isExpressionStatement(statement) && ts.isBinaryExpression(statement.expression) && statement.expression.left.getText() === 'module.exports'); if (moduleExportsStatement) { return resolveCypressConfigObjectFromExportExpression(moduleExportsStatement.expression.right, sourceFile); } return null; } function resolveCypressConfigObjectFromExportExpression(exportExpression, sourceFile) { const ts = (0, ensure_typescript_1.ensureTypescript)(); if (ts.isObjectLiteralExpression(exportExpression)) { return exportExpression; } if (ts.isIdentifier(exportExpression)) { // try to locate the identifier in the source file const variableStatements = sourceFile.statements.filter((statement) => ts.isVariableStatement(statement)); for (const variableStatement of variableStatements) { for (const declaration of variableStatement.declarationList .declarations) { if (ts.isIdentifier(declaration.name) && declaration.name.getText() === exportExpression.getText() && ts.isObjectLiteralExpression(declaration.initializer)) { return declaration.initializer; } } } return null; } if (ts.isCallExpression(exportExpression) && ts.isIdentifier(exportExpression.expression) && exportExpression.expression.getText() === 'defineConfig' && ts.isObjectLiteralExpression(exportExpression.arguments[0])) { return exportExpression.arguments[0]; } return null; }