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

在Cypress测试中引入Cerbos导致模块解析错误

Cypress测试中引入Cerbos库导致Webpack编译错误的解决办法

在Cypress中运行端到端测试,尝试引入封装Cerbos权限调用的函数时,触发Webpack编译错误,错误提示@cerbos/http库中的代码包含未被处理的ES6+语法(可选链?.和空值合并运算符??),当前没有配置对应的loader处理该文件类型。

错误详情:

Error: Webpack Compilation Error
./node_modules/@cerbos/http/lib/index.js 177:56
Module parse failed: Unexpected token (177:56)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file.
| const headers = ({ headers: optionalHeaders, playgroundInstance }, adminCredentials) => {
|     const headers = new Headers(typeof optionalHeaders === "function" ? optionalHeaders() : optionalHeaders);
>     headers.set("User-Agent", headers.get("User-Agent")?.concat(" ", defaultUserAgent) ?? defaultUserAgent);
|     if (adminCredentials) {
|         headers.set("Authorization", `Basic ${(0, abab_1.btoa)(`${adminCredentials.username}:${adminCredentials.password}`) ?? ""}`);
 @ ./src/shared/cerbos/cerbos.tsx 1:0-36 16:23-27
 @ ./cypress/e2e/reviewPage.cy.ts
    at Watching.handle [as handler] (/Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/packages/server/node_modules/@cypress/webpack-preprocessor/dist/index.js:212:23)
    at /Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/webpack/lib/Watching.js:99:9
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at Watching._done (/Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/webpack/lib/Watching.js:98:28)
    at /Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/webpack/lib/Watching.js:73:19
    at Compiler.emitRecords (/Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/webpack/lib/Compiler.js:499:39)
    at /Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/webpack/lib/Watching.js:54:20
    at /Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/webpack/lib/Compiler.js:485:14
    at AsyncSeriesHook.eval [as callAsync] (eval at create (/Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/tapable/lib/HookCodeFactory.js:33:10), <anonymous>:6:1)
    at /Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/webpack/lib/Compiler.js:482:27
    at /Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/neo-async/async.js:2818:7
    at done (/Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/neo-async/async.js:3522:9)
    at writeOut (/Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/webpack/lib/Compiler.js:452:16)
    at /Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/webpack/lib/Compiler.js:476:7
    at arrayIterator (/Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/neo-async/async.js:3467:9)
    at timesSync (/Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/neo-async/async.js:2297:7)
    at Object.eachLimit (/Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/neo-async/async.js:3463:5)
    at emitFiles (/Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/webpack/lib/Compiler.js:358:13)
    at /Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/node_modules/mkdirp/index.js:49:26
    at callback (/Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/packages/server/node_modules/graceful-fs/polyfills.js:299:20)
    at callback (/Users/thomasheill/Library/Caches/Cypress/12.16.0/Cypress.app/Contents/Resources/app/packages/server/node_modules/graceful-fs/polyfills.js:299:20)
    at FSReqCallback.oncomplete (node:fs:200:5)

解决办法

方法1:配置Webpack转译Cerbos库代码

默认情况下Webpack不会转译node_modules下的文件,而Cerbos的库代码使用了未被Cypress内置Webpack支持的ES6+语法。需要修改Cypress的Webpack配置,让babel-loader处理@cerbos目录下的文件:

  1. 安装必要依赖
npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/plugin-proposal-optional-chaining @babel/plugin-proposal-nullish-coalescing-operator
  1. 修改cypress.config.js
    添加Webpack预处理器配置,指定转译@cerbos:
const { defineConfig } = require("cypress");
const webpackPreprocessor = require("@cypress/webpack-preprocessor");
const path = require("path");

module.exports = defineConfig({
  e2e: {
    setupNodeEvents(on, config) {
      const webpackOptions = {
        module: {
          rules: [
            {
              test: /\.(js|jsx|ts|tsx)$/,
              include: [
                path.resolve(__dirname, "src"),
                path.resolve(__dirname, "node_modules/@cerbos") // 让babel处理Cerbos代码
              ],
              use: {
                loader: "babel-loader",
                options: {
                  presets: ["@babel/preset-env"],
                  plugins: [
                    "@babel/plugin-proposal-optional-chaining",
                    "@babel/plugin-proposal-nullish-coalescing-operator"
                  ]
                }
              }
            }
          ]
        },
        resolve: {
          extensions: [".ts", ".tsx", ".js", ".jsx"]
        }
      };

      on("file:preprocessor", webpackPreprocessor({ webpackOptions }));
      return config;
    },
  },
});
  1. (可选)配置babel.config.json
    如果项目已有babel配置,也可以直接在babel.config.json中添加包含规则:
{
  "presets": ["@babel/preset-env"],
  "plugins": [
    "@babel/plugin-proposal-optional-chaining",
    "@babel/plugin-proposal-nullish-coalescing-operator"
  ],
  "include": ["node_modules/@cerbos"]
}

方法2:直接模拟Cerbos调用(绕过编译问题)

如果只是在测试中验证逻辑,不需要实际调用Cerbos服务,可以用Cypress的cy.stub()模拟封装函数的返回值,避免引入Cerbos库:

// 在测试文件中
import { myCerbosFunction } from "../../src/shared/cerbos/cerbos";

describe("Review Page", () => {
  beforeEach(() => {
    // 模拟Cerbos函数的返回值
    cy.stub(myCerbosFunction).returns({ allowed: true });
  });

  it("should render review content if allowed", () => {
    // 测试逻辑
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 05:04:53