@dhis2/app-service-data 3.2.4 → 3.2.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/__tests__/integration.test.js +19 -45
- package/build/cjs/__tests__/mutations.test.js +55 -64
- package/build/cjs/links/RestAPILink/queryToRequestOptions/textPlainMatchers.js +18 -8
- package/build/cjs/links/RestAPILink/queryToRequestOptions/textPlainMatchers.test.js +38 -10
- package/build/cjs/react/hooks/useDataMutation.test.js +320 -52
- package/build/cjs/react/hooks/useDataQuery.js +16 -9
- package/build/cjs/react/hooks/useDataQuery.test.js +143 -0
- package/build/es/__tests__/integration.test.js +19 -45
- package/build/es/__tests__/mutations.test.js +53 -64
- package/build/es/links/RestAPILink/queryToRequestOptions/textPlainMatchers.js +13 -6
- package/build/es/links/RestAPILink/queryToRequestOptions/textPlainMatchers.test.js +39 -11
- package/build/es/react/hooks/useDataMutation.test.js +315 -50
- package/build/es/react/hooks/useDataQuery.js +17 -10
- package/build/es/react/hooks/useDataQuery.test.js +143 -0
- package/build/types/links/RestAPILink/queryToRequestOptions/textPlainMatchers.d.ts +2 -1
- package/package.json +2 -2
|
@@ -1,72 +1,337 @@
|
|
|
1
1
|
import { renderHook, act } from '@testing-library/react-hooks';
|
|
2
|
-
import React from 'react';
|
|
2
|
+
import * as React from 'react';
|
|
3
3
|
import { CustomDataProvider } from '../components/CustomDataProvider';
|
|
4
|
+
import { useDataEngine } from './useDataEngine';
|
|
4
5
|
import { useDataMutation } from './useDataMutation';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
6
|
+
describe('useDataMutation', () => {
|
|
7
|
+
it('should render without failing', async () => {
|
|
8
|
+
const mutation = {
|
|
9
|
+
type: 'create',
|
|
10
|
+
resource: 'answer',
|
|
11
|
+
data: {
|
|
12
|
+
answer: '?'
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const data = {
|
|
16
|
+
answer: 42
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const wrapper = ({
|
|
20
|
+
children
|
|
21
|
+
}) => /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
22
|
+
data: data
|
|
23
|
+
}, children);
|
|
24
|
+
|
|
25
|
+
const {
|
|
26
|
+
result,
|
|
27
|
+
waitFor
|
|
28
|
+
} = renderHook(() => useDataMutation(mutation), {
|
|
29
|
+
wrapper
|
|
30
|
+
});
|
|
31
|
+
const [mutate, beforeMutation] = result.current;
|
|
32
|
+
expect(beforeMutation).toMatchObject({
|
|
33
|
+
loading: false,
|
|
34
|
+
called: false
|
|
35
|
+
});
|
|
36
|
+
act(() => {
|
|
37
|
+
mutate();
|
|
38
|
+
});
|
|
39
|
+
await waitFor(() => {
|
|
40
|
+
const [, duringMutation] = result.current;
|
|
41
|
+
expect(duringMutation).toMatchObject({
|
|
42
|
+
loading: true,
|
|
43
|
+
called: true
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
await waitFor(() => {
|
|
47
|
+
const [, afterMutation] = result.current;
|
|
48
|
+
expect(afterMutation).toMatchObject({
|
|
49
|
+
loading: false,
|
|
50
|
+
called: true,
|
|
51
|
+
data: 42
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
it('should run immediately with lazy: false', async () => {
|
|
56
|
+
const mutation = {
|
|
57
|
+
type: 'create',
|
|
58
|
+
resource: 'answer',
|
|
59
|
+
data: {
|
|
60
|
+
answer: '?'
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const data = {
|
|
64
|
+
answer: 42
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const wrapper = ({
|
|
68
|
+
children
|
|
69
|
+
}) => /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
70
|
+
data: data
|
|
71
|
+
}, children);
|
|
72
|
+
|
|
73
|
+
const {
|
|
74
|
+
result,
|
|
75
|
+
waitFor
|
|
76
|
+
} = renderHook(() => useDataMutation(mutation, {
|
|
77
|
+
lazy: false
|
|
78
|
+
}), {
|
|
79
|
+
wrapper
|
|
80
|
+
});
|
|
81
|
+
const [, duringMutation] = result.current;
|
|
82
|
+
expect(duringMutation).toMatchObject({
|
|
83
|
+
loading: true,
|
|
84
|
+
called: true
|
|
85
|
+
});
|
|
86
|
+
await waitFor(() => {
|
|
87
|
+
const [, afterMutation] = result.current;
|
|
88
|
+
expect(afterMutation).toMatchObject({
|
|
89
|
+
loading: false,
|
|
90
|
+
called: true,
|
|
91
|
+
data: 42
|
|
92
|
+
});
|
|
93
|
+
});
|
|
26
94
|
});
|
|
27
|
-
it('
|
|
28
|
-
|
|
29
|
-
|
|
95
|
+
it('should call onComplete on success', async () => {
|
|
96
|
+
const onComplete = jest.fn();
|
|
97
|
+
const mutation = {
|
|
98
|
+
type: 'create',
|
|
99
|
+
resource: 'answer',
|
|
100
|
+
data: {
|
|
101
|
+
answer: '?'
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
const data = {
|
|
105
|
+
answer: 42
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const wrapper = ({
|
|
109
|
+
children
|
|
110
|
+
}) => /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
111
|
+
data: data
|
|
112
|
+
}, children);
|
|
113
|
+
|
|
114
|
+
const {
|
|
115
|
+
result,
|
|
116
|
+
waitFor
|
|
117
|
+
} = renderHook(() => useDataMutation(mutation, {
|
|
118
|
+
onComplete
|
|
119
|
+
}), {
|
|
120
|
+
wrapper
|
|
121
|
+
});
|
|
122
|
+
expect(onComplete).toHaveBeenCalledTimes(0);
|
|
123
|
+
const [mutate] = result.current;
|
|
30
124
|
act(() => {
|
|
31
|
-
|
|
32
|
-
|
|
125
|
+
mutate();
|
|
126
|
+
});
|
|
127
|
+
await waitFor(() => {
|
|
128
|
+
const [, state] = result.current;
|
|
129
|
+
expect(state).toMatchObject({
|
|
130
|
+
loading: false,
|
|
131
|
+
called: true,
|
|
132
|
+
data: 42
|
|
33
133
|
});
|
|
134
|
+
expect(onComplete).toHaveBeenCalledTimes(1);
|
|
135
|
+
expect(onComplete).toHaveBeenLastCalledWith(42);
|
|
34
136
|
});
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
137
|
+
});
|
|
138
|
+
it('should call onError on error', async () => {
|
|
139
|
+
const error = new Error('Something went wrong');
|
|
140
|
+
const onError = jest.fn();
|
|
141
|
+
const mutation = {
|
|
142
|
+
type: 'create',
|
|
143
|
+
resource: 'answer',
|
|
144
|
+
data: {
|
|
145
|
+
answer: 42
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
const data = {
|
|
149
|
+
answer: () => {
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const wrapper = ({
|
|
155
|
+
children
|
|
156
|
+
}) => /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
157
|
+
data: data
|
|
158
|
+
}, children);
|
|
159
|
+
|
|
160
|
+
const {
|
|
161
|
+
result,
|
|
162
|
+
waitFor
|
|
163
|
+
} = renderHook(() => useDataMutation(mutation, {
|
|
164
|
+
onError
|
|
165
|
+
}), {
|
|
166
|
+
wrapper
|
|
39
167
|
});
|
|
168
|
+
expect(onError).toHaveBeenCalledTimes(0);
|
|
169
|
+
const [mutate] = result.current;
|
|
40
170
|
act(() => {
|
|
41
171
|
mutate();
|
|
42
172
|
});
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
173
|
+
await waitFor(() => {
|
|
174
|
+
const [, state] = result.current;
|
|
175
|
+
expect(state).toMatchObject({
|
|
176
|
+
loading: false,
|
|
177
|
+
called: true,
|
|
178
|
+
error
|
|
179
|
+
});
|
|
48
180
|
});
|
|
181
|
+
expect(onError).toHaveBeenCalledTimes(1);
|
|
182
|
+
expect(onError).toHaveBeenLastCalledWith(error);
|
|
49
183
|
});
|
|
50
|
-
it('
|
|
51
|
-
|
|
52
|
-
|
|
184
|
+
it('should resolve variables', async () => {
|
|
185
|
+
const mutation = {
|
|
186
|
+
type: 'update',
|
|
187
|
+
resource: 'answer',
|
|
188
|
+
id: ({
|
|
189
|
+
id
|
|
190
|
+
}) => id,
|
|
191
|
+
data: {
|
|
192
|
+
answer: '?'
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
const answerSpy = jest.fn(() => 42);
|
|
196
|
+
const data = {
|
|
197
|
+
answer: answerSpy
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
const wrapper = ({
|
|
201
|
+
children
|
|
202
|
+
}) => /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
203
|
+
data: data
|
|
204
|
+
}, children);
|
|
205
|
+
|
|
206
|
+
const {
|
|
207
|
+
result,
|
|
208
|
+
waitFor
|
|
209
|
+
} = renderHook(() => useDataMutation(mutation, {
|
|
210
|
+
lazy: false,
|
|
211
|
+
variables: {
|
|
212
|
+
id: '1'
|
|
213
|
+
}
|
|
214
|
+
}), {
|
|
215
|
+
wrapper
|
|
216
|
+
});
|
|
217
|
+
await waitFor(() => {
|
|
218
|
+
expect(answerSpy).toHaveBeenLastCalledWith(expect.any(String), expect.objectContaining({
|
|
219
|
+
id: '1'
|
|
220
|
+
}), expect.any(Object));
|
|
221
|
+
});
|
|
222
|
+
const [mutate] = result.current;
|
|
53
223
|
act(() => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}), {
|
|
57
|
-
wrapper
|
|
224
|
+
mutate({
|
|
225
|
+
id: '2'
|
|
58
226
|
});
|
|
59
227
|
});
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
228
|
+
await waitFor(() => {
|
|
229
|
+
expect(answerSpy).toHaveBeenLastCalledWith(expect.any(String), expect.objectContaining({
|
|
230
|
+
id: '2'
|
|
231
|
+
}), expect.any(Object));
|
|
64
232
|
});
|
|
65
|
-
|
|
66
|
-
|
|
233
|
+
});
|
|
234
|
+
it('should return a reference to the engine', async () => {
|
|
235
|
+
const mutation = {
|
|
236
|
+
type: 'create',
|
|
237
|
+
resource: 'answer',
|
|
238
|
+
data: {
|
|
239
|
+
answer: '?'
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
const wrapper = ({
|
|
244
|
+
children
|
|
245
|
+
}) => /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
246
|
+
data: {}
|
|
247
|
+
}, children);
|
|
248
|
+
|
|
249
|
+
const engineHook = renderHook(() => useDataEngine(), {
|
|
250
|
+
wrapper
|
|
251
|
+
});
|
|
252
|
+
const mutationHook = renderHook(() => useDataMutation(mutation), {
|
|
253
|
+
wrapper
|
|
254
|
+
});
|
|
255
|
+
/**
|
|
256
|
+
* Ideally we'd check referential equality here with .toBe, but since
|
|
257
|
+
* both hooks run in a different context that doesn't work.
|
|
258
|
+
*/
|
|
259
|
+
|
|
260
|
+
expect(mutationHook.result.current[1].engine).toStrictEqual(engineHook.result.current);
|
|
261
|
+
});
|
|
262
|
+
it('should return a stable mutate function', async () => {
|
|
263
|
+
const mutation = {
|
|
264
|
+
type: 'create',
|
|
265
|
+
resource: 'answer',
|
|
266
|
+
data: {
|
|
267
|
+
answer: '?'
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
const data = {
|
|
271
|
+
answer: 42
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const wrapper = ({
|
|
275
|
+
children
|
|
276
|
+
}) => /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
277
|
+
data: data
|
|
278
|
+
}, children);
|
|
279
|
+
|
|
280
|
+
const {
|
|
281
|
+
result
|
|
282
|
+
} = renderHook(() => useDataMutation(mutation), {
|
|
283
|
+
wrapper
|
|
284
|
+
});
|
|
285
|
+
const [firstMutate] = result.current;
|
|
286
|
+
await act(async () => {
|
|
287
|
+
await firstMutate({
|
|
288
|
+
variable: 'variable'
|
|
289
|
+
});
|
|
290
|
+
});
|
|
291
|
+
const [secondMutate, state] = result.current;
|
|
67
292
|
expect(state).toMatchObject({
|
|
68
293
|
loading: false,
|
|
69
|
-
|
|
294
|
+
called: true
|
|
295
|
+
});
|
|
296
|
+
expect(firstMutate).toBe(secondMutate);
|
|
297
|
+
});
|
|
298
|
+
it('should resolve with the data from mutate on success', async () => {
|
|
299
|
+
const mutation = {
|
|
300
|
+
type: 'create',
|
|
301
|
+
resource: 'answer',
|
|
302
|
+
data: {
|
|
303
|
+
answer: '?'
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
const data = {
|
|
307
|
+
answer: 42
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
const wrapper = ({
|
|
311
|
+
children
|
|
312
|
+
}) => /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
313
|
+
data: data
|
|
314
|
+
}, children);
|
|
315
|
+
|
|
316
|
+
const {
|
|
317
|
+
result,
|
|
318
|
+
waitFor
|
|
319
|
+
} = renderHook(() => useDataMutation(mutation), {
|
|
320
|
+
wrapper
|
|
321
|
+
});
|
|
322
|
+
let mutatePromise;
|
|
323
|
+
const [mutate] = result.current;
|
|
324
|
+
act(() => {
|
|
325
|
+
mutatePromise = mutate();
|
|
326
|
+
});
|
|
327
|
+
await waitFor(() => {
|
|
328
|
+
const [, state] = result.current;
|
|
329
|
+
expect(state).toMatchObject({
|
|
330
|
+
loading: false,
|
|
331
|
+
called: true,
|
|
332
|
+
data: 42
|
|
333
|
+
});
|
|
334
|
+
expect(mutatePromise).resolves.toBe(42);
|
|
70
335
|
});
|
|
71
336
|
});
|
|
72
337
|
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useRef } from 'react';
|
|
1
|
+
import { useState, useRef, useCallback } from 'react';
|
|
2
2
|
import { useQuery, setLogger } from 'react-query';
|
|
3
3
|
import { stableVariablesHash } from './stableVariablesHash';
|
|
4
4
|
import { useDataEngine } from './useDataEngine';
|
|
@@ -84,9 +84,13 @@ export const useDataQuery = (query, {
|
|
|
84
84
|
/**
|
|
85
85
|
* Refetch allows a user to update the variables or just
|
|
86
86
|
* trigger a refetch of the query with the current variables.
|
|
87
|
+
*
|
|
88
|
+
* We're using useCallback to make the identity of the function
|
|
89
|
+
* as stable as possible, so that it won't trigger excessive
|
|
90
|
+
* rerenders when used for side-effects.
|
|
87
91
|
*/
|
|
88
92
|
|
|
89
|
-
const refetch = newVariables => {
|
|
93
|
+
const refetch = useCallback(newVariables => {
|
|
90
94
|
/**
|
|
91
95
|
* If there are no updates that will trigger an automatic refetch
|
|
92
96
|
* we'll need to call react-query's refetch directly
|
|
@@ -100,10 +104,6 @@ export const useDataQuery = (query, {
|
|
|
100
104
|
}) => data);
|
|
101
105
|
}
|
|
102
106
|
|
|
103
|
-
if (!enabled) {
|
|
104
|
-
setEnabled(true);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
107
|
if (newVariables) {
|
|
108
108
|
// Use cached hash if it exists
|
|
109
109
|
const currentHash = variablesHash.current || stableVariablesHash(variables);
|
|
@@ -113,8 +113,11 @@ export const useDataQuery = (query, {
|
|
|
113
113
|
const mergedHash = stableVariablesHash(mergedVariables);
|
|
114
114
|
const identical = currentHash === mergedHash;
|
|
115
115
|
|
|
116
|
-
if (identical) {
|
|
117
|
-
|
|
116
|
+
if (identical && enabled) {
|
|
117
|
+
/**
|
|
118
|
+
* If the variables are identical and the query is enabled
|
|
119
|
+
* we'll need to trigger the refetch manually
|
|
120
|
+
*/
|
|
118
121
|
return queryRefetch({
|
|
119
122
|
cancelRefetch: true,
|
|
120
123
|
throwOnError: false
|
|
@@ -125,6 +128,11 @@ export const useDataQuery = (query, {
|
|
|
125
128
|
variablesHash.current = mergedHash;
|
|
126
129
|
setVariables(mergedVariables);
|
|
127
130
|
}
|
|
131
|
+
} // Enable the query after the variables have been set to prevent extra request
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
if (!enabled) {
|
|
135
|
+
setEnabled(true);
|
|
128
136
|
} // This promise does not currently reject on errors
|
|
129
137
|
|
|
130
138
|
|
|
@@ -133,13 +141,12 @@ export const useDataQuery = (query, {
|
|
|
133
141
|
resolve(data);
|
|
134
142
|
};
|
|
135
143
|
});
|
|
136
|
-
};
|
|
144
|
+
}, [enabled, queryRefetch, variables]);
|
|
137
145
|
/**
|
|
138
146
|
* react-query returns null or an error, but we return undefined
|
|
139
147
|
* or an error, so this ensures consistency with the other types.
|
|
140
148
|
*/
|
|
141
149
|
|
|
142
|
-
|
|
143
150
|
const ourError = error || undefined;
|
|
144
151
|
return {
|
|
145
152
|
engine,
|
|
@@ -497,6 +497,149 @@ describe('useDataQuery', () => {
|
|
|
497
497
|
});
|
|
498
498
|
});
|
|
499
499
|
describe('return values: refetch', () => {
|
|
500
|
+
it('Should only trigger a single request when refetch is called on a lazy query with new variables', async () => {
|
|
501
|
+
const spy = jest.fn((type, query) => {
|
|
502
|
+
if (query.id === '1') {
|
|
503
|
+
return 42;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
return 0;
|
|
507
|
+
});
|
|
508
|
+
const data = {
|
|
509
|
+
answer: spy
|
|
510
|
+
};
|
|
511
|
+
const query = {
|
|
512
|
+
x: {
|
|
513
|
+
resource: 'answer',
|
|
514
|
+
id: ({
|
|
515
|
+
id
|
|
516
|
+
}) => id
|
|
517
|
+
}
|
|
518
|
+
};
|
|
519
|
+
|
|
520
|
+
const wrapper = ({
|
|
521
|
+
children
|
|
522
|
+
}) => /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
523
|
+
data: data
|
|
524
|
+
}, children);
|
|
525
|
+
|
|
526
|
+
const {
|
|
527
|
+
result,
|
|
528
|
+
waitFor
|
|
529
|
+
} = renderHook(() => useDataQuery(query, {
|
|
530
|
+
lazy: true
|
|
531
|
+
}), {
|
|
532
|
+
wrapper
|
|
533
|
+
});
|
|
534
|
+
expect(spy).not.toHaveBeenCalled();
|
|
535
|
+
act(() => {
|
|
536
|
+
result.current.refetch({
|
|
537
|
+
id: '1'
|
|
538
|
+
});
|
|
539
|
+
});
|
|
540
|
+
await waitFor(() => {
|
|
541
|
+
expect(result.current).toMatchObject({
|
|
542
|
+
loading: false,
|
|
543
|
+
called: true,
|
|
544
|
+
data: {
|
|
545
|
+
x: 42
|
|
546
|
+
}
|
|
547
|
+
});
|
|
548
|
+
});
|
|
549
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
550
|
+
});
|
|
551
|
+
it('Should only trigger a single request when refetch is called on a lazy query with identical variables', async () => {
|
|
552
|
+
const spy = jest.fn((type, query) => {
|
|
553
|
+
if (query.id === '1') {
|
|
554
|
+
return 42;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
return 0;
|
|
558
|
+
});
|
|
559
|
+
const data = {
|
|
560
|
+
answer: spy
|
|
561
|
+
};
|
|
562
|
+
const query = {
|
|
563
|
+
x: {
|
|
564
|
+
resource: 'answer',
|
|
565
|
+
id: ({
|
|
566
|
+
id
|
|
567
|
+
}) => id
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
|
|
571
|
+
const wrapper = ({
|
|
572
|
+
children
|
|
573
|
+
}) => /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
574
|
+
data: data
|
|
575
|
+
}, children);
|
|
576
|
+
|
|
577
|
+
const {
|
|
578
|
+
result,
|
|
579
|
+
waitFor
|
|
580
|
+
} = renderHook(() => useDataQuery(query, {
|
|
581
|
+
lazy: true,
|
|
582
|
+
variables: {
|
|
583
|
+
id: '1'
|
|
584
|
+
}
|
|
585
|
+
}), {
|
|
586
|
+
wrapper
|
|
587
|
+
});
|
|
588
|
+
expect(spy).not.toHaveBeenCalled();
|
|
589
|
+
act(() => {
|
|
590
|
+
result.current.refetch({
|
|
591
|
+
id: '1'
|
|
592
|
+
});
|
|
593
|
+
});
|
|
594
|
+
await waitFor(() => {
|
|
595
|
+
expect(result.current).toMatchObject({
|
|
596
|
+
loading: false,
|
|
597
|
+
called: true,
|
|
598
|
+
data: {
|
|
599
|
+
x: 42
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
});
|
|
603
|
+
expect(spy).toHaveBeenCalledTimes(1);
|
|
604
|
+
});
|
|
605
|
+
it('Should have a stable identity if the variables have not changed', async () => {
|
|
606
|
+
const data = {
|
|
607
|
+
answer: () => 42
|
|
608
|
+
};
|
|
609
|
+
const query = {
|
|
610
|
+
x: {
|
|
611
|
+
resource: 'answer'
|
|
612
|
+
}
|
|
613
|
+
};
|
|
614
|
+
|
|
615
|
+
const wrapper = ({
|
|
616
|
+
children
|
|
617
|
+
}) => /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
618
|
+
data: data
|
|
619
|
+
}, children);
|
|
620
|
+
|
|
621
|
+
const {
|
|
622
|
+
result,
|
|
623
|
+
waitForNextUpdate,
|
|
624
|
+
rerender
|
|
625
|
+
} = renderHook(() => useDataQuery(query), {
|
|
626
|
+
wrapper
|
|
627
|
+
});
|
|
628
|
+
const firstRefetch = result.current.refetch;
|
|
629
|
+
await waitForNextUpdate();
|
|
630
|
+
act(() => {
|
|
631
|
+
result.current.refetch();
|
|
632
|
+
/**
|
|
633
|
+
* FIXME: https://github.com/tannerlinsley/react-query/issues/2481
|
|
634
|
+
* This forced rerender is not necessary in the app, just when testing.
|
|
635
|
+
* It is unclear why.
|
|
636
|
+
*/
|
|
637
|
+
|
|
638
|
+
rerender();
|
|
639
|
+
});
|
|
640
|
+
await waitForNextUpdate();
|
|
641
|
+
expect(result.current.refetch).toBe(firstRefetch);
|
|
642
|
+
});
|
|
500
643
|
it('Should return stale data and set loading to true on refetch', async () => {
|
|
501
644
|
const answers = [42, 43];
|
|
502
645
|
const mockSpy = jest.fn(() => Promise.resolve(answers.shift()));
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ResolvedResourceQuery, FetchType } from '../../../engine';
|
|
2
2
|
export declare const isReplyToMessageConversation: (type: FetchType, { resource }: ResolvedResourceQuery) => boolean;
|
|
3
3
|
export declare const isCreateFeedbackMessage: (type: FetchType, { resource }: ResolvedResourceQuery) => boolean;
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const isCreateInterpretation: (type: FetchType, { resource }: ResolvedResourceQuery) => boolean;
|
|
5
|
+
export declare const isUpdateInterpretation: (type: FetchType, { resource, id }: ResolvedResourceQuery) => boolean;
|
|
5
6
|
export declare const isCommentOnInterpretation: (type: FetchType, { resource }: ResolvedResourceQuery) => boolean;
|
|
6
7
|
export declare const isInterpretationCommentUpdate: (type: FetchType, { resource, id }: ResolvedResourceQuery) => boolean;
|
|
7
8
|
export declare const isAddOrUpdateSystemOrUserSetting: (type: FetchType, { resource }: ResolvedResourceQuery) => boolean;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dhis2/app-service-data",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.8",
|
|
4
4
|
"main": "./build/cjs/index.js",
|
|
5
5
|
"module": "./build/es/index.js",
|
|
6
6
|
"types": "build/types/index.d.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"build/**"
|
|
23
23
|
],
|
|
24
24
|
"peerDependencies": {
|
|
25
|
-
"@dhis2/app-service-config": "3.2.
|
|
25
|
+
"@dhis2/app-service-config": "3.2.8",
|
|
26
26
|
"@dhis2/cli-app-scripts": "^7.1.1",
|
|
27
27
|
"prop-types": "^15.7.2",
|
|
28
28
|
"react": "^16.8",
|