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

React项目Jest测试内部Webpack依赖包时遇publicPath不支持错误

问题:Jest测试环境中使用Webpack构建的内部React包时出现Automatic publicPath is not supported in this browser错误

问题详情

运行涉及内部依赖包的Jest测试时触发错误,该包由React+Webpack构建。仅Jest环境会出现此问题,Storybook或应用直接运行时一切正常。

报错信息:

Automatic publicPath is not supported in this browser

该内部包用于提供组件和主题配置,推测是Jest使用的jsdom环境未正确处理Webpack的publicPath导致此错误。

项目配置

jest.config.ts

module.exports = {
  collectCoverageFrom: [
    'src/**/*.{js,jsx,ts,tsx}',
    '!src/**/*.d.ts',
    '!src/index.tsx',
    '!src/constants/**/*',
  ],
  coverageDirectory: 'output/coverage',
  coveragePathIgnorePatterns: [
    './src/*/*.types.{ts,tsx}',
    './src/index.tsx',
    './src/redux',
  ],
  coverageReporters: ['clover'],
  testEnvironment: 'jest-environment-jsdom',
  setupFilesAfterEnv: [
    '<rootDir>/src/config/setupTests.ts',
  ],
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': [
      '@swc/jest', {
        jsc: {
          transform: {
            react: {
              runtime: 'automatic',
            },
          },
        },
      },
    ],
    '\\.css$': 'jest-css-modules-transform',
  },
  transformIgnorePatterns: [
    '[/\\\\]node_modules[/\\\\].+\\.(js|jsx|ts|tsx)$',
    '^.+\\.module\\.(css|sass|scss)$',
  ],
  moduleDirectories: ['node_modules', __dirname],
  moduleNameMapper: {
    '\\.(css|scss)$': 'identity-obj-proxy',
  },
  snapshotFormat: {
    printBasicPrototype: true,
  },
  reporters: [
    'default',
    ['jest-junit', { outputDirectory: 'output', outputName: 'junit.xml' }],
  ],
};

package.json

{
  "name": "project",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite --host",
    "build": "tsc && vite build",
    "lint": "npm run lint:js; js_status=$?; npm run lint:css; css_status=$?; [ $js_status -ne 0 ] || [ $css_status -ne 0 ] && exit 1 || exit 0",
    "lint:js": "npx eslint src/**/*.{ts,tsx}",
    "lint:js:fix": "npx eslint src/**/*.{ts,tsx} --fix",
    "lint:css": "npx stylelint src/**/*.{css,scss} --aei",
    "lint:css:fix": "npx stylelint src/**/*.{css,scss} --fix",
    "test": "jest --verbose",
    "test:coverage": "jest --coverage",
    "test:coverage:html": "jest --coverage --coverageReporters=html",
    "storybook": "storybook dev -p 6006",
    "storybook:build": "storybook build -o dist/storybook"
  },
  "dependencies": {
    "@babel/core": "^7.22.9",
    "@babel/preset-env": "^7.22.9",
    "@babel/preset-react": "^7.22.5",
    "@this-is-the-package-but-its-internal": "1.2.5",
    "@emotion/react": "^11.11.1",
    "@emotion/styled": "^11.11.0",
    "@mui/icons-material": "^5.14.1",
    "@mui/material": "^5.14.2",
    "@mui/utils": "^5.15.14",
    "@reduxjs/toolkit": "^1.9.5",
    "@storybook/addon-a11y": "^8.3.6",
    "@storybook/addon-actions": "^8.3.6",
    "@storybook/addon-essentials": "^8.3.6",
    "@storybook/addon-interactions": "^8.3.6",
    "@storybook/addon-links": "^8.3.6",
    "@storybook/blocks": "^8.3.6",
    "@storybook/react": "^8.3.6",
    "@storybook/react-vite": "^8.3.6",
    "@storybook/test": "^8.3.6",
    "@swc/jest": "^0.2.27",
    "@testing-library/jest-dom": "^5.17.0",
    "@testing-library/react": "^14.0.0",
    "@testing-library/user-event": "^14.4.3",
    "@types/jest": "^29.5.3",
    "@types/pendo-io-browser": "^2.17.9",
    "@types/react": "^18.2.15",
    "@types/react-dom": "^18.2.7",
    "@types/react-redux": "^7.1.25",
    "@typescript-eslint/eslint-plugin": "^5.37.0",
    "@typescript-eslint/parser": "^5.37.0",
    "@vitejs/plugin-react": "^4.0.3",
    "axios": "^1.6.7",
    "babel-jest": "^29.6.2",
    "classnames": "^2.3.2",
    "eslint": "^8.55.0",
    "eslint-config-airbnb": "^19.0.4",
    "eslint-config-airbnb-typescript": "^17.0.0",
    "eslint-config-react-app": "^7.0.1",
    "eslint-plugin-import": "^2.26.0",
    "eslint-plugin-jsx-a11y": "^6.6.1",
    "eslint-plugin-react": "^7.31.8",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-storybook": "^0.10.1",
    "i18next": "^23.3.0",
    "i18next-browser-languagedetector": "^7.1.0",
    "i18next-http-backend": "^2.2.1",
    "identity-obj-proxy": "^3.0.0",
    "jest": "^29.6.1",
    "jest-css-modules-transform": "^4.4.2",
    "jest-environment-jsdom": "^29.6.2",
    "jest-junit": "^16.0.0",
    "js-cookie": "^3.0.5",
    "jwt-decode": "^4.0.0",
    "lodash": "^4.17.21",
    "msw": "^1.3.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-hook-form": "^7.51.2",
    "react-i18next": "^13.5.0",
    "react-redux": "^8.1.1",
    "react-router-dom": "^6.14.2",
    "redux": "^4.2.1",
    "redux-persist": "^6.0.0",
    "redux-thunk": "^2.4.2",
    "sass": "^1.64.1",
    "storybook": "^8.3.6",
    "storybook-react-i18next": "^3.1.7",
    "stylelint": "^14.11.0",
    "stylelint-config-standard-scss": "^5.0.0",
    "ts-node": "^10.9.1",
    "typescript": "5.1.6",
    "vite": "^4.4.5"
  },
  "jest-junit": {
    "output": "output/coverage/junit/junit.xml",
    "usePathForSuiteName": "true"
  },
  "devDependencies": {
    "@types/js-cookie": "^3.0.6"
  }
}

环境信息

  • Node: v20.18.0
  • npm: 10.8.2

解决方案

方案1:在Jest全局环境中模拟publicPath

在setupTests.ts中添加以下代码,为jsdom环境注入Webpack所需的publicPath相关全局变量:

// 模拟Webpack的publicPath
global.__webpack_public_path__ = '/';

方案2:修改Jest的transformIgnorePatterns,让内部包被转译

由于内部包是Webpack构建的,可能包含未转译的代码导致jsdom不兼容。修改jest.config.ts中的transformIgnorePatterns,排除内部包:

transformIgnorePatterns: [
  '[/\\\\]node_modules[/\\\\].+\\.(js|jsx|ts|tsx)$',
  '^.+\\.module\\.(css|sass|scss)$',
  // 排除内部包,让它被@swc/jest转译
  '!node_modules/@this-is-the-package-but-its-internal/',
],

方案3:在内部包的Webpack配置中显式设置publicPath

如果有权限修改内部包的Webpack配置,添加publicPath配置,避免自动检测:

// 内部包的webpack.config.js
module.exports = {
  output: {
    publicPath: '/', // 或者根据实际部署路径设置
  },
};

方案4:使用moduleNameMock模拟内部包

如果测试不需要内部包的真实逻辑,可以直接模拟整个包:
在jest.config.ts的moduleNameMapper中添加:

moduleNameMapper: {
  '\\.(css|scss)$': 'identity-obj-proxy',
  '@this-is-the-package-but-its-internal': '<rootDir>/__mocks__/internal-package.ts',
},

然后创建__mocks__/internal-package.ts,导出模拟的组件和配置:

// 模拟内部包的核心导出
export const Button = () => null;
export const themeConfig = {};
// 其他组件/配置按需模拟

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 09:25:57