Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
1import { pipe, map, makeSubject, publish, tap } from 'wonka';
2import { vi, expect, it, beforeEach } from 'vitest';
3
4import {
5 gql,
6 createClient,
7 Operation,
8 OperationResult,
9 ExchangeIO,
10} from '@urql/core';
11
12import { queryResponse } from '../../../packages/core/src/test-utils';
13import { requestPolicyExchange } from './requestPolicyExchange';
14
15const dispatchDebug = vi.fn();
16
17const mockOptions = {
18 ttl: 5,
19};
20
21const queryOne = gql`
22 {
23 author {
24 id
25 name
26 }
27 }
28`;
29
30const queryOneData = {
31 __typename: 'Query',
32 author: {
33 __typename: 'Author',
34 id: '123',
35 name: 'Author',
36 },
37};
38
39let client, op, ops$, next;
40beforeEach(() => {
41 client = createClient({
42 url: 'http://0.0.0.0',
43 exchanges: [],
44 });
45 op = client.createRequestOperation('query', {
46 key: 1,
47 query: queryOne,
48 });
49
50 ({ source: ops$, next } = makeSubject<Operation>());
51});
52
53it(`upgrades to cache-and-network`, async () => {
54 const response = vi.fn((forwardOp: Operation): OperationResult => {
55 return {
56 ...queryResponse,
57 operation: forwardOp,
58 data: queryOneData,
59 };
60 });
61
62 const result = vi.fn();
63 const forward: ExchangeIO = ops$ => {
64 return pipe(ops$, map(response));
65 };
66
67 pipe(
68 requestPolicyExchange(mockOptions)({
69 forward,
70 client,
71 dispatchDebug,
72 })(ops$),
73 tap(result),
74 publish
75 );
76
77 next(op);
78
79 expect(response).toHaveBeenCalledTimes(1);
80 expect(response.mock.calls[0][0].context.requestPolicy).toEqual(
81 'cache-and-network'
82 );
83 expect(result).toHaveBeenCalledTimes(1);
84
85 await new Promise(res => {
86 setTimeout(() => {
87 next(op);
88 expect(response).toHaveBeenCalledTimes(2);
89 expect(response.mock.calls[1][0].context.requestPolicy).toEqual(
90 'cache-and-network'
91 );
92 expect(result).toHaveBeenCalledTimes(2);
93 res(null);
94 }, 10);
95 });
96});
97
98it(`doesn't upgrade when shouldUpgrade returns false`, async () => {
99 const response = vi.fn((forwardOp: Operation): OperationResult => {
100 return {
101 ...queryResponse,
102 operation: forwardOp,
103 data: queryOneData,
104 };
105 });
106
107 const result = vi.fn();
108 const forward: ExchangeIO = ops$ => {
109 return pipe(ops$, map(response));
110 };
111
112 const shouldUpgrade = vi.fn(() => false);
113 pipe(
114 requestPolicyExchange({ ...mockOptions, shouldUpgrade })({
115 forward,
116 client,
117 dispatchDebug,
118 })(ops$),
119 tap(result),
120 publish
121 );
122
123 next(op);
124
125 expect(response).toHaveBeenCalledTimes(1);
126 expect(response.mock.calls[0][0].context.requestPolicy).toEqual(
127 'cache-first'
128 );
129 expect(result).toHaveBeenCalledTimes(1);
130
131 await new Promise(res => {
132 setTimeout(() => {
133 next(op);
134 expect(response).toHaveBeenCalledTimes(2);
135 expect(response.mock.calls[1][0].context.requestPolicy).toEqual(
136 'cache-first'
137 );
138 expect(result).toHaveBeenCalledTimes(2);
139 expect(shouldUpgrade).toBeCalledTimes(2);
140 res(null);
141 }, 10);
142 });
143});