Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Transforming Vue 3 components for unit testing with Jest #35

Closed
michaelprather opened this issue Dec 10, 2021 · 3 comments
Closed

Transforming Vue 3 components for unit testing with Jest #35

michaelprather opened this issue Dec 10, 2021 · 3 comments

Comments

@michaelprather
Copy link

If you need to transform Vue 3 components created using Vite SVG Loader for the purpose of Jest unit testing:

  1. Create a mock component. I saved mine to the tests directory.
<template>
  <svg />
</template>

You could alternatively use jest-transform-stub, but it may log warnings to the console. Plus this way the rendered HTML includes an <svg> tag.

  1. Update your jest.config.js to transform SVG components into the mock component:
// jest.config.js
module.exports = {
  transform: {
    "^.+\\.[t|j]sx?$": "babel-jest",
    "^[^.]+.vue$": "@vue/vue3-jest",
  },
  testMatch: ["**/tests/**/*.spec.js"],
  moduleFileExtensions: ["js", "vue"],
  moduleNameMapper: {
    ".+\\.(svg)(\\?component)?$": "<rootDir>/tests/svgMock.vue",
    "^@/(.*)$": "<rootDir>/src/$1",
  },
  testEnvironment: "jsdom",
  collectCoverage: true,
}

I've included my entire jest.config.js file for reference, but the key part is here:

module.exports = {
  ...
  moduleNameMapper: {
    ".+\\.(svg)(\\?component)?$": "<rootDir>/tests/svgMock.vue",
    ...
  },
  ...
}

Now all components created using Vite SVG Loader will be automatically transformed to the mock component.

@jpkleemans
Copy link
Owner

Thanks for this guide!

@pdcmoreira
Copy link

This doesn't work if you want to test that the icon is rendered:

import EditIcon from '@/assets/icons/edit.svg'

// ...

expect(wrapper.findComponent(EditIcon).exists()).toBeTruthy() // doesn't work

But if instead of setting up the moduleNameMapper, you simply mock it in each test suite, it works:

jest.mock('@/assets/icons/edit.svg', () => ({ el: '<svg />' }))

import EditIcon from '@/assets/icons/edit.svg'

// ...

expect(wrapper.findComponent(EditIcon).exists()).toBeTruthy() // works

@pdcmoreira
Copy link

Nevermind my previous comment, it also doesn't seem to work properly in some cases.
I've created a simple custom transformer which appears to work in all cases I've tested so far:

tests/jest-svg-component-transformer.js:

module.exports = {
  process(sourceText, sourcePath) {
    const mockComponent = {
      name: sourcePath,

      template: sourceText
    }

    return {
      code: `module.exports = ${JSON.stringify(mockComponent)};`
    }
  }
}

jest.config.js:

module.exports = {
  // ...
  transform: {
    '^.+\\.vue$': '@vue/vue3-jest',
    // remove 'svg' from here:
    '.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2|mp3)$':
    'jest-transform-stub',
    '^.+\\.(js|jsx)?$': 'babel-jest',
    // specific transformer for svg:
    '.+\\.svg$': '<rootDir>/tests/jest-svg-component-transformer.js'
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants