1// @vitest-environment jsdom
2
3import { testEffect } from '@solidjs/testing-library';
4import { expect, it, describe, vi } from 'vitest';
5import { CreateMutationState, createMutation } from './createMutation';
6import {
7 OperationResult,
8 OperationResultSource,
9 createClient,
10 gql,
11} from '@urql/core';
12import { makeSubject } from 'wonka';
13import { createEffect } from 'solid-js';
14
15const QUERY = gql`
16 mutation {
17 test
18 }
19`;
20
21const client = createClient({
22 url: '/graphql',
23 exchanges: [],
24 suspense: false,
25});
26
27vi.mock('./context', () => {
28 const useClient = () => {
29 return client!;
30 };
31
32 return { useClient };
33});
34
35// Given that it is not possible to directly listen to all store changes it is necessary
36// to access all relevant parts on which `createEffect` should listen on
37const markStateDependencies = (state: CreateMutationState<any, any>) => {
38 state.data;
39 state.error;
40 state.extensions;
41 state.fetching;
42 state.operation;
43 state.stale;
44};
45
46describe('createMutation', () => {
47 it('should have expected state before and after finish', () => {
48 const subject = makeSubject<any>();
49 const clientMutation = vi
50 .spyOn(client, 'executeMutation')
51 .mockImplementation(
52 () => subject.source as OperationResultSource<OperationResult>
53 );
54
55 return testEffect(done => {
56 const [state, execute] = createMutation<
57 { test: boolean },
58 { variable: number }
59 >(QUERY);
60
61 createEffect((run: number = 0) => {
62 markStateDependencies(state);
63
64 switch (run) {
65 case 0: {
66 expect(state).toMatchObject({
67 data: undefined,
68 stale: false,
69 fetching: false,
70 error: undefined,
71 extensions: undefined,
72 operation: undefined,
73 });
74
75 execute({ variable: 1 });
76 break;
77 }
78
79 case 1: {
80 expect(state).toMatchObject({
81 data: undefined,
82 stale: false,
83 fetching: true,
84 error: undefined,
85 extensions: undefined,
86 operation: undefined,
87 });
88
89 expect(clientMutation).toHaveBeenCalledTimes(1);
90 subject.next({ data: { test: true }, stale: false });
91
92 break;
93 }
94
95 case 2: {
96 expect(state).toMatchObject({
97 data: { test: true },
98 stale: false,
99 fetching: false,
100 error: undefined,
101 extensions: undefined,
102 });
103
104 done();
105 break;
106 }
107 }
108
109 return run + 1;
110 });
111 });
112 });
113});