0👍
URL parsing in SFCs
vue-jest
doesn’t resolve src
URLs for the top-level block tags in SFCs, so you’ll have to use un-aliased relative paths in src/components/core/App/index.vue
:
<script src="./script.js" />
<style module src="./style.css" />
<template src="./template.html" />
URL parsing in <template>
contents
vue-jest
uses @vue/component-compiler-utils
to compile the template, but URL parsing requires the transformAssetUrls
option. vue-jest
3.x does not support passing options to @vue/component-compiler-utils
, but that now works in 4.0.0-rc.1 via a templateCompiler.transformAssetUrls
config.
Even with this URL parsing enabled, Vue CLI configures jest
to return an empty string for require
-ed media, including images. If your tests need to work with the normally resolved URLs in production, you’ll need a Jest transform that mimics url-loader
. Vue CLI configures the loader to return the resolved filename if greater than 4KB; or the base64 data URL otherwise.
To enable the URL parsing:
-
Update to
vue-jest
4:npm i -D vue-jest@4
-
Create the following file for the custom
my-jest-url-loader
, which we’ll use later below:// <rootDir>/tests/my-jest-url-loader.js const urlLoader = require('url-loader') module.exports = { process(src, filename) { const urlLoaderOptions = { esModule: false, limit: 4096, fallback: { loader: 'file-loader', options: { esModule: false, emitFile: false, name: filename, }, }, } const results = urlLoader.call({ query: urlLoaderOptions, resourcePath: filename, }, src) // strip leading Webpack prefix from file path if it exists return results.replace(/^module.exports = __webpack_public_path__ \+ /, 'module.exports = ') } }
-
To avoid accidentally overwriting Vue CLI’s default Jest presets, use a merge utility (e.g.,
lodash.merge
) to insert a custom config injest.config.js
. -
Add a
vue-jest
config in a Jest global, settingtemplateCompiler.transformAssetUrls
. -
Modify the merged preset’s
transform
property to use ourmy-jest-url-loader
transform for images. This requires removing other image transforms from the default Jest preset to avoid conflicts.// jest.config.js const vueJestPreset = require('@vue/cli-plugin-unit-jest/presets/default/jest-preset') const merge = require('lodash.merge') 3️⃣ const newJestPreset = merge(vueJestPreset, { globals: { 4️⃣ 'vue-jest': { templateCompiler: { transformAssetUrls: { video: ['src', 'poster'], source: 'src', img: 'src', image: ['xlink:href', 'href'], use: ['xlink:href', 'href'] } } } }, moduleNameMapper: { '^foo/(.*)$': '<rootDir>/$1', }, }) function useUrlLoaderForImages(preset) { 5️⃣ const imageTypes = ['jpg', 'jpeg', 'png', 'svg', 'gif', 'webp'] const imageTypesRegex = new RegExp(`(${imageTypes.join('|')})\\|?`, 'ig') // remove the image types from the transforms Object.entries(preset.transform).filter(([key]) => { const regex = new RegExp(key) return imageTypes.some(ext => regex.test(`filename.${ext}`)) }).forEach(([key, value]) => { delete preset.transform[key] const newKey = key.replace(imageTypesRegex, '') preset.transform[newKey] = value }) preset.transform = { ...preset.transform, [`.+\\.(${imageTypes.join('|')})$`]: '<rootDir>/tests/my-jest-url-loader', } } useUrlLoaderForImages(newJestPreset) module.exports = newJestPreset