Let’s assume a basic Bootstrap driven HTML form as part of a custom Vue component MyForm.vue
<template> <form> <div class="form-group"> <label for="email">Email address</label> <input type="email" class="form-control" id="email"> </div> <button type="submit" class="btn btn-primary">Submit</button> </form> </template>
A unit test for testing if the template is rendered successfully is pretty simple
describe('MyForm', () => { let wrapper; beforeEach(...); it('Should be rendered', () => { let field = wrapper.find('#email'); expect(field.element.value).toEqual(''); }); });
This line works field.element.value
works because field.element
is of native type HtmlInputElement
with value
attribute.
What if I want access an attribute of a complex component let’s say of b-form-input, the Bootstrap-Vue’s default input element? b-form-input
is of type BFormInput
how to deal with it? Just cast the HtmlElement
to BFormInput
?
<template> <b-form> <b-form-group label="Email"> <b-form-input type="email" id="email"></b-form-input> </b-form-group> <b-button type="submit" variant="primary">Submit</button> </b-form> </template>
How to test non-native components? Specially with type-safety means TypeScript. Any ideas?
Edit 03/01/2020
Following up to muka.gergely‘s answer I found this article. shallowMount
is stubbing all child components by default which prevents also event handling. Moreover shallowMount
allows to manually unstub components, in my case to unstub b-form
and b-button
for submit event testing.
const stubs = { // Originally intended to provide custom stubs, here used to unstub components BButton, BForm, }; wrapper = shallowMount<MyComponent>(MyComponent, {stubs});
This effects that these components are rendered instead of stubbed. All remaining components like the b-form-input
are still automatically stubbed.
Advertisement
Answer
You have to mount
the elements before testing them. You don’t test the Vue component that you wrote, but the rendered output.
You should add vue-test-utils then your unit testing library (Jest and Mocha are well supported).
- You can find vue-test-utils here: https://www.npmjs.com/package/@vue/test-utils
- More on Vue unit testing: https://v2.vuejs.org/v2/guide/unit-testing.html
- More on vue-test-utils: https://vue-test-utils.vuejs.org/guides/#getting-started
Here’s a basic unit test for App.vue (with Vuetify and vue-router):
import Vue from 'vue' import { shallowMount, createLocalVue } from '@vue/test-utils' import Vuetify from 'vuetify' import VueRouter from 'vue-router' import App from '@/App'; Vue.use(Vuetify) const localVue = createLocalVue() localVue.use(VueRouter) const router = new VueRouter() describe('App.vue', () => { let vuetify beforeEach(() => { vuetify = new Vuetify() }) it('mounts and renders', () => { const wrapper = shallowMount(App, { localVue, vuetify, router }); expect(wrapper.html()).toBeTruthy(); }); });
You can see that I used shallowMount()
as I wasn’t interested in testing the children of App.vue (they all have their separate unit tests). If I had been, then I should’ve used mount()
instead.