You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于自定义配置在Cypress运行SpiceCRM组件测试遇错求助

SpiceCRM中Cypress组件测试TypeScript编译错误及适配方案

在开源系统SpiceCRM中运行组件测试时,Cypress针对所有模块抛出TypeScript编译错误,提示模块未被纳入编译流程,具体错误信息如下:

ERROR in ./src/admincomponents/admincomponents.module.ts
Module build failed (from ./node_modules/@ngtools/webpack/src/ivy/index.js):
Error: /home/evolpe/Desktop/SpiceCRM/sanpol/src/admincomponents/admincomponents.module.ts is missing from the TypeScript compilation. Please make sure it is in your tsconfig via the 'files' or 'include' property.
at /home/evolpe/Desktop/SpiceCRM/sanpol/node_modules/@ngtools/webpack/src/ivy/loader.js:64:26

提问:能否通过配置Cypress组件测试,使其适配项目的自定义webpack/TypeScript配置?


相关配置文件

webpack.config.js

const TerserPlugin = require("terser-webpack-plugin");
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
const fs = require('fs');

require('./gulpfile_globals.js');
const moment = require("moment");
const now = Date.now();
const buildDate = moment().format('YYYY-MM-DD HH:mm:ss');
const copyright = `© 2015 -  ${moment().format('YYYY')} aac services k.s. All rights reserved.`;

/**
 * write the environment file
 */
fs.writeFileSync('environments/environment.prod.ts', `
export const environment = {
    production: true,
    buildNumber: "${global.build.releaseNumber}.${now}",
    copyright: "${copyright}"
    }
`);

/**
 * generate options for HtmlWebpackPlugin
 * @param file
 */
const generateOptions = (file) => ({
    filename: file.name,
    template: file.template,
    hash: true,
    minify: false,
    aacServices: copyright,
    buildNumber: `${global.build.releaseNumber}.${now}`,
    chunksSortMode: (a) => a === 'scripts' ? -1 : 1
});

module.exports = {
    mode: "production",
    output: {
        // needed to adjust the dynamic import path
        publicPath: "app/",
        // modify the modules file name
        chunkFilename: (pathData) => {
            const path = pathData.chunk.id.split('_');
            if (path[0] === 'default-src') {
                return pathData.chunk.id.replace(/_ts$/, '') + '.js';
            }
            return path[['include', 'modules', 'custom'].indexOf(path[1]) > -1 ? 3 : 2] + '.js';
        }
    },
    optimization: {
        chunkIds: 'named',
        minimize: true,
        minimizer: [
            // custom minimize to keep class names for lazy loading
            new TerserPlugin({
                parallel: true,
                extractComments: false,
                terserOptions: {
                    mangle: true,
                    keep_classnames: true
                },
            }),
            // add spice header
            new webpack.BannerPlugin({
                banner: () => {
                    return `
                    aacService \n
                    release: ${global.build.releaseNumber} \n
                    date: ${buildDate} \n
                    build: ${global.build.releaseNumber}.${now}
                    `;
                },
            }),
            new CssMinimizerPlugin()
        ],
    },
    plugins: [
        new HtmlWebpackPlugin(
            generateOptions({name: "../index.html", template: "assets/index.html"})
        ),
        new HtmlWebpackPlugin(
            generateOptions({name: "../outlook.html", template: "assets/outlook/outlook.html"})
       ),
        new HtmlWebpackPlugin(
            generateOptions({name: "../outlookcrm.html", template: "assets/outlook/outlookcrm.html"})
        )
    ],
};

cypress.config.ts

import { defineConfig } from 'cypress'

export default defineConfig({
  component: {
    devServer: {
      framework: 'angular',
      bundler: 'webpack',
      options: {
        projectConfig: {
          root: '',
          sourceRoot: 'src',
          buildOptions: {
            outputPath: "dev",
            index: "index-dev.html",
            main: "src/spiceui.ts",
            tsConfig: "tsconfig.json",
            aot: true,
            extractLicenses: false,
            buildOptimizer: false,
            sourceMap: true,
            optimization: false,
            styles: [
              "vendor/sldassets/styles/salesforce-lightning-design-system.min.css",
              "assets/css/spicecrm.css",
              "node_modules/cropperjs/dist/cropper.min.css",
              "node_modules/croppie/croppie.css"
            ],
            scripts: [
              "node_modules/zone.js/dist/zone.min.js",
              "node_modules/underscore/underscore-min.js",
              "node_modules/moment/min/moment.min.js",
              "node_modules/moment/min/locales.min.js",
              "node_modules/moment-timezone/builds/moment-timezone-with-data.min.js",
              "node_modules/socket.io-client/dist/socket.io.min.js",
              "node_modules/libphonenumber-js/bundle/libphonenumber-js.min.js",
              "node_modules/cropperjs/dist/cropper.min.js",
              "node_modules/croppie/croppie.min.js"
            ]
          },
        },
      }
    },
    specPattern: '**/*.cy.ts',
  },
})

angular.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "cli": {
    "analytics": false
  },
  "version": 1,
  "newProjectRoot": "src",
  "projects": {
    "core": {
      "root": "",
      "sourceRoot": "src",
      "projectType": "application",
      "architect": {
        "build": {
          "builder": "@angular-builders/custom-webpack:browser",
          "options": {
            "outputPath": "dev",
            "index": "index-dev.html",
            "main": "src/spiceui.ts",
            "tsConfig": "tsconfig.json",
            "aot": true,
            "extractLicenses": false,
            "buildOptimizer": false,
            "sourceMap": true,
            "optimization": false,
            "styles": [
              "vendor/sldassets/styles/salesforce-lightning-design-system.min.css",
              "assets/css/spicecrm.css",
              "node_modules/cropperjs/dist/cropper.min.css",
              "node_modules/croppie/croppie.css"
            ],
            "scripts": [
              "node_modules/zone.js/dist/zone.min.js",
              "node_modules/underscore/underscore-min.js",
              "node_modules/moment/min/moment.min.js",
              "node_modules/moment/min/locales.min.js",
              "node_modules/moment-timezone/builds/moment-timezone-with-data.min.js",
              "node_modules/socket.io-client/dist/socket.io.min.js",
              "node_modules/libphonenumber-js/bundle/libphonenumber-js.min.js",
              "node_modules/cropperjs/dist/cropper.min.js",
              "node_modules/croppie/croppie.min.js"
            ]
          },
          "configurations": {
            "production": {
              "customWebpackConfig": {
                "path": "./webpack.config.js",
                "mergeRules": {
                  "externals": "replace"
                }
              },
              "index": "",
              "outputPath": "app",
              "fileReplacements": [
                {
                  "replace": "environments/environment.ts",
                  "with": "environments/environment.prod.ts"
                }
              ],
              "optimization": false,
              "outputHashing": "none",
              "sourceMap": false,
              "namedChunks": true,
              "extractLicenses": true,
              "vendorChunk": true,
              "buildOptimizer": true
            }
          }
        },
        "serve": {
          "builder": "@angular-builders/custom-webpack:dev-server",
          "options": {
            "browserTarget": "core:build",
            "port": 3333,
            "proxyConfig": "proxy.conf.js"
          }
        }
      }
    }
},
  "defaultProject": "core"
}

解决方案

1. 调整Cypress配置以适配自定义webpack

当前Cypress配置手动定义了projectConfig,未关联项目的自定义webpack配置。修改cypress.config.ts,改为引用angular.json中的项目配置,并添加自定义webpack配置引用:

import { defineConfig } from 'cypress'

export default defineConfig({
  component: {
    devServer: {
      framework: 'angular',
      bundler: 'webpack',
      options: {
        // 引用angular.json中的项目配置
        angularCliConfig: 'angular.json',
        // 添加自定义webpack配置
        customWebpackConfig: {
          path: './webpack.config.js',
          mergeRules: {
            externals: 'replace'
          }
        }
      }
    },
    specPattern: '**/*.cy.ts',
  },
})

2. 确保TypeScript配置包含所有模块

检查项目根目录的tsconfig.json,确保include数组包含所有需要编译的源文件及测试文件:

{
  "compilerOptions": {
    // 原有编译选项...
  },
  "include": [
    "src/**/*.ts",
    "**/*.cy.ts"
  ]
}

3. 可选:创建Cypress专用TypeScript配置

如果需要为测试环境单独配置TypeScript规则,可以新建tsconfig.cypress.json,并在Cypress配置中指定:

// tsconfig.cypress.json
{
  "extends": "./tsconfig.json",
  "include": [
    "src/**/*.ts",
    "**/*.cy.ts"
  ]
}

修改cypress.config.ts添加:

export default defineConfig({
  component: {
    // ...其他配置
    tsConfig: 'tsconfig.cypress.json',
  },
})

4. 验证配置

重新运行Cypress组件测试命令,检查编译错误是否解决。


内容的提问来源于stack exchange,提问作者Damian Kowalski

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:10:31