wildcard-mock-link
Advanced tools
Comparing version 1.0.3 to 1.0.4
import { MockLink, MockedResponse } from '@apollo/react-testing'; | ||
import { Operation, FetchResult, Observable, GraphQLRequest } from 'apollo-link'; | ||
import { DocumentNode } from 'graphql'; | ||
export { withApolloMocks, hookWrapperWithApolloMocks } from './utils'; | ||
export declare const MATCH_ANY_PARAMETERS: unique symbol; | ||
@@ -67,3 +68,3 @@ export declare type GraphQLVariables = Record<string, any>; | ||
*/ | ||
lastSubscriptionRequestMatches(request: DocumentNode): boolean; | ||
lastSubscriptionMatches(request: DocumentNode): boolean; | ||
/** | ||
@@ -83,2 +84,1 @@ * Wait for the response of the last query or mutation. | ||
} | ||
export {}; |
@@ -6,2 +6,3 @@ import { MockLink } from '@apollo/react-testing'; | ||
import { print } from 'graphql'; | ||
export { withApolloMocks, hookWrapperWithApolloMocks } from './utils'; | ||
export const MATCH_ANY_PARAMETERS = Symbol(); | ||
@@ -177,3 +178,3 @@ function notWildcard(mock) { | ||
*/ | ||
lastSubscriptionRequestMatches(request) { | ||
lastSubscriptionMatches(request) { | ||
return (!!this.lastSubscription && | ||
@@ -180,0 +181,0 @@ this.queryToString(request) === this.queryToString(this.lastSubscription.query)); |
@@ -1,8 +0,176 @@ | ||
"use strict"; | ||
describe('wildcard-mock-link', () => { | ||
/* eslint-disable @typescript-eslint/no-empty-function */ | ||
it('handles multiple requests matching a query', () => { | ||
// TODO: | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
import { useQuery, useSubscription } from '@apollo/react-hooks'; | ||
import { render, act, waitFor } from '@testing-library/react'; | ||
import { renderHook, act as actHook } from '@testing-library/react-hooks'; | ||
import gql from 'graphql-tag'; | ||
import React from 'react'; | ||
import { MATCH_ANY_PARAMETERS, hookWrapperWithApolloMocks, withApolloMocks } from '.'; | ||
/* eslint-disable @typescript-eslint/explicit-function-return-type */ | ||
const CAT_QUALITIES_QUERY = gql ` | ||
query($catName: String!) { | ||
qualities(cats: $catName) { | ||
loveliness | ||
} | ||
} | ||
`; | ||
describe('WildcardMockLink', () => { | ||
describe('handles wildcard queries', () => { | ||
it('for a single request', () => __awaiter(void 0, void 0, void 0, function* () { | ||
var _a; | ||
const useQueryOnce = (catName) => { | ||
const { data } = useQuery(CAT_QUALITIES_QUERY, { variables: { catName } }); | ||
return data; | ||
}; | ||
const data = { | ||
qualities: { | ||
__typename: 'Qualities', | ||
loveliness: 'very', | ||
}, | ||
}; | ||
const { wrapper, link } = hookWrapperWithApolloMocks([ | ||
{ | ||
request: { | ||
query: CAT_QUALITIES_QUERY, | ||
variables: MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data }, | ||
}, | ||
]); | ||
const { result } = renderHook(() => useQueryOnce('tortand'), { wrapper }); | ||
yield actHook(() => link.waitForLastResponse()); | ||
expect(link.lastQueryMatches(CAT_QUALITIES_QUERY)).toBeTruthy(); | ||
expect((_a = link.lastQuery) === null || _a === void 0 ? void 0 : _a.variables).toEqual({ catName: 'tortand' }); | ||
expect(result.current).toEqual(data); | ||
})); | ||
it('for multiple requests with the same mock', () => __awaiter(void 0, void 0, void 0, function* () { | ||
var _b; | ||
const useQueryTwice = () => { | ||
const { data: firstData } = useQuery(CAT_QUALITIES_QUERY, { | ||
variables: { catName: 'snorf' }, | ||
}); | ||
const { data: secondData } = useQuery(CAT_QUALITIES_QUERY, { | ||
variables: { catName: 'candrle' }, | ||
}); | ||
return { firstData, secondData }; | ||
}; | ||
const data = { | ||
qualities: { | ||
__typename: 'Qualities', | ||
loveliness: 'highest', | ||
}, | ||
}; | ||
const { wrapper, link } = hookWrapperWithApolloMocks([ | ||
{ | ||
request: { | ||
query: CAT_QUALITIES_QUERY, | ||
variables: MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data }, | ||
}, | ||
]); | ||
const rendered = renderHook(useQueryTwice, { wrapper }); | ||
yield actHook(() => link.waitForLastResponse()); | ||
expect(link.lastQueryMatches(CAT_QUALITIES_QUERY)).toBeTruthy(); | ||
expect((_b = link.lastQuery) === null || _b === void 0 ? void 0 : _b.variables).toEqual({ catName: 'candrle' }); | ||
expect(rendered.result.current).toEqual({ firstData: data, secondData: data }); | ||
})); | ||
}); | ||
describe('can be used to mock subscriptions', () => { | ||
const MISCHIEF_SUBSCRIPTION = gql ` | ||
subscription($catName: String!) { | ||
actsOfMischief(cats: $catName) { | ||
description | ||
severity | ||
} | ||
} | ||
`; | ||
it('by pushing updates via the API', () => __awaiter(void 0, void 0, void 0, function* () { | ||
var _a; | ||
const useActsOfMischief = (catName) => { | ||
const { data } = useSubscription(MISCHIEF_SUBSCRIPTION, { variables: { catName } }); | ||
return data; | ||
}; | ||
const initialData = { | ||
actsOfMischief: { | ||
__typename: 'ActsOfMischief', | ||
description: 'did not stay away from my bins', | ||
severity: 'extreme', | ||
}, | ||
}; | ||
const { wrapper, link } = hookWrapperWithApolloMocks([ | ||
{ | ||
request: { | ||
query: MISCHIEF_SUBSCRIPTION, | ||
variables: MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data: initialData }, | ||
}, | ||
]); | ||
const rendered = renderHook(() => useActsOfMischief('la don'), { wrapper }); | ||
expect(link.lastSubscriptionMatches(MISCHIEF_SUBSCRIPTION)).toBeTruthy(); | ||
expect((_a = link.lastSubscription) === null || _a === void 0 ? void 0 : _a.variables).toEqual({ catName: 'la don' }); | ||
yield actHook(() => waitFor(() => { | ||
expect(rendered.result.current).toEqual(initialData); | ||
})); | ||
const updateData = { | ||
actsOfMischief: { | ||
__typename: 'ActsOfMischief', | ||
description: 'pushed that button', | ||
severity: 'mild', | ||
}, | ||
}; | ||
actHook(() => { | ||
link.sendWildcardSubscriptionResult(MISCHIEF_SUBSCRIPTION, { data: updateData }); | ||
}); | ||
yield actHook(() => waitFor(() => { | ||
expect(rendered.result.current).toEqual(updateData); | ||
})); | ||
})); | ||
}); | ||
}); | ||
describe('withApolloMocks utility', () => { | ||
const MyCatComponent = ({ catName }) => { | ||
const { data } = useQuery(CAT_QUALITIES_QUERY, { variables: { catName } }); | ||
if (!data) { | ||
return React.createElement("h1", { role: "main" }, "Loading"); | ||
} | ||
else { | ||
return React.createElement("h1", { role: "main" }, | ||
"Loveliness: ", | ||
data.qualities.loveliness); | ||
} | ||
}; | ||
it('can be used to supply mock data to a component tree', () => __awaiter(void 0, void 0, void 0, function* () { | ||
var _a; | ||
const data = { | ||
qualities: { | ||
__typename: 'Qualities', | ||
loveliness: 'very', | ||
}, | ||
}; | ||
const { element, link } = withApolloMocks(() => React.createElement(MyCatComponent, { catName: "mr bad actor face" }), [ | ||
{ | ||
request: { | ||
query: CAT_QUALITIES_QUERY, | ||
variables: MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data }, | ||
}, | ||
]); | ||
const { getByRole } = render(element); | ||
yield act(() => link.waitForLastResponse()); | ||
expect(link.lastQueryMatches(CAT_QUALITIES_QUERY)).toBeTruthy(); | ||
expect((_a = link.lastQuery) === null || _a === void 0 ? void 0 : _a.variables).toEqual({ catName: 'mr bad actor face' }); | ||
const mainContent = getByRole('main'); | ||
expect(mainContent === null || mainContent === void 0 ? void 0 : mainContent.textContent).toEqual('Loveliness: very'); | ||
})); | ||
}); | ||
//# sourceMappingURL=index.spec.js.map |
import { MockLink, MockedResponse } from '@apollo/react-testing'; | ||
import { Operation, FetchResult, Observable, GraphQLRequest } from 'apollo-link'; | ||
import { DocumentNode } from 'graphql'; | ||
export { withApolloMocks, hookWrapperWithApolloMocks } from './utils'; | ||
export declare const MATCH_ANY_PARAMETERS: unique symbol; | ||
@@ -67,3 +68,3 @@ export declare type GraphQLVariables = Record<string, any>; | ||
*/ | ||
lastSubscriptionRequestMatches(request: DocumentNode): boolean; | ||
lastSubscriptionMatches(request: DocumentNode): boolean; | ||
/** | ||
@@ -83,2 +84,1 @@ * Wait for the response of the last query or mutation. | ||
} | ||
export {}; |
@@ -24,2 +24,5 @@ "use strict"; | ||
var graphql_1 = require("graphql"); | ||
var utils_1 = require("./utils"); | ||
exports.withApolloMocks = utils_1.withApolloMocks; | ||
exports.hookWrapperWithApolloMocks = utils_1.hookWrapperWithApolloMocks; | ||
exports.MATCH_ANY_PARAMETERS = Symbol(); | ||
@@ -205,3 +208,3 @@ function notWildcard(mock) { | ||
*/ | ||
WildcardMockLink.prototype.lastSubscriptionRequestMatches = function (request) { | ||
WildcardMockLink.prototype.lastSubscriptionMatches = function (request) { | ||
return (!!this.lastSubscription && | ||
@@ -208,0 +211,0 @@ this.queryToString(request) === this.queryToString(this.lastSubscription.query)); |
"use strict"; | ||
describe('wildcard-mock-link', function () { | ||
/* eslint-disable @typescript-eslint/no-empty-function */ | ||
it('handles multiple requests matching a query', function () { | ||
// TODO: | ||
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { | ||
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } | ||
return cooked; | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
var react_hooks_1 = require("@apollo/react-hooks"); | ||
var react_1 = require("@testing-library/react"); | ||
var react_hooks_2 = require("@testing-library/react-hooks"); | ||
var graphql_tag_1 = __importDefault(require("graphql-tag")); | ||
var react_2 = __importDefault(require("react")); | ||
var _1 = require("."); | ||
/* eslint-disable @typescript-eslint/explicit-function-return-type */ | ||
var CAT_QUALITIES_QUERY = graphql_tag_1.default(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n query($catName: String!) {\n qualities(cats: $catName) {\n loveliness\n }\n }\n"], ["\n query($catName: String!) {\n qualities(cats: $catName) {\n loveliness\n }\n }\n"]))); | ||
describe('WildcardMockLink', function () { | ||
describe('handles wildcard queries', function () { | ||
it('for a single request', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var useQueryOnce, data, _a, wrapper, link, result; | ||
var _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
useQueryOnce = function (catName) { | ||
var data = react_hooks_1.useQuery(CAT_QUALITIES_QUERY, { variables: { catName: catName } }).data; | ||
return data; | ||
}; | ||
data = { | ||
qualities: { | ||
__typename: 'Qualities', | ||
loveliness: 'very', | ||
}, | ||
}; | ||
_a = _1.hookWrapperWithApolloMocks([ | ||
{ | ||
request: { | ||
query: CAT_QUALITIES_QUERY, | ||
variables: _1.MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data: data }, | ||
}, | ||
]), wrapper = _a.wrapper, link = _a.link; | ||
result = react_hooks_2.renderHook(function () { return useQueryOnce('tortand'); }, { wrapper: wrapper }).result; | ||
return [4 /*yield*/, react_hooks_2.act(function () { return link.waitForLastResponse(); })]; | ||
case 1: | ||
_c.sent(); | ||
expect(link.lastQueryMatches(CAT_QUALITIES_QUERY)).toBeTruthy(); | ||
expect((_b = link.lastQuery) === null || _b === void 0 ? void 0 : _b.variables).toEqual({ catName: 'tortand' }); | ||
expect(result.current).toEqual(data); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
it('for multiple requests with the same mock', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var useQueryTwice, data, _a, wrapper, link, rendered; | ||
var _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
useQueryTwice = function () { | ||
var firstData = react_hooks_1.useQuery(CAT_QUALITIES_QUERY, { | ||
variables: { catName: 'snorf' }, | ||
}).data; | ||
var secondData = react_hooks_1.useQuery(CAT_QUALITIES_QUERY, { | ||
variables: { catName: 'candrle' }, | ||
}).data; | ||
return { firstData: firstData, secondData: secondData }; | ||
}; | ||
data = { | ||
qualities: { | ||
__typename: 'Qualities', | ||
loveliness: 'highest', | ||
}, | ||
}; | ||
_a = _1.hookWrapperWithApolloMocks([ | ||
{ | ||
request: { | ||
query: CAT_QUALITIES_QUERY, | ||
variables: _1.MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data: data }, | ||
}, | ||
]), wrapper = _a.wrapper, link = _a.link; | ||
rendered = react_hooks_2.renderHook(useQueryTwice, { wrapper: wrapper }); | ||
return [4 /*yield*/, react_hooks_2.act(function () { return link.waitForLastResponse(); })]; | ||
case 1: | ||
_c.sent(); | ||
expect(link.lastQueryMatches(CAT_QUALITIES_QUERY)).toBeTruthy(); | ||
expect((_b = link.lastQuery) === null || _b === void 0 ? void 0 : _b.variables).toEqual({ catName: 'candrle' }); | ||
expect(rendered.result.current).toEqual({ firstData: data, secondData: data }); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
}); | ||
describe('can be used to mock subscriptions', function () { | ||
var MISCHIEF_SUBSCRIPTION = graphql_tag_1.default(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n subscription($catName: String!) {\n actsOfMischief(cats: $catName) {\n description\n severity\n }\n }\n "], ["\n subscription($catName: String!) {\n actsOfMischief(cats: $catName) {\n description\n severity\n }\n }\n "]))); | ||
it('by pushing updates via the API', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var useActsOfMischief, initialData, _a, wrapper, link, rendered, updateData; | ||
var _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
useActsOfMischief = function (catName) { | ||
var data = react_hooks_1.useSubscription(MISCHIEF_SUBSCRIPTION, { variables: { catName: catName } }).data; | ||
return data; | ||
}; | ||
initialData = { | ||
actsOfMischief: { | ||
__typename: 'ActsOfMischief', | ||
description: 'did not stay away from my bins', | ||
severity: 'extreme', | ||
}, | ||
}; | ||
_a = _1.hookWrapperWithApolloMocks([ | ||
{ | ||
request: { | ||
query: MISCHIEF_SUBSCRIPTION, | ||
variables: _1.MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data: initialData }, | ||
}, | ||
]), wrapper = _a.wrapper, link = _a.link; | ||
rendered = react_hooks_2.renderHook(function () { return useActsOfMischief('la don'); }, { wrapper: wrapper }); | ||
expect(link.lastSubscriptionMatches(MISCHIEF_SUBSCRIPTION)).toBeTruthy(); | ||
expect((_b = link.lastSubscription) === null || _b === void 0 ? void 0 : _b.variables).toEqual({ catName: 'la don' }); | ||
return [4 /*yield*/, react_hooks_2.act(function () { | ||
return react_1.waitFor(function () { | ||
expect(rendered.result.current).toEqual(initialData); | ||
}); | ||
})]; | ||
case 1: | ||
_c.sent(); | ||
updateData = { | ||
actsOfMischief: { | ||
__typename: 'ActsOfMischief', | ||
description: 'pushed that button', | ||
severity: 'mild', | ||
}, | ||
}; | ||
react_hooks_2.act(function () { | ||
link.sendWildcardSubscriptionResult(MISCHIEF_SUBSCRIPTION, { data: updateData }); | ||
}); | ||
return [4 /*yield*/, react_hooks_2.act(function () { | ||
return react_1.waitFor(function () { | ||
expect(rendered.result.current).toEqual(updateData); | ||
}); | ||
})]; | ||
case 2: | ||
_c.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
}); | ||
}); | ||
describe('withApolloMocks utility', function () { | ||
var MyCatComponent = function (_a) { | ||
var catName = _a.catName; | ||
var data = react_hooks_1.useQuery(CAT_QUALITIES_QUERY, { variables: { catName: catName } }).data; | ||
if (!data) { | ||
return react_2.default.createElement("h1", { role: "main" }, "Loading"); | ||
} | ||
else { | ||
return react_2.default.createElement("h1", { role: "main" }, | ||
"Loveliness: ", | ||
data.qualities.loveliness); | ||
} | ||
}; | ||
it('can be used to supply mock data to a component tree', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var data, _a, element, link, getByRole, mainContent; | ||
var _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
data = { | ||
qualities: { | ||
__typename: 'Qualities', | ||
loveliness: 'very', | ||
}, | ||
}; | ||
_a = _1.withApolloMocks(function () { return react_2.default.createElement(MyCatComponent, { catName: "mr bad actor face" }); }, [ | ||
{ | ||
request: { | ||
query: CAT_QUALITIES_QUERY, | ||
variables: _1.MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data: data }, | ||
}, | ||
]), element = _a.element, link = _a.link; | ||
getByRole = react_1.render(element).getByRole; | ||
return [4 /*yield*/, react_1.act(function () { return link.waitForLastResponse(); })]; | ||
case 1: | ||
_c.sent(); | ||
expect(link.lastQueryMatches(CAT_QUALITIES_QUERY)).toBeTruthy(); | ||
expect((_b = link.lastQuery) === null || _b === void 0 ? void 0 : _b.variables).toEqual({ catName: 'mr bad actor face' }); | ||
mainContent = getByRole('main'); | ||
expect(mainContent === null || mainContent === void 0 ? void 0 : mainContent.textContent).toEqual('Loveliness: very'); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
}); | ||
var templateObject_1, templateObject_2; | ||
//# sourceMappingURL=index.spec.js.map |
import { MockLink, MockedResponse } from '@apollo/react-testing'; | ||
import { Operation, FetchResult, Observable, GraphQLRequest } from 'apollo-link'; | ||
import { DocumentNode } from 'graphql'; | ||
export { withApolloMocks, hookWrapperWithApolloMocks } from './utils'; | ||
export declare const MATCH_ANY_PARAMETERS: unique symbol; | ||
@@ -67,3 +68,3 @@ export declare type GraphQLVariables = Record<string, any>; | ||
*/ | ||
lastSubscriptionRequestMatches(request: DocumentNode): boolean; | ||
lastSubscriptionMatches(request: DocumentNode): boolean; | ||
/** | ||
@@ -83,2 +84,1 @@ * Wait for the response of the last query or mutation. | ||
} | ||
export {}; |
@@ -19,2 +19,3 @@ var __extends = (this && this.__extends) || (function () { | ||
import { print } from 'graphql'; | ||
export { withApolloMocks, hookWrapperWithApolloMocks } from './utils'; | ||
export var MATCH_ANY_PARAMETERS = Symbol(); | ||
@@ -200,3 +201,3 @@ function notWildcard(mock) { | ||
*/ | ||
WildcardMockLink.prototype.lastSubscriptionRequestMatches = function (request) { | ||
WildcardMockLink.prototype.lastSubscriptionMatches = function (request) { | ||
return (!!this.lastSubscription && | ||
@@ -203,0 +204,0 @@ this.queryToString(request) === this.queryToString(this.lastSubscription.query)); |
@@ -1,8 +0,238 @@ | ||
"use strict"; | ||
describe('wildcard-mock-link', function () { | ||
/* eslint-disable @typescript-eslint/no-empty-function */ | ||
it('handles multiple requests matching a query', function () { | ||
// TODO: | ||
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) { | ||
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } | ||
return cooked; | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
var __generator = (this && this.__generator) || function (thisArg, body) { | ||
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; | ||
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; | ||
function verb(n) { return function (v) { return step([n, v]); }; } | ||
function step(op) { | ||
if (f) throw new TypeError("Generator is already executing."); | ||
while (_) try { | ||
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; | ||
if (y = 0, t) op = [op[0] & 2, t.value]; | ||
switch (op[0]) { | ||
case 0: case 1: t = op; break; | ||
case 4: _.label++; return { value: op[1], done: false }; | ||
case 5: _.label++; y = op[1]; op = [0]; continue; | ||
case 7: op = _.ops.pop(); _.trys.pop(); continue; | ||
default: | ||
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } | ||
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } | ||
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } | ||
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } | ||
if (t[2]) _.ops.pop(); | ||
_.trys.pop(); continue; | ||
} | ||
op = body.call(thisArg, _); | ||
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } | ||
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; | ||
} | ||
}; | ||
import { useQuery, useSubscription } from '@apollo/react-hooks'; | ||
import { render, act, waitFor } from '@testing-library/react'; | ||
import { renderHook, act as actHook } from '@testing-library/react-hooks'; | ||
import gql from 'graphql-tag'; | ||
import React from 'react'; | ||
import { MATCH_ANY_PARAMETERS, hookWrapperWithApolloMocks, withApolloMocks } from '.'; | ||
/* eslint-disable @typescript-eslint/explicit-function-return-type */ | ||
var CAT_QUALITIES_QUERY = gql(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n query($catName: String!) {\n qualities(cats: $catName) {\n loveliness\n }\n }\n"], ["\n query($catName: String!) {\n qualities(cats: $catName) {\n loveliness\n }\n }\n"]))); | ||
describe('WildcardMockLink', function () { | ||
describe('handles wildcard queries', function () { | ||
it('for a single request', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var useQueryOnce, data, _a, wrapper, link, result; | ||
var _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
useQueryOnce = function (catName) { | ||
var data = useQuery(CAT_QUALITIES_QUERY, { variables: { catName: catName } }).data; | ||
return data; | ||
}; | ||
data = { | ||
qualities: { | ||
__typename: 'Qualities', | ||
loveliness: 'very', | ||
}, | ||
}; | ||
_a = hookWrapperWithApolloMocks([ | ||
{ | ||
request: { | ||
query: CAT_QUALITIES_QUERY, | ||
variables: MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data: data }, | ||
}, | ||
]), wrapper = _a.wrapper, link = _a.link; | ||
result = renderHook(function () { return useQueryOnce('tortand'); }, { wrapper: wrapper }).result; | ||
return [4 /*yield*/, actHook(function () { return link.waitForLastResponse(); })]; | ||
case 1: | ||
_c.sent(); | ||
expect(link.lastQueryMatches(CAT_QUALITIES_QUERY)).toBeTruthy(); | ||
expect((_b = link.lastQuery) === null || _b === void 0 ? void 0 : _b.variables).toEqual({ catName: 'tortand' }); | ||
expect(result.current).toEqual(data); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
it('for multiple requests with the same mock', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var useQueryTwice, data, _a, wrapper, link, rendered; | ||
var _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
useQueryTwice = function () { | ||
var firstData = useQuery(CAT_QUALITIES_QUERY, { | ||
variables: { catName: 'snorf' }, | ||
}).data; | ||
var secondData = useQuery(CAT_QUALITIES_QUERY, { | ||
variables: { catName: 'candrle' }, | ||
}).data; | ||
return { firstData: firstData, secondData: secondData }; | ||
}; | ||
data = { | ||
qualities: { | ||
__typename: 'Qualities', | ||
loveliness: 'highest', | ||
}, | ||
}; | ||
_a = hookWrapperWithApolloMocks([ | ||
{ | ||
request: { | ||
query: CAT_QUALITIES_QUERY, | ||
variables: MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data: data }, | ||
}, | ||
]), wrapper = _a.wrapper, link = _a.link; | ||
rendered = renderHook(useQueryTwice, { wrapper: wrapper }); | ||
return [4 /*yield*/, actHook(function () { return link.waitForLastResponse(); })]; | ||
case 1: | ||
_c.sent(); | ||
expect(link.lastQueryMatches(CAT_QUALITIES_QUERY)).toBeTruthy(); | ||
expect((_b = link.lastQuery) === null || _b === void 0 ? void 0 : _b.variables).toEqual({ catName: 'candrle' }); | ||
expect(rendered.result.current).toEqual({ firstData: data, secondData: data }); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
}); | ||
describe('can be used to mock subscriptions', function () { | ||
var MISCHIEF_SUBSCRIPTION = gql(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n subscription($catName: String!) {\n actsOfMischief(cats: $catName) {\n description\n severity\n }\n }\n "], ["\n subscription($catName: String!) {\n actsOfMischief(cats: $catName) {\n description\n severity\n }\n }\n "]))); | ||
it('by pushing updates via the API', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var useActsOfMischief, initialData, _a, wrapper, link, rendered, updateData; | ||
var _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
useActsOfMischief = function (catName) { | ||
var data = useSubscription(MISCHIEF_SUBSCRIPTION, { variables: { catName: catName } }).data; | ||
return data; | ||
}; | ||
initialData = { | ||
actsOfMischief: { | ||
__typename: 'ActsOfMischief', | ||
description: 'did not stay away from my bins', | ||
severity: 'extreme', | ||
}, | ||
}; | ||
_a = hookWrapperWithApolloMocks([ | ||
{ | ||
request: { | ||
query: MISCHIEF_SUBSCRIPTION, | ||
variables: MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data: initialData }, | ||
}, | ||
]), wrapper = _a.wrapper, link = _a.link; | ||
rendered = renderHook(function () { return useActsOfMischief('la don'); }, { wrapper: wrapper }); | ||
expect(link.lastSubscriptionMatches(MISCHIEF_SUBSCRIPTION)).toBeTruthy(); | ||
expect((_b = link.lastSubscription) === null || _b === void 0 ? void 0 : _b.variables).toEqual({ catName: 'la don' }); | ||
return [4 /*yield*/, actHook(function () { | ||
return waitFor(function () { | ||
expect(rendered.result.current).toEqual(initialData); | ||
}); | ||
})]; | ||
case 1: | ||
_c.sent(); | ||
updateData = { | ||
actsOfMischief: { | ||
__typename: 'ActsOfMischief', | ||
description: 'pushed that button', | ||
severity: 'mild', | ||
}, | ||
}; | ||
actHook(function () { | ||
link.sendWildcardSubscriptionResult(MISCHIEF_SUBSCRIPTION, { data: updateData }); | ||
}); | ||
return [4 /*yield*/, actHook(function () { | ||
return waitFor(function () { | ||
expect(rendered.result.current).toEqual(updateData); | ||
}); | ||
})]; | ||
case 2: | ||
_c.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
}); | ||
}); | ||
describe('withApolloMocks utility', function () { | ||
var MyCatComponent = function (_a) { | ||
var catName = _a.catName; | ||
var data = useQuery(CAT_QUALITIES_QUERY, { variables: { catName: catName } }).data; | ||
if (!data) { | ||
return React.createElement("h1", { role: "main" }, "Loading"); | ||
} | ||
else { | ||
return React.createElement("h1", { role: "main" }, | ||
"Loveliness: ", | ||
data.qualities.loveliness); | ||
} | ||
}; | ||
it('can be used to supply mock data to a component tree', function () { return __awaiter(void 0, void 0, void 0, function () { | ||
var data, _a, element, link, getByRole, mainContent; | ||
var _b; | ||
return __generator(this, function (_c) { | ||
switch (_c.label) { | ||
case 0: | ||
data = { | ||
qualities: { | ||
__typename: 'Qualities', | ||
loveliness: 'very', | ||
}, | ||
}; | ||
_a = withApolloMocks(function () { return React.createElement(MyCatComponent, { catName: "mr bad actor face" }); }, [ | ||
{ | ||
request: { | ||
query: CAT_QUALITIES_QUERY, | ||
variables: MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data: data }, | ||
}, | ||
]), element = _a.element, link = _a.link; | ||
getByRole = render(element).getByRole; | ||
return [4 /*yield*/, act(function () { return link.waitForLastResponse(); })]; | ||
case 1: | ||
_c.sent(); | ||
expect(link.lastQueryMatches(CAT_QUALITIES_QUERY)).toBeTruthy(); | ||
expect((_b = link.lastQuery) === null || _b === void 0 ? void 0 : _b.variables).toEqual({ catName: 'mr bad actor face' }); | ||
mainContent = getByRole('main'); | ||
expect(mainContent === null || mainContent === void 0 ? void 0 : mainContent.textContent).toEqual('Loveliness: very'); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); }); | ||
}); | ||
var templateObject_1, templateObject_2; | ||
//# sourceMappingURL=index.spec.js.map |
{ | ||
"name": "wildcard-mock-link", | ||
"version": "1.0.3", | ||
"version": "1.0.4", | ||
"description": "apollo client mocking", | ||
@@ -34,2 +34,3 @@ "author": "insidewhy <github@chilon.net>", | ||
"run-prettier": "prettier 'src/*.ts' '*.md'", | ||
"typecheck": "tsc -p src --noEmit", | ||
"validate-prettiness": "yarn run-prettier -c", | ||
@@ -40,3 +41,3 @@ "make-prettier": "yarn run-prettier --write", | ||
"validate": "yarn test && yarn lint && yarn validate-prettiness", | ||
"jest-watch": "yarn jest --watch" | ||
"jest-watch": "yarn jest --watchAll" | ||
}, | ||
@@ -48,3 +49,6 @@ "dependencies": { | ||
"devDependencies": { | ||
"@apollo/react-hooks": "3.1.5", | ||
"@apollo/react-testing": "3.1.3", | ||
"@testing-library/react": "10.0.3", | ||
"@testing-library/react-hooks": "3.2.1", | ||
"@types/jest": "25.2.1", | ||
@@ -61,3 +65,7 @@ "@types/react": "16.9.34", | ||
"eslint-config-prettier": "6.10.1", | ||
"eslint-plugin-import": "2.20.1", | ||
"eslint-plugin-react": "7.16.0", | ||
"eslint-plugin-react-hooks": "2.5.0", | ||
"graphql": "14.5.8", | ||
"graphql-tag": "2.10.3", | ||
"husky": "4.2.5", | ||
@@ -68,2 +76,4 @@ "jest": "25.3.0", | ||
"react": "16.13.1", | ||
"react-dom": "16.13.1", | ||
"react-test-renderer": "16.13.1", | ||
"rimraf": "3.0.2", | ||
@@ -70,0 +80,0 @@ "typescript": "3.8.3" |
221
readme.md
@@ -7,5 +7,5 @@ # wildcard-mock-link | ||
WildcardMockLink is a replacement for `MockLink` which can: | ||
`WildcardMockLink` is a replacement for `MockLink` which can: | ||
- Match requests with any variables. | ||
- Match requests with arbitrary variables. | ||
- Provide mocks that match more than one request. | ||
@@ -17,2 +17,217 @@ - Mock subscriptions and push out subscription responses during a test via method calls. | ||
Coming soon | ||
### Wildcard queries | ||
The `MockLink` provided with apollo requires the variables for every matching query to be specified ahead of time. In certain circumstances this is not convenient, i.e. using the `MockedProvider` in storybook stories. `WildcardMockLink` allows mocks to be specified that match a query with any variables, and these mocks can be configured to match more than once. | ||
```typescript | ||
const CAT_QUALITIES_QUERY = gql` | ||
query($catName: String!) { | ||
qualities(cats: $catName) { | ||
loveliness | ||
} | ||
} | ||
` | ||
const link = new WildcardMockLink([ | ||
{ | ||
request: { | ||
query: CAT_QUALITIES_QUERY, | ||
variables: MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data }, | ||
nMatches: 2, | ||
}, | ||
]) | ||
return ( | ||
<MockedProvider link={link}> | ||
<MyCatComponent /> | ||
</MockedProvider> | ||
) | ||
``` | ||
The above mocked provider will match two requests for `CAT_QUALITIES_QUERY` no matter what the variables are due to `nMatches: 2`. If `nMatches` is omitted then the mock will match an infinite number of requests. | ||
### Asserting against the latest request/mutation/subscription. | ||
The following returns true if the last query matches `CAT_QUALITIES_QUERY`. | ||
```typescript | ||
link.lastQueryMatches(CAT_QUALITIES_QUERY) | ||
``` | ||
There is also `lastMutationMatches` and `lastSubscriptionMatches`. | ||
### Waiting for the latest response to return data | ||
```typescript | ||
await link.waitForLastResponse() | ||
``` | ||
This can be used to ensure updates don't happen outside of `act`. | ||
### Testing components with mock data | ||
This library provides a utility function `withApolloMocks` which can be used to created a component tree with access to mocked data. It returns the react element at the head of the component tree and a `WildcardMockLink` object and can be used in conjunction with the functionality mentioned above to create a test like this: | ||
```typescript | ||
import { useQuery } from '@apollo/react-hooks' | ||
import { render, act } from '@testing-library/react' | ||
import gql from 'graphql-tag' | ||
import React, { FC } from 'react' | ||
import { MATCH_ANY_PARAMETERS, hookWrapperWithApolloMocks } from 'wildcard-mock-link' | ||
const CAT_QUALITIES_QUERY = gql` | ||
query($catName: String!) { | ||
qualities(cats: $catName) { | ||
loveliness | ||
} | ||
} | ||
` | ||
it('can be used to mock data for a component tree', async () => { | ||
const data = { | ||
qualities: { | ||
__typename: 'Qualities', | ||
loveliness: 'very', | ||
}, | ||
} | ||
const { element, link } = withApolloMocks( | ||
() => <MyCatComponent catName="mr bad actor face" />, | ||
[ | ||
{ | ||
request: { | ||
query: CAT_QUALITIES_QUERY, | ||
variables: MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data }, | ||
}, | ||
], | ||
) | ||
const { getByRole } = render(element) | ||
await act(() => link.waitForLastResponse()) | ||
expect(link.lastQueryMatches(CAT_QUALITIES_QUERY)).toBeTruthy() | ||
expect(link.lastQuery?.variables).toEqual({ catName: 'mr bad actor face' }) | ||
const mainContent = getByRole('main') | ||
expect(mainContent?.textContent).toEqual('Loveliness: very') | ||
}) | ||
``` | ||
### Testing hooks with mock data | ||
This library provides a utility function `hookWrapperWithApolloMocks` for creating a wrapper object which can be used with `@testing-library/react-hooks`. It returns a `WildcardMockLink` and a `wrapper` and can be used in conjunction with the functionality mentioned above to create a test like this: | ||
```typescript | ||
import { useQuery } from '@apollo/react-hooks' | ||
import { renderHook, act as actHook } from '@testing-library/react-hooks' | ||
import gql from 'graphql-tag' | ||
import { MATCH_ANY_PARAMETERS, hookWrapperWithApolloMocks } from 'wildcard-mock-link' | ||
const CAT_QUALITIES_QUERY = gql` | ||
query($catName: String!) { | ||
qualities(cats: $catName) { | ||
loveliness | ||
} | ||
} | ||
` | ||
it('can be used to mock data for a hook', async () => { | ||
const useQueryOnce = (catName: string) => { | ||
const { data } = useQuery(CAT_QUALITIES_QUERY, { variables: { catName } }) | ||
return data | ||
} | ||
const data = { | ||
qualities: { | ||
__typename: 'Qualities', | ||
loveliness: 'very', | ||
}, | ||
} | ||
const { wrapper, link } = hookWrapperWithApolloMocks([ | ||
{ | ||
request: { | ||
query: CAT_QUALITIES_QUERY, | ||
variables: MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data }, | ||
}, | ||
]) | ||
const { result } = renderHook(() => useQueryOnce('tortand'), { wrapper }) | ||
await act(() => link.waitForLastResponse()) | ||
expect(link.lastQueryMatches(CAT_QUALITIES_QUERY)).toBeTruthy() | ||
expect(link.lastQuery!.variables).toEqual({ catName: 'tortand' }) | ||
expect(result.current).toEqual(data) | ||
}) | ||
``` | ||
### Testing subscriptions with multiple responses | ||
The `WildcardMockLink` provides a way to push new responses out to subscriptions. This can be used during tests to make it easier to test how components respond to subscription updates. The `sendWildcardSubscriptionResult` method can be used to send a new response which matches a wildcard mock, otherwise `sendSubscriptionResult` can be used. Here is an example: | ||
```typescript | ||
import { useQuery } from '@apollo/react-hooks' | ||
import { waitFor } from '@testing-library/react' | ||
import { renderHook, act as actHook } from '@testing-library/react-hooks' | ||
import gql from 'graphql-tag' | ||
import { MATCH_ANY_PARAMETERS, hookWrapperWithApolloMocks } from 'wildcard-mock-link' | ||
const MISCHIEF_SUBSCRIPTION = gql` | ||
subscription($catName: String!) { | ||
actsOfMischief(cats: $catName) { | ||
description | ||
severity | ||
} | ||
} | ||
` | ||
it('can push updates using the API', async () => { | ||
const useActsOfMischief = (catName: string) => { | ||
const { data } = useSubscription(MISCHIEF_SUBSCRIPTION, { variables: { catName } }) | ||
return data | ||
} | ||
const initialData = { | ||
actsOfMischief: { | ||
__typename: 'ActsOfMischief', | ||
description: 'did not stay away from my bins', | ||
severity: 'extreme', | ||
}, | ||
} | ||
const { wrapper, link } = hookWrapperWithApolloMocks([ | ||
{ | ||
request: { | ||
query: MISCHIEF_SUBSCRIPTION, | ||
variables: MATCH_ANY_PARAMETERS, | ||
}, | ||
result: { data: initialData }, | ||
}, | ||
]) | ||
const rendered = renderHook(() => useActsOfMischief('la don'), { wrapper }) | ||
expect(link.lastSubscriptionMatches(MISCHIEF_SUBSCRIPTION)).toBeTruthy() | ||
expect(link.lastSubscription?.variables).toEqual({ catName: 'la don' }) | ||
await actHook(() => | ||
waitFor(() => { | ||
expect(rendered.result.current).toEqual(initialData) | ||
}), | ||
) | ||
const updateData = { | ||
actsOfMischief: { | ||
__typename: 'ActsOfMischief', | ||
description: 'pushed that button', | ||
severity: 'mild', | ||
}, | ||
} | ||
actHook(() => { | ||
link.sendWildcardSubscriptionResult(MISCHIEF_SUBSCRIPTION, { data: updateData }) | ||
}) | ||
await actHook(() => | ||
waitFor(() => { | ||
expect(rendered.result.current).toEqual(updateData) | ||
}), | ||
) | ||
}) | ||
``` |
@@ -7,2 +7,4 @@ import { MockLink, MockedResponse } from '@apollo/react-testing' | ||
export { withApolloMocks, hookWrapperWithApolloMocks } from './utils' | ||
export const MATCH_ANY_PARAMETERS = Symbol() | ||
@@ -239,3 +241,3 @@ | ||
*/ | ||
lastSubscriptionRequestMatches(request: DocumentNode): boolean { | ||
lastSubscriptionMatches(request: DocumentNode): boolean { | ||
return ( | ||
@@ -242,0 +244,0 @@ !!this.lastSubscription && |
@@ -12,4 +12,5 @@ { | ||
"outDir": "../dist.es2015", | ||
"jsx": "react", | ||
"target": "es2015" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
149927
41
2282
232
29