Configuring vue-jest: Does anyone know how to set up aliases for template/script src attributes in Vue?

Dependencies: "@vue/cli-plugin-unit-jest": "^4.5.13", "@vue/test-utils": "^1.2.1", "vue-jest": "^3.0.7"

I am dealing with an application that utilizes an alias (referred to as "foo") defined in vue.config.js:

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

This alias is used for both import statements and HTML tag src attributes...

In main.js:

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

In ../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" />

I have tried using a moduleNameMapper in jest.config.js like this:

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

However, this approach does not seem to work for aliases present in the src attribute of HTML tags. Is there a way for vue-jest to interpret these paths specified in attribute paths through configuration options or other methods?

Any suggestions would be highly valuable.

Answer №1

Decoding URLs in Single File Components

vue-jest does not handle the resolution of src URLs for top-level block tags in SFCs. As a workaround, utilize relative paths without aliases in

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

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

URL Parsing within <template> Contents

vue-jest leverages @vue/component-compiler-utils for template compilation. However, enabling URL parsing mandates the use of the transformAssetUrls option. While version 3.x lacks support for passing options to @vue/component-compiler-utils, this capability is now available in 4.0.0-rc.1 through a

templateCompiler.transformAssetUrls
configuration.

Despite enabling URL parsing, Vue CLI configures jest to return an empty string for media required via require, such as images. To handle normally resolved URLs during production testing, implement a Jest transform akin to url-loader. Vue CLI customizes the loader to return the filename if exceeding 4KB or a base64 data URL otherwise.

To enable URL parsing:

  1. Upgrade to vue-jest 4:

    npm i -D vue-jest@4
    
  2. Create a file for a personalized my-jest-url-loader that will be utilized later:

    // <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. To prevent inadvertently overwriting Vue CLI's default Jest presets, employ a merging utility (e.g., lodash.merge) to integrate a customized configuration into jest.config.js.

  4. Add a vue-jest configuration within a Jest global, defining

    templateCompiler.transformAssetUrls
    .

  5. Adjust the transformed preset's transform property to include our my-jest-url-loader transform for handling images. This necessitates 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
    

Demonstration on GitHub

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to view and use the data stored within this JSON object?

Obtaining information from a straightforward API (). I retrieve the data using getJSON: var police = $.getJSON(queryurl); A console.log on police displays this: However, I am unable to access the properties within the object. I assumed that I could ac ...

Using VueLoaderPlugin() results in an 'undefined error for 'findIndex' function

Currently, I am in the process of integrating a Vue CLI app into another web project that we are actively developing. The Vue app functions without any issues when utilizing the development server bundled with Vue CLI. Due to the presence of .vue files wi ...

implementing automatic ajax requests when user scrolls

This is a piece of JavaScript code: $(window).scroll(function() { $.ajax({ type: "GET", url: "not_data.php", data: dataString, success: function my_func () { //show new name ...

Is there a way to verify if a Backbone.View is actively displayed in the DOM?

Is there a way to determine if a Backbone.View is currently rendered in the DOM, so that I do not need to rerender it? Any suggestions on how this can be achieved? Thanks and regards ...

Receiving JSON information from a web address using Javascript

I'm currently faced with a challenge in extracting JSON data from a web server. Despite the absence of errors in my code, I encounter difficulties displaying any output. Below is a snippet of the issue: <!DOCTYPE HTML> <html> <head ...

Find the differences between the values in two arrays of objects and eliminate them from the first array

const arrayOne = [ { id: 22, value: 'hello' }, { id: 33, value: 'there' }, { id: 44, value: 'apple' } ]; const arrayTwo = [ { id: 55, value: 'world' }, { id: 66, value: 'banana' }, ...

Ways to check requests that need authentication of the user in Express

Is it possible to test requests that require user authentication? I am currently using local passport.js in my express app and testing with Jest and Supertest. Despite researching various solutions and attempting different methods, such as supertest-sessio ...

Analyzing string values in Cypress

When attempting to compare two values within a page and make an assertion, my goal is to retrieve the value of one text element and compare it with another value on the same page. While I find this process straightforward in Java/selenium, achieving the ...

Unable to implement multiple draggable inner objects using Angular 5 and dragula library

After struggling for the past few days, I can't seem to get it to work... Here is a brief explanation of my issue: In this example, I have an array of objects structured like this: public containers: Array<object> = [ { "name": "contain ...

I am curious about the inner workings of the `createApplication()` function in the ExpressJS source code. Can you shed some light on

My goal is to deeply comprehend the inner workings of the Express library, step by step. From what I gather, when we import and invoke the 'express()' function in our codebase, the execution flow navigates to the ExpressJS library and searches fo ...

Is there a way to implement absolute imports in both Storybook and Next.js?

Within my .storybook/main.js file, I've included the following webpack configuration: webpackFinal: async (config) => { config.resolve.modules = [ ...(config.resolve.modules || []), path.resolve(__dirname), ]; return ...

Having trouble retrieving information from the local API in React-Native

Currently, I have a web application built using React and an API developed in Laravel. Now, I am planning to create a mobile app that will also utilize the same API. However, I'm encountering an issue where I cannot fetch data due to receiving the err ...

Developing desktop applications using C# scripting

I currently have a C# desktop program that is able to work with new C# plugins. My goal is to modify the existing C# application to allow for scripts to be used as plugins. These scripts could be in JavaScript, Windows Script Host (WSh), or any other form ...

Contrast between PHP and JavaScript output texts

Hey everyone, I'm dealing with a bit of an awkward situation here. I am trying to return a string variable from PHP to JavaScript and use it for a simple comparison in my code. However, the results are not turning out as expected. Initially, I send a ...

Leveraging Ajax with Google Analytics

Currently, I am working on a website that utilizes Ajax calls to update the main content. In order to integrate Google Analytics tracking code using the async _gaq method, I need to push a _trackPageview event with the URI to _gaq. There are two approaches ...

Select the send all text option when making a request

Using ajax, I can dynamically fill a drop-down select menu. My next step is to include all the text from the selected options in my request. <select name=".." > <option value="0"> ... </option> <option value="1"> xxx </option ...

I'm currently in the process of creating a snake game using HTML5. Can you help me identify any issues or problems that

I am experiencing an issue where nothing is appearing on the screen. Below are the contents of my index.html file: <html> <body> <canvas id="canvas" width="480" height="480" style="background-color:grey;"></canvas> <script src=" ...

Tips for creating a filter in React JS using checkboxes

In my current situation, I have a constant that will eventually be replaced with an API. For now, it resembles the future API in the following way: const foo = { {'id':1, 'price':200, 'type':1,}, {'id':2, &apo ...

The behavior of Date's constructor differs when applied to trimmed versus untrimmed strings

Although it's commonly advised against creating a date from a string, I stumbled upon an interesting phenomenon: adding a space before or after the date string can impact the resulting date value. console.log([ new Date('2019-03'), ...

Trouble accessing environment variables within a React application, specifically when using webpack's DefinePlugin in a Dockerfile

I can't figure out why console.log is printing undefined. The files Makefile, config.env, webpack.config.js, and package.json are all located in the root of my project. Makefile: docker-run: docker docker run -it --env-file config.env -p "80:80" ...