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 { contextExchange } from './context';
14
15const queryOne = gql`
16 {
17 author {
18 id
19 name
20 }
21 }
22`;
23
24const queryOneData = {
25 __typename: 'Query',
26 author: {
27 __typename: 'Author',
28 id: '123',
29 name: 'Author',
30 },
31};
32
33const dispatchDebug = vi.fn();
34let client, op, ops$, next;
35beforeEach(() => {
36 client = createClient({
37 url: 'http://0.0.0.0',
38 exchanges: [],
39 });
40 op = client.createRequestOperation('query', {
41 key: 1,
42 query: queryOne,
43 });
44
45 ({ source: ops$, next } = makeSubject<Operation>());
46});
47
48it(`calls getContext`, () => {
49 const response = vi.fn((forwardOp: Operation): OperationResult => {
50 return {
51 ...queryResponse,
52 operation: forwardOp,
53 data: queryOneData,
54 };
55 });
56
57 const result = vi.fn();
58 const forward: ExchangeIO = ops$ => {
59 return pipe(ops$, map(response));
60 };
61
62 const headers = { hello: 'world' };
63 pipe(
64 contextExchange({
65 getContext: op => ({ ...op.context, headers }),
66 })({
67 forward,
68 client,
69 dispatchDebug,
70 })(ops$),
71 tap(result),
72 publish
73 );
74
75 next(op);
76
77 expect(response).toHaveBeenCalledTimes(1);
78 expect(response.mock.calls[0][0].context.headers).toEqual(headers);
79 expect(result).toHaveBeenCalledTimes(1);
80});
81
82it(`calls getContext async`, async () => {
83 const response = vi.fn((forwardOp: Operation): OperationResult => {
84 return {
85 ...queryResponse,
86 operation: forwardOp,
87 data: queryOneData,
88 };
89 });
90
91 const result = vi.fn();
92 const forward: ExchangeIO = ops$ => {
93 return pipe(ops$, map(response));
94 };
95
96 const headers = { hello: 'world' };
97 pipe(
98 contextExchange({
99 getContext: async op => {
100 await Promise.resolve();
101 return { ...op.context, headers };
102 },
103 })({
104 forward,
105 client,
106 dispatchDebug,
107 })(ops$),
108 tap(result),
109 publish
110 );
111
112 next(op);
113
114 await new Promise(res => {
115 setTimeout(() => {
116 expect(response).toHaveBeenCalledTimes(1);
117 expect(response.mock.calls[0][0].context.headers).toEqual(headers);
118 expect(result).toHaveBeenCalledTimes(1);
119 res(null);
120 }, 10);
121 });
122});