Using Vue Test Utils with Jest to test Vue.js under Webpacker in Rails
When it comes to testing for Ruby on Rails project, RSpec must be the most common tool that people would implement. By using RSpec, we could easily write a good testing script for our Rails project and test our project thoroughly. But after Rails 6 integrates Webpacker in the project as default, there are more chances that we would implement Javascript frameworks in the Rails project, and RSpec might no longer enough for us to test our Rails project thoroughly including testing those Javascript functions, so is that a good way for us to test those Javascript functions and scripts under Webpacker in a Rails project? one of the answers is using Vue Test Utils with Jest. In the following section, I’ll show how to set up and test Vue.js under Webpacker in Rails project by using Vue Test Utils with Jest.
Package Installation
Before start testing, there are some packages that need to be installed in our project.
Install Vue Test Utils and vue-jest
to process vue single file components.
yarn add @vue/test-utils
yarn add vue-jest --dev
Installing babel-core, because we are going to use babel
and import vue single file components .vue
extension inside our tests.
yarn add babel-core@bridge --dev
Setting Config
After all the packages are installed, some settings need to be added to package.json
before start testing.
Adding the scripts
to package.json
, and you could run your tests through yarn test
"scripts": {
"test": "jest"
}
You could define the location of your tests. To do this you could add roots
to package.json
You also need to tell Jest to transform .vue
files using vue-jest
and transform .js
files with babel-jest
, and to do so the moduleFileExtensions
and transform
params need to set as below. The test environment also need to be clarified, so testEnvironment
params need to set in package.json
The example config setting is as below.
"jest": {
"roots": [
"app/javascript/spec"
],
"moduleFileExtensions": [
"js",
"json",
// tell Jest to handle `*.vue` files
"vue"
],
"transform": {
// process `*.js` files with `babel-jest`
"^.+\\.js$": "babel-jest",
"^.+\\.vue$": "vue-jest"
},
"testEnvironment": "jsdom"
}
Writing Test
First of all, Creating a test file under the testing root(app/javascript/spec
), and the file name should end with .test.js
For example, creating a Home.test.js
(the script is as below). At first, I just want to try if all the settings are done and the .test.js
could run, so I only addconsole.log('Done!')
in the testing script. Then, run yarn test
test('the very first test', () => {
console.log('Done!')
})
After running yarn test
, If the test file could run and all the tests are pass, the results in the console might show as below picture. It would show a green pass.
But if some tests failed, you might see some red fail in the result as below picture.
The code style of Vue Test Utils is similar to RSpec. You could also use describe
function to add more description of what you are testing. For example, we could add describe
function outside the test function to describe more about the test.
describe('Just try if it works', () => {
test('the very first test', () => {
console.log('Done')
})
})
Run yarn test
and the result in the console will show the description we put in the describe
function.
After checking the test files could run, we could test some vue components in our Rails project. In the test file, Vue Test Utils should be imported first, and we also need to import the vue component we want to test. The example code is as below.
import { mount, shallowMount } from '@vue/test-utils'
import Home from '../src/components/XXX.vue'
When import Vue Test Utils, mount
or shallowMount
should be imported. They both could be used to wrap vue components and render them when testing. These two method work similarly. The only difference is shallowMount
doesn’t render child components so that it allows us to test the component in isolation to make sure that child components are not included in the test. Vue Test Utils provides many methods for us to test vue components, for example, it provides a find method to find an element in components and it also provides a html method to check if the component html is as expected.
For example, there is a AuthPanel.test.js
to test the AuthPanel component AuthPanel.vue
in my example project. For more information, the AuthPanel component is a component that I use on the login page in this project
We could see In AuthPanel.test.js
as below, the Vue Test Utils and AuthPanel.vue
are imported. In this case, I want to test if the component is rendered as expected, so I use shallowMount
to wrap the component AuthPanel.vue
and render it, then using html method to check if the component is rendered as expected or not.
import { shallowMount } from '@vue/test-utils'
import AuthPanel from '../src/components/AuthPanel.vue'describe('AuthPanel.vue', () => {
test('check html', () => {
const wrapper = shallowMount(AuthPanel);
expect(wrapper.html()).toBe(
`<div class="auth-panel">
<br>
<input type="email" name="email" id="email">
<br>
<input type="password" name="password" id="password">
<button type="button" class="btn btn-secondary">Sign Up</button>
</div>`)
})
})
After running yarn test
if the test passes and shows a green pass in the console, it means that the component renders just as we expect.
But if the test fails, the result in the console will show what is different from what we expect as below picture, and we could follow the instruction to modify our code.
After reading the example above, we have a basic idea about how to start testing Vue.js under Webpacker in a Rails project. I only share using the html method to test vue component, but actually, there are more useful methods that Vue Test Utils provides for us to implement in testing, so I’ll share more articles about this related topic in the future. The source code I provide in the examples in this article could be found in the below repo of my Github page. If you are interested in the detail of settings and scripts, feel free to reach the below link. Thank you for your watching!