Проблема с модульным тестом Jest: модуль не найден

В настоящее время Jest не проходит тесты, потому что не может найти модуль, вызываемый внутри компонента:

 FAIL  tests/Unit/VHeaderBar.spec.ts
  ● Test suite failed to run

    Cannot find module '@@/public/assets/images/placeholder.png' from 'VHeaderBar.vue'



      at Resolver.resolveModule (node_modules/jest-runtime/node_modules/jest-resolve/build/index.js:221:17)
      at src/components/VHeaderBar.vue:687:18
      at Object.<anonymous> (src/components/VHeaderBar.vue:749:3)

Случай

В NuxtJs знаки @@ относятся к корневому каталогу, потому что в конечном решении мы хотим хранить изображения в общей папке или папке хранения, которая находится в корне проэкт.

При запуске тестов jest проверяет папку src, затем пытается смонтировать изображения, хранящиеся в корне, и не может их найти.

Я пробовал много разных способов решить эту проблему, но, похоже, не нашел решения. Вот краткий список того, что я уже пробовал:

  • Изменение regex для проверки файлов изображений и перехода в нужную папку с помощью параметра moduleNameMapper в файле конфигурации Jest.
  • Я читал что-то в Stack об использовании «фиктивной» папки, которая экспортирует файлы изображений через javascript, но это не сработало.
  • Используя параметр modulePaths в файле конфигурации Jest.
  • Создание псевдонима в tsconfig.js для папки assets и использование его в moduleNameMapper
  • Пробовал другой подход в компоненте VueJS и тестовом файле для загрузки ресурсов, что нарушило процесс компиляции (поэтому я вернул это).

Текущий файл конфигурации Jest

module.exports = {
    moduleFileExtensions: [
        "ts",
        "tsx",
        "vue",
        "js",
        "json"
    ],
    watchman: false,
    moduleNameMapper: {
        "/\.(gif|jpg|jpeg|tiff|png)$/i": "<rootDir>/public/assets/images/$1",
        "^@/(.*)$": "<rootDir>/src/$1",
        "^~/(.*)$": "<rootDir>/src/$1",
        "^~~/(.*)$": "<rootDir>/src/$1"
    },
    transform: {
        // process js with `babel-jest`
        "^.+\\.js$": "<rootDir>/node_modules/babel-jest",
        // process `*.vue` files with `vue-jest`
        ".*\\.(vue)$": "<rootDir>/node_modules/vue-jest",
        // process `*.ts` files with `ts-jest`
        "^.+\\.(ts|tsx)$": "<rootDir>/node_modules/ts-jest",
    },
    snapshotSerializers: [
        "<rootDir>/node_modules/jest-serializer-vue"
    ],
    collectCoverage: true,
    collectCoverageFrom: [
        "<rootDir>/src/components/**/*.vue",
        "<rootDir>/src/pages/**/*.vue",
        "<rootDir>/src/layouts/**/*.vue"
    ],
    testMatch: [
        '**/tests/Unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
    ],
}

Текущая структура папок (только папки, которые мы используем для теста)

project folder
- public
-- assets
--- **images**

- src
-- components
--- **mounted component** (works)

- tests
-- Unit
--- mountedComponent.spec.ts

Какие-либо предложения?

Исправить jest.config?

Что-то не так с синтаксисом?

Мне нужно исправить tsconfig?


person Christopher.Communiq    schedule 13.11.2019    source источник


Ответы (1)


У меня была аналогичная проблема, и она сводится к тому, что машинописный текст не может импортировать этот файл.

Я решил это, добавив определение типа файла в files.d.ts:

declare module "*.pdf" {
  const file: Buffer;
  export default file;
}

declare module "*.jpeg" {
  const src: string;
  export default src;
}

declare module "*.png" {
  const src: string;
  export default src;
}

Ссылаясь на этот файл в tsconfig.json:

{
  "compilerOptions": {
    /* ... */
  },
  "files": ["./src/@types/files.d.ts"],
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

И добавление файловых преобразований в jest.config.js:

module.exports = {
  preset: "ts-jest",
  testEnvironment: "node",
  roots: ["<rootDir>/src/"],

  moduleNameMapper: {
    "@app/(.*)": "<rootDir>/src/$1",
    "@lib/(.*)": "<rootDir>/src/lib/$1",
  },
  transform: { // Transforms here
    "\\.(gql|graphql)$": "@jagi/jest-transform-graphql",
    "\\.(html|html|txt|pem|key)$": "./jest-transform-text.js",
    "\\.(p12|pdf|otf|ttf)$": "./jest-transform-buffer.js",
    "^(?!.*\\.(js|jsx|ts|tsx|css|json)$)": "<rootDir>/config/jest/fileTransform.js"

  },
  coverageReporters: ["text", "lcov"],
};

Примеры файлов преобразования:

// jest-transform-buffer.js

"use strict";
const fs = require("fs");
module.exports = {
  process(src, filename) {
    const data = fs.readFileSync(filename, "hex");
    return (
      'module.exports=Buffer.from("' +
      data +
      '","hex");module.exports.default=module.exports;'
    );
  },
};

А для изображений (или других файлов, где вам нужно только имя файла) из приложения create response:

'use strict';

const path = require('path');
const camelcase = require('camelcase');

// This is a custom Jest transformer turning file imports into filenames.
// http://facebook.github.io/jest/docs/en/webpack.html

module.exports = {
  process(src, filename) {
    const assetFilename = JSON.stringify(path.basename(filename));

    if (filename.match(/\.svg$/)) {
      // Based on how SVGR generates a component name:
      // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6
      const pascalCaseFilename = camelcase(path.parse(filename).name, {
        pascalCase: true,
      });
      const componentName = `Svg${pascalCaseFilename}`;
      return `const React = require('react');
      module.exports = {
        __esModule: true,
        default: ${assetFilename},
        ReactComponent: React.forwardRef(function ${componentName}(props, ref) {
          return {
            $$typeof: Symbol.for('react.element'),
            type: 'svg',
            ref: ref,
            key: null,
            props: Object.assign({}, props, {
              children: ${assetFilename}
            })
          };
        }),
      };`;
    }

    return `module.exports = ${assetFilename};`;
  },
};
person Valeria Viana Gusmao    schedule 01.10.2020