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

Jest转换器在Typescript+Webpack+PEGJS环境下失效,导入值为undefined

Jest测试中PEGJS导入值为undefined的问题解决

项目配置

{
  "scripts": {
    "test": "jest --config=jest.config.js"
  },
  "devDependencies": {
    "@types/pegjs": "0.10.3",
    "@types/jest": "29.1.1",
    "ts-loader": "9.3.1",
    "raw-loader": "4.0.2",
    "typescript": "4.8.3",
    "webpack": "5.74.0",
    "webpack-cli": "4.10.0",
    "jest": "29.1.2",
    "ts-jest": "29.0.3"
  },
  "dependencies": {
    "pegjs": "0.10.0"
  }
}

项目特点

  • 源码使用TypeScript编写
  • 使用Webpack打包
  • 集成PEGJS语法解析
  • 使用Jest进行单元测试

项目结构

myproj
|-src/
  |-grammar.pegjs
  |-index.ts
  |-index.test.ts
|-package.json
|-jest.config.js
|-transformer.js

测试配置与问题

项目中index.ts通过以下方式导入PEGJS语法文件:

import pegjsgrammar from './grammar.pegjs'

为了让Jest处理这类静态资源导入,自定义了transformer.js转换器:

const fs = require("fs");

module.exports = {
    process(sourceText, sourcePath, options) {
        const fileContents = fs.readFileSync(sourcePath, { encoding: "utf8" }).toString();
        const json = JSON.stringify(fileContents).replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029');

        return {
            code: `module.exports = ${json};`,
        };
    },
};

并在jest.config.js中配置:

module.exports = {
    preset: "ts-jest",

    transform: {
      "\\.tsx?$": "ts-jest",
      "\\.jsx?$": "babel-jest",
      "\\.pegjs$": "<rootDir>/pegjs_jest_transformer.js"
    },

    moduleFileExtensions: ["ts", "js", "pegjs"],
  };

运行测试时出现错误:index.ts中的pegjsgrammar值为undefined。

解决方案

1. 修正转换器路径配置

jest.config.js中配置的PEGJS转换器路径是<rootDir>/pegjs_jest_transformer.js,但实际转换器文件名是transformer.js,路径不匹配导致Jest无法加载转换器,进而无法正确处理PEGJS文件导入。

修改jest.config.js中的transform配置:

module.exports = {
    preset: "ts-jest",

    transform: {
      "\\.tsx?$": "ts-jest",
      "\\.jsx?$": "babel-jest",
      "\\.pegjs$": "<rootDir>/transformer.js" // 修正为实际文件名
    },

    moduleFileExtensions: ["ts", "js", "pegjs"],
  };

2. 优化转换器逻辑

转换器的process函数已经接收了sourceText参数(即PEGJS文件的内容),无需再通过fs.readFileSync读取文件,重复读取可能引发路径或权限问题。简化transformer.js:

module.exports = {
    process(sourceText) {
        const json = JSON.stringify(sourceText).replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029');
        return {
            code: `module.exports = ${json};`,
        };
    },
};

3. 添加TypeScript类型声明

TypeScript无法识别.pegjs文件的导入类型,需要添加类型声明文件以确保导入的语法正确性。在src目录下创建typings.d.ts:

declare module '*.pegjs' {
  const content: string;
  export default content;
}

完成以上修改后,重新运行测试,pegjsgrammar即可正确获取到PEGJS文件的内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 21:10:36