UNPKG

@nx/angular

Version:

The Nx Plugin for Angular contains executors, generators, and utilities for managing Angular applications and libraries within an Nx workspace. It provides: - Integration with libraries such as Storybook, Jest, ESLint, Tailwind CSS, Playwright and Cypre

188 lines (187 loc) • 9.56 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.cypressComponentConfiguration = cypressComponentConfiguration; const devkit_1 = require("@nx/devkit"); const path_1 = require("path"); const zoneless_1 = require("../../utils/zoneless"); const versions_1 = require("../../utils/versions"); const component_test_1 = require("../component-test/component-test"); const component_info_1 = require("../utils/storybook-ast/component-info"); const entry_point_1 = require("../utils/storybook-ast/entry-point"); const module_info_1 = require("../utils/storybook-ast/module-info"); const update_app_editor_tsconfig_excluded_files_1 = require("../utils/update-app-editor-tsconfig-excluded-files"); const semver_1 = require("semver"); const webpackExecutors = new Set([ '@nx/angular:webpack-browser', '@nrwl/angular:webpack-browser', '@angular-devkit/build-angular:browser', ]); const esbuildExecutors = new Set([ '@angular/build:application', '@angular-devkit/build-angular:application', '@nx/angular:application', '@angular-devkit/build-angular:browser-esbuild', '@nx/angular:browser-esbuild', ]); /** * This is for cypress built in component testing, if you want to test with * storybook + cypress then use the componentCypressGenerator instead. */ async function cypressComponentConfiguration(tree, options) { const { componentConfigurationGenerator: baseCyCTConfig } = (0, devkit_1.ensurePackage)('@nx/cypress', versions_1.nxVersion); const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project); let isZoneless; if (projectConfig.projectType === 'application') { // For applications, check the polyfills in the build target isZoneless = (0, zoneless_1.isZonelessApp)(projectConfig); } else { // For libraries, check if zone.js is installed in the workspace isZoneless = (0, devkit_1.getDependencyVersionFromPackageJson)(tree, 'zone.js') === null; } if (isZoneless) { const { getInstalledCypressVersion } = await Promise.resolve().then(() => __importStar(require('@nx/cypress/src/utils/versions'))); const installedCypressVersion = getInstalledCypressVersion(tree); // Zoneless support was introduced in Cypress 15.8.0 // If Cypress is not yet installed, we'll install the latest version, which will have zoneless support if (installedCypressVersion && (0, semver_1.lt)(installedCypressVersion, '15.8.0')) { throw new Error(`Cypress Component Testing doesn't support Zoneless Angular projects for your installed Cypress version (${installedCypressVersion}). ` + `The project "${options.project}" is configured without Zone.js. ` + `Please upgrade Cypress to version 15.8.0 or higher.`); } } const tasks = []; tasks.push(await baseCyCTConfig(tree, { project: options.project, skipFormat: true, addPlugin: false, addExplicitTargets: true, skipPackageJson: options.skipPackageJson, })); await configureCypressCT(tree, options); tasks.push(await addFiles(tree, projectConfig, options, isZoneless)); if (projectConfig.projectType === 'application') { (0, update_app_editor_tsconfig_excluded_files_1.updateAppEditorTsConfigExcludedFiles)(tree, projectConfig); } if (!options.skipFormat) { await (0, devkit_1.formatFiles)(tree); } return (0, devkit_1.runTasksInSerial)(...tasks); } async function addFiles(tree, projectConfig, options, isZoneless) { const componentFile = (0, devkit_1.joinPathFragments)(projectConfig.root, 'cypress', 'support', 'component.ts'); const { addMountDefinition } = require('@nx/cypress/src/utils/config'); const updatedCmpContents = await addMountDefinition(tree.read(componentFile, 'utf-8')); tree.write(componentFile, `import { mount } from '${isZoneless ? 'cypress/angular-zoneless' : 'cypress/angular'}';\n${updatedCmpContents}`); if (!options.generateTests) { return () => { }; } const entryPoints = (0, entry_point_1.getProjectEntryPoints)(tree, options.project); const componentInfo = []; for (const entryPoint of entryPoints) { const moduleFilePaths = (0, module_info_1.getModuleFilePaths)(tree, entryPoint); componentInfo.push(...(0, component_info_1.getComponentsInfo)(tree, entryPoint, moduleFilePaths, options.project), ...(0, component_info_1.getStandaloneComponentsInfo)(tree, entryPoint)); } let ctTask; for (const info of componentInfo) { if (info === undefined) { continue; } const componentDirFromProjectRoot = (0, path_1.relative)(projectConfig.root, (0, devkit_1.joinPathFragments)(info.moduleFolderPath, info.path)); const task = await (0, component_test_1.componentTestGenerator)(tree, { project: options.project, componentName: info.name, componentDir: componentDirFromProjectRoot, componentFileName: info.componentFileName, skipFormat: true, skipPackageJson: options.skipPackageJson, }); // the ct generator only installs one dependency, which will only be installed // if !skipPackageJson and not already installed, so only the first run can // result in a generator callback that would actually install the dependency if (!ctTask) { ctTask = task; } } return ctTask ?? (() => { }); } async function configureCypressCT(tree, options) { let found = { target: options.buildTarget, config: undefined }; if (!options.buildTarget) { const { findBuildConfig } = require('@nx/cypress/src/utils/find-target-options'); found = await findBuildConfig(tree, { project: options.project, buildTarget: options.buildTarget, validExecutorNames: webpackExecutors, }); if (!found?.config) { // Check if the project uses an esbuild-based executor const esbuildTarget = await findBuildConfig(tree, { project: options.project, validExecutorNames: esbuildExecutors, skipGetOptions: true, }); if (esbuildTarget?.target) { const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, esbuildTarget.target.split(':')[0]); const targetName = esbuildTarget.target.split(':')[1]; const executor = projectConfig.targets?.[targetName]?.executor; throw new Error(`Cypress Component Testing for Angular requires a webpack-based build target, ` + `but the project "${options.project}" uses an esbuild-based executor (${executor}).\n\n` + `Cypress only supports webpack as the bundler for Angular component testing.`); } throw new Error('Unable to find a valid build configuration. Try passing in a target for an Angular app (e.g. --build-target=<project>:<target>[:<configuration>]).'); } } const ctConfigOptions = {}; const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project); if (projectConfig.targets?.['component-test']?.executor === '@nx/cypress:cypress') { projectConfig.targets['component-test'].options = { ...projectConfig.targets['component-test'].options, skipServe: true, devServerTarget: found.target, }; (0, devkit_1.updateProjectConfiguration)(tree, options.project, projectConfig); } else { ctConfigOptions.buildTarget = found.target; } const { addDefaultCTConfig, getProjectCypressConfigPath } = require('@nx/cypress/src/utils/config'); const cypressConfigPath = getProjectCypressConfigPath(tree, projectConfig.root); const updatedCyConfig = await addDefaultCTConfig(tree.read(cypressConfigPath, 'utf-8'), ctConfigOptions); tree.write(cypressConfigPath, `import { nxComponentTestingPreset } from '@nx/angular/plugins/component-testing';\n${updatedCyConfig}`); } exports.default = cypressComponentConfiguration;