1// @vitest-environment jsdom
2
3import { FunctionalComponent as FC, h } from 'preact';
4import { render, cleanup, act } from '@testing-library/preact';
5import { print } from 'graphql';
6import { gql } from '@urql/core';
7import { fromValue, delay, pipe } from 'wonka';
8import {
9 vi,
10 expect,
11 it,
12 beforeEach,
13 describe,
14 beforeAll,
15 afterEach,
16 Mock,
17} from 'vitest';
18
19import { useMutation } from './useMutation';
20import { Provider } from '../context';
21
22const mock = {
23 executeMutation: vi.fn(() =>
24 pipe(fromValue({ data: 1, error: 2, extensions: { i: 1 } }), delay(200))
25 ),
26};
27
28const client = mock as { executeMutation: Mock };
29const props = {
30 query: 'mutation Example { example }',
31};
32
33let state: any;
34let execute: any;
35
36const MutationUser: FC<typeof props> = ({ query }) => {
37 [state, execute] = useMutation(query);
38 return h('p', {}, state.data);
39};
40
41beforeAll(() => {
42 vi.spyOn(globalThis.console, 'error').mockImplementation(() => {
43 // do nothing
44 });
45});
46
47describe('useMutation', () => {
48 beforeEach(() => {
49 client.executeMutation.mockClear();
50 state = undefined;
51 execute = undefined;
52 });
53
54 afterEach(() => cleanup());
55
56 it('does not execute subscription', () => {
57 render(
58 h(Provider, {
59 value: client as any,
60 children: [h(MutationUser, { ...props })],
61 })
62 );
63 expect(client.executeMutation).toBeCalledTimes(0);
64 });
65
66 it('executes mutation', () => {
67 render(
68 h(Provider, {
69 value: client as any,
70 children: [h(MutationUser, { ...props })],
71 })
72 );
73 const vars = { test: 1234 };
74 act(() => {
75 execute(vars);
76 });
77 const call = client.executeMutation.mock.calls[0][0];
78 expect(state).toHaveProperty('fetching', true);
79 expect(client.executeMutation).toBeCalledTimes(1);
80 expect(print(call.query)).toBe(print(gql(props.query)));
81 expect(call).toHaveProperty('variables', vars);
82 });
83
84 it('respects context changes', () => {
85 render(
86 h(Provider, {
87 value: client as any,
88 children: [h(MutationUser, { ...props })],
89 })
90 );
91 const vars = { test: 1234 };
92 act(() => {
93 execute(vars, { url: 'test' });
94 });
95 const call = client.executeMutation.mock.calls[0][1];
96 expect(call.url).toBe('test');
97 });
98
99 describe('on sub update', () => {
100 const vars = { test: 1234 };
101
102 it('receives data', async () => {
103 const { rerender } = render(
104 h(Provider, {
105 value: client as any,
106 children: [h(MutationUser, { ...props })],
107 })
108 );
109 await execute(vars);
110 rerender(
111 h(Provider, {
112 value: client as any,
113 children: [h(MutationUser, { ...props })],
114 })
115 );
116
117 expect(state).toHaveProperty('data', 1);
118 expect(state).toHaveProperty('error', 2);
119 expect(state).toHaveProperty('extensions', { i: 1 });
120 expect(state).toHaveProperty('fetching', false);
121 });
122 });
123});