【问题标题】:jest issue with typescript react components打字稿反应组件的笑话问题
【发布时间】:2020-11-27 00:45:46
【问题描述】:

我目前在 Lerna mono repo 中遇到 Jest 和 Typescript 问题。

在测试文件里面,我已经导入了组件import { Doctor } from '../src';,测试步骤如下:

it('should be selectable by class "btn-doctor"', function() {
    expect(shallow(<Doctor/>).is('.btn-doctor')).toBe(true);
  });

&lt;Doctor /&gt; 下划线表示警告;说:'Doctor' refers to a value, but is being used as a type here. Did you mean 'typeof Doctor'?ts(2749)

我认为问题与配置有关,但我在 Typescript 和 Jest 的官方文档中没有找到任何内容。

运行lerna run test时,此问题可以在此repo https://github.com/umarmw/lopital-sdk中重现

lerna ERR! npm run test stderr:
FAIL __tests__/doctor.test.ts
  ● Test suite failed to run

    __tests__/doctor.test.ts:14:21 - error TS2749: 'Doctor' refers to a value, but is being used as a type here. Did you mean 'typeof Doctor'?

    14     expect(shallow(<Doctor/>).is('.btn-doctor')).toBe(true);
                           ~~~~~~
    __tests__/doctor.test.ts:18:19 - error TS2749: 'Doctor' refers to a value, but is being used as a type here. Did you mean 'typeof Doctor'?

    18     expect(mount(<Doctor title="MO" />).find('.btn-doctor').length).toBe(1);
                         ~~~~~~
    __tests__/doctor.test.ts:18:26 - error TS2304: Cannot find name 'title'.

    18     expect(mount(<Doctor title="MO" />).find('.btn-doctor').length).toBe(1);

当前配置文件如下:

tsconfig.json

{
  "compilerOptions": {
    "target": "es6", // Specify ECMAScript target version
    "sourceMap": true, //   Generates corresponding .map file.
    "lib": [
      "dom",
      "dom.iterable",
      "esnext"
    ], // List of library files to be included in the compilation.
    "allowJs": false, // Allow JavaScript files to be compiled.
    "skipLibCheck": true, // Skip type checking of all declaration files (*.d.ts).
    "esModuleInterop": true, // Emit __importStar and __importDefault helpers for runtime babel ecosystem compatibility and enable --allowSyntheticDefaultImports for typesystem compatibility.
    "allowSyntheticDefaultImports": true, // Allow default imports from modules with no default export. This does not affect code emit, just typechecking.
    "strict": true, // Enable all strict type checking options.
    "forceConsistentCasingInFileNames": true, // Disallow inconsistently-cased references to the same file.
    "noImplicitAny": false, //  Raise error on expressions and declarations with an implied any type.
    "noLib": false, // Do not include the default library file (lib.d.ts).
    "emitDecoratorMetadata": true, // Emit design-type metadata for decorated declarations in source.
    "experimentalDecorators": true, // Enables experimental support for ES decorators.
    "module": "commonjs", // Specify module code generation: "None", "CommonJS", "AMD", "System", "UMD", "ES6", "ES2015" or "ESNext".
    // "moduleResolution": "node",
    // "resolveJsonModule": true,
    "jsx": "react", // Support JSX in .tsx files: "react", "preserve", "react-native". See JSX.
    "declaration": true, //     Generates corresponding .d.ts file.
  },
  "exclude": [
    "node_modules",
    "**/*.spec.ts"
  ]
}

jest.config.js

module.exports = {
  preset: "ts-jest",
  testEnvironment: "node",
  globals: {
    "ts-jest": {
      extends: './babel.config.js',
      tsConfig: {
        // allow js in typescript
        allowJs: true,
      },
    },
  },
  verbose: true,
  moduleFileExtensions: ['ts', 'tsx', 'js'],
  notify: true,
  notifyMode: 'always',
  testMatch: ['**/__tests__/*.+(ts|tsx|js)', '**/*.test.+(ts|tsx|js)'],
  transform: {
    '^.+\\.(ts|tsx)$': 'ts-jest',
  },
  // testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
  testPathIgnorePatterns: [
    '/node_modules/',
    '(/__tests__/.*|(\\.|/)(test|spec))\\.d\.ts$'
  ],
  snapshotSerializers: ['enzyme-to-json/serializer'],
  // setupFilesAfterEnv: ['<rootDir>../setupTests.js'],
}

babel.config.js

module.exports = {
    presets: [
      '@babel/preset-react',
      '@babel/preset-typescript',
      [
        '@babel/preset-env',
        {
          targets: {node: 'current'}
        }
      ],
    ],
    "plugins": [
      [
        "@babel/plugin-proposal-class-properties",
        {
          "loose": true
        }
      ]
    ]
  }

有什么想法吗?

【问题讨论】:

    标签: reactjs typescript jestjs babeljs lerna


    【解决方案1】:

    该错误表示 TypeScript 编译器无法识别 JSX 语法并被解析为泛型。

    由于 tsconfig.json 有 "jsx": "react",这意味着它没有被 ts-jest 出于某种原因拾取。原因是它被tsConfig 选项覆盖。为测试提供配置的常用方法是扩展另一个配置

    tsconfig.test.json

    {
      "extends": "./tsconfig",
      "compilerOptions": {
        "allowJs": true
      }
    }
    

    并为 ts-jest 指定它:

    "tsConfig": "tsconfig.test.json"
    

    另外,ts-jest 没有 extends 选项,即使有,它也不会接受 Babel 配置。有babelConfig option。由于 ts-jest 会转换 TypeScript 和 JSX,所以在 Babel 配置中可能不需要 @babel/preset-react@babel/preset-typescript

    【讨论】:

    • 将配置更改为全局变量:{ "ts-jest": { tsConfig: "./tsconfig.test.json" }, },并没有真正解决问题。还有其他解决方案吗?
    • 这不像查看不同的食谱,希望其中一些能奏效。如果做得正确,这个应该可以工作。问题是为什么它在你的情况下不起作用。尝试在 tsconfig.test.json 中出现语法错误,然后在 tsconfig.json 中,然后在 jest.config.js 中。查看其中哪些会失败,以及 Jest 无法识别哪些。
    • 另见kulshekhar.github.io/ts-jest/user/config/tsConfig,如果你在包目录中有jest.config.js,在monorepo目录中有tsconfigs,你可能需要指定"tsConfig": "&lt;rootDir&gt;/../../tsconfig.test.json"之类的东西,因为rootDir指的是那里的包目录。此时,它非常适合您的设置。
    • 我已经尝试在所有配置文件中制作语法问题,并且在执行任务时会引发它们。所以我们确信它当前可以读取它们。至于rootDir,我已经加了,但是不行。
    • 没有注意到最重要的事情。它应该是 .test.tsx,而不是 .test.ts。我想这应该会有所帮助。
    【解决方案2】:

    您似乎没有在此处使用正确的文件扩展名。您的测试是否命名为“doctor.test.tsinstead ofdoctor.test.tsx”?

    在测试 React 组件时,您需要确保使用 (j|t)sx 扩展。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-09-13
      • 2017-09-26
      • 1970-01-01
      • 2020-01-29
      • 1970-01-01
      • 2020-07-28
      相关资源
      最近更新 更多