45

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!

1
  • 1
    you need to register router-link as a stub. Commented May 7, 2018 at 14:09

4 Answers 4

100

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.

Sign up to request clarification or add additional context in comments.

4 Comments

Second way worked for me. The html() function returned <!----> wherever I was using <router-link.... After using a localVue and RouterLinkStub, it rendered my <router-link... properly to the <a... so that I could test the existence and values for data inside the <router-link. The OP was trying to use wrapper.find('router-link') and I don't think this answer solves that problem. But it solved mine, which was a similar one.
This is not working in version 1.0.0-beta.11. For what version is this solution?
Is there a way to make the test fail instead of outputting the warning message?
also can use const wrapper = mount(Status, { stubs: ['router-link'] })
6

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.

1 Comment

accepted answer didn't work for me but this one did. Nice job!
2

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

Comments

0
const wrapper = shallow(TempComponent, {
  propsData: { temp },
  localVue
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.