Skip to content

Commit d9b1b5e

Browse files
committed
feat: Update to Vue 3.0 and Vue Test Utils 2.0 (#137) (#163)
BREAKING CHANGE: - Snapshots are potentially different due to whitespaces. - Some options such as stubs are now moved to `global.stubs`. - Previous usage of vue instance as a parameter for the callback function is not replaced with global `config` options (for example, `global.directives`). - `isUnmounted` is gone. - `updateProps` is now called setProps to align with VTU. Some of the missing steps is to provide support to Vue Router, and also to update libraries of the ecosystem to their Vue 3 version. This is an exciting release! 🎉 It marks the first release aiming to support Vue 3 and Vue Test Utils 2. Please [head to the PR](#137) to get more information, and feel free to open up issues and PRs to fix missing features / ports 😄
1 parent 357bc84 commit d9b1b5e

31 files changed

+637
-648
lines changed

package.json

+29-23
Original file line numberDiff line numberDiff line change
@@ -35,44 +35,50 @@
3535
"vue.js 2",
3636
"vue.js 2 testing",
3737
"vue 2",
38-
"vue 2 testing"
38+
"vue 2 testing",
39+
"vue.js 3",
40+
"vue.js 3 testing",
41+
"vue 3",
42+
"vue 3 testing"
3943
],
4044
"author": "Daniel Cook",
4145
"license": "MIT",
4246
"dependencies": {
43-
"@babel/runtime": "^7.11.2",
44-
"@testing-library/dom": "^7.24.3",
45-
"@types/testing-library__vue": "^5.0.0",
46-
"@vue/test-utils": "^1.1.0"
47+
"@babel/runtime": "^7.12.1",
48+
"@testing-library/dom": "^7.26.3",
49+
"@types/testing-library__vue": "*",
50+
"@vue/test-utils": "^2.0.0-beta.7",
51+
"lodash.merge": "^4.6.2"
4752
},
4853
"devDependencies": {
49-
"@babel/plugin-transform-runtime": "^7.11.5",
50-
"@testing-library/jest-dom": "^5.11.4",
54+
"@babel/plugin-transform-runtime": "^7.12.1",
55+
"@testing-library/jest-dom": "^5.11.5",
56+
"@vue/compiler-sfc": "^3.0.2",
5157
"apollo-boost": "^0.4.9",
5258
"apollo-cache-inmemory": "^1.6.6",
59+
"apollo-client": "^2.6.10",
5360
"axios": "^0.20.0",
5461
"eslint-plugin-vue": "^6.2.2",
55-
"graphql": "^15.3.0",
62+
"graphql": "^15.4.0",
5663
"graphql-tag": "^2.11.0",
57-
"isomorphic-unfetch": "^3.0.0",
64+
"isomorphic-unfetch": "^3.1.0",
5865
"jest-serializer-vue": "^2.0.2",
59-
"kcd-scripts": "^6.5.1",
60-
"lodash.merge": "^4.6.2",
61-
"msw": "^0.21.2",
66+
"kcd-scripts": "^6.6.0",
67+
"msw": "^0.21.3",
6268
"portal-vue": "^2.1.7",
63-
"vee-validate": "^2.2.15",
64-
"vue": "^2.6.12",
65-
"vue-apollo": "^3.0.4",
66-
"vue-i18n": "^8.21.1",
67-
"vue-jest": "^4.0.0-rc.0",
68-
"vue-router": "^3.4.5",
69-
"vue-template-compiler": "^2.6.12",
70-
"vuetify": "^2.3.10",
71-
"vuex": "^3.5.1"
69+
"typescript": "^3.8.3",
70+
"vee-validate": "^4.0.0-beta.16",
71+
"vue": "^3.0.2",
72+
"vue-apollo": "^3.0.5",
73+
"vue-i18n": "^9.0.0-beta.6",
74+
"vue-jest": "^5.0.0-alpha.5",
75+
"vue-router": "^4.0.0-rc.1",
76+
"vuetify": "^2.3.16",
77+
"vuex": "^4.0.0-rc.1"
7278
},
7379
"peerDependencies": {
74-
"vue": "^2.6.10",
75-
"vue-template-compiler": "^2.6.10"
80+
"vue": "^3.0",
81+
"@vue/compiler-sfc": "^3.0"
7682
},
7783
"husky": {
7884
"hooks": {

src/__tests__/auto-cleanup.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import {render} from '@testing-library/vue'
22
import '@testing-library/jest-dom'
33

4-
// This just verifies that by importing VTL in an environment which supports
4+
// This verifies that by importing VTL in an environment which supports
55
// afterEach (like jest) we'll get automatic cleanup between tests.
6-
test('render the first component', () => {
7-
render({
8-
template: `<h1>Hello World</h1>`,
9-
})
6+
test('renders the component', () => {
7+
render({template: `<h1>Hello World</h1>`})
8+
109
expect(document.body.innerHTML).toMatchInlineSnapshot(`
1110
<div>
1211
<h1>Hello World</h1>

src/__tests__/axios-mock.js

+6-12
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,9 @@ import {render, fireEvent} from '@testing-library/vue'
44
import Component from './components/Fetch.vue'
55

66
test('mocks an API call when load-greeting is clicked', async () => {
7-
axiosMock.get.mockImplementationOnce(() =>
8-
Promise.resolve({
9-
data: {greeting: 'hello there'},
10-
}),
11-
)
7+
axiosMock.get.mockResolvedValueOnce({
8+
data: {greeting: 'hello there'},
9+
})
1210

1311
const {html, getByText} = render(Component, {props: {url: '/greeting'}})
1412

@@ -22,11 +20,7 @@ test('mocks an API call when load-greeting is clicked', async () => {
2220
// that Snapshot Testing should not be treated as a replacement for regular
2321
// tests.
2422
// More about the topic: https://twitter.com/searls/status/919594505938112512
25-
expect(html()).toMatchInlineSnapshot(`
26-
<div><button>
27-
Fetch
28-
</button> <span>
29-
hello there
30-
</span></div>
31-
`)
23+
expect(html()).toMatchInlineSnapshot(
24+
`<div><button> Fetch </button><span>hello there</span></div>`,
25+
)
3226
})

src/__tests__/cleanup-throw.js

+22-20
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
1-
import {render, cleanup} from '@testing-library/vue'
2-
import Vue from 'vue'
1+
test.todo('check if this test still makes sense')
32

4-
test('cleanup re-throws errors from async lifecycle hooks', async () => {
5-
const err = new Error('foo')
6-
render({
7-
async mounted() {
8-
await new Promise((resolve, reject) => {
9-
reject(err)
10-
})
11-
},
12-
template: `<h1>Hello World</h1>`,
13-
})
14-
// thrown errors are logged redundantly by vue-test-utils injected Vue.config.errorHandler
15-
// mute console
16-
const spy = jest.spyOn(console, 'error').mockImplementation(() => {})
3+
// import {render, cleanup} from '@testing-library/vue'
4+
// import {nextTick} from 'vue'
175

18-
await Vue.nextTick()
19-
expect(cleanup).toThrow(err)
6+
// test('cleanup re-throws errors from async lifecycle hooks', async () => {
7+
// const err = new Error('foo')
8+
// render({
9+
// async mounted() {
10+
// await new Promise((resolve, reject) => {
11+
// reject(err)
12+
// })
13+
// },
14+
// template: `<h1>Hello World</h1>`,
15+
// })
16+
// // thrown errors are logged redundantly by vue-test-utils injected Vue.config.errorHandler
17+
// // mute console
18+
// const spy = jest.spyOn(console, 'error').mockImplementation(() => {})
2019

21-
// unmute console
22-
spy.mockReset()
23-
})
20+
// await nextTick()
21+
// expect(cleanup).toThrow(err)
22+
23+
// // unmute console
24+
// spy.mockReset()
25+
// })

src/__tests__/components/Card.vue

-16
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,6 @@
11
<template>
22
<div class="card">
33
<slot name="header" />
4-
<slot :content="content">
5-
<!-- Fallback content if no default slot is given -->
6-
<p>Nothing used the {{ content }}</p>
7-
</slot>
84
<slot name="footer" />
95
</div>
106
</template>
11-
12-
<script>
13-
// For the sake of demoing scopedSlots, this Card component
14-
// passes a simple string down to its default slot.
15-
export default {
16-
data() {
17-
return {
18-
content: 'Scoped content!'
19-
}
20-
}
21-
}
22-
</script>

src/__tests__/components/Form.vue

+73-73
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,73 @@
1-
<template>
2-
<div>
3-
<h1>Movie Review</h1>
4-
<form @submit.prevent="submit">
5-
<label for="movie-input">Title of the movie</label>
6-
<input id="movie-input" v-model="title" name="title" />
7-
8-
<label id="review-textarea">Your review</label>
9-
<textarea
10-
v-model="review"
11-
name="review-textarea"
12-
placeholder="Write an awesome review"
13-
aria-labelledby="review-textarea"
14-
/>
15-
16-
<label>
17-
<input v-model="rating" type="radio" value="3" />
18-
Wonderful
19-
</label>
20-
<label>
21-
<input v-model="rating" type="radio" value="2" />
22-
Average
23-
</label>
24-
<label>
25-
<input v-model="rating" type="radio" value="1" />
26-
Awful
27-
</label>
28-
29-
<label id="recommend-label">Would you recommend this movie?</label>
30-
<input
31-
id="recommend"
32-
v-model="recommend"
33-
type="checkbox"
34-
name="recommend"
35-
/>
36-
37-
<button :disabled="submitDisabled" type="submit">
38-
Submit
39-
</button>
40-
</form>
41-
</div>
42-
</template>
43-
44-
<script>
45-
export default {
46-
data() {
47-
return {
48-
title: '',
49-
review: '',
50-
rating: '1',
51-
recommend: false,
52-
}
53-
},
54-
computed: {
55-
submitDisabled() {
56-
return !this.title || !this.review
57-
},
58-
},
59-
60-
methods: {
61-
submit() {
62-
if (this.submitDisabled) return
63-
64-
this.$emit('submit', {
65-
title: this.title,
66-
review: this.review,
67-
rating: this.rating,
68-
recommend: this.recommend,
69-
})
70-
},
71-
},
72-
}
73-
</script>
1+
<template>
2+
<div>
3+
<h1>Movie Review</h1>
4+
<form onsubmit="return false">
5+
<label for="movie-input">Title of the movie</label>
6+
<input id="movie-input" v-model="title" name="title" />
7+
8+
<label id="review-textarea">Your review</label>
9+
<textarea
10+
v-model="review"
11+
name="review-textarea"
12+
placeholder="Write an awesome review"
13+
aria-labelledby="review-textarea"
14+
/>
15+
16+
<label>
17+
<input v-model="rating" type="radio" value="3" />
18+
Wonderful
19+
</label>
20+
<label>
21+
<input v-model="rating" type="radio" value="2" />
22+
Average
23+
</label>
24+
<label>
25+
<input v-model="rating" type="radio" value="1" />
26+
Awful
27+
</label>
28+
29+
<label id="recommend-label">Would you recommend this movie?</label>
30+
<input
31+
id="recommend"
32+
v-model="recommend"
33+
type="checkbox"
34+
name="recommend"
35+
/>
36+
37+
<button :disabled="submitDisabled" type="submit" @click="submit">
38+
Submit
39+
</button>
40+
</form>
41+
</div>
42+
</template>
43+
44+
<script>
45+
export default {
46+
data() {
47+
return {
48+
title: '',
49+
review: '',
50+
rating: '1',
51+
recommend: false,
52+
}
53+
},
54+
computed: {
55+
submitDisabled() {
56+
return !this.title || !this.review
57+
},
58+
},
59+
60+
methods: {
61+
submit() {
62+
if (this.submitDisabled) return
63+
64+
this.$emit('submit', {
65+
title: this.title,
66+
review: this.review,
67+
rating: this.rating,
68+
recommend: this.recommend,
69+
})
70+
},
71+
},
72+
}
73+
</script>

0 commit comments

Comments
 (0)