Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue-Test-Utils Unknown custom element: <router-link>

I'm using Jest to run my tests utilizing the vue-test-utils library.

Even though I've added the VueRouter to the localVue instance, it says it can't actually find the router-link component. If the code looks a little funky, it's because I'm using TypeScript, but it should read pretty close to ES6... Main thing is that the @Prop() is the same as passing in props: {..}

Vue component:

<template>
  <div>
    <div class="temp">
      <div>
        <router-link :to="temp.url">{{temp.name}}</router-link>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
import { Prop } from 'vue-property-decorator'
import { Temp } from './Temp'

@Component({
  name: 'temp'
})
export default class TempComponent extends Vue {
  @Prop() private temp: Temp
}
</script>

<style lang="scss" scoped>
.temp {
  padding-top: 10px;
}
</style>

Temp model:

export class Temp {
  public static Default: Temp = new Temp(-1, '')

  public url: string

  constructor(public id: number, public name: string) {
    this.id = id
    this.name = name
    this.url = '/temp/' + id
  }
}

Jest test

import { createLocalVue, shallow } from '@vue/test-utils'
import TempComponent from '@/components/Temp.vue'
import { Temp } from '@/components/Temp'
import VueRouter from 'vue-router'

const localVue = createLocalVue()
localVue.use(VueRouter)

describe('Temp.vue Component', () => {
  test('renders a router-link tag with to temp.url', () => {
    const temp = Temp.Default
    temp.url = 'http://some-url.com'

    const wrapper = shallow(TempComponent, {
      propsData: { temp }
    })
    const aWrapper = wrapper.find('router-link')
    expect((aWrapper.attributes() as any).to).toBe(temp.url)
  })
})

What am I missing? The test actually passes, it just throws the warning. In fact, here is the output:

Test Output:

$ jest --config test/unit/jest.conf.js
 PASS  ClientApp\components\__tests__\temp.spec.ts
  Temp.vue Component
    √ renders a router-link tag with to temp.url (30ms)

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

    (found in <Root>)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.677s
Ran all test suites.
Done in 6.94s.

Appreciate any help you can give!

like image 669
Chad Carter Avatar asked Apr 05 '18 21:04

Chad Carter


3 Answers

Add the router-link stub to the shallow (or shallowMount) method options like this:

const wrapper = shallow(TempComponent, {      propsData: { temp },      stubs: ['router-link'] }) 

or this way:

import { RouterLinkStub } from '@vue/test-utils';  const wrapper = shallow(TempComponent, {      propsData: { temp },      stubs: {          RouterLink: RouterLinkStub      } }) 

The error should go away after you do this.

like image 195
Anna Tolochko Avatar answered Sep 21 '22 18:09

Anna Tolochko


Worked for me:

[ Package.json ] file

... "vue-jest": "^3.0.5", "vue-router": "~3.1.5", "vue": "~2.6.11", "@vue/test-utils": "1.0.0-beta.29", ... 

[ Test ] file

import App from '../../src/App'; import { mount, createLocalVue } from '@vue/test-utils'; import VueRouter from 'vue-router';  const localVue = createLocalVue(); localVue.use(VueRouter);  const router = new VueRouter({   routes: [     {       name: 'dashboard',       path: '/dashboard'     }   ] });  describe('Successful test', ()=>{   it('works', ()=>{         let wrapper = mount(App, {       localVue,       router     });      // Here is your assertion   }); }); 

Or you can try this: enter image description here

like image 34
Elmatsidis Paul Avatar answered Sep 17 '22 18:09

Elmatsidis Paul


With Vue 3 and Vue Test Utils Next (v4), it seems you just have to add your router (the return object from createRouter) as a plugin to your mountOptions:

import router from "@/router";

const mountOptions = {
  global: {
    plugins: [router],
  },
};

https://next.vue-test-utils.vuejs.org/api/#global

Or a more full example:

import router from "@/router";
import Button from "@/components/Button.vue";

const mountOptions = {
  global: {
    mocks: {
      $route: "home",
      $router: {
        push: jest.fn(),
      },
    },
    plugins: [router],
  },
};


it("Renders", () => {
  const wrapper = shallowMount(Button, mountOptions);
  expect(wrapper.get("nav").getComponent({ name: "router-link" })).toExist();
});

Note, in the example above I'm using a project setup with Vue CLI.

like image 28
V. Rubinetti Avatar answered Sep 20 '22 18:09

V. Rubinetti