diff --git a/.babelrc b/.babelrc deleted file mode 100644 index 6849ed4f..00000000 --- a/.babelrc +++ /dev/null @@ -1,8 +0,0 @@ -{ - "presets": [ - ["@babel/env"] - ], - "plugins": [ - "@babel/plugin-transform-runtime" - ] -} \ No newline at end of file diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 00000000..424f157b --- /dev/null +++ b/babel.config.js @@ -0,0 +1,14 @@ +module.exports = { + sourceType: 'module', + presets: [ + [ + '@babel/preset-env', + { + targets: { + node: 'current', + esmodules: true, + }, + }, + ], + ], +} diff --git a/compatibility-scripts/vue-apollo-patch.js b/compatibility-scripts/vue-apollo-patch.js new file mode 100644 index 00000000..e1702929 --- /dev/null +++ b/compatibility-scripts/vue-apollo-patch.js @@ -0,0 +1,34 @@ +// This patch is run from post-install script and it is a temporary hack until a pending PR is merged +// More details here: +// https://github.com/vuejs/vue-apollo/issues/1011 +const fs = require('fs') +const path = require('path') + +const useQueryPath = path.resolve( + __dirname, + '../node_modules/@vue/apollo-composable/dist/useQuery.js', +) + +const vueApolloComposablePath = path.resolve( + __dirname, + '../node_modules/@vue/apollo-composable/dist/vue-apollo-composable.js', +) + +fs.writeFileSync( + useQueryPath, + fs.readFileSync(useQueryPath, 'utf8').replace(/^onServerPrefetch, /mu, ''), +) + +fs.writeFileSync( + useQueryPath, + fs + .readFileSync(useQueryPath, 'utf8') + .replace(/onServerPrefetch === null.*?\}\);/msu, ''), +) + +fs.writeFileSync( + vueApolloComposablePath, + fs + .readFileSync(vueApolloComposablePath, 'utf8') + .replace(/vue_demi_5.onServerPrefetch === null.*?\}\);/msu, ''), +) diff --git a/jest.config.js b/jest.config.js index 09a45c1d..9d901b60 100644 --- a/jest.config.js +++ b/jest.config.js @@ -12,8 +12,14 @@ module.exports = merge(config, { }, snapshotSerializers: ['/node_modules/jest-serializer-vue'], testPathIgnorePatterns: [ - '/node_modules', + '/node_modules/', '/src/__tests__/components', '/src/__tests__/directives', ], + moduleNameMapper: { + '@vue/apollo-composable': [ + '/node_modules/@vue/apollo-composable/dist/index.js', + ], + }, + transformIgnorePatterns: ['node_modules/(?!(@vue/apollo-composable)/)'], }) diff --git a/package.json b/package.json index a316663e..622a3162 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "test": "kcd-scripts test", "test:update": "npm test -- --updateSnapshot --coverage", "validate": "kcd-scripts validate", - "setup": "npm install && npm run validate -s" + "setup": "npm install && npm run validate -s", + "postinstall": "node compatibility-scripts/vue-apollo-patch.js" }, "engines": { "node": ">10.18" @@ -52,14 +53,14 @@ "lodash.merge": "^4.6.2" }, "devDependencies": { + "@apollo/client": "3.3.6", "@babel/plugin-transform-runtime": "^7.12.1", "@testing-library/jest-dom": "^5.11.5", "@testing-library/user-event": "^12.4.0", "@types/estree": "0.0.45", + "@vue/apollo-composable": "^4.0.0-alpha.12", "@vue/compiler-sfc": "^3.0.4", "apollo-boost": "^0.4.9", - "apollo-cache-inmemory": "^1.6.6", - "apollo-client": "^2.6.10", "axios": "^0.20.0", "dtslint": "^4.0.6", "element-plus": "^1.0.1-beta.7", @@ -81,8 +82,8 @@ "vuex": "^4.0.0-rc.2" }, "peerDependencies": { - "vue": ">= 3", - "@vue/compiler-sfc": ">= 3" + "@vue/compiler-sfc": ">= 3", + "vue": ">= 3" }, "husky": { "hooks": { diff --git a/src/__tests__/components/VueApollo.vue b/src/__tests__/components/VueApollo.vue index a491c0e4..372978d3 100644 --- a/src/__tests__/components/VueApollo.vue +++ b/src/__tests__/components/VueApollo.vue @@ -1,6 +1,7 @@ diff --git a/src/__tests__/components/VueApollo/queries.js b/src/__tests__/components/VueApollo/queries.js index 05cd43c2..cd85fa2f 100644 --- a/src/__tests__/components/VueApollo/queries.js +++ b/src/__tests__/components/VueApollo/queries.js @@ -1,19 +1,18 @@ -import gql from 'graphql-tag' +import {gql} from 'apollo-boost' -export const updateUserMutation = gql` - mutation updateUser($data: UpdateUserInput) { - updateUser(input: $data) { +export const getUserQuery = gql` + query getUser($id: String!) { + user(id: $id) { id email } } ` - -export const userQuery = gql` - query User($id: String!) { - user(id: $id) { +export const updateUserMutation = gql` + mutation updateUser($data: UpdateUserInput) { + updateUser(input: $data) { id email } } -` +` \ No newline at end of file diff --git a/src/__tests__/vue-apollo.js b/src/__tests__/vue-apollo.js index d7728ed8..a7d04e01 100644 --- a/src/__tests__/vue-apollo.js +++ b/src/__tests__/vue-apollo.js @@ -1,75 +1,94 @@ -test.todo('Your test suite must contain at least one test.') -// import '@testing-library/jest-dom' -// import fetch from 'isomorphic-unfetch' -// import {render, fireEvent, screen} from '..' -// import VueApollo from 'vue-apollo' -// import {InMemoryCache} from 'apollo-cache-inmemory' -// import ApolloClient from 'apollo-boost' +import '@testing-library/jest-dom' +import fetch from 'isomorphic-unfetch' +import {render, fireEvent, screen} from '..' +import {DefaultApolloClient} from '@vue/apollo-composable' +import ApolloClient from 'apollo-boost' +import {setupServer} from 'msw/node' +import {graphql} from 'msw' +import Component from './components/VueApollo.vue' -// // Since vue-apollo doesn't provides a MockProvider for Vue, -// // you need to use some kind of mocks for the queries. +// Since vue-apollo doesn't provide a MockProvider for Vue, +// you need to use some kind of mocks for the queries. -// // We recommend using Mock Service Worker library to declaratively mock API communication -// // in your tests instead of stubbing window.fetch, or relying on third-party adapters. +// We are using Mock Service Worker (aka MSW) library to declaratively mock API communication +// in your tests instead of stubbing window.fetch, or relying on third-party adapters. -// import {setupServer} from 'msw/node' -// import {graphql} from 'msw' +const server = setupServer( + ...[ + graphql.query('getUser', (req, res, ctx) => { + const {variables} = req -// import Component from './components/VueApollo.vue' + if (variables.id !== '1') { + return res( + ctx.errors([ + { + message: 'User not found', + }, + ]), + ) + } -// const apolloClient = new ApolloClient({ -// uri: 'http://localhost:3020/graphql', -// cache: new InMemoryCache({ -// addTypename: false, -// }), -// fetch, -// }) + return res( + ctx.data({ + user: { + id: 1, + email: 'alice@example.com', + __typename: 'User', + }, + }), + ) + }), -// const server = setupServer( -// ...[ -// graphql.mutation('updateUser', (req, res, ctx) => { -// const {variables} = req + graphql.mutation('updateUser', (req, res, ctx) => { + const {variables} = req -// return res( -// ctx.data({ -// updateUser: {id: variables.input.id, email: variables.input.email}, -// }), -// ) -// }), -// graphql.query('User', (req, res, ctx) => { -// return res(ctx.data({user: {id: '1', email: 'alice@example.com'}})) -// }), -// ], -// ) + return res( + ctx.data({ + updateUser: { + id: variables.input.id, + email: variables.input.email, + __typename: 'User', + }, + }), + ) + }), + ], +) -// beforeAll(() => server.listen()) -// afterEach(() => server.resetHandlers()) -// afterAll(() => server.close()) +beforeAll(() => server.listen()) +afterEach(() => server.resetHandlers()) +afterAll(() => server.close()) -// test('mocking queries and mutations', async () => { -// render(Component, {props: {id: '1'}}, localVue => { -// localVue.use(VueApollo) +test('mocking queries and mutations', async () => { + const apolloClient = new ApolloClient({ + uri: 'http://localhost:3000', + fetch, + }) -// return { -// apolloProvider: new VueApollo({defaultClient: apolloClient}), -// } -// }) + render(Component, { + props: {id: '1'}, + global: { + provide: { + [DefaultApolloClient]: apolloClient, + }, + }, + }) -// //Initial rendering will be in the loading state, -// expect(screen.getByText('Loading')).toBeInTheDocument() + //Initial rendering will be in the loading state, + expect(screen.getByText('Loading')).toBeInTheDocument() -// expect( -// await screen.findByText('Email: alice@example.com'), -// ).toBeInTheDocument() + expect( + await screen.findByText('Email: alice@example.com'), + ).toBeInTheDocument() -// await fireEvent.update( -// screen.getByLabelText('Email'), -// 'alice+new@example.com', -// ) + await fireEvent.update( + screen.getByLabelText('Email'), + 'alice+new@example.com', + ) -// await fireEvent.click(screen.getByRole('button', {name: 'Change email'})) + await fireEvent.click(screen.getByRole('button', {name: 'Change email'})) -// expect( -// await screen.findByText('Email: alice+new@example.com'), -// ).toBeInTheDocument() -// }) + expect( + await screen.findByText('Email: alice+new@example.com'), + ).toBeInTheDocument() +})