UNPKG

@nx/cypress

Version:

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

124 lines (123 loc) 5.58 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = updateAngularComponentTestingSupport; const devkit_1 = require("@nx/devkit"); const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript"); const tsquery_1 = require("@phenomnomnominal/tsquery"); const semver_1 = require("semver"); const config_1 = require("../../utils/config"); const migrations_1 = require("../../utils/migrations"); const DEPRECATED_MAX_ANGULAR_VERSION = '18.0.0'; const CYPRESS_ANGULAR_FALLBACK_VERSION = '^3.0.0'; let printer; let ts; async function updateAngularComponentTestingSupport(tree) { const projectGraph = await (0, devkit_1.createProjectGraphAsync)(); let wereProjectsMigrated = false; for await (const { projectConfig, projectName, cypressConfigPath, } of (0, migrations_1.cypressProjectConfigs)(tree)) { if (!tree.exists(cypressConfigPath)) { continue; } const migrationInfo = await getMigrationInfo(tree, cypressConfigPath, projectName, projectGraph); if (!migrationInfo) { continue; } migrateProject(tree, projectConfig); wereProjectsMigrated = true; } if (wereProjectsMigrated) { (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { '@cypress/angular': CYPRESS_ANGULAR_FALLBACK_VERSION, }); } await (0, devkit_1.formatFiles)(tree); } async function getMigrationInfo(tree, cypressConfigPath, projectName, projectGraph) { ts ??= (0, ensure_typescript_1.ensureTypescript)(); const cypressConfig = tree.read(cypressConfigPath, 'utf-8'); const config = (0, config_1.resolveCypressConfigObject)(cypressConfig); if (!config) { return false; } const component = (0, migrations_1.getObjectProperty)(config, 'component'); if (!component) { return false; } const framework = resolveFramework(cypressConfig, config, projectName, projectGraph); if (framework !== 'angular') { return false; } const angularVersion = resolveAngularVersion(projectName, projectGraph); if (!angularVersion || !(0, semver_1.valid)(angularVersion)) { return false; } return (0, semver_1.lt)(angularVersion, DEPRECATED_MAX_ANGULAR_VERSION); } function migrateProject(tree, projectConfig) { ts ??= (0, ensure_typescript_1.ensureTypescript)(); printer ??= ts.createPrinter(); (0, devkit_1.visitNotIgnoredFiles)(tree, projectConfig.root, (filePath) => { if (!isJsTsFile(filePath) || !tree.exists(filePath)) { return; } const originalContent = tree.read(filePath, 'utf-8'); const sourceFile = tsquery_1.tsquery.ast(originalContent); const updatedContent = tsquery_1.tsquery.replace(originalContent, 'ImportDeclaration', (node) => { if (!ts.isStringLiteral(node.moduleSpecifier) || node.moduleSpecifier.text !== 'cypress/angular') { return node.getText(); } const updatedImport = ts.factory.updateImportDeclaration(node, node.modifiers, node.importClause, ts.factory.createStringLiteral('@cypress/angular'), node.attributes); return printer.printNode(ts.EmitHint.Unspecified, updatedImport, sourceFile); }); if (updatedContent !== originalContent) { tree.write(filePath, updatedContent); } }); } function resolveFramework(cypressConfig, config, projectName, projectGraph) { ts ??= (0, ensure_typescript_1.ensureTypescript)(); const frameworkProperty = tsquery_1.tsquery.query(config, 'PropertyAssignment:has(Identifier[name=component]) PropertyAssignment:has(Identifier[name=devServer]) PropertyAssignment:has(Identifier[name=framework])')[0]; if (frameworkProperty) { return ts.isStringLiteral(frameworkProperty.initializer) ? frameworkProperty.initializer.text : null; } const sourceFile = tsquery_1.tsquery.ast(cypressConfig); const nxPresetModuleSpecifiers = [ '@nx/angular/plugins/component-testing', '@nx/react/plugins/component-testing', '@nx/next/plugins/component-testing', '@nx/remix/plugins/component-testing', ]; const imports = tsquery_1.tsquery.query(sourceFile, 'ImportDeclaration'); const nxPresetImport = imports.find((decl) => { const moduleSpec = decl.moduleSpecifier.getText().replace(/['"`]/g, ''); return nxPresetModuleSpecifiers.includes(moduleSpec); }); if (nxPresetImport) { const moduleSpecifier = nxPresetImport.moduleSpecifier .getText() .replace(/['"`]/g, ''); const plugin = moduleSpecifier.split('/').at(1); return plugin === 'angular' ? 'angular' : 'react'; } if (projectGraph.dependencies[projectName]?.some((dependency) => dependency.target.startsWith('npm:@angular/core'))) { return 'angular'; } if (projectGraph.dependencies[projectName]?.some((dependency) => dependency.target.startsWith('npm:react') || dependency.target.startsWith('npm:next'))) { return 'react'; } return null; } function resolveAngularVersion(projectName, projectGraph) { const angularDep = projectGraph.dependencies[projectName]?.find((dependency) => dependency.target.startsWith('npm:@angular/core')); if (!angularDep) { return null; } return projectGraph.externalNodes?.[angularDep.target]?.data?.version ?? null; } function isJsTsFile(filePath) { return /\.[cm]?[jt]sx?$/.test(filePath); }