Search code examples
typescriptvue.jsjestjsvuetify.jsts-jest

Vuetify Jest Unknown custom element <v-*>


I am writing unit tests for my project, using Jest. Project is based on Vue, Vuetify (1.5) and TypeScript (and vue-property-decorator).

I have basic wrapper for <v-btn>. It looks like this:

<template>
  <v-btn
    :round="!square"
    v-on="$listeners"
  >
    <slot />
  </v-btn>
</template>

<script lang="ts">
import { Vue, Prop, Component } from 'vue-property-decorator';

import { VBtn } from 'vuetify/lib';

@Component({
  components: {
    VBtn,
  },
})
export default class Btn extends Vue {
  @Prop({ default: false, type: Boolean }) private square!: boolean;
}
</script>

And I wrote basic test, just to mount this component:

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

describe('Btn', () => {

  it('should render button', () => {
    const wrapper = mount(Btn, {
      propsData: {
        onClick: () => {}
      }
    });

    console.log((Vue as any).options.components.VBtn)

    console.log('=======================');
    console.log(wrapper.html());
    console.log('=======================');
  });
});

When running test I'm getting this error:

  console.error node_modules/vue/dist/vue.runtime.common.dev.js:621
    [Vue warn]: Unknown custom element: <v-btn> - did you register the component correctly? For recursive components, make sure to provide the "name" option.

    found in

    ---> <Btn>

But I know that component is registered - it works when running the project (not test). Also, I have console log in test that checks if it is registered (console.log((Vue as any).options.components.VBtn)) and it shows that component is registered globally.

Here is my jest.config.js:

module.exports = {
  moduleFileExtensions: [
    "js",
    "ts",
    "json",
    "vue"
  ],
  moduleNameMapper: {
    "^@/(.*)$": "<rootDir>/src/$1",
    "^vuetify/lib$": "vuetify",
  },
  modulePaths: [
    "<rootDir>/src",
    "<rootDir>/node_modules"
  ],
  transform: {
    ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub",
    "^.+\\.ts?$": "ts-jest",
    ".*\\.(vue)$": "vue-jest",
  },
  transformIgnorePatterns: [
    "<rootDir>/node_modules/(?!(vuetify)/)",
  ],
  testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(js?|ts?)$",
  setupFilesAfterEnv: ['<rootDir>/tests/unit/setup.ts'],
}

And setup.ts file:

import Vue from 'vue';
import Vuetify from 'vuetify';

Vue.config.productionTip = false;
Vue.use(Vuetify);

I was trying to move code from setup.ts to the test but it doesn't changed anything. I think there may be problem with 'vue-property-decorator' but my whole project is based on it so I don't want to change it. Can you help me? Maybe something is wrong in my Jest transform configuration?


Solution

  • I managed to solve this problem. Had to change two lines of code:

    In my Btn component, changed VBtn import to: import { VBtn } from 'vuetify/lib/components/VBtn'; (imported from vuetify/lib/components/VBtn, not from vuetify/lib).

    In jest.config.js update in moduleNameMapper to 'vuetify/lib(.*)': '<rootDir>/node_modules/vuetify/es5$1'.

    And that is all, now it works :)

    My whole jest.config.js:

    module.exports = {
      moduleFileExtensions: [
        "js",
        "ts",
        "json",
        "vue"
      ],
      moduleNameMapper: {
        "^@/(.*)$": "<rootDir>/src/$1",
        'vuetify/lib(.*)': '<rootDir>/node_modules/vuetify/es5$1',
      },
      modulePaths: [
        "<rootDir>/src",
        "<rootDir>/node_modules"
      ],
      transform: {
        ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub",
        "^.+\\.ts?$": "ts-jest",
        ".*\\.(vue)$": "vue-jest",
      },
      transformIgnorePatterns: [
        "<rootDir>/node_modules/(?!(vuetify)/)",
      ],
      testRegex: "(/__tests__/.*|(\\.|/)(test|spec))\\.(js?|ts?)$",
      setupFilesAfterEnv: ['<rootDir>/tests/unit/setup.ts'],
    }