После длительного использования отдельных файлов css в общей папке и ссылки на них непосредственно из index.html, мы недавно перешли на совместное размещение наших css с компонентом и импортируя его в компонент с помощью webpack (с помощью css-loader и style-loader). Мы не ожидали, что это сломает какую-либо из наших существующих настроек, потому что, почему, кто еще использует файлы css помимо компонентов? Оказывается, раньше все было нормально, но теперь, поскольку css импортирован в файл компонента, jest не знает, что с ним делать. Почему?

Потому что jest не знает, что делать со статическим импортом компонентов. Это что-то особенное для webpack, и шутка не понимает этого.

Что возвращает нас к этому. Как jest понимает импорт ES6 для модулей javascript по умолчанию?

Оказывается, нет. Можно использовать синтаксис ES6 с jest, потому что jest по умолчанию поставляется с babel-jest, который гарантирует, что если есть .babelrc (или любой другой файл конфигурации bable) в вашем проекте, jest будет уважать его.

С webpack это не так просто. Интеграция jest для webpack не такая прямая, потому что jest не может напрямую понять ваш webpack.config.js и на основе этого используйте загрузчики, чтобы вы могли импортировать статические активы.

Итак, какое разрешение?

Есть 2 варианта:

  • мы можем издеваться над этими статическими активами
  • или мы можем как-то попросить шутку изменить ее и придать ей какой-то смысл вместо насмешек. (см. здесь и здесь)

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

Чем мы издеваемся над этим?

  • Для файлов css мы можем просто экспортировать пустой объект.
  • Для файлов изображений (которые мы используем как импорт чего-либо из «./something.jpg») мы можем просто экспортировать некоторую строку.

Как насмехаться над этим?

Есть несколько способов имитировать этот импорт. Мы можем сделать это на уровне файла или настроить jest на «игнорирование» всех импортированных файлов css.

На уровне файла:

jest.mock("./something.css", () => {
  return {};
});

Или глобально:

// jest.config.js
moduleNameMapper: {
  "\\.  (jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m  4a|aac|oga)$":"<rootDir>/__mocks__/fileMock.js",
  "\\.(css|less)$": "<rootDir>/__mocks__/styleMock.js"
},
// <rootDir>/__mocks__/styleMock.js
module.exports = {};
// <rootDir>/__mocks__/fileMock.js
module.exports = "test-file-stub";

Or

вы можете использовать конфигурацию преобразования в шутку, чтобы выполнить некоторые конкретные преобразования:

// fileTransformer.js 
const path = require('path');  
module.exports = {   
  process(src, filename, config, options) {     
    return 'module.exports = ' +   JSON.stringify(path.basename(filename)) + ';';   
  }, 
};
// config
"moduleNameMapper": {       
  "\\.(css|less)$": "identity-obj-proxy"     
},    
 
"transform": {       
  "\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/fileTransformer.js"     
}

Этого достаточно для случая использования, с которым мы столкнулись.

Ниже я расскажу о некоторых других распространенных случаях использования:

Что, если ваши статические ресурсы действительно содержат что-то, что используется в вашем коде, например css-modules, и в этом случае имена классов в вашем компоненте отображаются из импортированного css файл. Оказывается, и для этого есть легкое решение. Вместо того, чтобы издеваться над ним с помощью пустого файла, вы можете имитировать его с помощью чего-то, что возвращает строковое имя класса всякий раз, когда на него ссылаются.

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

Использованная литература: