在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目录下的文件:
- 安装必要依赖
npm install --save-dev babel-loader @babel/core @babel/preset-env @babel/plugin-proposal-optional-chaining @babel/plugin-proposal-nullish-coalescing-operator
- 修改
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; }, }, });
- (可选)配置
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
相关产品推荐
相关产品推荐

