Skip to content

Commit 94f57f8

Browse files
agualisafontcuheywhy
authored
docs: Add example for Apollo GraphQL + composition API (#192)
* feat: Add vue-router types * docs: Add example for external UI library * docs: Add example for Apollo GraphQL + composition API * Remove not used import * Use global provider to inject apollo client * fix: resolve failing test * fix: remove coverage provider in jest.config * Fron apollo/client 3.2.3 to 3.0.0 * Fron apollo/client 3.0.0 to 3.3.6 * Delete not needed apollo in memory dependency Co-authored-by: Adrià Fontcuberta <[email protected]> Co-authored-by: atanda rasheed <[email protected]>
1 parent 49208ef commit 94f57f8

File tree

8 files changed

+173
-115
lines changed

8 files changed

+173
-115
lines changed

.babelrc

-8
This file was deleted.

babel.config.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module.exports = {
2+
sourceType: 'module',
3+
presets: [
4+
[
5+
'@babel/preset-env',
6+
{
7+
targets: {
8+
node: 'current',
9+
esmodules: true,
10+
},
11+
},
12+
],
13+
],
14+
}
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// This patch is run from post-install script and it is a temporary hack until a pending PR is merged
2+
// More details here:
3+
// https://github.com/vuejs/vue-apollo/issues/1011
4+
const fs = require('fs')
5+
const path = require('path')
6+
7+
const useQueryPath = path.resolve(
8+
__dirname,
9+
'../node_modules/@vue/apollo-composable/dist/useQuery.js',
10+
)
11+
12+
const vueApolloComposablePath = path.resolve(
13+
__dirname,
14+
'../node_modules/@vue/apollo-composable/dist/vue-apollo-composable.js',
15+
)
16+
17+
fs.writeFileSync(
18+
useQueryPath,
19+
fs.readFileSync(useQueryPath, 'utf8').replace(/^onServerPrefetch, /mu, ''),
20+
)
21+
22+
fs.writeFileSync(
23+
useQueryPath,
24+
fs
25+
.readFileSync(useQueryPath, 'utf8')
26+
.replace(/onServerPrefetch === null.*?\}\);/msu, ''),
27+
)
28+
29+
fs.writeFileSync(
30+
vueApolloComposablePath,
31+
fs
32+
.readFileSync(vueApolloComposablePath, 'utf8')
33+
.replace(/vue_demi_5.onServerPrefetch === null.*?\}\);/msu, ''),
34+
)

jest.config.js

+7-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,14 @@ module.exports = merge(config, {
1212
},
1313
snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
1414
testPathIgnorePatterns: [
15-
'<rootDir>/node_modules',
15+
'<rootDir>/node_modules/',
1616
'<rootDir>/src/__tests__/components',
1717
'<rootDir>/src/__tests__/directives',
1818
],
19+
moduleNameMapper: {
20+
'@vue/apollo-composable': [
21+
'<rootDir>/node_modules/@vue/apollo-composable/dist/index.js',
22+
],
23+
},
24+
transformIgnorePatterns: ['node_modules/(?!(@vue/apollo-composable)/)'],
1925
})

package.json

+6-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
"test": "kcd-scripts test",
1212
"test:update": "npm test -- --updateSnapshot --coverage",
1313
"validate": "kcd-scripts validate",
14-
"setup": "npm install && npm run validate -s"
14+
"setup": "npm install && npm run validate -s",
15+
"postinstall": "node compatibility-scripts/vue-apollo-patch.js"
1516
},
1617
"engines": {
1718
"node": ">10.18"
@@ -52,14 +53,14 @@
5253
"lodash.merge": "^4.6.2"
5354
},
5455
"devDependencies": {
56+
"@apollo/client": "3.3.6",
5557
"@babel/plugin-transform-runtime": "^7.12.1",
5658
"@testing-library/jest-dom": "^5.11.5",
5759
"@testing-library/user-event": "^12.4.0",
5860
"@types/estree": "0.0.45",
61+
"@vue/apollo-composable": "^4.0.0-alpha.12",
5962
"@vue/compiler-sfc": "^3.0.4",
6063
"apollo-boost": "^0.4.9",
61-
"apollo-cache-inmemory": "^1.6.6",
62-
"apollo-client": "^2.6.10",
6364
"axios": "^0.20.0",
6465
"dtslint": "^4.0.6",
6566
"element-plus": "^1.0.1-beta.7",
@@ -81,8 +82,8 @@
8182
"vuex": "^4.0.0-rc.2"
8283
},
8384
"peerDependencies": {
84-
"vue": ">= 3",
85-
"@vue/compiler-sfc": ">= 3"
85+
"@vue/compiler-sfc": ">= 3",
86+
"vue": ">= 3"
8687
},
8788
"husky": {
8889
"hooks": {
+25-32
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<template>
22
<div>
3-
<div v-if="$apollo.queries.user.loading">Loading</div>
3+
<div v-if="loading">Loading</div>
4+
45
<div v-if="user">
56
<div>Email: {{ user.email }}</div>
67
<form @submit.prevent="updateUser">
@@ -15,47 +16,39 @@
1516
</template>
1617

1718
<script>
18-
import {userQuery, updateUserMutation} from './VueApollo/queries'
19+
import {reactive, ref} from 'vue'
20+
import {useQuery, useMutation, useResult} from '@vue/apollo-composable'
21+
import {updateUserMutation, getUserQuery} from './VueApollo/queries'
1922
2023
export default {
21-
apollo: {
22-
user: {
23-
query: userQuery,
24-
variables() {
25-
return {id: this.id}
26-
},
27-
},
28-
},
2924
props: {
3025
id: {
3126
type: String,
3227
required: true,
3328
},
3429
},
35-
data() {
36-
return {
37-
user: null,
38-
email: '',
39-
}
40-
},
41-
methods: {
42-
async updateUser() {
43-
const {
44-
data: {
45-
updateUser: {email},
46-
},
47-
} = await this.$apollo.mutate({
48-
mutation: updateUserMutation,
49-
variables: {
50-
input: {
51-
email: this.email,
52-
id: this.id,
53-
},
30+
setup(props) {
31+
const email = ref('')
32+
33+
const {result, loading, error} = useQuery(getUserQuery, {id: props.id})
34+
const user = useResult(result, null, data => data.user)
35+
36+
const {mutate: updateUser} = useMutation(updateUserMutation, () => ({
37+
variables: {
38+
input: {
39+
email: email.value,
40+
id: props.id,
5441
},
55-
})
42+
},
43+
}))
5644
57-
this.user.email = email
58-
},
45+
return {
46+
email,
47+
user,
48+
loading,
49+
error,
50+
updateUser,
51+
}
5952
},
6053
}
6154
</script>
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
1-
import gql from 'graphql-tag'
1+
import {gql} from 'apollo-boost'
22

3-
export const updateUserMutation = gql`
4-
mutation updateUser($data: UpdateUserInput) {
5-
updateUser(input: $data) {
3+
export const getUserQuery = gql`
4+
query getUser($id: String!) {
5+
user(id: $id) {
66
id
77
email
88
}
99
}
1010
`
11-
12-
export const userQuery = gql`
13-
query User($id: String!) {
14-
user(id: $id) {
11+
export const updateUserMutation = gql`
12+
mutation updateUser($data: UpdateUserInput) {
13+
updateUser(input: $data) {
1514
id
1615
email
1716
}
1817
}
19-
`
18+
`

src/__tests__/vue-apollo.js

+79-60
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,94 @@
1-
test.todo('Your test suite must contain at least one test.')
2-
// import '@testing-library/jest-dom'
3-
// import fetch from 'isomorphic-unfetch'
4-
// import {render, fireEvent, screen} from '..'
5-
// import VueApollo from 'vue-apollo'
6-
// import {InMemoryCache} from 'apollo-cache-inmemory'
7-
// import ApolloClient from 'apollo-boost'
1+
import '@testing-library/jest-dom'
2+
import fetch from 'isomorphic-unfetch'
3+
import {render, fireEvent, screen} from '..'
4+
import {DefaultApolloClient} from '@vue/apollo-composable'
5+
import ApolloClient from 'apollo-boost'
6+
import {setupServer} from 'msw/node'
7+
import {graphql} from 'msw'
8+
import Component from './components/VueApollo.vue'
89

9-
// // Since vue-apollo doesn't provides a MockProvider for Vue,
10-
// // you need to use some kind of mocks for the queries.
10+
// Since vue-apollo doesn't provide a MockProvider for Vue,
11+
// you need to use some kind of mocks for the queries.
1112

12-
// // We recommend using Mock Service Worker library to declaratively mock API communication
13-
// // in your tests instead of stubbing window.fetch, or relying on third-party adapters.
13+
// We are using Mock Service Worker (aka MSW) library to declaratively mock API communication
14+
// in your tests instead of stubbing window.fetch, or relying on third-party adapters.
1415

15-
// import {setupServer} from 'msw/node'
16-
// import {graphql} from 'msw'
16+
const server = setupServer(
17+
...[
18+
graphql.query('getUser', (req, res, ctx) => {
19+
const {variables} = req
1720

18-
// import Component from './components/VueApollo.vue'
21+
if (variables.id !== '1') {
22+
return res(
23+
ctx.errors([
24+
{
25+
message: 'User not found',
26+
},
27+
]),
28+
)
29+
}
1930

20-
// const apolloClient = new ApolloClient({
21-
// uri: 'http://localhost:3020/graphql',
22-
// cache: new InMemoryCache({
23-
// addTypename: false,
24-
// }),
25-
// fetch,
26-
// })
31+
return res(
32+
ctx.data({
33+
user: {
34+
id: 1,
35+
36+
__typename: 'User',
37+
},
38+
}),
39+
)
40+
}),
2741

28-
// const server = setupServer(
29-
// ...[
30-
// graphql.mutation('updateUser', (req, res, ctx) => {
31-
// const {variables} = req
42+
graphql.mutation('updateUser', (req, res, ctx) => {
43+
const {variables} = req
3244

33-
// return res(
34-
// ctx.data({
35-
// updateUser: {id: variables.input.id, email: variables.input.email},
36-
// }),
37-
// )
38-
// }),
39-
// graphql.query('User', (req, res, ctx) => {
40-
// return res(ctx.data({user: {id: '1', email: 'alice@example.com'}}))
41-
// }),
42-
// ],
43-
// )
45+
return res(
46+
ctx.data({
47+
updateUser: {
48+
id: variables.input.id,
49+
email: variables.input.email,
50+
__typename: 'User',
51+
},
52+
}),
53+
)
54+
}),
55+
],
56+
)
4457

45-
// beforeAll(() => server.listen())
46-
// afterEach(() => server.resetHandlers())
47-
// afterAll(() => server.close())
58+
beforeAll(() => server.listen())
59+
afterEach(() => server.resetHandlers())
60+
afterAll(() => server.close())
4861

49-
// test('mocking queries and mutations', async () => {
50-
// render(Component, {props: {id: '1'}}, localVue => {
51-
// localVue.use(VueApollo)
62+
test('mocking queries and mutations', async () => {
63+
const apolloClient = new ApolloClient({
64+
uri: 'http://localhost:3000',
65+
fetch,
66+
})
5267

53-
// return {
54-
// apolloProvider: new VueApollo({defaultClient: apolloClient}),
55-
// }
56-
// })
68+
render(Component, {
69+
props: {id: '1'},
70+
global: {
71+
provide: {
72+
[DefaultApolloClient]: apolloClient,
73+
},
74+
},
75+
})
5776

58-
// //Initial rendering will be in the loading state,
59-
// expect(screen.getByText('Loading')).toBeInTheDocument()
77+
//Initial rendering will be in the loading state,
78+
expect(screen.getByText('Loading')).toBeInTheDocument()
6079

61-
// expect(
62-
// await screen.findByText('Email: [email protected]'),
63-
// ).toBeInTheDocument()
80+
expect(
81+
await screen.findByText('Email: [email protected]'),
82+
).toBeInTheDocument()
6483

65-
// await fireEvent.update(
66-
// screen.getByLabelText('Email'),
67-
68-
// )
84+
await fireEvent.update(
85+
screen.getByLabelText('Email'),
86+
87+
)
6988

70-
// await fireEvent.click(screen.getByRole('button', {name: 'Change email'}))
89+
await fireEvent.click(screen.getByRole('button', {name: 'Change email'}))
7190

72-
// expect(
73-
// await screen.findByText('Email: [email protected]'),
74-
// ).toBeInTheDocument()
75-
// })
91+
expect(
92+
await screen.findByText('Email: [email protected]'),
93+
).toBeInTheDocument()
94+
})

0 commit comments

Comments
 (0)