@dhis2/app-service-data 3.2.7 → 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 +1 -1
- package/build/cjs/react/hooks/useDataMutation.test.js +320 -52
- 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 +1 -1
- package/build/es/react/hooks/useDataMutation.test.js +315 -50
- package/package.json +2 -2
|
@@ -10,8 +10,8 @@ function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return
|
|
|
10
10
|
|
|
11
11
|
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
12
12
|
|
|
13
|
-
describe('
|
|
14
|
-
it('
|
|
13
|
+
describe('<DataQuery />', () => {
|
|
14
|
+
it('should render without failing', async () => {
|
|
15
15
|
const data = {
|
|
16
16
|
answer: 42
|
|
17
17
|
};
|
|
@@ -22,18 +22,8 @@ describe('Testing custom data provider and useQuery hook', () => {
|
|
|
22
22
|
data: data
|
|
23
23
|
}, children);
|
|
24
24
|
|
|
25
|
-
const renderFunction = jest.fn((
|
|
26
|
-
|
|
27
|
-
error,
|
|
28
|
-
data
|
|
29
|
-
}) => {
|
|
30
|
-
if (loading) return 'loading';
|
|
31
|
-
if (error) return /*#__PURE__*/React.createElement("div", null, "error: ", error.message);
|
|
32
|
-
return /*#__PURE__*/React.createElement("div", null, "data: ", data && data.answer);
|
|
33
|
-
});
|
|
34
|
-
const {
|
|
35
|
-
getByText
|
|
36
|
-
} = (0, _react.render)( /*#__PURE__*/React.createElement(_react3.DataQuery, {
|
|
25
|
+
const renderFunction = jest.fn(() => null);
|
|
26
|
+
(0, _react.render)( /*#__PURE__*/React.createElement(_react3.DataQuery, {
|
|
37
27
|
query: {
|
|
38
28
|
answer: {
|
|
39
29
|
resource: 'answer'
|
|
@@ -42,24 +32,21 @@ describe('Testing custom data provider and useQuery hook', () => {
|
|
|
42
32
|
}, renderFunction), {
|
|
43
33
|
wrapper
|
|
44
34
|
});
|
|
45
|
-
expect(getByText(/loading/i)).not.toBeUndefined();
|
|
46
35
|
expect(renderFunction).toHaveBeenCalledTimes(1);
|
|
47
36
|
expect(renderFunction).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
48
37
|
called: true,
|
|
49
38
|
loading: true
|
|
50
39
|
}));
|
|
51
40
|
await (0, _react.waitFor)(() => {
|
|
52
|
-
|
|
41
|
+
expect(renderFunction).toHaveBeenCalledTimes(2);
|
|
42
|
+
expect(renderFunction).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
43
|
+
called: true,
|
|
44
|
+
loading: false,
|
|
45
|
+
data
|
|
46
|
+
}));
|
|
53
47
|
});
|
|
54
|
-
expect(getByText(/data: /i)).toHaveTextContent("data: ".concat(data.answer));
|
|
55
|
-
expect(renderFunction).toHaveBeenCalledTimes(2);
|
|
56
|
-
expect(renderFunction).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
57
|
-
called: true,
|
|
58
|
-
loading: false,
|
|
59
|
-
data
|
|
60
|
-
}));
|
|
61
48
|
});
|
|
62
|
-
it('
|
|
49
|
+
it('should render an error', async () => {
|
|
63
50
|
const expectedError = new Error('Something went wrong');
|
|
64
51
|
const data = {
|
|
65
52
|
test: () => {
|
|
@@ -73,18 +60,8 @@ describe('Testing custom data provider and useQuery hook', () => {
|
|
|
73
60
|
data: data
|
|
74
61
|
}, children);
|
|
75
62
|
|
|
76
|
-
const renderFunction = jest.fn((
|
|
77
|
-
|
|
78
|
-
error,
|
|
79
|
-
data
|
|
80
|
-
}) => {
|
|
81
|
-
if (loading) return 'loading';
|
|
82
|
-
if (error) return /*#__PURE__*/React.createElement("div", null, "error: ", error.message);
|
|
83
|
-
return /*#__PURE__*/React.createElement("div", null, "data: ", data && data.test);
|
|
84
|
-
});
|
|
85
|
-
const {
|
|
86
|
-
getByText
|
|
87
|
-
} = (0, _react.render)( /*#__PURE__*/React.createElement(_react3.DataQuery, {
|
|
63
|
+
const renderFunction = jest.fn(() => null);
|
|
64
|
+
(0, _react.render)( /*#__PURE__*/React.createElement(_react3.DataQuery, {
|
|
88
65
|
query: {
|
|
89
66
|
test: {
|
|
90
67
|
resource: 'test'
|
|
@@ -93,21 +70,18 @@ describe('Testing custom data provider and useQuery hook', () => {
|
|
|
93
70
|
}, renderFunction), {
|
|
94
71
|
wrapper
|
|
95
72
|
});
|
|
96
|
-
expect(getByText(/loading/i)).not.toBeUndefined();
|
|
97
73
|
expect(renderFunction).toHaveBeenCalledTimes(1);
|
|
98
74
|
expect(renderFunction).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
99
75
|
called: true,
|
|
100
76
|
loading: true
|
|
101
77
|
}));
|
|
102
78
|
await (0, _react.waitFor)(() => {
|
|
103
|
-
|
|
79
|
+
expect(renderFunction).toHaveBeenCalledTimes(2);
|
|
80
|
+
expect(renderFunction).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
81
|
+
called: true,
|
|
82
|
+
loading: false,
|
|
83
|
+
error: expectedError
|
|
84
|
+
}));
|
|
104
85
|
});
|
|
105
|
-
expect(renderFunction).toHaveBeenCalledTimes(2);
|
|
106
|
-
expect(getByText(/error: /i)).toHaveTextContent("error: ".concat(expectedError.message));
|
|
107
|
-
expect(renderFunction).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
108
|
-
called: true,
|
|
109
|
-
loading: false,
|
|
110
|
-
error: expectedError
|
|
111
|
-
}));
|
|
112
86
|
});
|
|
113
87
|
});
|
|
@@ -2,82 +2,73 @@
|
|
|
2
2
|
|
|
3
3
|
var _react = require("@testing-library/react");
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var React = _interopRequireWildcard(require("react"));
|
|
6
6
|
|
|
7
7
|
var _react3 = require("../react");
|
|
8
8
|
|
|
9
|
-
function
|
|
9
|
+
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return Promise.resolve({
|
|
19
|
-
answer: 42
|
|
20
|
-
});
|
|
21
|
-
})
|
|
22
|
-
};
|
|
23
|
-
describe('Test mutations', () => {
|
|
24
|
-
it('Should call the mock callback', async () => {
|
|
25
|
-
let doMutation;
|
|
26
|
-
const renderFunction = jest.fn(([mutate, {
|
|
27
|
-
called,
|
|
28
|
-
loading,
|
|
29
|
-
error,
|
|
30
|
-
data
|
|
31
|
-
}]) => {
|
|
32
|
-
doMutation = mutate;
|
|
33
|
-
if (!called) return 'uncalled';
|
|
34
|
-
if (loading) return 'loading';
|
|
35
|
-
if (error) return /*#__PURE__*/_react2.default.createElement("div", null, "error: ", error.message);
|
|
36
|
-
if (data) return /*#__PURE__*/_react2.default.createElement("div", null, "data: ", data.answer);
|
|
37
|
-
});
|
|
38
|
-
const testMutation = {
|
|
39
|
-
resource: 'target',
|
|
11
|
+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
12
|
+
|
|
13
|
+
describe('<DataMutation />', () => {
|
|
14
|
+
it('should render without failing', async () => {
|
|
15
|
+
const endpointSpy = jest.fn(() => Promise.resolve(42));
|
|
16
|
+
const mutation = {
|
|
17
|
+
resource: 'answer',
|
|
40
18
|
type: 'create',
|
|
41
19
|
data: {
|
|
42
20
|
question: '?'
|
|
43
21
|
}
|
|
44
22
|
};
|
|
45
|
-
const {
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
},
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
23
|
+
const data = {
|
|
24
|
+
answer: endpointSpy
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const wrapper = ({
|
|
28
|
+
children
|
|
29
|
+
}) => /*#__PURE__*/React.createElement(_react3.CustomDataProvider, {
|
|
30
|
+
data: data
|
|
31
|
+
}, children);
|
|
32
|
+
|
|
33
|
+
const renderSpy = jest.fn(() => null);
|
|
34
|
+
(0, _react.render)( /*#__PURE__*/React.createElement(_react3.DataMutation, {
|
|
35
|
+
mutation: mutation
|
|
36
|
+
}, renderSpy), {
|
|
37
|
+
wrapper
|
|
38
|
+
});
|
|
39
|
+
expect(endpointSpy).toHaveBeenCalledTimes(0);
|
|
40
|
+
expect(renderSpy).toHaveBeenCalledTimes(1);
|
|
41
|
+
expect(renderSpy).toHaveBeenLastCalledWith([expect.any(Function), expect.objectContaining({
|
|
56
42
|
called: false,
|
|
57
43
|
loading: false,
|
|
58
44
|
engine: expect.any(Object)
|
|
59
|
-
}]);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
45
|
+
})]);
|
|
46
|
+
await (0, _react.act)(async () => {
|
|
47
|
+
const firstRenderSpyCall = renderSpy.mock.calls[0];
|
|
48
|
+
const firstRenderSpyArgument = firstRenderSpyCall[0];
|
|
49
|
+
const [mutate] = firstRenderSpyArgument;
|
|
50
|
+
await mutate();
|
|
51
|
+
});
|
|
52
|
+
(0, _react.waitFor)(() => {
|
|
53
|
+
expect(endpointSpy).toHaveBeenCalledTimes(1);
|
|
54
|
+
expect(renderSpy).toHaveBeenCalledTimes(2);
|
|
55
|
+
expect(renderSpy).toHaveBeenLastCalledWith([expect.any(Function), expect.objectContaining({
|
|
56
|
+
called: true,
|
|
57
|
+
loading: true,
|
|
58
|
+
engine: expect.any(Object)
|
|
59
|
+
})]);
|
|
60
|
+
});
|
|
61
|
+
(0, _react.waitFor)(() => {
|
|
62
|
+
expect(endpointSpy).toHaveBeenCalledTimes(1);
|
|
63
|
+
expect(renderSpy).toHaveBeenCalledTimes(3);
|
|
64
|
+
expect(renderSpy).toHaveBeenLastCalledWith([expect.any(Function), expect.objectContaining({
|
|
65
|
+
called: true,
|
|
66
|
+
loading: false,
|
|
67
|
+
data: {
|
|
68
|
+
answer: 42
|
|
69
|
+
},
|
|
70
|
+
engine: expect.any(Object)
|
|
71
|
+
})]);
|
|
63
72
|
});
|
|
64
|
-
expect(renderFunction).toHaveBeenCalledTimes(2);
|
|
65
|
-
expect(renderFunction).toHaveBeenLastCalledWith([doMutation, {
|
|
66
|
-
called: true,
|
|
67
|
-
loading: true,
|
|
68
|
-
engine: expect.any(Object)
|
|
69
|
-
}]);
|
|
70
|
-
expect(mockBackend.target).toHaveBeenCalledTimes(1);
|
|
71
|
-
await (0, _react.waitFor)(() => getByText(/data: /i));
|
|
72
|
-
expect(renderFunction).toHaveBeenCalledTimes(3);
|
|
73
|
-
expect(renderFunction).toHaveBeenLastCalledWith([doMutation, {
|
|
74
|
-
called: true,
|
|
75
|
-
loading: false,
|
|
76
|
-
data: {
|
|
77
|
-
answer: 42
|
|
78
|
-
},
|
|
79
|
-
engine: expect.any(Object)
|
|
80
|
-
}]);
|
|
81
|
-
expect(getByText(/data: /i)).toHaveTextContent("data: 42");
|
|
82
73
|
});
|
|
83
74
|
});
|
|
@@ -36,7 +36,7 @@ exports.isCreateFeedbackMessage = isCreateFeedbackMessage;
|
|
|
36
36
|
const isCreateInterpretation = (type, {
|
|
37
37
|
resource
|
|
38
38
|
}) => {
|
|
39
|
-
const pattern = /^interpretations\/(?:reportTable|chart|visualization|map|eventReport|eventChart|dataSetReport)\/[a-zA-Z0-9]{11}$/;
|
|
39
|
+
const pattern = /^interpretations\/(?:reportTable|chart|visualization|map|eventVisualization|eventReport|eventChart|dataSetReport)\/[a-zA-Z0-9]{11}$/;
|
|
40
40
|
return type === 'create' && pattern.test(resource);
|
|
41
41
|
}; // PUT to `interpretations/${id}` (update an interpretation)
|
|
42
42
|
|
|
@@ -2,79 +2,347 @@
|
|
|
2
2
|
|
|
3
3
|
var _reactHooks = require("@testing-library/react-hooks");
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var React = _interopRequireWildcard(require("react"));
|
|
6
6
|
|
|
7
7
|
var _CustomDataProvider = require("../components/CustomDataProvider");
|
|
8
8
|
|
|
9
|
+
var _useDataEngine = require("./useDataEngine");
|
|
10
|
+
|
|
9
11
|
var _useDataMutation = require("./useDataMutation");
|
|
10
12
|
|
|
11
|
-
function
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
13
|
+
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
14
|
+
|
|
15
|
+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
16
|
+
|
|
17
|
+
describe('useDataMutation', () => {
|
|
18
|
+
it('should render without failing', async () => {
|
|
19
|
+
const mutation = {
|
|
20
|
+
type: 'create',
|
|
21
|
+
resource: 'answer',
|
|
22
|
+
data: {
|
|
23
|
+
answer: '?'
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
const data = {
|
|
27
|
+
answer: 42
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const wrapper = ({
|
|
31
|
+
children
|
|
32
|
+
}) => /*#__PURE__*/React.createElement(_CustomDataProvider.CustomDataProvider, {
|
|
33
|
+
data: data
|
|
34
|
+
}, children);
|
|
35
|
+
|
|
36
|
+
const {
|
|
37
|
+
result,
|
|
38
|
+
waitFor
|
|
39
|
+
} = (0, _reactHooks.renderHook)(() => (0, _useDataMutation.useDataMutation)(mutation), {
|
|
40
|
+
wrapper
|
|
41
|
+
});
|
|
42
|
+
const [mutate, beforeMutation] = result.current;
|
|
43
|
+
expect(beforeMutation).toMatchObject({
|
|
44
|
+
loading: false,
|
|
45
|
+
called: false
|
|
46
|
+
});
|
|
47
|
+
(0, _reactHooks.act)(() => {
|
|
48
|
+
mutate();
|
|
49
|
+
});
|
|
50
|
+
await waitFor(() => {
|
|
51
|
+
const [, duringMutation] = result.current;
|
|
52
|
+
expect(duringMutation).toMatchObject({
|
|
53
|
+
loading: true,
|
|
54
|
+
called: true
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
await waitFor(() => {
|
|
58
|
+
const [, afterMutation] = result.current;
|
|
59
|
+
expect(afterMutation).toMatchObject({
|
|
60
|
+
loading: false,
|
|
61
|
+
called: true,
|
|
62
|
+
data: 42
|
|
63
|
+
});
|
|
64
|
+
});
|
|
34
65
|
});
|
|
35
|
-
it('
|
|
36
|
-
|
|
37
|
-
|
|
66
|
+
it('should run immediately with lazy: false', async () => {
|
|
67
|
+
const mutation = {
|
|
68
|
+
type: 'create',
|
|
69
|
+
resource: 'answer',
|
|
70
|
+
data: {
|
|
71
|
+
answer: '?'
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
const data = {
|
|
75
|
+
answer: 42
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const wrapper = ({
|
|
79
|
+
children
|
|
80
|
+
}) => /*#__PURE__*/React.createElement(_CustomDataProvider.CustomDataProvider, {
|
|
81
|
+
data: data
|
|
82
|
+
}, children);
|
|
83
|
+
|
|
84
|
+
const {
|
|
85
|
+
result,
|
|
86
|
+
waitFor
|
|
87
|
+
} = (0, _reactHooks.renderHook)(() => (0, _useDataMutation.useDataMutation)(mutation, {
|
|
88
|
+
lazy: false
|
|
89
|
+
}), {
|
|
90
|
+
wrapper
|
|
91
|
+
});
|
|
92
|
+
const [, duringMutation] = result.current;
|
|
93
|
+
expect(duringMutation).toMatchObject({
|
|
94
|
+
loading: true,
|
|
95
|
+
called: true
|
|
96
|
+
});
|
|
97
|
+
await waitFor(() => {
|
|
98
|
+
const [, afterMutation] = result.current;
|
|
99
|
+
expect(afterMutation).toMatchObject({
|
|
100
|
+
loading: false,
|
|
101
|
+
called: true,
|
|
102
|
+
data: 42
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
it('should call onComplete on success', async () => {
|
|
107
|
+
const onComplete = jest.fn();
|
|
108
|
+
const mutation = {
|
|
109
|
+
type: 'create',
|
|
110
|
+
resource: 'answer',
|
|
111
|
+
data: {
|
|
112
|
+
answer: '?'
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const data = {
|
|
116
|
+
answer: 42
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
const wrapper = ({
|
|
120
|
+
children
|
|
121
|
+
}) => /*#__PURE__*/React.createElement(_CustomDataProvider.CustomDataProvider, {
|
|
122
|
+
data: data
|
|
123
|
+
}, children);
|
|
124
|
+
|
|
125
|
+
const {
|
|
126
|
+
result,
|
|
127
|
+
waitFor
|
|
128
|
+
} = (0, _reactHooks.renderHook)(() => (0, _useDataMutation.useDataMutation)(mutation, {
|
|
129
|
+
onComplete
|
|
130
|
+
}), {
|
|
131
|
+
wrapper
|
|
132
|
+
});
|
|
133
|
+
expect(onComplete).toHaveBeenCalledTimes(0);
|
|
134
|
+
const [mutate] = result.current;
|
|
38
135
|
(0, _reactHooks.act)(() => {
|
|
39
|
-
|
|
40
|
-
|
|
136
|
+
mutate();
|
|
137
|
+
});
|
|
138
|
+
await waitFor(() => {
|
|
139
|
+
const [, state] = result.current;
|
|
140
|
+
expect(state).toMatchObject({
|
|
141
|
+
loading: false,
|
|
142
|
+
called: true,
|
|
143
|
+
data: 42
|
|
41
144
|
});
|
|
145
|
+
expect(onComplete).toHaveBeenCalledTimes(1);
|
|
146
|
+
expect(onComplete).toHaveBeenLastCalledWith(42);
|
|
42
147
|
});
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
148
|
+
});
|
|
149
|
+
it('should call onError on error', async () => {
|
|
150
|
+
const error = new Error('Something went wrong');
|
|
151
|
+
const onError = jest.fn();
|
|
152
|
+
const mutation = {
|
|
153
|
+
type: 'create',
|
|
154
|
+
resource: 'answer',
|
|
155
|
+
data: {
|
|
156
|
+
answer: 42
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
const data = {
|
|
160
|
+
answer: () => {
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
const wrapper = ({
|
|
166
|
+
children
|
|
167
|
+
}) => /*#__PURE__*/React.createElement(_CustomDataProvider.CustomDataProvider, {
|
|
168
|
+
data: data
|
|
169
|
+
}, children);
|
|
170
|
+
|
|
171
|
+
const {
|
|
172
|
+
result,
|
|
173
|
+
waitFor
|
|
174
|
+
} = (0, _reactHooks.renderHook)(() => (0, _useDataMutation.useDataMutation)(mutation, {
|
|
175
|
+
onError
|
|
176
|
+
}), {
|
|
177
|
+
wrapper
|
|
47
178
|
});
|
|
179
|
+
expect(onError).toHaveBeenCalledTimes(0);
|
|
180
|
+
const [mutate] = result.current;
|
|
48
181
|
(0, _reactHooks.act)(() => {
|
|
49
182
|
mutate();
|
|
50
183
|
});
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
184
|
+
await waitFor(() => {
|
|
185
|
+
const [, state] = result.current;
|
|
186
|
+
expect(state).toMatchObject({
|
|
187
|
+
loading: false,
|
|
188
|
+
called: true,
|
|
189
|
+
error
|
|
190
|
+
});
|
|
56
191
|
});
|
|
192
|
+
expect(onError).toHaveBeenCalledTimes(1);
|
|
193
|
+
expect(onError).toHaveBeenLastCalledWith(error);
|
|
57
194
|
});
|
|
58
|
-
it('
|
|
59
|
-
|
|
60
|
-
|
|
195
|
+
it('should resolve variables', async () => {
|
|
196
|
+
const mutation = {
|
|
197
|
+
type: 'update',
|
|
198
|
+
resource: 'answer',
|
|
199
|
+
id: ({
|
|
200
|
+
id
|
|
201
|
+
}) => id,
|
|
202
|
+
data: {
|
|
203
|
+
answer: '?'
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
const answerSpy = jest.fn(() => 42);
|
|
207
|
+
const data = {
|
|
208
|
+
answer: answerSpy
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
const wrapper = ({
|
|
212
|
+
children
|
|
213
|
+
}) => /*#__PURE__*/React.createElement(_CustomDataProvider.CustomDataProvider, {
|
|
214
|
+
data: data
|
|
215
|
+
}, children);
|
|
216
|
+
|
|
217
|
+
const {
|
|
218
|
+
result,
|
|
219
|
+
waitFor
|
|
220
|
+
} = (0, _reactHooks.renderHook)(() => (0, _useDataMutation.useDataMutation)(mutation, {
|
|
221
|
+
lazy: false,
|
|
222
|
+
variables: {
|
|
223
|
+
id: '1'
|
|
224
|
+
}
|
|
225
|
+
}), {
|
|
226
|
+
wrapper
|
|
227
|
+
});
|
|
228
|
+
await waitFor(() => {
|
|
229
|
+
expect(answerSpy).toHaveBeenLastCalledWith(expect.any(String), expect.objectContaining({
|
|
230
|
+
id: '1'
|
|
231
|
+
}), expect.any(Object));
|
|
232
|
+
});
|
|
233
|
+
const [mutate] = result.current;
|
|
61
234
|
(0, _reactHooks.act)(() => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}), {
|
|
65
|
-
wrapper
|
|
235
|
+
mutate({
|
|
236
|
+
id: '2'
|
|
66
237
|
});
|
|
67
238
|
});
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
239
|
+
await waitFor(() => {
|
|
240
|
+
expect(answerSpy).toHaveBeenLastCalledWith(expect.any(String), expect.objectContaining({
|
|
241
|
+
id: '2'
|
|
242
|
+
}), expect.any(Object));
|
|
72
243
|
});
|
|
73
|
-
|
|
74
|
-
|
|
244
|
+
});
|
|
245
|
+
it('should return a reference to the engine', async () => {
|
|
246
|
+
const mutation = {
|
|
247
|
+
type: 'create',
|
|
248
|
+
resource: 'answer',
|
|
249
|
+
data: {
|
|
250
|
+
answer: '?'
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
const wrapper = ({
|
|
255
|
+
children
|
|
256
|
+
}) => /*#__PURE__*/React.createElement(_CustomDataProvider.CustomDataProvider, {
|
|
257
|
+
data: {}
|
|
258
|
+
}, children);
|
|
259
|
+
|
|
260
|
+
const engineHook = (0, _reactHooks.renderHook)(() => (0, _useDataEngine.useDataEngine)(), {
|
|
261
|
+
wrapper
|
|
262
|
+
});
|
|
263
|
+
const mutationHook = (0, _reactHooks.renderHook)(() => (0, _useDataMutation.useDataMutation)(mutation), {
|
|
264
|
+
wrapper
|
|
265
|
+
});
|
|
266
|
+
/**
|
|
267
|
+
* Ideally we'd check referential equality here with .toBe, but since
|
|
268
|
+
* both hooks run in a different context that doesn't work.
|
|
269
|
+
*/
|
|
270
|
+
|
|
271
|
+
expect(mutationHook.result.current[1].engine).toStrictEqual(engineHook.result.current);
|
|
272
|
+
});
|
|
273
|
+
it('should return a stable mutate function', async () => {
|
|
274
|
+
const mutation = {
|
|
275
|
+
type: 'create',
|
|
276
|
+
resource: 'answer',
|
|
277
|
+
data: {
|
|
278
|
+
answer: '?'
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
const data = {
|
|
282
|
+
answer: 42
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
const wrapper = ({
|
|
286
|
+
children
|
|
287
|
+
}) => /*#__PURE__*/React.createElement(_CustomDataProvider.CustomDataProvider, {
|
|
288
|
+
data: data
|
|
289
|
+
}, children);
|
|
290
|
+
|
|
291
|
+
const {
|
|
292
|
+
result
|
|
293
|
+
} = (0, _reactHooks.renderHook)(() => (0, _useDataMutation.useDataMutation)(mutation), {
|
|
294
|
+
wrapper
|
|
295
|
+
});
|
|
296
|
+
const [firstMutate] = result.current;
|
|
297
|
+
await (0, _reactHooks.act)(async () => {
|
|
298
|
+
await firstMutate({
|
|
299
|
+
variable: 'variable'
|
|
300
|
+
});
|
|
301
|
+
});
|
|
302
|
+
const [secondMutate, state] = result.current;
|
|
75
303
|
expect(state).toMatchObject({
|
|
76
304
|
loading: false,
|
|
77
|
-
|
|
305
|
+
called: true
|
|
306
|
+
});
|
|
307
|
+
expect(firstMutate).toBe(secondMutate);
|
|
308
|
+
});
|
|
309
|
+
it('should resolve with the data from mutate on success', async () => {
|
|
310
|
+
const mutation = {
|
|
311
|
+
type: 'create',
|
|
312
|
+
resource: 'answer',
|
|
313
|
+
data: {
|
|
314
|
+
answer: '?'
|
|
315
|
+
}
|
|
316
|
+
};
|
|
317
|
+
const data = {
|
|
318
|
+
answer: 42
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
const wrapper = ({
|
|
322
|
+
children
|
|
323
|
+
}) => /*#__PURE__*/React.createElement(_CustomDataProvider.CustomDataProvider, {
|
|
324
|
+
data: data
|
|
325
|
+
}, children);
|
|
326
|
+
|
|
327
|
+
const {
|
|
328
|
+
result,
|
|
329
|
+
waitFor
|
|
330
|
+
} = (0, _reactHooks.renderHook)(() => (0, _useDataMutation.useDataMutation)(mutation), {
|
|
331
|
+
wrapper
|
|
332
|
+
});
|
|
333
|
+
let mutatePromise;
|
|
334
|
+
const [mutate] = result.current;
|
|
335
|
+
(0, _reactHooks.act)(() => {
|
|
336
|
+
mutatePromise = mutate();
|
|
337
|
+
});
|
|
338
|
+
await waitFor(() => {
|
|
339
|
+
const [, state] = result.current;
|
|
340
|
+
expect(state).toMatchObject({
|
|
341
|
+
loading: false,
|
|
342
|
+
called: true,
|
|
343
|
+
data: 42
|
|
344
|
+
});
|
|
345
|
+
expect(mutatePromise).resolves.toBe(42);
|
|
78
346
|
});
|
|
79
347
|
});
|
|
80
348
|
});
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { render, waitFor } from '@testing-library/react';
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { CustomDataProvider, DataQuery } from '../react';
|
|
4
|
-
describe('
|
|
5
|
-
it('
|
|
4
|
+
describe('<DataQuery />', () => {
|
|
5
|
+
it('should render without failing', async () => {
|
|
6
6
|
const data = {
|
|
7
7
|
answer: 42
|
|
8
8
|
};
|
|
@@ -13,18 +13,8 @@ describe('Testing custom data provider and useQuery hook', () => {
|
|
|
13
13
|
data: data
|
|
14
14
|
}, children);
|
|
15
15
|
|
|
16
|
-
const renderFunction = jest.fn((
|
|
17
|
-
|
|
18
|
-
error,
|
|
19
|
-
data
|
|
20
|
-
}) => {
|
|
21
|
-
if (loading) return 'loading';
|
|
22
|
-
if (error) return /*#__PURE__*/React.createElement("div", null, "error: ", error.message);
|
|
23
|
-
return /*#__PURE__*/React.createElement("div", null, "data: ", data && data.answer);
|
|
24
|
-
});
|
|
25
|
-
const {
|
|
26
|
-
getByText
|
|
27
|
-
} = render( /*#__PURE__*/React.createElement(DataQuery, {
|
|
16
|
+
const renderFunction = jest.fn(() => null);
|
|
17
|
+
render( /*#__PURE__*/React.createElement(DataQuery, {
|
|
28
18
|
query: {
|
|
29
19
|
answer: {
|
|
30
20
|
resource: 'answer'
|
|
@@ -33,24 +23,21 @@ describe('Testing custom data provider and useQuery hook', () => {
|
|
|
33
23
|
}, renderFunction), {
|
|
34
24
|
wrapper
|
|
35
25
|
});
|
|
36
|
-
expect(getByText(/loading/i)).not.toBeUndefined();
|
|
37
26
|
expect(renderFunction).toHaveBeenCalledTimes(1);
|
|
38
27
|
expect(renderFunction).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
39
28
|
called: true,
|
|
40
29
|
loading: true
|
|
41
30
|
}));
|
|
42
31
|
await waitFor(() => {
|
|
43
|
-
|
|
32
|
+
expect(renderFunction).toHaveBeenCalledTimes(2);
|
|
33
|
+
expect(renderFunction).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
34
|
+
called: true,
|
|
35
|
+
loading: false,
|
|
36
|
+
data
|
|
37
|
+
}));
|
|
44
38
|
});
|
|
45
|
-
expect(getByText(/data: /i)).toHaveTextContent("data: ".concat(data.answer));
|
|
46
|
-
expect(renderFunction).toHaveBeenCalledTimes(2);
|
|
47
|
-
expect(renderFunction).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
48
|
-
called: true,
|
|
49
|
-
loading: false,
|
|
50
|
-
data
|
|
51
|
-
}));
|
|
52
39
|
});
|
|
53
|
-
it('
|
|
40
|
+
it('should render an error', async () => {
|
|
54
41
|
const expectedError = new Error('Something went wrong');
|
|
55
42
|
const data = {
|
|
56
43
|
test: () => {
|
|
@@ -64,18 +51,8 @@ describe('Testing custom data provider and useQuery hook', () => {
|
|
|
64
51
|
data: data
|
|
65
52
|
}, children);
|
|
66
53
|
|
|
67
|
-
const renderFunction = jest.fn((
|
|
68
|
-
|
|
69
|
-
error,
|
|
70
|
-
data
|
|
71
|
-
}) => {
|
|
72
|
-
if (loading) return 'loading';
|
|
73
|
-
if (error) return /*#__PURE__*/React.createElement("div", null, "error: ", error.message);
|
|
74
|
-
return /*#__PURE__*/React.createElement("div", null, "data: ", data && data.test);
|
|
75
|
-
});
|
|
76
|
-
const {
|
|
77
|
-
getByText
|
|
78
|
-
} = render( /*#__PURE__*/React.createElement(DataQuery, {
|
|
54
|
+
const renderFunction = jest.fn(() => null);
|
|
55
|
+
render( /*#__PURE__*/React.createElement(DataQuery, {
|
|
79
56
|
query: {
|
|
80
57
|
test: {
|
|
81
58
|
resource: 'test'
|
|
@@ -84,21 +61,18 @@ describe('Testing custom data provider and useQuery hook', () => {
|
|
|
84
61
|
}, renderFunction), {
|
|
85
62
|
wrapper
|
|
86
63
|
});
|
|
87
|
-
expect(getByText(/loading/i)).not.toBeUndefined();
|
|
88
64
|
expect(renderFunction).toHaveBeenCalledTimes(1);
|
|
89
65
|
expect(renderFunction).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
90
66
|
called: true,
|
|
91
67
|
loading: true
|
|
92
68
|
}));
|
|
93
69
|
await waitFor(() => {
|
|
94
|
-
|
|
70
|
+
expect(renderFunction).toHaveBeenCalledTimes(2);
|
|
71
|
+
expect(renderFunction).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
72
|
+
called: true,
|
|
73
|
+
loading: false,
|
|
74
|
+
error: expectedError
|
|
75
|
+
}));
|
|
95
76
|
});
|
|
96
|
-
expect(renderFunction).toHaveBeenCalledTimes(2);
|
|
97
|
-
expect(getByText(/error: /i)).toHaveTextContent("error: ".concat(expectedError.message));
|
|
98
|
-
expect(renderFunction).toHaveBeenLastCalledWith(expect.objectContaining({
|
|
99
|
-
called: true,
|
|
100
|
-
loading: false,
|
|
101
|
-
error: expectedError
|
|
102
|
-
}));
|
|
103
77
|
});
|
|
104
78
|
});
|
|
@@ -1,76 +1,65 @@
|
|
|
1
|
-
import { render,
|
|
2
|
-
import React from 'react';
|
|
1
|
+
import { render, waitFor, act } from '@testing-library/react';
|
|
2
|
+
import * as React from 'react';
|
|
3
3
|
import { CustomDataProvider, DataMutation } from '../react';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
question: '?'
|
|
10
|
-
});
|
|
11
|
-
return Promise.resolve({
|
|
12
|
-
answer: 42
|
|
13
|
-
});
|
|
14
|
-
})
|
|
15
|
-
};
|
|
16
|
-
describe('Test mutations', () => {
|
|
17
|
-
it('Should call the mock callback', async () => {
|
|
18
|
-
let doMutation;
|
|
19
|
-
const renderFunction = jest.fn(([mutate, {
|
|
20
|
-
called,
|
|
21
|
-
loading,
|
|
22
|
-
error,
|
|
23
|
-
data
|
|
24
|
-
}]) => {
|
|
25
|
-
doMutation = mutate;
|
|
26
|
-
if (!called) return 'uncalled';
|
|
27
|
-
if (loading) return 'loading';
|
|
28
|
-
if (error) return /*#__PURE__*/React.createElement("div", null, "error: ", error.message);
|
|
29
|
-
if (data) return /*#__PURE__*/React.createElement("div", null, "data: ", data.answer);
|
|
30
|
-
});
|
|
31
|
-
const testMutation = {
|
|
32
|
-
resource: 'target',
|
|
4
|
+
describe('<DataMutation />', () => {
|
|
5
|
+
it('should render without failing', async () => {
|
|
6
|
+
const endpointSpy = jest.fn(() => Promise.resolve(42));
|
|
7
|
+
const mutation = {
|
|
8
|
+
resource: 'answer',
|
|
33
9
|
type: 'create',
|
|
34
10
|
data: {
|
|
35
11
|
question: '?'
|
|
36
12
|
}
|
|
37
13
|
};
|
|
38
|
-
const {
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
14
|
+
const data = {
|
|
15
|
+
answer: endpointSpy
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const wrapper = ({
|
|
19
|
+
children
|
|
20
|
+
}) => /*#__PURE__*/React.createElement(CustomDataProvider, {
|
|
21
|
+
data: data
|
|
22
|
+
}, children);
|
|
23
|
+
|
|
24
|
+
const renderSpy = jest.fn(() => null);
|
|
25
|
+
render( /*#__PURE__*/React.createElement(DataMutation, {
|
|
26
|
+
mutation: mutation
|
|
27
|
+
}, renderSpy), {
|
|
28
|
+
wrapper
|
|
29
|
+
});
|
|
30
|
+
expect(endpointSpy).toHaveBeenCalledTimes(0);
|
|
31
|
+
expect(renderSpy).toHaveBeenCalledTimes(1);
|
|
32
|
+
expect(renderSpy).toHaveBeenLastCalledWith([expect.any(Function), expect.objectContaining({
|
|
49
33
|
called: false,
|
|
50
34
|
loading: false,
|
|
51
35
|
engine: expect.any(Object)
|
|
52
|
-
}]);
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
36
|
+
})]);
|
|
37
|
+
await act(async () => {
|
|
38
|
+
const firstRenderSpyCall = renderSpy.mock.calls[0];
|
|
39
|
+
const firstRenderSpyArgument = firstRenderSpyCall[0];
|
|
40
|
+
const [mutate] = firstRenderSpyArgument;
|
|
41
|
+
await mutate();
|
|
42
|
+
});
|
|
43
|
+
waitFor(() => {
|
|
44
|
+
expect(endpointSpy).toHaveBeenCalledTimes(1);
|
|
45
|
+
expect(renderSpy).toHaveBeenCalledTimes(2);
|
|
46
|
+
expect(renderSpy).toHaveBeenLastCalledWith([expect.any(Function), expect.objectContaining({
|
|
47
|
+
called: true,
|
|
48
|
+
loading: true,
|
|
49
|
+
engine: expect.any(Object)
|
|
50
|
+
})]);
|
|
51
|
+
});
|
|
52
|
+
waitFor(() => {
|
|
53
|
+
expect(endpointSpy).toHaveBeenCalledTimes(1);
|
|
54
|
+
expect(renderSpy).toHaveBeenCalledTimes(3);
|
|
55
|
+
expect(renderSpy).toHaveBeenLastCalledWith([expect.any(Function), expect.objectContaining({
|
|
56
|
+
called: true,
|
|
57
|
+
loading: false,
|
|
58
|
+
data: {
|
|
59
|
+
answer: 42
|
|
60
|
+
},
|
|
61
|
+
engine: expect.any(Object)
|
|
62
|
+
})]);
|
|
56
63
|
});
|
|
57
|
-
expect(renderFunction).toHaveBeenCalledTimes(2);
|
|
58
|
-
expect(renderFunction).toHaveBeenLastCalledWith([doMutation, {
|
|
59
|
-
called: true,
|
|
60
|
-
loading: true,
|
|
61
|
-
engine: expect.any(Object)
|
|
62
|
-
}]);
|
|
63
|
-
expect(mockBackend.target).toHaveBeenCalledTimes(1);
|
|
64
|
-
await waitFor(() => getByText(/data: /i));
|
|
65
|
-
expect(renderFunction).toHaveBeenCalledTimes(3);
|
|
66
|
-
expect(renderFunction).toHaveBeenLastCalledWith([doMutation, {
|
|
67
|
-
called: true,
|
|
68
|
-
loading: false,
|
|
69
|
-
data: {
|
|
70
|
-
answer: 42
|
|
71
|
-
},
|
|
72
|
-
engine: expect.any(Object)
|
|
73
|
-
}]);
|
|
74
|
-
expect(getByText(/data: /i)).toHaveTextContent("data: 42");
|
|
75
64
|
});
|
|
76
65
|
});
|
|
@@ -23,7 +23,7 @@ export const isCreateFeedbackMessage = (type, {
|
|
|
23
23
|
export const isCreateInterpretation = (type, {
|
|
24
24
|
resource
|
|
25
25
|
}) => {
|
|
26
|
-
const pattern = /^interpretations\/(?:reportTable|chart|visualization|map|eventReport|eventChart|dataSetReport)\/[a-zA-Z0-9]{11}$/;
|
|
26
|
+
const pattern = /^interpretations\/(?:reportTable|chart|visualization|map|eventVisualization|eventReport|eventChart|dataSetReport)\/[a-zA-Z0-9]{11}$/;
|
|
27
27
|
return type === 'create' && pattern.test(resource);
|
|
28
28
|
}; // PUT to `interpretations/${id}` (update an interpretation)
|
|
29
29
|
|
|
@@ -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
|
});
|
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",
|