Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit f7bb066

Browse files
authoredJun 21, 2019
Merge pull request #43 from afontcu/master
Improve onboarding by adding explanations
2 parents 07bdd1b + 3d09b68 commit f7bb066

37 files changed

+163
-224
lines changed
 

‎package-lock.json

Lines changed: 19 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
"author": "Daniel Cook",
3232
"license": "MIT",
3333
"dependencies": {
34-
"@testing-library/dom": "^5.0.1",
34+
"@testing-library/dom": "^5.2.0",
3535
"@vue/test-utils": "^1.0.0-beta.29",
3636
"vue": "^2.6.10",
3737
"vue-template-compiler": "^2.6.10"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`makes an API call and displays the greeting when load-greeting is clicked 1`] = `
4+
<div><button>
5+
Fetch
6+
</button> <span>
7+
hello there
8+
</span></div>
9+
`;

‎tests/__tests__/__snapshots__/fetch.js.snap

Lines changed: 0 additions & 9 deletions
This file was deleted.

‎tests/__tests__/axios-mock.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import axiosMock from 'axios'
2+
import { render, fireEvent } from '@testing-library/vue'
3+
import Component from './components/Fetch.vue'
4+
import 'jest-dom/extend-expect'
5+
6+
test('makes an API call and displays the greeting when load-greeting is clicked', async () => {
7+
axiosMock.get.mockImplementationOnce(() =>
8+
Promise.resolve({
9+
data: { greeting: 'hello there' }
10+
})
11+
)
12+
13+
const { html, getByText } = render(Component, { props: { url: '/greeting' } })
14+
15+
// Act
16+
await fireEvent.click(getByText('Fetch'))
17+
18+
expect(axiosMock.get).toHaveBeenCalledTimes(1)
19+
expect(axiosMock.get).toHaveBeenCalledWith('/greeting')
20+
getByText('hello there')
21+
22+
// You can render component snapshots by using html(). However, bear in mind
23+
// that Snapshot Testing should not be treated as a replacement for regular
24+
// tests.
25+
// More about the topic: https://twitter.com/searls/status/919594505938112512
26+
expect(html()).toMatchSnapshot()
27+
})

‎tests/__tests__/components/Button.vue

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,13 @@
11
<template>
2-
<button :class="typeClass" @click="handleClick">{{ text }}</button>
2+
<button @click="handleClick">{{ text }}</button>
33
</template>
44

55
<script>
66
export default {
77
props: {
88
text: {
99
type: String,
10-
default: ''
11-
},
12-
type: {
13-
validator: value => ['primary', 'secondary'].includes(value),
14-
default: 'primary'
15-
}
16-
},
17-
computed: {
18-
typeClass: function() {
19-
if (this.type) {
20-
return `button button--${this.type}`
21-
}
22-
return 'button'
10+
required: true
2311
}
2412
},
2513
methods: {

‎tests/__tests__/components/EndToEnd.vue renamed to ‎tests/__tests__/components/Disappearance.vue

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
<template>
2-
<div>
3-
<div v-if="loading">Loading...</div>
4-
<div v-else data-testid="message">
5-
Loaded this message: {{ data.returnedMessage }}
6-
</div>
7-
</div>
2+
<p v-if="loading">Loading...</p>
3+
<p v-else data-testid="message">
4+
Loaded this message: {{ data.returnedMessage }}
5+
</p>
86
</template>
97

108
<script>
@@ -13,6 +11,7 @@ const fetchAMessage = () =>
1311
// we are using random timeout here to fireEvent a real-time example
1412
// of an async operation calling a callback at a non-deterministic time
1513
const randomTimeout = Math.floor(Math.random() * 100)
14+
1615
setTimeout(() => {
1716
resolve({ returnedMessage: 'Hello World' })
1817
}, randomTimeout)

‎tests/__tests__/components/Fetch.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
<template>
22
<div>
3-
<button data-testid="load-greeting" @click="fetch">
3+
<button @click="fetch">
44
Fetch
55
</button>
6-
<span v-if="data" data-testid="greeting-text">
6+
<span v-if="data">
77
{{ data.greeting }}
88
</span>
99
</div>

‎tests/__tests__/components/Form.vue

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
v-model="recommend"
4141
type="checkbox"
4242
name="recommend"
43-
data-testid="recommend-checkbox"
4443
/>
4544

4645
<button :disabled="submitDisabled" type="submit">

‎tests/__tests__/components/StopWatch.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<template>
22
<div>
33
<span data-testid="elapsed">{{ lapse }}ms</span>
4-
<button data-testid="start-stop-button" @click="handleRunClick">
4+
<button @click="handleRunClick">
55
{{ running ? 'Stop' : 'Start' }}
66
</button>
77
</div>

‎tests/__tests__/components/Validate.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
aria-labelledby="username-label"
1111
/>
1212

13-
<span v-show="errors.has('username')" data-testid="username-errors">{{
13+
<span v-if="errors.has('username')" data-testid="username-errors">{{
1414
errors.first('username')
1515
}}</span>
1616

‎tests/__tests__/components/queries/AltText.vue

Lines changed: 0 additions & 3 deletions
This file was deleted.

‎tests/__tests__/components/queries/Attribute.vue

Lines changed: 0 additions & 5 deletions
This file was deleted.

‎tests/__tests__/components/queries/Empty.vue

Lines changed: 0 additions & 3 deletions
This file was deleted.

‎tests/__tests__/components/queries/GetByAltText.vue

Lines changed: 0 additions & 6 deletions
This file was deleted.

‎tests/__tests__/components/queries/JestHelpers.vue

Lines changed: 0 additions & 3 deletions
This file was deleted.

‎tests/__tests__/components/queries/LabelText.vue

Lines changed: 0 additions & 13 deletions
This file was deleted.

‎tests/__tests__/components/queries/LabelWithNoFormControl.vue

Lines changed: 0 additions & 3 deletions
This file was deleted.

‎tests/__tests__/components/queries/Placeholder.vue

Lines changed: 0 additions & 3 deletions
This file was deleted.

‎tests/__tests__/components/queries/TotallyEmptyLabel.vue

Lines changed: 0 additions & 3 deletions
This file was deleted.

‎tests/__tests__/components/queries/index.js

Lines changed: 0 additions & 21 deletions
This file was deleted.

‎tests/__tests__/disappearance.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { render, waitForElementToBeRemoved } from '@testing-library/vue'
2+
import Disappearance from './components/Disappearance'
3+
import 'jest-dom/extend-expect'
4+
5+
test('it waits for the data to be loaded', async () => {
6+
const { getByText, queryByText, queryByTestId } = render(Disappearance)
7+
8+
// Assert initial state
9+
getByText('Loading...')
10+
expect(queryByText(/Loaded this message/)).not.toBeInTheDocument()
11+
12+
// Line reads as follows "Wait until element with test 'Loading...' is gone."
13+
await waitForElementToBeRemoved(() => queryByText('Loading...'))
14+
// It is equivalent to:
15+
//
16+
// await wait(() => {
17+
// expect(queryByText('Loading...')).not.toBeInTheDocument()
18+
// })
19+
//
20+
// `wait()` waits until the callback function passes or times out.
21+
22+
// After 'Loading...' element is gone, we can assert that fetched data is
23+
// rendered.
24+
expect(queryByTestId('message')).toHaveTextContent(/Hello World/)
25+
26+
// Read more about async utilities:
27+
// https://testing-library.com/docs/dom-testing-library/api-async
28+
})

‎tests/__tests__/end-to-end.js

Lines changed: 0 additions & 11 deletions
This file was deleted.

‎tests/__tests__/fetch.js

Lines changed: 0 additions & 22 deletions
This file was deleted.

‎tests/__tests__/form.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ test('Review form submits', async () => {
1414
const {
1515
getByLabelText,
1616
getByText,
17-
getByTestId,
17+
getByRole,
1818
getByDisplayValue,
1919
getByPlaceholderText,
2020
emitted
@@ -44,7 +44,8 @@ test('Review form submits', async () => {
4444
const genreSelect = getByDisplayValue('Comedy')
4545
await fireEvent.update(genreSelect, fakeReview.genre)
4646

47-
const recommendInput = getByTestId('recommend-checkbox')
47+
// Get the Input element by its implicit ARIA role.
48+
const recommendInput = getByRole('checkbox')
4849
await fireEvent.update(recommendInput, fakeReview.recommend)
4950

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

‎tests/__tests__/number-display.js

Lines changed: 0 additions & 15 deletions
This file was deleted.

‎tests/__tests__/router/programmatic-routing/components/About.vue

Lines changed: 0 additions & 3 deletions
This file was deleted.

‎tests/__tests__/router/programmatic-routing/components/App.vue

Lines changed: 0 additions & 12 deletions
This file was deleted.

‎tests/__tests__/router/programmatic-routing/components/Home.vue

Lines changed: 0 additions & 16 deletions
This file was deleted.

‎tests/__tests__/router/programmatic-routing/components/LocationDisplay.vue

Lines changed: 0 additions & 3 deletions
This file was deleted.

‎tests/__tests__/router/programmatic-routing/components/NoMatch.vue

Lines changed: 0 additions & 3 deletions
This file was deleted.

‎tests/__tests__/router/programmatic-routing/index.js

Lines changed: 0 additions & 22 deletions
This file was deleted.

‎tests/__tests__/simple-button.js

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
11
import { render, cleanup, fireEvent } from '@testing-library/vue'
2-
import SimpleButton from './components/Button'
2+
import Button from './components/Button'
3+
import 'jest-dom/extend-expect'
34

45
afterEach(cleanup)
56

67
test('renders button with text', () => {
7-
const buttonText = "Click me; I'm sick"
8-
const { getByText } = render(SimpleButton, {
9-
props: { text: buttonText }
8+
const text = "Click me; I'm sick"
9+
10+
// Set the prop value by using the second argument of `render()`
11+
const { getByRole } = render(Button, {
12+
props: { text }
1013
})
1114

12-
getByText(buttonText)
15+
expect(getByRole('button')).toHaveTextContent(text)
1316
})
1417

15-
test('click event is emitted when button is clicked', () => {
18+
test('click event is emitted when button is clicked', async () => {
1619
const text = 'Click me'
17-
const { getByText, emitted } = render(SimpleButton, {
20+
21+
const { getByRole, emitted } = render(Button, {
1822
props: { text }
1923
})
20-
fireEvent.click(getByText(text))
24+
25+
// Send a click event to the element with a 'button' role
26+
await fireEvent.click(getByRole('button'))
27+
2128
expect(emitted().click).toHaveLength(1)
2229
})

‎tests/__tests__/stopwatch.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ test('unmounts a component', async () => {
1010
const { unmount, isUnmounted, getByText } = render(StopWatch)
1111
await fireEvent.click(getByText('Start'))
1212

13+
// Destroys a Vue component instance.
1314
unmount()
15+
1416
expect(isUnmounted()).toBe(true)
1517

1618
await wait()
19+
1720
expect(console.error).not.toHaveBeenCalled()
1821
})
1922

@@ -23,11 +26,21 @@ test('updates component state', async () => {
2326
const startButton = getByText('Start')
2427
const elapsedTime = getByTestId('elapsed')
2528

29+
// Assert initial state.
2630
expect(elapsedTime).toHaveTextContent('0ms')
31+
getByText('Start')
2732

2833
await fireEvent.click(startButton)
34+
35+
getByText('Stop')
36+
37+
// Wait for one tick of the event loop.
2938
await wait()
39+
40+
// Stop the timer.
3041
await fireEvent.click(startButton)
3142

43+
// We can't assert a specific amount of time. Instead, we assert that the
44+
// content has changed.
3245
expect(elapsedTime).not.toHaveTextContent('0ms')
3346
})

‎tests/__tests__/update-props.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import NumberDisplay from './components/NumberDisplay.vue'
2+
import { render } from '@testing-library/vue'
3+
import 'jest-dom/extend-expect'
4+
5+
test('calling render with the same component but different props does not remount', async () => {
6+
const { getByTestId, updateProps } = render(NumberDisplay, {
7+
props: { number: 1 }
8+
})
9+
10+
expect(getByTestId('number-display')).toHaveTextContent('1')
11+
12+
await updateProps({ number: 2 })
13+
14+
expect(getByTestId('number-display')).toHaveTextContent('2')
15+
16+
// Assert that, even after updating props, the component hasn't remounted,
17+
// meaning we are testing the same component instance we rendered initially.
18+
expect(getByTestId('instance-id')).toHaveTextContent('1')
19+
})

‎tests/__tests__/validate-plugin.js

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,24 @@ import { render, fireEvent } from '@testing-library/vue'
55
import Validate from './components/Validate'
66

77
test('can validate using plugin', async () => {
8-
const { getByPlaceholderText, queryByTestId } = render(Validate, {}, vue =>
9-
vue.use(VeeValidate, { events: 'blur' })
8+
// The third argument of `render` is a callback function that receives the
9+
// Vue instance as a parameter. This way, we can register plugins such as
10+
// VeeValidate.
11+
const { getByPlaceholderText, queryByTestId, getByTestId } = render(
12+
Validate,
13+
{},
14+
vue => vue.use(VeeValidate, { events: 'blur' })
1015
)
1116

17+
// Assert error messages are not in the DOM when rendering the component.
18+
expect(queryByTestId('username-errors')).toBeNull()
19+
1220
const usernameInput = getByPlaceholderText('Username...')
1321
await fireEvent.touch(usernameInput)
1422

15-
expect(queryByTestId('username-errors')).toHaveTextContent(
23+
// After "touching" the input (focusing and blurring), validation error
24+
// should appear.
25+
expect(getByTestId('username-errors')).toHaveTextContent(
1626
'The username field is required.'
1727
)
1828
})

‎tests/__tests__/vue-router.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,20 @@ const routes = [
1515
afterEach(cleanup)
1616

1717
test('full app rendering/navigating', async () => {
18+
// Notice how we pass a `routes` object to our render function.
1819
const { queryByTestId } = render(App, { routes })
1920

20-
// normally I'd use a data-testid, but just wanted to show this is also possible
2121
expect(queryByTestId('location-display')).toHaveTextContent('/')
22+
2223
await fireEvent.click(queryByTestId('about-link'))
2324

2425
expect(queryByTestId('location-display')).toHaveTextContent('/about')
2526
})
2627

2728
test('setting initial route', () => {
29+
// The callback function receives three parameters: the Vue instance where
30+
// the component is mounted, the store instance (if any) and the router
31+
// object.
2832
const { queryByTestId } = render(App, { routes }, (vue, store, router) => {
2933
router.push('/about')
3034
})

0 commit comments

Comments
 (0)
Please sign in to comment.