Skip to content

Commit 295c870

Browse files
committed
Update readme with examples
1 parent 7d3ad72 commit 295c870

11 files changed

+89
-50
lines changed

README.md

+46-8
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<div align="center">
22
<h1>vue-testing-library</h1>
33

4-
<p>Port of the ultra-low surface area testing library <a href="https://github.com/kentcdodds/react-testing-library/">react-testing-library</a> to <a href="https://github.com/vuejs/vue">Vue.js</a> using <a href="https://github.com/vuejs/vue-test-utils">@vue/test-utils</a></p>
4+
<p>Lightweight adapter allowing <a href="https://github.com/kentcdodds/dom-testing-library/">dom-testing-library</a> to be used to test <a href="https://github.com/vuejs/vue">Vue.js</a> components built on top of <a href="https://github.com/vuejs/vue-test-utils">@vue/test-utils</a></p>
55

66
</div>
77

@@ -16,14 +16,15 @@
1616

1717
## This library
1818

19-
The `vue-testing-library` is a very light-weight solution for testing Vue
20-
components. It provides light utility functions on top of `@vue/test-utils`, in a way that encourages better testing practices.
21-
It's primary guiding principle is:
22-
23-
The more your tests resemble the way your software is used, the more confidence they can give you.
24-
25-
The intention is to closely track react-test-utils and its capabilities. To this end it uses the marvellous `dom-testing-utils` library for querying the DOM.
19+
The `vue-testing-library` is a an adapter that enables Vue testing using the framework-agnostic DOM testing library `dom-testing-library`
2620

21+
* [Installation](#installation)
22+
* [Usage](#usage)
23+
* [`render`](#render)
24+
* [`Simulate`](#simulate)
25+
* [`wait`](#wait)
26+
* [Examples](#examples)
27+
* [LICENSE](#license)
2728

2829
## Installation
2930

@@ -108,6 +109,43 @@ test('should render HelloWorld', () => {
108109

109110
```
110111

112+
### render
113+
114+
The `render` function takes up to 3 parameters and returns an object with some helper methods
115+
116+
1. Component - the Vue component to be tested.
117+
2. RenderOptions - an object containing additional information to be passed to @vue/test-utils mount. This can be:
118+
* props - The component props to be passed to TestComponent
119+
* store - The object definition of a Vuex store, if present `render` will configure a Vuex store and pass to mount.
120+
* routes - A set of routes, if present render will configure VueRouter and pass to mount.
121+
3. configurationCb - A callback to be called passing the Vue instance when created. This allows 3rd party plugins to be installed prior to mount.
122+
123+
### Simulate
124+
125+
Lightweight wrapper around DOM element methods
126+
127+
### wait
128+
129+
When in need to wait for non-deterministic periods of time you can use `wait`,
130+
to wait for your expectations to pass. The `wait` function is a small wrapper
131+
around the
132+
[`wait-for-expect`](https://github.com/TheBrainFamily/wait-for-expect) module.
133+
134+
Waiting can be very important in Vue components, @vue/test-utils has succeeded in making the majority of updates happen
135+
synchronously however there are occasions when wait will allow the DOM to update. For example, see [`here`](https://github.com/dfcook/vue-testing-library/tree/master/tests/__tests__/validate-plugin.js)
136+
137+
## Examples
138+
139+
You'll find examples of testing with different libraries in
140+
[the test directory](https://github.com/dfcook/vue-testing-library/tree/master/tests/__tests__).
141+
Some included are:
142+
143+
* [`vuex`](https://github.com/dfcook/vue-testing-library/tree/master/tests/__tests__/vuex.js)
144+
* [`vue-router`](https://github.com/dfcook/vue-testing-library/tree/master/__tests__/vue-router.js)
145+
* [`vee-validate`](https://github.com/dfcook/vue-testing-library/tree/master/tests/__tests__/validate-plugin.js)
146+
147+
Feel free to contribute more!
148+
111149
## LICENSE
112150

113151
MIT

package-lock.json

+5-18
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Simulate.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,18 @@ const simulate = (event, elem, ...params) => {
1212

1313
const click = simulate.bind(null, 'click')
1414
const submit = simulate.bind(null, 'submit')
15-
const change = simulate.bind(null, 'change')
1615
const focus = simulate.bind(null, 'focus')
1716
const blur = simulate.bind(null, 'blur')
1817

18+
const touch = (elem) => {
19+
focus(elem)
20+
blur(elem)
21+
}
22+
1923
export default {
24+
blur,
2025
click,
21-
submit,
22-
change,
2326
focus,
24-
blur
27+
submit,
28+
touch
2529
}

tests/__tests__/components/Login.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export default {
3434
password: ''
3535
}
3636
},
37-
methods: {
37+
methods: {
3838
submit () {
3939
this.onSubmit({
4040
username: this.username,

tests/__tests__/components/StopWatch.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<template>
22
<div>
3-
<span>{{ lapse }}ms</span>
3+
<span data-testid="elapsed">{{ lapse }}ms</span>
44
<button @click="handleRunClick" data-testid="start-stop-button">
55
{{ running ? 'Stop' : 'Start' }}
66
</button>

tests/__tests__/components/Validate.vue

+1-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<form @submit.prevent="submit">
2+
<form>
33
<label for="username-input">Username</label>
44
<input
55
id="username-input"
@@ -31,10 +31,6 @@ export default {
3131
username: '',
3232
password: ''
3333
}
34-
},
35-
methods: {
36-
submit () {
37-
}
3834
}
3935
}
4036
</script>

tests/__tests__/end-to-end.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { render, wait } from '../../src'
22
import EndToEnd from './components/EndToEnd'
33

44
test('it waits for the data to be loaded', async () => {
5-
const { html, queryByText, queryByTestId } = render(EndToEnd)
5+
const { queryByText, queryByTestId } = render(EndToEnd)
66

77
expect(queryByText('Loading...')).toBeTruthy()
88

tests/__tests__/form.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import Vue from 'vue'
2-
import { render, Simulate, wait } from '../../src'
2+
import { html, render, Simulate, wait } from '../../src'
33
import Login from './components/Login'
44

55
test('login form submits', async () => {
66
const fakeUser = {username: 'jackiechan', password: 'hiya! 🥋'}
77
const handleSubmit = jest.fn()
8-
const {updateState, getByLabelText, getByText} = render(
8+
const { updateState, getByLabelText, getByText } = render(
99
Login, { props: { onSubmit: handleSubmit } }
1010
)
1111

@@ -15,7 +15,6 @@ test('login form submits', async () => {
1515

1616
// Act - this is waiting on an issue in @vue/test-utils to allow v-model to be updated by
1717
// changes to DOM elements
18-
1918
updateState(fakeUser)
2019

2120
// NOTE: in jsdom, it's not possible to trigger a form submission

tests/__tests__/stopwatch.js

+22-6
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,34 @@
11
import Vue from 'vue'
22
import StopWatch from './components/StopWatch.vue'
3-
import { render, select, Simulate } from '../../src'
4-
5-
const wait = time => new Promise(resolve => setTimeout(resolve, time))
3+
import { render, select, wait, Simulate } from '../../src'
64

75
test('unmounts a component', async () => {
86
jest.spyOn(console, 'error').mockImplementation(() => {})
97

10-
const { unmount, isUnmounted, getByText, wrapper } = render(StopWatch)
8+
const { unmount, isUnmounted, getByText } = render(StopWatch)
119
Simulate.click(getByText('start'))
1210

13-
unmount()
11+
await wait()
12+
13+
unmount()
1414
expect(isUnmounted()).toBe(true)
1515

16-
await wait()
16+
await wait()
1717
expect(console.error).not.toHaveBeenCalled()
1818
})
19+
20+
test('updates component state', async () => {
21+
const { getByTestId, getByText } = render(StopWatch)
22+
23+
const startButton = getByText('start')
24+
const elapsedTime = getByTestId('elapsed')
25+
26+
expect(elapsedTime.textContent).toBe('0ms')
27+
28+
Simulate.click(startButton)
29+
await wait()
30+
Simulate.click(startButton)
31+
32+
expect(elapsedTime.textContent).not.toBe('0ms')
33+
})
34+

tests/__tests__/validate-plugin.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ test('can validate using plugin', async () => {
99
vue => vue.use(VeeValidate, { events: 'blur' }))
1010

1111
const usernameInput = getByPlaceholderText('Username...')
12-
Simulate.focus(usernameInput)
13-
Simulate.blur(usernameInput)
12+
Simulate.touch(usernameInput)
1413

1514
await wait()
1615

tests/__tests__/vue-router.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const routes = [
1111
]
1212

1313
test('full app rendering/navigating', () => {
14-
const { wrapper, queryByTestId } = render(App, { routes })
14+
const { queryByTestId } = render(App, { routes })
1515
// normally I'd use a data-testid, but just wanted to show this is also possible
1616
expect(queryByTestId('location-display').textContent).toBe('/')
1717
Simulate.click(queryByTestId('about-link'))

0 commit comments

Comments
 (0)