Official test tool
Be especially careful to use version 2.0.0 and above: document address
Purpose: Provides specific methods for mounting components in an isolated environment, as well as a series of tests
Configuring the Development Environment
Skip this step if you select unit tests when creating your project
Before configuration, vuE-CLI has the following features:
- Vue-cli is developed based on plug-ins that can:
- Install the corresponding dependencies
- Modifying Internal Configurations
- Into the command
- Install plug-ins in existing projects
- vue add xxx
Installing a plug-in
Vue add unit-jest Add-on address unit-jest
Json, and generate the tests folder and jest.config.js in the root directory:
Plug-in runtime
- Install dependencies
- vue-test-unit
- vue-jest
- A new command was injected
- vue-cli-server test:unit
- any files in
tests/unit
that end in .spec.(js|jsx|ts|tsx) - any (js(x) | ts(x))files inside
__tests__
directories
- any files in
- Vue – jest transformation
- Convert the VUE SFC file format to the corresponding TS file
- Convert ts via presets/typescript-babel to the corresponding JS file
To begin testing
Here’s what we need to know before we start testing:
- Rendering component
mount
andshallowMount
- Passing attributes
- Whether the element was successfully displayed
- Find different ways to write elements
- The get, getAl
- The find, the.findall
- FindComponent, getComponent
- Triggering event
- trigger
- Test whether the interface is updated
- Note in particular that DOM updates are a one-step process, and note the use of ASyn, await in tests
It feels like jquery
The test case
Let’s start with a simple example of determining the text content of an element and what happens when the click event is triggered.
Judge text content
{{MSG}}
and
{{count}}
after the addCount event
<template>
<div>
<p class="msg">{{ msg }}</p>
<h1 class="number">{{ count }}</h1>
<button @click="addCount">ADD</button>
</div>
</template>
<script lang='ts'>
import { ref } from 'vue'
interface DataProps {}
export default {
name: 'Test'.props: {
msg: {
type: String.default: ' '}},setup() {
const count = ref<number>(0)
const addCount = () = > {
count.value++
}
return {
count,
addCount
}
}
};
</script>
Copy the code
Next write the test case and create the test.spec.ts file under tests/ Unit
import Test from '@/components/test.vue'
import { mount, shallowMount } from '@vue/test-utils'
describe('test.vue'.() = > {
it('renders props.msg when passed'.() = >{
const msg = "new msg"
// Get the component instance
const wrapper = mount(Test, {
// Pass props in the instance
props: {
msg
}
})
// Get the HTML text of the component
console.log(wrapper.html())
// case
expect(wrapper.get('.msg').text()).toBe(msg)
})
})
Copy the code
- First introduced
Test
Component, call@vue/test-utils
In themount
Method, get totest.vue
Component instance object - We hope that
<p class="msg">{{ msg }}</p>
The text fornew msg
- Start test command
npm run test:unit -- --watch
, note that — –watch isjest
Webpack-like wacth comes with it - Take a look at the test results:
It has been passed. Let’s change the case toexpect(wrapper.get('.msg').text()).toBe('222')
, failed to pass
Indicates that the test case is OK
Next we trigger the click event
Trigger click event
describe('test.vue'.() = > {
it('renders props.msg when passed'.() = >{...// Trigger the click event
wrapper.get('.addCount').trigger('click')
expect(wrapper.get('.number').text()).toBe('1')})})Copy the code
The code above triggers the click event and then gets the expected value because it is count.value++. The count should be 1. The addCount can be triggered by running project discovery, so it is possible to have async and await.
describe('test.vue'.() = > {
it('renders props.msg when passed'.async() = > {...// Trigger the click event
await wrapper.get('.addCount').trigger('click')
expect(wrapper.get('.number').text()).toBe('1')})})Copy the code
View the console again as shown below:
Update the form
<template>
<div>
<p class="msg">{{ msg }}</p>
<h1 class="number">{{ count }}</h1>
<button class="addCount" @click="addCount">ADD</button>
<! - form - >
<input type="text" v-model="inputValue" />
<! -- Trigger add -->
<button @click="addTodo" class="addTodo">Add data</button>
<! Render list -->
<ul>
<li v-for="(item, index) in list" :key="index">
{{ item }}
</li>
</ul>
</div></template> <script lang='ts'> import { ref } from 'vue' interface DataProps {} export default { name: 'Test', props: { msg: { type: String, default: '' } }, setup(props, context) { const count = ref<number>(0) const inputValue = ref<string>('') const list = ref<string[]>([]) const addCount = ()=> { count.value++ } const addTodo = () => { if(inputValue.value) { list.value.push(inputValue.value) context.emit('send', inputValue.value) } } return { count, addCount, inputValue, addTodo } } }; </script>Copy the code
The process is as follows:
- Input box to enter text content
- Enter and click
Add data
A push button tolist
In the - Render on the page
Start writing test cases:
describe('test.vue'.() = > {
it('renders props.msg when passed'.async() = > {const msg = "new msg"
const wrapper = mount(Test, {
props: {
msg
}
})
// Mock a line of data
const value = 'inputValue'
// Write to input
await wrapper.get('input').setValue(value)
// Validate input value input usage
expect(wrapper.get('input').element.value).toBe(value)
// Trigger the click addTodo event
await wrapper.get('.addTodo').trigger('click')
// Get the length of all rendered Li's
expect(wrapper.findAll('li')).toHaveLength(1)
// Determine the text of the first li
expect(wrapper.get('li').text()).toBe(value)
})
})
Copy the code
You can see that all the test cases have passed the following figure:
Verify the event
We’re going to have some send event handling in the component, so let’s look at the code. We’re going to send an send event when we click the button, and we’re going to pass in inputValue.value
export default {
name: 'Test'./ / add the send
emits: ['send'].setup(props, context){...const addTodo = () = > {
if(inputValue.value) {
...
context.emit('send', inputValue.value) } } .... }};Copy the code
Next, start writing test cases:
it('renders props.msg when passed'.async() = > {const msg = "new msg"
const wrapper = mount(Test, {
props: {
msg
}
})
...
// Determine whether the launch event exists
expect(wrapper.emitted()).toHaveProperty('send')
const events = wrapper.emitted('send')
// Determine the parameters passed in
expect(events ? events[0]: []).toEqual([value])
// 2. Input and click 'Add Data' button push to 'list'
// 3. Render the page
})
Copy the code
The result is shown in the following figure, indicating that it has passed
An asynchronous request
<template>
<div>.<button class="loadUser" @click="loadUser">load</button>
<p v-if="user.loading" class="loading">Loading</p>
<div v-else class="userName">{{user.data && user.data.username}}</div>
<p v-if="user.error" class="error">error!</p>.</div>
</template>
<script lang="ts">
import { defineComponent, watchEffect, ref, reactive } from "vue";
import userLoader from '@/hooks/useLoader'
import axios from "axios";
import Hello from './hello.vue'
interface PostProps {
count: number,
errorCode: number,
message: string,
result: boolean,
data?: [
{
agentId: string,
agentName: string,
id: string
}
]
}
export default defineComponent({
...
setup(props,context) {
const user = reactive({
data: null as any,
loading: false.error: false
})
const loadUser = () = > {
user.loading = true
axios.get('https://jsonplaceholder.typicode.com/users/1').then(resp= > {
console.log(resp)
user.data = resp.data
}).catch(() = > {
user.error = true
}).finally(() = > {
user.loading = false})}return{ user, loadUser }; }});</script>
Copy the code
The process is also simple: first click the Button, then trigger the AXIos request, and finally render to the page
Start test case writing:
import { shallowMount, mount, VueWrapper } from '@vue/test-utils'
/ / introduce axios
import axios from 'axios'
// Flush-promises will clear all Promise handles waiting to be completed
import flushPromises from 'flush-promises'
/ / simulation axios
jest.mock('axios')
// The important step is to assert true mock types while preserving axios methods
const mockAxios = axios as jest.Mocked<typeof axios>
describe('axios'.() = > {
it('test axios'.async ()=> {
mockAxios.get.mockResolvedValueOnce({ data: {username: 'xxxx'}})/ / click
await wrapper.get('.loadUser').trigger('click')
// Determine whether the request is invoked
expect(mockAxios.get).toHaveBeenCalled()
// Check whether the button is displayed
expect(wrapper.find('.loading').exists()).toBeTruthy()
// The interface is updated
await flushPromises()
// Check whether loading Loading
exists after the request succeeds
expect(wrapper.find('.loading').exists()).toBeFalsy()
The final text is XXXX
expect(wrapper.get('.userName').text()).toBe('xxxx')})})Copy the code
All right, that’s the basic introduction.
Write in the last
Finally, recommend a full set of TS tutorials. Recent TS in ascension, collect a set of very good tutorial, free to share with XDM www.yidengxuetang.com/pub-page/in…