@dhis2/app-service-data 3.17.1 → 3.18.0-beta.2
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/README.md +104 -0
- package/build/cjs/react/hooks/useDataQuery.js +4 -0
- package/build/es/react/hooks/useDataQuery.js +5 -0
- package/build/types/react/hooks/useDataQuery.d.ts +6 -2
- package/package.json +5 -4
- package/.gitignore +0 -5
- package/d2.config.js +0 -9
- package/jest.config.js +0 -14
- package/src/__tests__/integration.test.tsx +0 -80
- package/src/__tests__/mutations.test.tsx +0 -71
- package/src/index.ts +0 -5
- package/src/react/components/CustomDataProvider.tsx +0 -33
- package/src/react/components/DataMutation.tsx +0 -24
- package/src/react/components/DataProvider.test.tsx +0 -22
- package/src/react/components/DataProvider.tsx +0 -58
- package/src/react/components/DataQuery.tsx +0 -26
- package/src/react/components/index.ts +0 -4
- package/src/react/context/DataContext.tsx +0 -5
- package/src/react/context/defaultDataContext.test.ts +0 -46
- package/src/react/context/defaultDataContext.ts +0 -9
- package/src/react/hooks/index.ts +0 -3
- package/src/react/hooks/mergeAndCompareVariables.test.ts +0 -65
- package/src/react/hooks/mergeAndCompareVariables.ts +0 -32
- package/src/react/hooks/stableVariablesHash.test.ts +0 -53
- package/src/react/hooks/stableVariablesHash.ts +0 -56
- package/src/react/hooks/useDataEngine.ts +0 -8
- package/src/react/hooks/useDataMutation.test.tsx +0 -296
- package/src/react/hooks/useDataMutation.ts +0 -42
- package/src/react/hooks/useDataQuery.test.tsx +0 -1029
- package/src/react/hooks/useDataQuery.ts +0 -170
- package/src/react/hooks/useQueryExecutor.test.tsx +0 -195
- package/src/react/hooks/useQueryExecutor.ts +0 -99
- package/src/react/hooks/useStaticInput.test.ts +0 -101
- package/src/react/hooks/useStaticInput.ts +0 -27
- package/src/react/index.ts +0 -2
- package/src/setupRTL.ts +0 -5
- package/src/types.ts +0 -72
- package/tsconfig.json +0 -10
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { mergeAndCompareVariables } from './mergeAndCompareVariables'
|
|
2
|
-
import { stableVariablesHash } from './stableVariablesHash'
|
|
3
|
-
jest.mock('./stableVariablesHash', () => ({
|
|
4
|
-
stableVariablesHash: (object: unknown) => JSON.stringify(object),
|
|
5
|
-
}))
|
|
6
|
-
|
|
7
|
-
const testVariables = {
|
|
8
|
-
question: 'What do you get when you multiply six by nine?',
|
|
9
|
-
answer: 42,
|
|
10
|
-
}
|
|
11
|
-
const testHash = stableVariablesHash(testVariables)
|
|
12
|
-
|
|
13
|
-
describe('mergeAndCompareVariables', () => {
|
|
14
|
-
it('Should return previous variables and hash when no new variables are provided', () => {
|
|
15
|
-
expect(
|
|
16
|
-
mergeAndCompareVariables(testVariables, undefined, undefined)
|
|
17
|
-
).toMatchObject({
|
|
18
|
-
identical: true,
|
|
19
|
-
mergedVariables: testVariables,
|
|
20
|
-
mergedVariablesHash: undefined,
|
|
21
|
-
})
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
it('Should return identical: true when merged variables are identical to old variables (without prev hash)', () => {
|
|
25
|
-
const newVariables = { answer: testVariables.answer }
|
|
26
|
-
|
|
27
|
-
expect(
|
|
28
|
-
mergeAndCompareVariables(testVariables, newVariables, undefined)
|
|
29
|
-
).toMatchObject({
|
|
30
|
-
identical: true,
|
|
31
|
-
mergedVariables: testVariables,
|
|
32
|
-
mergedVariablesHash: testHash,
|
|
33
|
-
})
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
it('Should return identical: false with incorrect previous hash', () => {
|
|
37
|
-
const incorrectPreviousHash = 'IAmAHash'
|
|
38
|
-
const newVariables = { answer: 42 }
|
|
39
|
-
|
|
40
|
-
expect(
|
|
41
|
-
mergeAndCompareVariables(
|
|
42
|
-
testVariables,
|
|
43
|
-
newVariables,
|
|
44
|
-
incorrectPreviousHash
|
|
45
|
-
)
|
|
46
|
-
).toMatchObject({
|
|
47
|
-
identical: false,
|
|
48
|
-
mergedVariables: testVariables,
|
|
49
|
-
mergedVariablesHash: testHash,
|
|
50
|
-
})
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
it('Should return identical: false when merged variables are different than old variables', () => {
|
|
54
|
-
const newVariables = { answer: 43 }
|
|
55
|
-
const expectedMergedVariables = { ...testVariables, ...newVariables }
|
|
56
|
-
|
|
57
|
-
expect(
|
|
58
|
-
mergeAndCompareVariables(testVariables, newVariables, testHash)
|
|
59
|
-
).toMatchObject({
|
|
60
|
-
identical: false,
|
|
61
|
-
mergedVariables: expectedMergedVariables,
|
|
62
|
-
mergedVariablesHash: stableVariablesHash(expectedMergedVariables),
|
|
63
|
-
})
|
|
64
|
-
})
|
|
65
|
-
})
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { QueryVariables } from '@dhis2/data-engine'
|
|
2
|
-
import { stableVariablesHash } from './stableVariablesHash'
|
|
3
|
-
|
|
4
|
-
export const mergeAndCompareVariables = (
|
|
5
|
-
previousVariables?: QueryVariables,
|
|
6
|
-
newVariables?: QueryVariables,
|
|
7
|
-
previousHash?: string
|
|
8
|
-
) => {
|
|
9
|
-
if (!newVariables) {
|
|
10
|
-
return {
|
|
11
|
-
identical: true,
|
|
12
|
-
mergedVariablesHash: previousHash,
|
|
13
|
-
mergedVariables: previousVariables,
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Use cached hash if it exists
|
|
18
|
-
const currentHash = previousHash || stableVariablesHash(previousVariables)
|
|
19
|
-
|
|
20
|
-
const mergedVariables = {
|
|
21
|
-
...previousVariables,
|
|
22
|
-
...newVariables,
|
|
23
|
-
}
|
|
24
|
-
const mergedVariablesHash = stableVariablesHash(mergedVariables)
|
|
25
|
-
const identical = currentHash === mergedVariablesHash
|
|
26
|
-
|
|
27
|
-
return {
|
|
28
|
-
identical,
|
|
29
|
-
mergedVariablesHash,
|
|
30
|
-
mergedVariables,
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import { stableVariablesHash } from './stableVariablesHash'
|
|
2
|
-
|
|
3
|
-
describe('stableVariablesHash', () => {
|
|
4
|
-
it('sorts objects before hashing', () => {
|
|
5
|
-
const one = {
|
|
6
|
-
a: {
|
|
7
|
-
one: 1,
|
|
8
|
-
two: 2,
|
|
9
|
-
three: 3,
|
|
10
|
-
},
|
|
11
|
-
b: [1, 2, 3],
|
|
12
|
-
c: 'c',
|
|
13
|
-
}
|
|
14
|
-
const two = {
|
|
15
|
-
c: 'c',
|
|
16
|
-
b: [1, 2, 3],
|
|
17
|
-
a: {
|
|
18
|
-
three: 3,
|
|
19
|
-
two: 2,
|
|
20
|
-
one: 1,
|
|
21
|
-
},
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
expect(stableVariablesHash(one)).toEqual(stableVariablesHash(two))
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
it('can handle primitives', () => {
|
|
28
|
-
const one = undefined
|
|
29
|
-
const two = 'string'
|
|
30
|
-
const three = 3
|
|
31
|
-
const four = null
|
|
32
|
-
const five = true
|
|
33
|
-
|
|
34
|
-
expect(stableVariablesHash(one)).toMatchInlineSnapshot(`undefined`)
|
|
35
|
-
expect(stableVariablesHash(two)).toMatchInlineSnapshot(`"\\"string\\""`)
|
|
36
|
-
expect(stableVariablesHash(three)).toMatchInlineSnapshot(`"3"`)
|
|
37
|
-
expect(stableVariablesHash(four)).toMatchInlineSnapshot(`"null"`)
|
|
38
|
-
expect(stableVariablesHash(five)).toMatchInlineSnapshot(`"true"`)
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
it('throws a clear error when the variables contain a circular reference', () => {
|
|
42
|
-
const unserializable: any = {
|
|
43
|
-
value: 'value',
|
|
44
|
-
}
|
|
45
|
-
unserializable.circular = unserializable
|
|
46
|
-
|
|
47
|
-
expect(() =>
|
|
48
|
-
stableVariablesHash(unserializable)
|
|
49
|
-
).toThrowErrorMatchingInlineSnapshot(
|
|
50
|
-
`"Could not serialize variables. Make sure that the variables do not contain circular references and can be processed by JSON.stringify."`
|
|
51
|
-
)
|
|
52
|
-
})
|
|
53
|
-
})
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
function hasObjectPrototype(o: any): boolean {
|
|
2
|
-
return Object.prototype.toString.call(o) === '[object Object]'
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
export function isPlainObject(o: any): o is object {
|
|
6
|
-
if (!hasObjectPrototype(o)) {
|
|
7
|
-
return false
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
// If has modified constructor
|
|
11
|
-
const ctor = o.constructor
|
|
12
|
-
if (typeof ctor === 'undefined') {
|
|
13
|
-
return true
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// If has modified prototype
|
|
17
|
-
const prot = ctor.prototype
|
|
18
|
-
if (!hasObjectPrototype(prot)) {
|
|
19
|
-
return false
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// If constructor does not have an Object-specific method
|
|
23
|
-
if (!Object.prototype.hasOwnProperty.call(prot, 'isPrototypeOf')) {
|
|
24
|
-
return false
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// Most likely a plain Object
|
|
28
|
-
return true
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Hashes the value into a stable hash.
|
|
33
|
-
*/
|
|
34
|
-
|
|
35
|
-
export function stableVariablesHash(value: any): string {
|
|
36
|
-
let hash
|
|
37
|
-
|
|
38
|
-
try {
|
|
39
|
-
hash = JSON.stringify(value, (_, val) =>
|
|
40
|
-
isPlainObject(val)
|
|
41
|
-
? Object.keys(val)
|
|
42
|
-
.sort()
|
|
43
|
-
.reduce((result: Record<string, unknown>, key) => {
|
|
44
|
-
result[key] = (val as Record<string, unknown>)[key]
|
|
45
|
-
return result
|
|
46
|
-
}, {})
|
|
47
|
-
: val
|
|
48
|
-
)
|
|
49
|
-
} catch (e) {
|
|
50
|
-
throw new Error(
|
|
51
|
-
'Could not serialize variables. Make sure that the variables do not contain circular references and can be processed by JSON.stringify.'
|
|
52
|
-
)
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return hash
|
|
56
|
-
}
|
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
CreateMutation,
|
|
3
|
-
UpdateMutation,
|
|
4
|
-
QueryVariables,
|
|
5
|
-
} from '@dhis2/data-engine'
|
|
6
|
-
import { renderHook, act, waitFor } from '@testing-library/react'
|
|
7
|
-
import * as React from 'react'
|
|
8
|
-
import { CustomDataProvider } from '../components/CustomDataProvider'
|
|
9
|
-
import { useDataEngine } from './useDataEngine'
|
|
10
|
-
import { useDataMutation } from './useDataMutation'
|
|
11
|
-
|
|
12
|
-
describe('useDataMutation', () => {
|
|
13
|
-
it('should render without failing', async () => {
|
|
14
|
-
const mutation: CreateMutation = {
|
|
15
|
-
type: 'create',
|
|
16
|
-
resource: 'answer',
|
|
17
|
-
data: { answer: '?' },
|
|
18
|
-
}
|
|
19
|
-
const data = { answer: 42 }
|
|
20
|
-
const wrapper = ({ children }: { children?: React.ReactNode }) => (
|
|
21
|
-
<CustomDataProvider data={data}>{children}</CustomDataProvider>
|
|
22
|
-
)
|
|
23
|
-
|
|
24
|
-
const { result } = renderHook(() => useDataMutation(mutation), {
|
|
25
|
-
wrapper,
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
const [mutate, beforeMutation] = result.current
|
|
29
|
-
expect(beforeMutation).toMatchObject({
|
|
30
|
-
loading: false,
|
|
31
|
-
called: false,
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
act(() => {
|
|
35
|
-
mutate()
|
|
36
|
-
})
|
|
37
|
-
|
|
38
|
-
await waitFor(() => {
|
|
39
|
-
const [, duringMutation] = result.current
|
|
40
|
-
expect(duringMutation).toMatchObject({
|
|
41
|
-
loading: true,
|
|
42
|
-
called: true,
|
|
43
|
-
})
|
|
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
|
-
|
|
56
|
-
it('should run immediately with lazy: false', async () => {
|
|
57
|
-
const mutation: CreateMutation = {
|
|
58
|
-
type: 'create',
|
|
59
|
-
resource: 'answer',
|
|
60
|
-
data: { answer: '?' },
|
|
61
|
-
}
|
|
62
|
-
const data = { answer: 42 }
|
|
63
|
-
const wrapper = ({ children }: { children?: React.ReactNode }) => (
|
|
64
|
-
<CustomDataProvider data={data}>{children}</CustomDataProvider>
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
const { result } = renderHook(
|
|
68
|
-
() => useDataMutation(mutation, { lazy: false }),
|
|
69
|
-
{ wrapper }
|
|
70
|
-
)
|
|
71
|
-
|
|
72
|
-
const [, duringMutation] = result.current
|
|
73
|
-
expect(duringMutation).toMatchObject({
|
|
74
|
-
loading: true,
|
|
75
|
-
called: true,
|
|
76
|
-
})
|
|
77
|
-
|
|
78
|
-
await waitFor(() => {
|
|
79
|
-
const [, afterMutation] = result.current
|
|
80
|
-
expect(afterMutation).toMatchObject({
|
|
81
|
-
loading: false,
|
|
82
|
-
called: true,
|
|
83
|
-
data: 42,
|
|
84
|
-
})
|
|
85
|
-
})
|
|
86
|
-
})
|
|
87
|
-
|
|
88
|
-
it('should call onComplete on success', async () => {
|
|
89
|
-
const onComplete = jest.fn()
|
|
90
|
-
const mutation: CreateMutation = {
|
|
91
|
-
type: 'create',
|
|
92
|
-
resource: 'answer',
|
|
93
|
-
data: { answer: '?' },
|
|
94
|
-
}
|
|
95
|
-
const data = { answer: 42 }
|
|
96
|
-
const wrapper = ({ children }: { children?: React.ReactNode }) => (
|
|
97
|
-
<CustomDataProvider data={data}>{children}</CustomDataProvider>
|
|
98
|
-
)
|
|
99
|
-
|
|
100
|
-
const { result } = renderHook(
|
|
101
|
-
() => useDataMutation(mutation, { onComplete }),
|
|
102
|
-
{ wrapper }
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
expect(onComplete).toHaveBeenCalledTimes(0)
|
|
106
|
-
const [mutate] = result.current
|
|
107
|
-
act(() => {
|
|
108
|
-
mutate()
|
|
109
|
-
})
|
|
110
|
-
|
|
111
|
-
await waitFor(() => {
|
|
112
|
-
const [, state] = result.current
|
|
113
|
-
expect(state).toMatchObject({
|
|
114
|
-
loading: false,
|
|
115
|
-
called: true,
|
|
116
|
-
data: 42,
|
|
117
|
-
})
|
|
118
|
-
expect(onComplete).toHaveBeenCalledTimes(1)
|
|
119
|
-
expect(onComplete).toHaveBeenLastCalledWith(42)
|
|
120
|
-
})
|
|
121
|
-
})
|
|
122
|
-
|
|
123
|
-
it('should call onError on error', async () => {
|
|
124
|
-
const error = new Error('Something went wrong')
|
|
125
|
-
const onError = jest.fn()
|
|
126
|
-
const mutation: CreateMutation = {
|
|
127
|
-
type: 'create',
|
|
128
|
-
resource: 'answer',
|
|
129
|
-
data: { answer: 42 },
|
|
130
|
-
}
|
|
131
|
-
const data = {
|
|
132
|
-
answer: () => {
|
|
133
|
-
throw error
|
|
134
|
-
},
|
|
135
|
-
}
|
|
136
|
-
const wrapper = ({ children }: { children?: React.ReactNode }) => (
|
|
137
|
-
<CustomDataProvider data={data}>{children}</CustomDataProvider>
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
const { result } = renderHook(
|
|
141
|
-
() => useDataMutation(mutation, { onError }),
|
|
142
|
-
{ wrapper }
|
|
143
|
-
)
|
|
144
|
-
|
|
145
|
-
expect(onError).toHaveBeenCalledTimes(0)
|
|
146
|
-
const [mutate] = result.current
|
|
147
|
-
|
|
148
|
-
act(() => {
|
|
149
|
-
mutate()
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
await waitFor(() => {
|
|
153
|
-
const [, state] = result.current
|
|
154
|
-
expect(state).toMatchObject({
|
|
155
|
-
loading: false,
|
|
156
|
-
called: true,
|
|
157
|
-
error,
|
|
158
|
-
})
|
|
159
|
-
})
|
|
160
|
-
expect(onError).toHaveBeenCalledTimes(1)
|
|
161
|
-
expect(onError).toHaveBeenLastCalledWith(error)
|
|
162
|
-
})
|
|
163
|
-
|
|
164
|
-
it('should resolve variables', async () => {
|
|
165
|
-
const mutation = {
|
|
166
|
-
type: 'update',
|
|
167
|
-
resource: 'answer',
|
|
168
|
-
id: ({ id }: QueryVariables) => id as string,
|
|
169
|
-
data: { answer: '?' },
|
|
170
|
-
} as unknown as UpdateMutation
|
|
171
|
-
const answerSpy = jest.fn(() => Promise.resolve(42))
|
|
172
|
-
const data = { answer: answerSpy }
|
|
173
|
-
const wrapper = ({ children }: { children?: React.ReactNode }) => (
|
|
174
|
-
<CustomDataProvider data={data}>{children}</CustomDataProvider>
|
|
175
|
-
)
|
|
176
|
-
|
|
177
|
-
const { result } = renderHook(
|
|
178
|
-
() =>
|
|
179
|
-
useDataMutation(mutation, {
|
|
180
|
-
lazy: false,
|
|
181
|
-
variables: { id: '1' },
|
|
182
|
-
}),
|
|
183
|
-
{ wrapper }
|
|
184
|
-
)
|
|
185
|
-
|
|
186
|
-
await waitFor(() => {
|
|
187
|
-
expect(answerSpy).toHaveBeenLastCalledWith(
|
|
188
|
-
expect.any(String),
|
|
189
|
-
expect.objectContaining({
|
|
190
|
-
id: '1',
|
|
191
|
-
}),
|
|
192
|
-
expect.any(Object)
|
|
193
|
-
)
|
|
194
|
-
})
|
|
195
|
-
|
|
196
|
-
const [mutate] = result.current
|
|
197
|
-
act(() => {
|
|
198
|
-
mutate({ id: '2' })
|
|
199
|
-
})
|
|
200
|
-
|
|
201
|
-
await waitFor(() => {
|
|
202
|
-
expect(answerSpy).toHaveBeenLastCalledWith(
|
|
203
|
-
expect.any(String),
|
|
204
|
-
expect.objectContaining({
|
|
205
|
-
id: '2',
|
|
206
|
-
}),
|
|
207
|
-
expect.any(Object)
|
|
208
|
-
)
|
|
209
|
-
})
|
|
210
|
-
})
|
|
211
|
-
|
|
212
|
-
it('should return a reference to the engine', async () => {
|
|
213
|
-
const mutation: CreateMutation = {
|
|
214
|
-
type: 'create',
|
|
215
|
-
resource: 'answer',
|
|
216
|
-
data: { answer: '?' },
|
|
217
|
-
}
|
|
218
|
-
const wrapper = ({ children }: { children?: React.ReactNode }) => (
|
|
219
|
-
<CustomDataProvider data={{}}>{children}</CustomDataProvider>
|
|
220
|
-
)
|
|
221
|
-
|
|
222
|
-
const engineHook = renderHook(() => useDataEngine(), { wrapper })
|
|
223
|
-
const mutationHook = renderHook(() => useDataMutation(mutation), {
|
|
224
|
-
wrapper,
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
/**
|
|
228
|
-
* Ideally we'd check referential equality here with .toBe, but since
|
|
229
|
-
* both hooks run in a different context that doesn't work.
|
|
230
|
-
*/
|
|
231
|
-
expect(mutationHook.result.current[1].engine).toStrictEqual(
|
|
232
|
-
engineHook.result.current
|
|
233
|
-
)
|
|
234
|
-
})
|
|
235
|
-
|
|
236
|
-
it('should return a stable mutate function', async () => {
|
|
237
|
-
const mutation: CreateMutation = {
|
|
238
|
-
type: 'create',
|
|
239
|
-
resource: 'answer',
|
|
240
|
-
data: { answer: '?' },
|
|
241
|
-
}
|
|
242
|
-
const data = { answer: 42 }
|
|
243
|
-
const wrapper = ({ children }: { children?: React.ReactNode }) => (
|
|
244
|
-
<CustomDataProvider data={data}>{children}</CustomDataProvider>
|
|
245
|
-
)
|
|
246
|
-
|
|
247
|
-
const { result } = renderHook(() => useDataMutation(mutation), {
|
|
248
|
-
wrapper,
|
|
249
|
-
})
|
|
250
|
-
|
|
251
|
-
const [firstMutate] = result.current
|
|
252
|
-
|
|
253
|
-
await act(async () => {
|
|
254
|
-
await firstMutate({ variable: 'variable' })
|
|
255
|
-
})
|
|
256
|
-
|
|
257
|
-
const [secondMutate, state] = result.current
|
|
258
|
-
expect(state).toMatchObject({
|
|
259
|
-
loading: false,
|
|
260
|
-
called: true,
|
|
261
|
-
})
|
|
262
|
-
expect(firstMutate).toBe(secondMutate)
|
|
263
|
-
})
|
|
264
|
-
|
|
265
|
-
it('should resolve with the data from mutate on success', async () => {
|
|
266
|
-
const mutation: CreateMutation = {
|
|
267
|
-
type: 'create',
|
|
268
|
-
resource: 'answer',
|
|
269
|
-
data: { answer: '?' },
|
|
270
|
-
}
|
|
271
|
-
const data = { answer: 42 }
|
|
272
|
-
const wrapper = ({ children }: { children?: React.ReactNode }) => (
|
|
273
|
-
<CustomDataProvider data={data}>{children}</CustomDataProvider>
|
|
274
|
-
)
|
|
275
|
-
|
|
276
|
-
const { result } = renderHook(() => useDataMutation(mutation), {
|
|
277
|
-
wrapper,
|
|
278
|
-
})
|
|
279
|
-
|
|
280
|
-
let mutatePromise!: Promise<unknown>
|
|
281
|
-
const [mutate] = result.current
|
|
282
|
-
act(() => {
|
|
283
|
-
mutatePromise = mutate()
|
|
284
|
-
})
|
|
285
|
-
|
|
286
|
-
await waitFor(() => {
|
|
287
|
-
const [, state] = result.current
|
|
288
|
-
expect(state).toMatchObject({
|
|
289
|
-
loading: false,
|
|
290
|
-
called: true,
|
|
291
|
-
data: 42,
|
|
292
|
-
})
|
|
293
|
-
expect(mutatePromise).resolves.toBe(42)
|
|
294
|
-
})
|
|
295
|
-
})
|
|
296
|
-
})
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
QueryOptions,
|
|
3
|
-
Mutation,
|
|
4
|
-
QueryExecuteOptions,
|
|
5
|
-
} from '@dhis2/data-engine'
|
|
6
|
-
import { useCallback } from 'react'
|
|
7
|
-
import { MutationRenderInput } from '../../types'
|
|
8
|
-
import { useDataEngine } from './useDataEngine'
|
|
9
|
-
import { useQueryExecutor } from './useQueryExecutor'
|
|
10
|
-
import { useStaticInput } from './useStaticInput'
|
|
11
|
-
|
|
12
|
-
const empty = {}
|
|
13
|
-
export const useDataMutation = (
|
|
14
|
-
mutation: Mutation,
|
|
15
|
-
{ onComplete, onError, variables = empty, lazy = true }: QueryOptions = {}
|
|
16
|
-
): MutationRenderInput => {
|
|
17
|
-
const engine = useDataEngine()
|
|
18
|
-
const [theMutation] = useStaticInput<Mutation>(mutation, {
|
|
19
|
-
warn: true,
|
|
20
|
-
name: 'mutation',
|
|
21
|
-
})
|
|
22
|
-
const execute = useCallback(
|
|
23
|
-
(options: QueryExecuteOptions) => engine.mutate(theMutation, options),
|
|
24
|
-
[engine, theMutation]
|
|
25
|
-
)
|
|
26
|
-
const {
|
|
27
|
-
refetch: mutate,
|
|
28
|
-
called,
|
|
29
|
-
loading,
|
|
30
|
-
error,
|
|
31
|
-
data,
|
|
32
|
-
} = useQueryExecutor({
|
|
33
|
-
execute,
|
|
34
|
-
variables,
|
|
35
|
-
singular: false,
|
|
36
|
-
immediate: !lazy,
|
|
37
|
-
onComplete,
|
|
38
|
-
onError,
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
return [mutate, { engine, called, loading, error, data }]
|
|
42
|
-
}
|