mock-apollo-client
Advanced tools
Comparing version 0.4.0 to 1.0.0
"use strict"; | ||
function __export(m) { | ||
for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p]; | ||
} | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __exportStar = (this && this.__exportStar) || function(m, exports) { | ||
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__export(require("./mockClient")); | ||
__exportStar(require("./mockClient"), exports); |
@@ -1,4 +0,3 @@ | ||
import ApolloClient, { ApolloClientOptions } from 'apollo-client'; | ||
import { NormalizedCacheObject } from 'apollo-cache-inmemory'; | ||
import { DocumentNode } from 'apollo-link'; | ||
import { ApolloClientOptions, ApolloClient, DocumentNode } from '@apollo/client/core'; | ||
import { NormalizedCacheObject } from '@apollo/client/cache'; | ||
export declare type RequestHandler<TData = any, TVariables = any> = (variables: TVariables) => Promise<RequestHandlerResponse<TData>>; | ||
@@ -5,0 +4,0 @@ export declare type RequestHandlerResponse<T> = { |
@@ -13,9 +13,6 @@ "use strict"; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var apollo_client_1 = __importDefault(require("apollo-client")); | ||
var apollo_cache_inmemory_1 = require("apollo-cache-inmemory"); | ||
var apollo_utilities_1 = require("apollo-utilities"); | ||
exports.createMockClient = void 0; | ||
var core_1 = require("@apollo/client/core"); | ||
var cache_1 = require("@apollo/client/cache"); | ||
var mockLink_1 = require("./mockLink"); | ||
@@ -28,18 +25,9 @@ exports.createMockClient = function (options) { | ||
var mockLink = new mockLink_1.MockLink(); | ||
var client = new apollo_client_1.default(__assign(__assign({ cache: new apollo_cache_inmemory_1.InMemoryCache({ | ||
var client = new core_1.ApolloClient(__assign(__assign({ cache: new cache_1.InMemoryCache({ | ||
addTypename: false, | ||
}) }, options), { link: mockLink })); | ||
var mockMethods = { | ||
setRequestHandler: function (query, handler) { | ||
if (apollo_utilities_1.removeClientSetsFromDocument(query) === null && areResolversDefined(client)) { | ||
console.warn('Warning: mock-apollo-client - The query is entirely client side (using @client directives) and resolvers have been configured. ' + | ||
'The request handler will not be called.'); | ||
} | ||
mockLink.setRequestHandler(query, handler); | ||
}, | ||
setRequestHandler: mockLink.setRequestHandler.bind(mockLink), | ||
}; | ||
return Object.assign(client, mockMethods); | ||
}; | ||
var areResolversDefined = function (client) { | ||
return client.getResolvers() === client.getResolvers(); | ||
}; |
@@ -1,2 +0,3 @@ | ||
import { ApolloLink, DocumentNode, Observable, Operation, FetchResult } from 'apollo-link'; | ||
/// <reference types="zen-observable" /> | ||
import { ApolloLink, DocumentNode, Observable, Operation, FetchResult } from '@apollo/client/core'; | ||
import { RequestHandler } from './mockClient'; | ||
@@ -6,5 +7,5 @@ export declare class MockLink extends ApolloLink { | ||
setRequestHandler(requestQuery: DocumentNode, handler: RequestHandler): void; | ||
request(operation: Operation): Observable<FetchResult<{ | ||
request: (operation: Operation) => Observable<FetchResult<{ | ||
[key: string]: any; | ||
}, Record<string, any>, Record<string, any>>>; | ||
} |
@@ -16,5 +16,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var apollo_link_1 = require("apollo-link"); | ||
var apollo_utilities_1 = require("apollo-utilities"); | ||
var printer_1 = require("graphql/language/printer"); | ||
exports.MockLink = void 0; | ||
var core_1 = require("@apollo/client/core"); | ||
var graphql_1 = require("graphql"); | ||
var utilities_1 = require("@apollo/client/utilities"); | ||
var MockLink = (function (_super) { | ||
@@ -25,66 +26,54 @@ __extends(MockLink, _super); | ||
_this.requestHandlers = {}; | ||
_this.request = function (operation) { | ||
return new core_1.Observable(function (observer) { | ||
var key = requestToKey(operation.query); | ||
var handler = _this.requestHandlers[key]; | ||
if (!handler) { | ||
throw new Error("Request handler not defined for query: " + graphql_1.print(operation.query)); | ||
} | ||
var resultPromise = undefined; | ||
try { | ||
resultPromise = handler(operation.variables); | ||
} | ||
catch (error) { | ||
throw new Error("Unexpected error whilst calling request handler: " + error.message); | ||
} | ||
if (!isPromise(resultPromise)) { | ||
throw new Error("Request handler must return a promise. Received '" + typeof resultPromise + "'."); | ||
} | ||
resultPromise | ||
.then(function (result) { | ||
observer.next(result); | ||
observer.complete(); | ||
}) | ||
.catch(function (error) { | ||
observer.error(error); | ||
}); | ||
return function () { }; | ||
}); | ||
}; | ||
return _this; | ||
} | ||
MockLink.prototype.setRequestHandler = function (requestQuery, handler) { | ||
var identifiers = getIdentifiers(requestQuery); | ||
for (var _i = 0, identifiers_1 = identifiers; _i < identifiers_1.length; _i++) { | ||
var identifier = identifiers_1[_i]; | ||
var key = requestToKey(identifier); | ||
if (this.requestHandlers[key]) { | ||
throw new Error("Request handler already defined for query: " + format(identifier)); | ||
} | ||
this.requestHandlers[key] = handler; | ||
var queryWithoutClientDirectives = utilities_1.removeClientSetsFromDocument(requestQuery); | ||
if (queryWithoutClientDirectives === null) { | ||
console.warn('Warning: mock-apollo-client - The query is entirely client side (using @client directives) so the request handler will not be registered.'); | ||
return; | ||
} | ||
}; | ||
MockLink.prototype.request = function (operation) { | ||
var key = requestToKey(operation.query); | ||
var handler = this.requestHandlers[key]; | ||
if (!handler) { | ||
throw new Error("Request handler not defined for query: " + format(operation.query)); | ||
var key = requestToKey(queryWithoutClientDirectives); | ||
if (this.requestHandlers[key]) { | ||
throw new Error("Request handler already defined for query: " + graphql_1.print(requestQuery)); | ||
} | ||
var resultPromise = undefined; | ||
try { | ||
resultPromise = handler(operation.variables); | ||
} | ||
catch (error) { | ||
throw new Error("Unexpected error whilst calling request handler: " + error.message); | ||
} | ||
if (!isPromise(resultPromise)) { | ||
throw new Error("Request handler must return a promise. Received '" + typeof resultPromise + "'."); | ||
} | ||
return new apollo_link_1.Observable(function (observer) { | ||
resultPromise | ||
.then(function (result) { | ||
observer.next(result); | ||
observer.complete(); | ||
}) | ||
.catch(function (error) { | ||
observer.error(error); | ||
}); | ||
return function () { }; | ||
}); | ||
this.requestHandlers[key] = handler; | ||
}; | ||
return MockLink; | ||
}(apollo_link_1.ApolloLink)); | ||
}(core_1.ApolloLink)); | ||
exports.MockLink = MockLink; | ||
var getIdentifiers = function (requestQuery) { | ||
var withoutClientSets = apollo_utilities_1.hasDirectives(['client'], requestQuery) | ||
? apollo_utilities_1.removeClientSetsFromDocument(requestQuery) | ||
: null; | ||
return withoutClientSets === null | ||
? [requestQuery] | ||
: [requestQuery, withoutClientSets]; | ||
}; | ||
var requestToKey = function (query) { | ||
var queryString = printer_1.print(query); | ||
var queryString = query && graphql_1.print(query); | ||
var requestKey = { query: queryString }; | ||
return JSON.stringify(requestKey); | ||
}; | ||
var format = function (query) { | ||
return query | ||
? printer_1.print(query) | ||
: 'null'; | ||
}; | ||
var isPromise = function (maybePromise) { | ||
return maybePromise && typeof maybePromise.then === 'function'; | ||
}; |
{ | ||
"name": "mock-apollo-client", | ||
"version": "0.4.0", | ||
"version": "1.0.0", | ||
"description": "Library to help unit testing when using apollo-client", | ||
@@ -32,14 +32,12 @@ "main": "dist/index.js", | ||
"devDependencies": { | ||
"@types/graphql": "^14.2.3", | ||
"@types/jest": "^25.1.4", | ||
"apollo-cache-inmemory": "^1.6.2", | ||
"apollo-client": "^2.6.3", | ||
"graphql": "^14.4.2", | ||
"graphql-tag": "^2.10.1", | ||
"jest": "^25.1.0", | ||
"ts-jest": "^25.2.1", | ||
"typescript": "^3.8.3" | ||
"@apollo/client": "^3.1.3", | ||
"@types/jest": "^26.0.10", | ||
"@types/node": "^14.6.0", | ||
"graphql": "^15.3.0", | ||
"jest": "^26.4.1", | ||
"ts-jest": "^26.2.0", | ||
"typescript": "^3.9.7" | ||
}, | ||
"peerDependencies": { | ||
"apollo-client": "~2.5.0 || ~2.6.0" | ||
"@apollo/client": "^3.0.0" | ||
}, | ||
@@ -46,0 +44,0 @@ "files": [ |
@@ -5,9 +5,11 @@ # Mock Apollo Client | ||
> **Note**: This library is currently only compatible with Apollo Client 2. | ||
> | ||
> Track version 3 support in [#11](https://github.com/Mike-Gibson/mock-apollo-client/issues/11). | ||
# Versions | ||
Version 0.x of this library is compatible with Apollo client 2 | ||
Version 1.x of this library is compatible with Apollo client 3 | ||
## Motivation | ||
Whilst using the impressive `react-apollo` library, I ran into issues while trying to unit test components which used the GraphQL `Query` and `Mutation` components. The `react-apollo` library includes a `MockedProvider` component which allows query and mutation results to be mocked, but didn't offer enough control within unit tests. The `react-apollo` documentation for testing can be found [here](https://www.apollographql.com/docs/react/recipes/testing). | ||
Whilst using the impressive `@apollo/client` library, I ran into issues while trying to unit test components which used the GraphQL `Query` and `Mutation` components. The Apollo client library includes a `MockedProvider` component which allows query and mutation results to be mocked, but didn't offer enough control within unit tests. The Apollo client documentation for testing can be found [here](https://www.apollographql.com/docs/react/development-testing/testing/). | ||
@@ -18,3 +20,3 @@ Specifically, some of the issues I faced were: | ||
- Unable to assert how many times a specific query was called | ||
- Unable to change the query/mutation result after the `MockProvider` was initialised | ||
- Unable to change the query/mutation result after the `MockedProvider` was initialised | ||
- Unable to easily control the query/mutation loading state | ||
@@ -30,9 +32,7 @@ | ||
Assuming `mock-apollo-client` is being used within unit tests and should be installed as a dev dependency. | ||
## Usage | ||
The examples below use `react-apollo`, `enzyme` and `Jest`, but `mock-apollo-client` is standalone and can used with any libraries and test frameworks. | ||
The examples below use `React`, `enzyme` and `Jest`, but `mock-apollo-client` is standalone and can used with any libraries and test frameworks. | ||
The examples have been adapted from the official `react-apollo` testing docs and are written in TypeScript. | ||
The examples have been adapted from the official Apollo testing docs and are written in TypeScript. | ||
@@ -44,7 +44,6 @@ ### Simple Query Example | ||
```tsx | ||
// dog.ts | ||
// dog.tsx | ||
import * as React from 'react'; | ||
import gql from 'graphql-tag'; | ||
import { Query } from 'react-apollo'; | ||
import { gql, useQuery } from '@apollo/client'; | ||
import React from 'react'; | ||
@@ -61,16 +60,16 @@ export const GET_DOG_QUERY = gql` | ||
export const Dog = ({ name }) => ( | ||
<Query query={GET_DOG_QUERY} variables={{ name }}> | ||
{({ loading, error, data }) => { | ||
if (loading) return 'Loading...'; | ||
if (error) return 'Error!'; | ||
export const Dog: React.FunctionComponent<{ name: string }> = ({ name }) => { | ||
const { loading, error, data } = useQuery( | ||
GET_DOG_QUERY, | ||
{ variables: { name } } | ||
); | ||
if (loading) return <p>Loading...</p>; | ||
if (error) return <p>Error!</p>; | ||
return ( | ||
<p> | ||
{data.dog.name} is a {data.dog.breed} | ||
</p> | ||
); | ||
}} | ||
</Query> | ||
); | ||
return ( | ||
<p> | ||
{data.dog.name} is a {data.dog.breed} | ||
</p> | ||
); | ||
}; | ||
``` | ||
@@ -81,8 +80,8 @@ | ||
```tsx | ||
// dog.test.ts | ||
// dog.test.tsx | ||
import { ApolloProvider } from '@apollo/client'; | ||
import { mount, ReactWrapper } from 'enzyme'; | ||
import { createMockClient } from 'mock-apollo-client'; | ||
import * as React from 'react'; | ||
import { ApolloProvider } from 'react-apollo'; | ||
import { createMockClient } from 'mock-apollo-client'; | ||
@@ -120,3 +119,3 @@ import { GET_DOG_QUERY, Dog } from './dog'; | ||
The method `setRequestHandler` is passed a function to call when Apollo client executes a given query and it is called with the variables for that query, so it is easy to assert the component is behaving as expected using a spy framework. | ||
The method `setRequestHandler` is passed a function to call when Apollo client executes a given query and it is called with the variables for that query, so it is easy to assert the component is behaving as expected using a spy library. | ||
@@ -155,3 +154,3 @@ ```typescript | ||
GET_DOG_QUERY, | ||
() => Promise.resolve({ errors: [{message: 'GraphQL Error'}] })); | ||
() => Promise.resolve({ errors: [{ message: 'GraphQL Error' }] })); | ||
``` | ||
@@ -167,6 +166,6 @@ | ||
For example, to specify the cache (and fragment matcher) that should be used: | ||
For example, to specify the cache (and possible types for fragment matching) that should be used: | ||
```typescript | ||
const cache = new InMemoryCache({ | ||
fragmentMatcher: myCustomFragmentMatcher, | ||
possibleTypes: myPossibleTypes, | ||
}); | ||
@@ -177,2 +176,2 @@ | ||
Note: it is not possible to specify the `link` to use as this is how Mock Apollo Client injects its behaviour. | ||
Note: it is not possible to specify the `link` to use as this is how `mock-apollo-client` injects its behaviour. |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
15803
7
10
0
144
168