svg-module icon indicating copy to clipboard operation
svg-module copied to clipboard

Issues when using with Jest

Open adamchipperfield opened this issue 4 years ago • 5 comments

This is a question and not an issue with this module (which I love, it's been super helpful in countless projects for me!)

I have Jest set up to run tests on my components, but as soon as I added SVGs into my components Jest started to throw errors. The main error I get is:

Could not locate module @/assets/icons/misc-close.svg?inline mapped as: /path/to/nuxt/$1.

I've tried to use a number of methods, including the one vue-svg-loader suggests, but nothing works. I even tried removing ?inline from the import but the same error persists.

Can anyone provide any guidance here please?

adamchipperfield avatar Sep 28 '21 17:09 adamchipperfield

Hi @adamchipperfield,

Can you provide a minimal example please?

manuelodelain avatar Sep 29 '21 20:09 manuelodelain

I stumble in the same error today. The problem is that jest can not transform inline SVGs.

Error message:

Test suite failed to run

    Configuration error:
    
    Could not locate module @/assets/logo.svg?inline mapped as:
    /path/to/nuxt/$1.
    
    Please check your configuration for these entries:
    {
      "moduleNameMapper": {
        "/^@\/(.*)$/": "/path/to/nuxt/$1"
      },
      "resolver": undefined
    }

Logo.vue

<template>
	<Logo />
</template>

<script>
import Logo from '@/assets/logo.svg?inline';

export default {
	components: {
		Logo
	}
};
</script>

Logo.test.js

import {mount} from '@vue/test-utils';
import Logo from './Logo';

describe('Logo', () => {
	test('is a Vue instance', () => {
		const wrapper = mount(Logo);
		expect(wrapper.vm).toBeTruthy();
	});
});

jest.config.js

module.exports = {
	moduleNameMapper: {
		'^@/(.*)$': '<rootDir>/$1',
		'^~/(.*)$': '<rootDir>/$1',
		'^vue$': 'vue/dist/vue.common.js'
	},
	moduleFileExtensions: [
		'js',
		'vue',
		'json'
	],
	testEnvironment: 'jsdom',
	transform: {
		'^.+\\.js$': 'babel-jest',
		'.*\\.(vue)$': 'vue-jest'
	},
	collectCoverage: true,
	collectCoverageFrom: [
		'<rootDir>/components/**/*.vue',
		'<rootDir>/pages/**/*.vue'
	]
};

Solution: Maybe something like this in the jest config https://github.com/visualfanatic/vue-svg-loader/issues/38#issuecomment-407657015 But unfortunately I have not yet found a solution that fits my project setup.

Schascha avatar Oct 12 '21 09:10 Schascha

The following configuration helped me, maybe it helps somebody else too:

my component

// Header.vue
<template>
    <navigation-header
        :title-component="{
            name: 'navigation-header-title',
            props: {
                imgSrcDefault:
                    theme === 'Default'
                        ? require('assets/images/logo_default.svg')
                        : require('assets/images/logo_graphite.svg')
            }
        }"
    />
</template>

<script>
import { mapGetters } from 'vuex'

export default {
    name: 'Header',
    computed: {
        ...mapGetters('config', ['theme'])
    }
}
</script>

my jest config

// jest.config.js
module.exports = {
    moduleNameMapper: {
        '^@/(.*)$': '<rootDir>/$1',
        '^~/(.*)$': '<rootDir>/$1',
        '^vue$': 'vue/dist/vue.common.js',
        '^.+/(.*\\.svg)': '<rootDir>/assets/images/$1'
    },
    moduleFileExtensions: ['js', 'vue', 'json'],
    transform: {
        '^.+\\.js$': 'babel-jest',
        '.*\\.(vue)$': 'vue-jest',
        '^.+\\.svg$': '<rootDir>/__tests__/setup/custom-transformers/svg-transformer.js'
    },
    collectCoverage: true,
    collectCoverageFrom: [
        '<rootDir>/components/**/*.vue',
    ],
    coverageReporters: ['cobertura', 'clover', 'json', 'lcov', ['text', { skipFull: true }]],
    testMatch: ['**/__tests__/**/?(*.)+(spec|test).[jt]s?(x)'] // respect only files in test folder which include spec or test in filename
}

my svg transformer:

// svg-transformer.js
module.exports = {
    process(src, filename) {
        return 'module.exports = ' + JSON.stringify(filename) + ';'
    }
}

my test:

    describe('renders navigation-header', () => {
        test('with default logo when theme is Default', () => {
            wrapper = shallowMount(Header, {
                localVue,
                store,
                computed: {
                    theme: () => 'Default'
                }
            })

            expect(wrapper.findComponent(NavigationHeader).props().titleComponent.props.imgSrcDefault).toBe(
                process.cwd() + '/assets/images/logo_default.svg'
            )
        })

        test('with graphite logo when theme is NOT Default', () => {
            wrapper = shallowMount(Header, {
                localVue,
                store,
                computed: {
                    theme: () => 'Special'
                }
            })

            expect(wrapper.findComponent(NavigationHeader).props().titleComponent.props.imgSrcDefault).toBe(
                process.cwd() + '/assets/images/logo_graphite.svg'
            )
        })
    })

andorfermichael avatar Jan 24 '22 08:01 andorfermichael

I was able to resolve this issue using jest-transform-stub and modifying this section in jest.config.js

moduleNameMapper: {
    '^.+/(.*\\.svg)': "jest-transform-stub",
    '^@/(.*)$': '<rootDir>/$1',
    '^~/(.*)$': '<rootDir>/$1',
    '^vue$': 'vue/dist/vue.common.js'
  }

wambugudavis avatar May 06 '22 08:05 wambugudavis

Thanks @wambugudavis this solved it for me perfectly 👍

RuNpiXelruN avatar May 13 '22 04:05 RuNpiXelruN