vue-jest 配置 - 有没有办法映射出现在模板/脚本 src 属性中的别名?

问题描述

依赖:"@vue/cli-plugin-unit-jest": "^4.5.13","@vue/test-utils": "^1.2.1","vue-jest": "^3.0 .7"

我有一个应用程序,它使用在 vue.config.js 中设置的别名(比如“foo”):

module.exports = {
  chainWebpack: (config) => {
    // Add project name as alias
    config.resolve.alias.set('foo',__dirname);
  },};

对于 import 语句和 HTML 标签 src...

在 main.js 中:

...
import App from 'foo/src/components/core/App';
...

在../src/core/App/index.vue:

<script src="foo/src/components/core/App/script.js" />
<style module src="foo/src/components/core/App/style.css" />
<template src="foo/src/components/core/App/template.html" />

我知道我可以在 jest.config.js 中使用 moduleNameMapper,例如:

'^foo(.*)$': '<rootDir>$1',

但是,这不会映射出现在我的 HTML 标签的 src 属性中的别名。有没有办法让 vue-jest 通过配置设置或其他方式解释这些属性路径?

任何建议将不胜感激。

解决方法

SFC 中的 URL 解析

vue-jest 不会为 SFC 中的顶级块标记解析 src URL,因此您必须在 src/components/core/App/index.vue 中使用无别名的相对路径:

<script src="./script.js" />
<style module src="./style.css" />
<template src="./template.html" />

<template> 内容中的 URL 解析

vue-jest 使用 @vue/component-compiler-utils 编译模板,但 URL 解析需要 transformAssetUrls optionvue-jest 3.x 不支持将选项传递给 @vue/component-compiler-utils,但现在可以通过 4.0.0-rc.1templateCompiler.transformAssetUrls config 中使用。

即使启用了此 URL 解析,Vue CLI 也会将 jest 配置为 return an empty string for require-ed media,including images。如果您的测试需要使用生产中正常解析的 URL,您将需要模拟 url-loader 的 Jest 转换。 Vue CLI 将加载器配置为 return the resolved filename if greater than 4KB; or the base64 data URL otherwise

启用 URL 解析:

  1. 更新到 vue-jest 4:

    npm i -D vue-jest@4
    
  2. 为自定义 my-jest-url-loader 创建以下文件,稍后我们将使用该文件:

    // <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 = ')
      }
    }
    
  3. 为避免意外覆盖 Vue CLI 的默认 Jest 预设,请使用合并实用程序(例如 lodash.merge)在 jest.config.js 中插入自定义配置。

  4. Jest global 中添加 vue-jest 配置,设置 templateCompiler.transformAssetUrls

  5. 修改合并预设的 transform 属性以使用我们的 my-jest-url-loader 转换图像。这需要从默认 Jest 预设中移除其他图像变换以避免冲突。

    // 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
    

GitHub demo

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...