Why need test?
- Get an error if we break code
- Save time (don't need to test manually)
- It speeds up development because you don’t have to test everything manually after every change.
- Integrate into build workflow
- Improve your code
Vite is an opinionated web dev build tool that serves your code via native ES Module imports during dev and bundles it with Rollup for production.
Vue-Test-Utils is a utilities for testing Vue components
Table Of Contents
Getting Started
- Lets create a folder
mkdir vue-testing
-
cd vue-testing
thennpm init -y
- Install dependencies
npm install vue@3.0.0
npm install vite @vue/test-utils@^2.0.0-beta.5 --save-dev
- Create
./src/App.vue
<template>
<h1>
Hello world!
</h1>
</template>
<script>
export default {
name: 'App'
}
</script>
- Create
./src/main.js
root director
import {createApp} from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
- Add
index.html
<!DOCTYPE html>
<html lang="en">
</head>
<body>
<div id="app"></div>
<script type="module" src="./src/main.js"></script>
</body>
</html>
- Update or Add scripts to your
package.json
file
"scripts": {
"serve": "vite",
....
}
- Now we can run our application to make sure everything is working.
npm run serve
Adding Test to your application
- Lets create a folder
mkdir test
cd test
- Create
./test/App.spec.js
import { mount } from '@vue/test-utils'
import App from '../src/App.vue'
describe('App.spec.js', () => {
it('renders', () => {
const wrapper = mount(App, { attachTo: '#root' })
expect(wrapper.html()).to.contain('Hello')
})
})
- Create
./test/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue Testing</title>
<link href="https://unpkg.com/mocha@4.0.1/mocha.css" rel="stylesheet"/>
<script src="https://unpkg.com/chai@4.1.2/chai.js"></script>
<script src="https://unpkg.com/mocha@4.0.1/mocha.js"></script>
<style>
#meta > * {
margin: 20px 50px 0 50px;
font-weight: 200;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
#meta > h1 { font-size: 2em; }
#meta > h2 { font-size: 1.5em; }
#root {
margin: 20px 50px 0 50px;
}
</style>
<script>
mocha.setup('bdd')
window.expect = chai.expect
</script>
</head>
<body>
<div id="meta">
<h2>Mocha HTML Reporter</h2>
<div>
<div id="mocha" style="margin: 0;"></div>
</div>
</div>
</body>
</html>
- Add setup
beforeEach(() => {
delete window["__VUE_DEVTOOLS_TOAST__"]
const existingRoot = document.getElementById('root')
if (existingRoot) {
existingRoot.innerHTML = ''
return
}
const root = document.createElement('div')
root.id = 'root'
document.body.appendChild(root)
})
afterEach(() => {
document.getElementById('root').remove()
})
- Load all spec or test files
import('./test/App.spec.js').then(() => {
mocha.setup({ reporter: 'html' })
mocha.checkLeaks()
mocha.run()
})
- Run the test
npm run serve
- Go to
http://localhost:3000/test
- Open the browser console, you will have expected error, vite can only process es module, and @babel/parser is commonjs module
- Vite under the hood uses rollup to build Single File Component
SFC
, so lets use rollup to convert@babel/parser
to es module - Create a file
./tools/babel-parser.js
export { parse } from '@babel/parser'
- Create
rollup.config.js
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
export default {
input: './tools/babel-parser.js',
plugins: [ commonjs(), resolve() ],
output: {
file: './node_modules/@babel/parser/index.js',
format: 'es',
sourcemap: true
}
}
- Also create
vite.config.js
to create alias for@babel/parser
and to use it later
export default {
alias: {
'@babel/parser': '@babel/parser/index.js'
}
}
- Add
npm script
to run the rollup
"scripts": {
...
"optimize": "rollup -c"
},
- Run
npm run optimize
andnpm run serve
Create a Vite Plugin
- Create file
./tools/testPlugin.js
import Router from 'koa-router'
import fs from 'aria-fs'
function getTestFiles() {
const router = new Router()
return ({ app }) => {
router.get('/test-files', async (ctx, next) => {
ctx.body = await fs.globFiles(`./test/**/*.spec.js`, true)
await next()
})
app.use(router.routes())
}
}
export default function testPlugin() {
return {
configureServer: [ getTestFiles() ]
}
}
- Install dependencies
npm install koa-router aria-fs --save-dev
- Update
vite.config.js
import testPlugin from './tools/testPlugin'
export default {
alias: {
'@babel/parser': '@babel/parser/index.js'
},
plugins: [ testPlugin() ]
}
- Update
script
in./test/index.html
(async function() {
beforeEach(() => {
delete window["__VUE_DEVTOOLS_TOAST__"]
const existingRoot = document.getElementById('root')
if (existingRoot) {
existingRoot.innerHTML = ''
return
}
const root = document.createElement('div')
root.id = 'root'
document.body.appendChild(root)
})
afterEach(() => {
document.getElementById('root').remove()
})
const response = await fetch('/test-files')
const files = await response.json()
await Promise.all(files.map(file => import(file)))
mocha.setup({ reporter: 'html' })
mocha.checkLeaks()
mocha.run()
})()
- Let's add another test
Button
increment, file./src/Button.vue
<template>
<div>
<p>Times clicked: {{ count }}</p>
<button @click="increment">increment</button>
</div>
</template>
<script>
export default {
name: 'Button',
data: () => ({
count: 0,
}),
methods: {
increment() {
this.count++
},
},
}
</script>
- And test for our
Button
,./tools/Button.spec.js
import { mount } from '@vue/test-utils'
import Button from '../src/Button.vue'
describe('Button.spec.js', () => {
it('increments value on click', async () => {
const wrapper = mount(Button, { attachTo: '#root' })
const button = wrapper.find('button')
await button.trigger('click')
expect(wrapper.find('p').html()).to.contain('Times clicked: 1')
})
})
- Run
npm run serve
and go tohttp://localhost:3000/test
Top comments (0)