1/** @jsxImportSource solid-js */
2// @vitest-environment jsdom
3
4import { describe, it, vi } from 'vitest';
5import {
6 OperationResult,
7 OperationResultSource,
8 createClient,
9} from '@urql/core';
10import { createQuery } from './createQuery';
11import { fireEvent, render, screen, waitFor } from '@solidjs/testing-library';
12import { Provider } from './context';
13import { Suspense } from 'solid-js';
14import { makeSubject } from 'wonka';
15
16describe('createQuery suspense', () => {
17 it('should not suspend', async () => {
18 const client = createClient({
19 url: '/graphql',
20 exchanges: [],
21 suspense: false,
22 });
23
24 const subject =
25 makeSubject<Pick<OperationResult<{ test: boolean }, any>, 'data'>>();
26 vi.spyOn(client, 'executeQuery').mockImplementation(
27 () => subject.source as OperationResultSource<OperationResult>
28 );
29
30 const Page = () => {
31 const [state, refetch] = createQuery<
32 { test: boolean },
33 { variable: number }
34 >({
35 query: '{ test }',
36 });
37
38 return (
39 <div>
40 <button data-testid="refetch" onClick={refetch} />
41 data: {String(state.data?.test)}
42 </div>
43 );
44 };
45
46 render(() => (
47 <Provider value={client}>
48 <Suspense fallback="loading">
49 <Page />
50 </Suspense>
51 </Provider>
52 ));
53
54 subject.next({ data: { test: true } });
55 await waitFor(() => screen.getByText('data: true'));
56
57 fireEvent.click(screen.getByTestId('refetch'));
58
59 subject.next({ data: { test: false } });
60 await waitFor(() => screen.getByText('data: false'));
61 });
62
63 it('should suspend', async () => {
64 const client = createClient({
65 url: '/graphql',
66 exchanges: [],
67 suspense: true,
68 });
69
70 const subject =
71 makeSubject<Pick<OperationResult<{ test: boolean }, any>, 'data'>>();
72 vi.spyOn(client, 'executeQuery').mockImplementation(
73 () => subject.source as OperationResultSource<OperationResult>
74 );
75
76 const Page = () => {
77 const [state] = createQuery<{ test: boolean }, { variable: number }>({
78 query: '{ test }',
79 });
80
81 return <div>data: {String(state.data?.test)}</div>;
82 };
83
84 render(() => (
85 <Provider value={client}>
86 <Suspense fallback="loading">
87 <Page />
88 </Suspense>
89 </Provider>
90 ));
91
92 await waitFor(() => screen.getByText('loading'));
93
94 subject.next({ data: { test: true } });
95 await waitFor(() => screen.getByText('data: true'));
96 });
97
98 it('context suspend should override client suspend', async () => {
99 const client = createClient({
100 url: '/graphql',
101 exchanges: [],
102 suspense: false,
103 });
104
105 const subject =
106 makeSubject<Pick<OperationResult<{ test: boolean }, any>, 'data'>>();
107 vi.spyOn(client, 'executeQuery').mockImplementation(
108 () => subject.source as OperationResultSource<OperationResult>
109 );
110
111 const Page = () => {
112 const [state] = createQuery<{ test: boolean }, { variable: number }>({
113 query: '{ test }',
114 context: {
115 suspense: true,
116 },
117 });
118
119 return <div>data: {String(state.data?.test)}</div>;
120 };
121
122 render(() => (
123 <Provider value={client}>
124 <Suspense fallback="loading">
125 <Page />
126 </Suspense>
127 </Provider>
128 ));
129
130 await waitFor(() => screen.getByText('loading'));
131
132 subject.next({ data: { test: true } });
133 await waitFor(() => screen.getByText('data: true'));
134 });
135});