17

I've been working with vuejs and bootstrap-vue lately. Decided to add unit testing to my project.

I'm not realy familiar with unit testing so I'm trying anything I could find to understand how it works.

Login.specs.js

import { shallowMount, mount } from '@vue/test-utils'
import Login from '@/components/auth/Login.vue'

describe('Login.vue', () => {
  it('is a Vue instance', () => {
   const wrapper = mount(Login, {
    mocks: {
     $t: () => 'Connexion' // i18N
    }
   })
  const h2 = wrapper.find('h2')
  expect(h2.text()).toBe('Connexion')
 })
})

Login.vue

<b-row align-h="center">
 <b-col class="text-center">
  <h2>{{ $t('login.connection') }}</h2>
 </b-col>
</b-row>

Everything seems ok with the test. But I got these wannings and could find a way to actualy fix it.

[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.

[Vue warn]: Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option.

So I looked around and it seems like I need to add these child components to the father.

Here is the documentation for these components.

I'm also adding my config files (There're the same as the vue-cli 3 generates them)

jest.congif.js

module.exports = {
  moduleFileExtensions: [
  'js',
  'jsx',
  'json',
  'vue'
 ],
 transform: {
  '^.+\\.vue$': 'vue-jest',
  '.+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$': 'jest- transform-stub',
  '^.+\\.jsx?$': 'babel-jest'
 },
 moduleNameMapper: {
  '^@/(.*)$': '<rootDir>/src/$1'
 },
 snapshotSerializers: [
  'jest-serializer-vue'
 ],
 testPathIgnorePatterns: [ //I've added this one, not sure if usefull
  '<rootDir>/node_modules'
 ],
 testMatch: [
  '**/tests/unit/**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)'
 ]
}
Community
  • 1
  • 1
Freezy
  • 173
  • 1
  • 10

4 Answers4

31

If you're adding bootstrap vue as a global plugin:

Vue.use(BootstrapVue);

Then in your tests, you're likely going to want to follow this tip:

https://vue-test-utils.vuejs.org/guides/common-tips.html#applying-global-plugins-and-mixins

Which outlines how you can use the createLocalVue() and set it up with the same global config as your app:

import { createLocalVue } from '@vue/test-utils'

// create an extended `Vue` constructor
const localVue = createLocalVue()

// install plugins as normal
localVue.use(BootstrapVue)

// pass the `localVue` to the mount options
mount(Component, {
  localVue
})

Then your components should be registered properly-

chrismarx
  • 8,268
  • 7
  • 69
  • 85
  • 1
    It still displays warns `[BootstrapVue warn]: tooltip unable to find target element in document` – BartusZak Jan 28 '20 at 10:14
  • 2
    i am facing the same issue and even after installing BootstrapVue plugin globally like this **localVue.use(BootstrapVue)** test run prints the warning in console "Unknown custom element: - did you register the component correctly? For recursive components, make sure to provide the "name" option." how to fix it? @BartusZak – Saradha Mar 02 '20 at 11:09
  • 1
    It still displays warns for me. I did not find any solution :( – BartusZak Mar 02 '20 at 13:31
  • 1
    @BartusZak stubbing the bootstrap vue component on mount solves the issue .. there are not warning in the console. – Saradha Mar 03 '20 at 15:12
  • Set `BOOTSTRAP_VUE_NO_WARN` to disable warnings. – moltar May 18 '20 at 12:33
  • @BartusZak I had the same issue and I also had to add `await wrapper.vm.$nextTick()` before `expect(wrapper.element).toMatchSnapshot()`. Sometimes I needed to add more than one `await wrapper.vm.$nextTick()` so all the children rendered. See how bootstrap-vue does it: https://github.com/bootstrap-vue/bootstrap-vue/blob/c3db7585ce6bc62c9b4ee50a934a471b185c94c9/src/directives/tooltip/tooltip.spec.js#L59 – ratherblue Jul 01 '20 at 22:26
  • @BartusZak Also sometimes I had to add `attachTo: createContainer()` (same function as bootstrap-vue). that got rid of 99% of my tooltip warnings – ratherblue Jul 01 '20 at 23:43
4

It is also possible to stub components like

const wrapper = mount(Login, {
  mocks: {
    $t: () => 'Connexion' // i18N
  },
  stubs: {
    BCol: true
  }
});
Jan Tumanov
  • 850
  • 7
  • 9
  • Thank you ! It kinda worked, i had 64 "errors", only 40 remains, some of them are b-cols or b-rows. I'll look it up later. – Freezy Sep 26 '18 at 16:05
1

Expanding on chrismarx answer.

Here is a example used in a vue/nuxt application with bootstrap-vue. While testing my component FormInput.vue that has some elements from bootstrap-vue, I was getting errors like Unknown custom element: <b-form-input> and Unknown custom element: <b-col> and Unknown custom element: <b-row>

Doc show example for using slots and custom components. I did the following to move past my errors. Note the bootstrap-vue import and the stubs section:

import { /* mount, */ shallowMount } from '@vue/test-utils'
import { BRow, BCol, BFormInput } from 'bootstrap-vue'
import FormInput from './FormInput.vue'

describe('FormInput test', () => {
  test('is a Vue instance', () => {
    const wrapper = shallowMount(FormInput, {
      stubs: {
        // used to register custom components
        'b-form-input': BFormInput,
        'b-row': BRow,
        'b-col': BCol,
      },
    })
    expect(wrapper.vm).toBeTruthy()
  })
})

learnsomemore
  • 516
  • 4
  • 12
0

There are two options for this. Firstly, If you use localVue instance you have to register your bootstrap-vue component as global object using this localVue.component("b-breadcrumb", BBreadcrumb)

I will mention to b-breadcrumb as if it any part of boostrap-vue's components.

const localVue = createLocalVue()
localVue.component("b-breadcrumb", BBreadcrumb)
mount(CustomComponent, {
  // Some options
})

Secondly, If you don't use localVueinstance you can register this component as a param of mount method like this

mount(CustomComponent, {
  // Some options
  components: {
    BBreadcrumb
  },
})

There is a important issue that If you use localVue instance components option of mount method will not work.

Also you can ignore any bootstrap-vue component to avoid unneccessary rendering using stubs option of mount method.

mount(CustomComponent, {
  stubs: ["b-breadcrumb"]
})

More information about options of mount here

Serhan C.
  • 742
  • 1
  • 8
  • 8