@thepalaceproject/circulation-admin 1.43.0-post.1 → 1.43.0-post.11
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/CLAUDE.md +16 -7
- package/dist/circulation-admin.js +1 -1
- package/eslint.config.mjs +9 -1
- package/jest.config.js +56 -9
- package/package.json +6 -16
- package/tests/jest/actions.test.ts +962 -0
- package/tests/jest/components/AccountPage.test.tsx +41 -0
- package/tests/jest/components/AdvancedSearchBooleanFilter.test.tsx +231 -0
- package/tests/jest/components/AdvancedSearchFilter.test.tsx +142 -0
- package/tests/jest/components/AdvancedSearchFilterInput.test.tsx +212 -0
- package/tests/jest/components/AdvancedSearchFilterViewer.test.tsx +52 -0
- package/tests/jest/components/AdvancedSearchValueFilter.test.tsx +123 -0
- package/tests/jest/components/Announcement.test.tsx +76 -0
- package/tests/jest/components/Autocomplete.test.tsx +67 -0
- package/tests/jest/components/BookDetails.test.tsx +133 -0
- package/tests/jest/components/BookDetailsContainer.test.tsx +116 -0
- package/tests/jest/components/BookDetailsEditor.test.tsx +275 -0
- package/tests/jest/components/BookEditForm.test.tsx +352 -0
- package/tests/jest/components/CatalogServices.test.tsx +63 -0
- package/tests/jest/components/CirculationEventsDownloadForm.test.tsx +41 -0
- package/tests/jest/components/Classifications.test.tsx +166 -0
- package/tests/jest/components/ClassificationsTable.test.tsx +57 -0
- package/tests/jest/components/ColorPicker.test.tsx +58 -0
- package/tests/jest/components/ComplaintForm.test.tsx +171 -0
- package/tests/jest/components/Complaints.test.tsx +259 -0
- package/tests/jest/components/ConfigPage.test.tsx +58 -0
- package/tests/jest/components/ContextProvider.test.tsx +138 -0
- package/tests/jest/components/CustomListEditor.test.tsx +367 -0
- package/tests/jest/components/CustomListPage.test.tsx +57 -0
- package/tests/jest/components/CustomListSearch.test.tsx +275 -0
- package/tests/jest/components/CustomListsForBook.test.tsx +315 -0
- package/tests/jest/components/CustomListsSidebar.test.tsx +251 -0
- package/tests/jest/components/DashboardPage.test.tsx +76 -0
- package/tests/jest/components/DebugAuthentication.test.tsx +1 -5
- package/tests/jest/components/DiagnosticsServiceTabs.test.tsx +141 -0
- package/tests/jest/components/DiagnosticsServiceType.test.tsx +75 -0
- package/tests/jest/components/DiagnosticsTabContainer.test.tsx +147 -0
- package/tests/jest/components/EditableConfigList.test.tsx +8 -2
- package/tests/jest/components/EntryPointsContainer.test.tsx +97 -0
- package/tests/jest/components/EntryPointsTabs.test.tsx +88 -0
- package/tests/jest/components/ErrorMessage.test.tsx +97 -0
- package/tests/jest/components/Footer.test.tsx +141 -0
- package/tests/jest/components/InventoryReportRequestModal.test.tsx +16 -42
- package/tests/jest/components/LaneEditor.test.tsx +2 -6
- package/tests/jest/components/LanePage.test.tsx +68 -0
- package/tests/jest/components/LanguageField.test.tsx +40 -0
- package/tests/jest/components/LibraryEditForm.test.tsx +383 -0
- package/tests/jest/components/LibraryRegistrationForm.test.tsx +203 -0
- package/tests/jest/components/LoadButton.test.tsx +49 -0
- package/tests/jest/components/ManagePatrons.test.tsx +73 -0
- package/tests/jest/components/ManagePatronsForm.test.tsx +180 -0
- package/tests/jest/components/ManagePatronsTabContainer.test.tsx +143 -0
- package/tests/jest/components/MetadataServices.test.tsx +59 -0
- package/tests/jest/components/PatronAuthServices.test.tsx +114 -0
- package/tests/jest/components/PatronBlockingRulesEditor.test.tsx +3 -1
- package/tests/jest/components/PatronInfo.test.tsx +54 -0
- package/tests/jest/components/ResetAdobeId.test.tsx +302 -0
- package/tests/jest/components/SaveButton.test.tsx +47 -0
- package/tests/jest/components/SelfTestResult.test.tsx +164 -0
- package/tests/jest/components/SelfTestsCategory.test.tsx +200 -0
- package/tests/jest/components/ServiceWithRegistrationsEditForm.test.tsx +110 -0
- package/tests/jest/components/SetupPage.test.tsx +41 -0
- package/tests/jest/components/SingleStatListItem.test.tsx +62 -0
- package/tests/jest/components/SitewideAnnouncements.test.tsx +134 -0
- package/tests/jest/components/Stats.test.tsx +4 -8
- package/tests/jest/components/TabContainer.test.tsx +68 -0
- package/tests/jest/components/Timestamp.test.tsx +74 -0
- package/tests/jest/components/TroubleshootingCategoryPage.test.tsx +69 -0
- package/tests/jest/components/TroubleshootingPage.test.tsx +94 -0
- package/tests/jest/components/TroubleshootingTabContainer.test.tsx +68 -0
- package/tests/jest/components/UpdatingLoader.test.tsx +36 -0
- package/tests/jest/components/WelcomePage.test.tsx +43 -0
- package/tests/jest/components/WithEditButton.test.tsx +55 -0
- package/tests/jest/components/WithRemoveButton.test.tsx +95 -0
- package/tests/jest/editorAdapter.test.ts +245 -0
- package/tests/jest/index.test.tsx +50 -0
- package/tests/jest/legacy-setup.ts +13 -0
- package/tests/jest/legacyJsdomEnvironment.js +49 -0
- package/tests/jest/models/Admin.test.ts +206 -0
- package/tests/jest/reducers/bookCoverPreview.test.ts +81 -0
- package/tests/jest/reducers/classifications.test.ts +161 -0
- package/tests/jest/reducers/collections.test.ts +96 -0
- package/tests/jest/reducers/complaints.test.ts +166 -0
- package/tests/jest/reducers/createFetchEditReducer.test.ts +220 -0
- package/tests/jest/reducers/createRegisterLibraryReducer.test.ts +51 -0
- package/tests/jest/reducers/customListDetails.test.ts +120 -0
- package/tests/jest/reducers/customListEditor.test.ts +2823 -0
- package/tests/jest/reducers/managePatrons.test.ts +71 -0
- package/tests/jest/testUtils/formDataShim.test.ts +135 -0
- package/tests/jest/testUtils/formDataShim.ts +112 -0
- package/tests/jest/utils/sharedFunctions.test.ts +121 -0
- package/tsconfig.json +3 -4
- package/testReporter.js +0 -29
- package/tests/jest/components/AdvancedSearchBuilder.test.tsx +0 -38
|
@@ -0,0 +1,962 @@
|
|
|
1
|
+
import * as fetchMock from "fetch-mock-jest";
|
|
2
|
+
|
|
3
|
+
import ActionCreator from "../../src/actions";
|
|
4
|
+
|
|
5
|
+
class MockDataFetcher {
|
|
6
|
+
resolve: boolean = true;
|
|
7
|
+
testData: any = "test";
|
|
8
|
+
|
|
9
|
+
fetchOPDSData(url) {
|
|
10
|
+
return new Promise((resolve, reject) => {
|
|
11
|
+
if (this.resolve) {
|
|
12
|
+
resolve(this.testData);
|
|
13
|
+
} else {
|
|
14
|
+
reject({
|
|
15
|
+
status: null,
|
|
16
|
+
response: "test error",
|
|
17
|
+
url: url,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
fetch(url, _options = {}) {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
if (this.resolve) {
|
|
26
|
+
resolve(this.testData);
|
|
27
|
+
} else {
|
|
28
|
+
reject({
|
|
29
|
+
message: "test error",
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const fetcher = new MockDataFetcher() as any;
|
|
37
|
+
const actions = new ActionCreator(fetcher, "token");
|
|
38
|
+
|
|
39
|
+
describe("actions", () => {
|
|
40
|
+
afterEach(() => {
|
|
41
|
+
fetchMock.restore();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe("postForm", () => {
|
|
45
|
+
const type = "TEST";
|
|
46
|
+
const url = "http://example.com/test";
|
|
47
|
+
const formData = new (window as any).FormData();
|
|
48
|
+
formData.append("test", "test");
|
|
49
|
+
|
|
50
|
+
it("dispatches request, success, and load", async () => {
|
|
51
|
+
const dispatch = jest.fn();
|
|
52
|
+
const responseText = "response";
|
|
53
|
+
fetchMock.post(url, responseText);
|
|
54
|
+
|
|
55
|
+
await actions.postForm(type, url, formData)(dispatch);
|
|
56
|
+
const fetchArgs = fetchMock.calls();
|
|
57
|
+
|
|
58
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
59
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
60
|
+
`${type}_${ActionCreator.REQUEST}`
|
|
61
|
+
);
|
|
62
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
63
|
+
`${type}_${ActionCreator.SUCCESS}`
|
|
64
|
+
);
|
|
65
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
66
|
+
`${type}_${ActionCreator.LOAD}`
|
|
67
|
+
);
|
|
68
|
+
expect(dispatch.mock.calls[2][0].data).toBe(responseText);
|
|
69
|
+
expect(fetchMock.called()).toBe(true);
|
|
70
|
+
expect(fetchArgs[0][0]).toBe(url);
|
|
71
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
72
|
+
const expectedHeaders = new Headers();
|
|
73
|
+
expectedHeaders.append("X-CSRF-Token", "token");
|
|
74
|
+
expect(fetchArgs[0][1].headers).toStrictEqual(expectedHeaders);
|
|
75
|
+
expect(fetchArgs[0][1].body).toBe(formData);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("postForm with JSON response dispatches request, success, and load", async () => {
|
|
79
|
+
const dispatch = jest.fn();
|
|
80
|
+
// prettier-ignore
|
|
81
|
+
const responseText = "{\"id\": \"test\", \"name\": \"test\"}";
|
|
82
|
+
fetchMock.mock(url, responseText);
|
|
83
|
+
|
|
84
|
+
await actions.postForm(type, url, formData, "POST", "", "JSON")(dispatch);
|
|
85
|
+
const fetchArgs = fetchMock.calls();
|
|
86
|
+
|
|
87
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
88
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
89
|
+
`${type}_${ActionCreator.REQUEST}`
|
|
90
|
+
);
|
|
91
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
92
|
+
`${type}_${ActionCreator.SUCCESS}`
|
|
93
|
+
);
|
|
94
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
95
|
+
`${type}_${ActionCreator.LOAD}`
|
|
96
|
+
);
|
|
97
|
+
expect(dispatch.mock.calls[2][0].data).toStrictEqual(
|
|
98
|
+
JSON.parse(responseText)
|
|
99
|
+
);
|
|
100
|
+
expect(fetchMock.called()).toBe(true);
|
|
101
|
+
expect(fetchArgs[0][0]).toBe(url);
|
|
102
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
103
|
+
const expectedHeaders = new Headers();
|
|
104
|
+
expectedHeaders.append("X-CSRF-Token", "token");
|
|
105
|
+
expect(fetchArgs[0][1].headers).toStrictEqual(expectedHeaders);
|
|
106
|
+
expect(fetchArgs[0][1].body).toBe(formData);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("dispatches a DELETE request", async () => {
|
|
110
|
+
const dispatch = jest.fn();
|
|
111
|
+
const responseText = "response";
|
|
112
|
+
fetchMock.mock(url, responseText);
|
|
113
|
+
|
|
114
|
+
await actions.postForm(type, url, formData, "DELETE")(dispatch);
|
|
115
|
+
const fetchArgs = fetchMock.calls();
|
|
116
|
+
|
|
117
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
118
|
+
expect(fetchMock.called()).toBe(true);
|
|
119
|
+
expect(fetchArgs[0][0]).toBe(url);
|
|
120
|
+
expect(fetchArgs[0][1].method).toBe("DELETE");
|
|
121
|
+
const expectedHeaders = new Headers();
|
|
122
|
+
expectedHeaders.append("X-CSRF-Token", "token");
|
|
123
|
+
expect(fetchArgs[0][1].headers).toStrictEqual(expectedHeaders);
|
|
124
|
+
expect(fetchArgs[0][1].body).toBe(formData);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("dispatches failure on bad response", async () => {
|
|
128
|
+
const dispatch = jest.fn();
|
|
129
|
+
fetchMock.mock(url, { status: 500, body: { detail: "problem detail" } });
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
await actions.postForm(type, url, formData)(dispatch);
|
|
133
|
+
// shouldn't get here
|
|
134
|
+
expect(false).toBe(true);
|
|
135
|
+
} catch (err) {
|
|
136
|
+
expect(dispatch.mock.calls.length).toBe(2);
|
|
137
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
138
|
+
`${type}_${ActionCreator.REQUEST}`
|
|
139
|
+
);
|
|
140
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
141
|
+
`${type}_${ActionCreator.FAILURE}`
|
|
142
|
+
);
|
|
143
|
+
expect(fetchMock.called()).toBe(true);
|
|
144
|
+
expect(err).toStrictEqual({
|
|
145
|
+
status: 500,
|
|
146
|
+
response: "problem detail",
|
|
147
|
+
url: url,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("dispatches failure on non-JSON response", async () => {
|
|
153
|
+
const dispatch = jest.fn();
|
|
154
|
+
fetchMock.mock(url, { status: 500, body: "Not JSON" });
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
await actions.postForm(
|
|
158
|
+
type,
|
|
159
|
+
url,
|
|
160
|
+
formData,
|
|
161
|
+
"POST",
|
|
162
|
+
"Default error"
|
|
163
|
+
)(dispatch);
|
|
164
|
+
// shouldn't get here
|
|
165
|
+
expect(false).toBe(true);
|
|
166
|
+
} catch (err) {
|
|
167
|
+
expect(dispatch.mock.calls.length).toBe(2);
|
|
168
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
169
|
+
`${type}_${ActionCreator.REQUEST}`
|
|
170
|
+
);
|
|
171
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
172
|
+
`${type}_${ActionCreator.FAILURE}`
|
|
173
|
+
);
|
|
174
|
+
expect(fetchMock.called()).toBe(true);
|
|
175
|
+
expect(err).toStrictEqual({
|
|
176
|
+
status: 500,
|
|
177
|
+
response: "Default error",
|
|
178
|
+
url: url,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it("dispatches failure on no response", async () => {
|
|
184
|
+
const dispatch = jest.fn();
|
|
185
|
+
fetchMock.mock(url, () => {
|
|
186
|
+
throw { message: "test error" };
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
try {
|
|
190
|
+
await actions.postForm(type, url, formData)(dispatch);
|
|
191
|
+
// shouldn't get here
|
|
192
|
+
expect(false).toBe(true);
|
|
193
|
+
} catch (err) {
|
|
194
|
+
expect(dispatch.mock.calls.length).toBe(2);
|
|
195
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
196
|
+
`${type}_${ActionCreator.REQUEST}`
|
|
197
|
+
);
|
|
198
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
199
|
+
`${type}_${ActionCreator.FAILURE}`
|
|
200
|
+
);
|
|
201
|
+
expect(fetchMock.called()).toBe(true);
|
|
202
|
+
expect(err).toStrictEqual({
|
|
203
|
+
status: null,
|
|
204
|
+
response: "test error",
|
|
205
|
+
url: url,
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
});
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
describe("postJSON", () => {
|
|
212
|
+
const type = "TEST";
|
|
213
|
+
const url = "http://example.com/test";
|
|
214
|
+
const jsonData = { test: 1 };
|
|
215
|
+
|
|
216
|
+
it("dispatches request and success", async () => {
|
|
217
|
+
const dispatch = jest.fn();
|
|
218
|
+
fetchMock.mock(url, 200);
|
|
219
|
+
|
|
220
|
+
await actions.postJSON<{ test: number }>(type, url, jsonData)(dispatch);
|
|
221
|
+
const fetchArgs = fetchMock.calls();
|
|
222
|
+
|
|
223
|
+
expect(dispatch.mock.calls.length).toBe(2);
|
|
224
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
225
|
+
`${type}_${ActionCreator.REQUEST}`
|
|
226
|
+
);
|
|
227
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
228
|
+
`${type}_${ActionCreator.SUCCESS}`
|
|
229
|
+
);
|
|
230
|
+
expect(fetchMock.called()).toBe(true);
|
|
231
|
+
expect(fetchArgs[0][0]).toBe(url);
|
|
232
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
233
|
+
const expectedHeaders = new Headers();
|
|
234
|
+
expectedHeaders.append("Accept", "application/json");
|
|
235
|
+
expectedHeaders.append("Content-Type", "application/json");
|
|
236
|
+
expectedHeaders.append("X-CSRF-Token", "token");
|
|
237
|
+
expect(fetchArgs[0][1].headers).toStrictEqual(expectedHeaders);
|
|
238
|
+
expect(fetchArgs[0][1].body).toBe(JSON.stringify(jsonData));
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it("dispatches failure on bad response", async () => {
|
|
242
|
+
const dispatch = jest.fn();
|
|
243
|
+
fetchMock.mock(url, { status: 500, body: { detail: "problem detail" } });
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
await actions.postJSON<{ test: number }>(type, url, jsonData)(dispatch);
|
|
247
|
+
// shouldn't get here
|
|
248
|
+
expect(false).toBe(true);
|
|
249
|
+
} catch (err) {
|
|
250
|
+
expect(dispatch.mock.calls.length).toBe(2);
|
|
251
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
252
|
+
`${type}_${ActionCreator.REQUEST}`
|
|
253
|
+
);
|
|
254
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
255
|
+
`${type}_${ActionCreator.FAILURE}`
|
|
256
|
+
);
|
|
257
|
+
expect(fetchMock.called()).toBe(true);
|
|
258
|
+
expect(err).toStrictEqual({
|
|
259
|
+
status: 500,
|
|
260
|
+
response: "problem detail",
|
|
261
|
+
url: url,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
it("dispatches failure on no response", async () => {
|
|
267
|
+
const dispatch = jest.fn();
|
|
268
|
+
fetchMock.mock(url, () => {
|
|
269
|
+
throw { message: "test error" };
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
await actions.postJSON<{ test: number }>(type, url, jsonData)(dispatch);
|
|
274
|
+
// shouldn't get here
|
|
275
|
+
expect(false).toBe(true);
|
|
276
|
+
} catch (err) {
|
|
277
|
+
expect(dispatch.mock.calls.length).toBe(2);
|
|
278
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
279
|
+
`${type}_${ActionCreator.REQUEST}`
|
|
280
|
+
);
|
|
281
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
282
|
+
`${type}_${ActionCreator.FAILURE}`
|
|
283
|
+
);
|
|
284
|
+
expect(fetchMock.called()).toBe(true);
|
|
285
|
+
expect(err).toStrictEqual({
|
|
286
|
+
status: null,
|
|
287
|
+
response: "test error",
|
|
288
|
+
url: url,
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
describe("fetchComplaints", () => {
|
|
295
|
+
it("dispatches request, load, and success", async () => {
|
|
296
|
+
const dispatch = jest.fn();
|
|
297
|
+
const complaintsData = {
|
|
298
|
+
book: { id: "test id" },
|
|
299
|
+
complaints: { "test-type": 1 },
|
|
300
|
+
};
|
|
301
|
+
fetcher.testData = {
|
|
302
|
+
ok: true,
|
|
303
|
+
status: 200,
|
|
304
|
+
json: () =>
|
|
305
|
+
new Promise<any>((resolve, _reject) => {
|
|
306
|
+
resolve(complaintsData);
|
|
307
|
+
}),
|
|
308
|
+
};
|
|
309
|
+
fetcher.resolve = true;
|
|
310
|
+
|
|
311
|
+
const data = await actions.fetchComplaints(
|
|
312
|
+
"http://example.com/complaints"
|
|
313
|
+
)(dispatch);
|
|
314
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
315
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
316
|
+
ActionCreator.COMPLAINTS_REQUEST
|
|
317
|
+
);
|
|
318
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
319
|
+
ActionCreator.COMPLAINTS_SUCCESS
|
|
320
|
+
);
|
|
321
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
322
|
+
ActionCreator.COMPLAINTS_LOAD
|
|
323
|
+
);
|
|
324
|
+
expect(data).toStrictEqual(complaintsData);
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
describe("postComplaint", () => {
|
|
329
|
+
it("dispatches request and success", async () => {
|
|
330
|
+
const postComplaintUrl = "http://example.com/postComplaint";
|
|
331
|
+
const dispatch = jest.fn();
|
|
332
|
+
const data = {
|
|
333
|
+
type: "test type",
|
|
334
|
+
};
|
|
335
|
+
|
|
336
|
+
fetchMock.mock(postComplaintUrl, 201);
|
|
337
|
+
|
|
338
|
+
await actions.postComplaint(postComplaintUrl, data)(dispatch);
|
|
339
|
+
const fetchArgs = fetchMock.calls();
|
|
340
|
+
|
|
341
|
+
expect(dispatch.mock.calls.length).toBe(2);
|
|
342
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
343
|
+
ActionCreator.POST_COMPLAINT_REQUEST
|
|
344
|
+
);
|
|
345
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
346
|
+
ActionCreator.POST_COMPLAINT_SUCCESS
|
|
347
|
+
);
|
|
348
|
+
expect(fetchMock.called()).toBe(true);
|
|
349
|
+
expect(fetchArgs[0][0]).toBe(postComplaintUrl);
|
|
350
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
351
|
+
expect(fetchArgs[0][1].body).toBe(JSON.stringify(data));
|
|
352
|
+
});
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
describe("resolveComplaints", () => {
|
|
356
|
+
it("dispatches request and success", async () => {
|
|
357
|
+
const resolveComplaintsUrl = "http://example.com/resolveComplaints";
|
|
358
|
+
const dispatch = jest.fn();
|
|
359
|
+
const formData = new (window as any).FormData();
|
|
360
|
+
formData.append("type", "test type");
|
|
361
|
+
|
|
362
|
+
fetchMock.mock(resolveComplaintsUrl, "server response");
|
|
363
|
+
|
|
364
|
+
await actions.resolveComplaints(resolveComplaintsUrl, formData)(dispatch);
|
|
365
|
+
const fetchArgs = fetchMock.calls();
|
|
366
|
+
|
|
367
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
368
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
369
|
+
ActionCreator.RESOLVE_COMPLAINTS_REQUEST
|
|
370
|
+
);
|
|
371
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
372
|
+
ActionCreator.RESOLVE_COMPLAINTS_SUCCESS
|
|
373
|
+
);
|
|
374
|
+
expect(fetchMock.called()).toBe(true);
|
|
375
|
+
expect(fetchArgs[0][0]).toBe(resolveComplaintsUrl);
|
|
376
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
377
|
+
expect(fetchArgs[0][1].body).toBe(formData);
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
describe("fetchGenreTree", () => {
|
|
382
|
+
it("dispatches request, load, and success", async () => {
|
|
383
|
+
const dispatch = jest.fn();
|
|
384
|
+
const genresData = "test data";
|
|
385
|
+
fetcher.testData = {
|
|
386
|
+
ok: true,
|
|
387
|
+
status: 200,
|
|
388
|
+
json: () =>
|
|
389
|
+
new Promise<any>((resolve, _reject) => {
|
|
390
|
+
resolve(genresData);
|
|
391
|
+
}),
|
|
392
|
+
};
|
|
393
|
+
fetcher.resolve = true;
|
|
394
|
+
|
|
395
|
+
const data = await actions.fetchGenreTree("http://example.com/genres")(
|
|
396
|
+
dispatch
|
|
397
|
+
);
|
|
398
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
399
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
400
|
+
ActionCreator.GENRE_TREE_REQUEST
|
|
401
|
+
);
|
|
402
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
403
|
+
ActionCreator.GENRE_TREE_SUCCESS
|
|
404
|
+
);
|
|
405
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
406
|
+
ActionCreator.GENRE_TREE_LOAD
|
|
407
|
+
);
|
|
408
|
+
expect(data).toBe(genresData);
|
|
409
|
+
});
|
|
410
|
+
});
|
|
411
|
+
|
|
412
|
+
describe("editClassifications", () => {
|
|
413
|
+
it("dispatches request and success", async () => {
|
|
414
|
+
const editClassificationsUrl = "http://example.com/editClassifications";
|
|
415
|
+
const dispatch = jest.fn();
|
|
416
|
+
const formData = new (window as any).FormData();
|
|
417
|
+
const newGenreTree = ["Drama", "Epic Fantasy", "Women Detectives"];
|
|
418
|
+
newGenreTree.forEach((genre) => formData.append("genres", genre));
|
|
419
|
+
|
|
420
|
+
fetchMock.mock(editClassificationsUrl, "server response");
|
|
421
|
+
|
|
422
|
+
await actions.editClassifications(
|
|
423
|
+
editClassificationsUrl,
|
|
424
|
+
formData
|
|
425
|
+
)(dispatch);
|
|
426
|
+
const fetchArgs = fetchMock.calls();
|
|
427
|
+
|
|
428
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
429
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
430
|
+
ActionCreator.EDIT_CLASSIFICATIONS_REQUEST
|
|
431
|
+
);
|
|
432
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
433
|
+
ActionCreator.EDIT_CLASSIFICATIONS_SUCCESS
|
|
434
|
+
);
|
|
435
|
+
expect(fetchMock.called()).toBe(true);
|
|
436
|
+
expect(fetchArgs[0][0]).toBe(editClassificationsUrl);
|
|
437
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
438
|
+
expect(fetchArgs[0][1].body).toBe(formData);
|
|
439
|
+
});
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
describe("fetchClassifications", () => {
|
|
443
|
+
it("dispatches request, load, and success", async () => {
|
|
444
|
+
const dispatch = jest.fn();
|
|
445
|
+
const classificationsData = {
|
|
446
|
+
book: { id: "test id" },
|
|
447
|
+
classifications: { "test-type": 1 },
|
|
448
|
+
};
|
|
449
|
+
fetcher.testData = {
|
|
450
|
+
ok: true,
|
|
451
|
+
status: 200,
|
|
452
|
+
json: () =>
|
|
453
|
+
new Promise<any>((resolve, _reject) => {
|
|
454
|
+
resolve(classificationsData);
|
|
455
|
+
}),
|
|
456
|
+
};
|
|
457
|
+
fetcher.resolve = true;
|
|
458
|
+
|
|
459
|
+
const data = await actions.fetchClassifications(
|
|
460
|
+
"http://example.com/classifications"
|
|
461
|
+
)(dispatch);
|
|
462
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
463
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
464
|
+
ActionCreator.CLASSIFICATIONS_REQUEST
|
|
465
|
+
);
|
|
466
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
467
|
+
ActionCreator.CLASSIFICATIONS_SUCCESS
|
|
468
|
+
);
|
|
469
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
470
|
+
ActionCreator.CLASSIFICATIONS_LOAD
|
|
471
|
+
);
|
|
472
|
+
expect(data).toBe(classificationsData);
|
|
473
|
+
});
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
describe("fetchDiagnostics", () => {
|
|
477
|
+
it("dispatches request, load, and success", async () => {
|
|
478
|
+
const dispatch = jest.fn();
|
|
479
|
+
const diagnosticsData = "diagnostics";
|
|
480
|
+
fetcher.testData = {
|
|
481
|
+
ok: true,
|
|
482
|
+
status: 200,
|
|
483
|
+
json: () =>
|
|
484
|
+
new Promise<any>((resolve, _reject) => {
|
|
485
|
+
resolve(diagnosticsData);
|
|
486
|
+
}),
|
|
487
|
+
};
|
|
488
|
+
fetcher.resolve = true;
|
|
489
|
+
|
|
490
|
+
const data = await actions.fetchDiagnostics()(dispatch);
|
|
491
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
492
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
493
|
+
`${ActionCreator.DIAGNOSTICS}_${ActionCreator.REQUEST}`
|
|
494
|
+
);
|
|
495
|
+
expect(dispatch.mock.calls[0][0].url).toBe("/admin/diagnostics");
|
|
496
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
497
|
+
`${ActionCreator.DIAGNOSTICS}_${ActionCreator.SUCCESS}`
|
|
498
|
+
);
|
|
499
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
500
|
+
`${ActionCreator.DIAGNOSTICS}_${ActionCreator.LOAD}`
|
|
501
|
+
);
|
|
502
|
+
expect(data).toStrictEqual(diagnosticsData);
|
|
503
|
+
});
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
describe("fetchLibraries", () => {
|
|
507
|
+
it("dispatches request, load, and success", async () => {
|
|
508
|
+
const dispatch = jest.fn();
|
|
509
|
+
const librariesData = "libraries";
|
|
510
|
+
fetcher.testData = {
|
|
511
|
+
ok: true,
|
|
512
|
+
status: 200,
|
|
513
|
+
json: () =>
|
|
514
|
+
new Promise<any>((resolve, _reject) => {
|
|
515
|
+
resolve(librariesData);
|
|
516
|
+
}),
|
|
517
|
+
};
|
|
518
|
+
fetcher.resolve = true;
|
|
519
|
+
|
|
520
|
+
const data = await actions.fetchLibraries()(dispatch);
|
|
521
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
522
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
523
|
+
`${ActionCreator.LIBRARIES}_${ActionCreator.REQUEST}`
|
|
524
|
+
);
|
|
525
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
526
|
+
`${ActionCreator.LIBRARIES}_${ActionCreator.SUCCESS}`
|
|
527
|
+
);
|
|
528
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
529
|
+
`${ActionCreator.LIBRARIES}_${ActionCreator.LOAD}`
|
|
530
|
+
);
|
|
531
|
+
expect(data).toStrictEqual(librariesData);
|
|
532
|
+
});
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
describe("editLibrary", () => {
|
|
536
|
+
it("dispatches request and success", async () => {
|
|
537
|
+
const editLibraryUrl = "/admin/libraries";
|
|
538
|
+
const dispatch = jest.fn();
|
|
539
|
+
const formData = new (window as any).FormData();
|
|
540
|
+
formData.append("name", "new name");
|
|
541
|
+
|
|
542
|
+
fetchMock.mock(editLibraryUrl, "server response");
|
|
543
|
+
|
|
544
|
+
await actions.editLibrary(formData)(dispatch);
|
|
545
|
+
const fetchArgs = fetchMock.calls();
|
|
546
|
+
|
|
547
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
548
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
549
|
+
`${ActionCreator.EDIT_LIBRARY}_${ActionCreator.REQUEST}`
|
|
550
|
+
);
|
|
551
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
552
|
+
`${ActionCreator.EDIT_LIBRARY}_${ActionCreator.SUCCESS}`
|
|
553
|
+
);
|
|
554
|
+
expect(fetchMock.called()).toBe(true);
|
|
555
|
+
expect(fetchArgs[0][0]).toBe(editLibraryUrl);
|
|
556
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
557
|
+
expect(fetchArgs[0][1].body).toBe(formData);
|
|
558
|
+
});
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
describe("fetchCollections", () => {
|
|
562
|
+
it("dispatches request, load, and success", async () => {
|
|
563
|
+
const dispatch = jest.fn();
|
|
564
|
+
const collectionsData = "collections";
|
|
565
|
+
fetcher.testData = {
|
|
566
|
+
ok: true,
|
|
567
|
+
status: 200,
|
|
568
|
+
json: () =>
|
|
569
|
+
new Promise<any>((resolve, _reject) => {
|
|
570
|
+
resolve(collectionsData);
|
|
571
|
+
}),
|
|
572
|
+
};
|
|
573
|
+
fetcher.resolve = true;
|
|
574
|
+
|
|
575
|
+
const data = await actions.fetchCollections()(dispatch);
|
|
576
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
577
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
578
|
+
`${ActionCreator.COLLECTIONS}_${ActionCreator.REQUEST}`
|
|
579
|
+
);
|
|
580
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
581
|
+
`${ActionCreator.COLLECTIONS}_${ActionCreator.SUCCESS}`
|
|
582
|
+
);
|
|
583
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
584
|
+
`${ActionCreator.COLLECTIONS}_${ActionCreator.LOAD}`
|
|
585
|
+
);
|
|
586
|
+
expect(data).toStrictEqual(collectionsData);
|
|
587
|
+
});
|
|
588
|
+
});
|
|
589
|
+
|
|
590
|
+
describe("editCollection", () => {
|
|
591
|
+
it("dispatches request and success", async () => {
|
|
592
|
+
const editCollectionUrl = "/admin/collections";
|
|
593
|
+
const dispatch = jest.fn();
|
|
594
|
+
const formData = new (window as any).FormData();
|
|
595
|
+
formData.append("name", "new name");
|
|
596
|
+
|
|
597
|
+
fetchMock.mock(editCollectionUrl, "server response");
|
|
598
|
+
|
|
599
|
+
await actions.editCollection(formData)(dispatch);
|
|
600
|
+
const fetchArgs = fetchMock.calls();
|
|
601
|
+
|
|
602
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
603
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
604
|
+
`${ActionCreator.EDIT_COLLECTION}_${ActionCreator.REQUEST}`
|
|
605
|
+
);
|
|
606
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
607
|
+
`${ActionCreator.EDIT_COLLECTION}_${ActionCreator.SUCCESS}`
|
|
608
|
+
);
|
|
609
|
+
expect(fetchMock.called()).toBe(true);
|
|
610
|
+
expect(fetchArgs[0][0]).toBe(editCollectionUrl);
|
|
611
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
612
|
+
expect(fetchArgs[0][1].body).toBe(formData);
|
|
613
|
+
});
|
|
614
|
+
});
|
|
615
|
+
|
|
616
|
+
describe("importCollection", () => {
|
|
617
|
+
it("dispatches request and success", async () => {
|
|
618
|
+
const importCollectionUrl = "/admin/collection/123/import";
|
|
619
|
+
const dispatch = jest.fn();
|
|
620
|
+
|
|
621
|
+
fetchMock.mock(importCollectionUrl, "server response");
|
|
622
|
+
|
|
623
|
+
await actions.importCollection("123", false)(dispatch);
|
|
624
|
+
const fetchArgs = fetchMock.calls();
|
|
625
|
+
|
|
626
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
627
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
628
|
+
`${ActionCreator.IMPORT_COLLECTION}_${ActionCreator.REQUEST}`
|
|
629
|
+
);
|
|
630
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
631
|
+
`${ActionCreator.IMPORT_COLLECTION}_${ActionCreator.SUCCESS}`
|
|
632
|
+
);
|
|
633
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
634
|
+
`${ActionCreator.IMPORT_COLLECTION}_${ActionCreator.LOAD}`
|
|
635
|
+
);
|
|
636
|
+
expect(fetchMock.called()).toBe(true);
|
|
637
|
+
expect(fetchArgs[0][0]).toBe(importCollectionUrl);
|
|
638
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
639
|
+
// `body` is typed as `BodyInit`; this request sends a FormData.
|
|
640
|
+
expect((fetchArgs[0][1].body as FormData).get("force")).toBe("false");
|
|
641
|
+
});
|
|
642
|
+
});
|
|
643
|
+
|
|
644
|
+
describe("fetchIndividualAdmins", () => {
|
|
645
|
+
it("dispatches request, load, and success", async () => {
|
|
646
|
+
const dispatch = jest.fn();
|
|
647
|
+
const individualAdminsData = "individualAdmins";
|
|
648
|
+
fetcher.testData = {
|
|
649
|
+
ok: true,
|
|
650
|
+
status: 200,
|
|
651
|
+
json: () =>
|
|
652
|
+
new Promise<any>((resolve, _reject) => {
|
|
653
|
+
resolve(individualAdminsData);
|
|
654
|
+
}),
|
|
655
|
+
};
|
|
656
|
+
fetcher.resolve = true;
|
|
657
|
+
|
|
658
|
+
const data = await actions.fetchIndividualAdmins()(dispatch);
|
|
659
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
660
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
661
|
+
`${ActionCreator.INDIVIDUAL_ADMINS}_${ActionCreator.REQUEST}`
|
|
662
|
+
);
|
|
663
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
664
|
+
`${ActionCreator.INDIVIDUAL_ADMINS}_${ActionCreator.SUCCESS}`
|
|
665
|
+
);
|
|
666
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
667
|
+
`${ActionCreator.INDIVIDUAL_ADMINS}_${ActionCreator.LOAD}`
|
|
668
|
+
);
|
|
669
|
+
expect(data).toStrictEqual(individualAdminsData);
|
|
670
|
+
});
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
describe("editIndividualAdmin", () => {
|
|
674
|
+
it("dispatches request and success", async () => {
|
|
675
|
+
const editIndividualAdminUrl = "/admin/individual_admins";
|
|
676
|
+
const dispatch = jest.fn();
|
|
677
|
+
const formData = new (window as any).FormData();
|
|
678
|
+
formData.append("email", "email");
|
|
679
|
+
|
|
680
|
+
fetchMock.mock(editIndividualAdminUrl, "server response");
|
|
681
|
+
|
|
682
|
+
await actions.editIndividualAdmin(formData)(dispatch);
|
|
683
|
+
const fetchArgs = fetchMock.calls();
|
|
684
|
+
|
|
685
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
686
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
687
|
+
`${ActionCreator.EDIT_INDIVIDUAL_ADMIN}_${ActionCreator.REQUEST}`
|
|
688
|
+
);
|
|
689
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
690
|
+
`${ActionCreator.EDIT_INDIVIDUAL_ADMIN}_${ActionCreator.SUCCESS}`
|
|
691
|
+
);
|
|
692
|
+
expect(fetchMock.called()).toBe(true);
|
|
693
|
+
expect(fetchArgs[0][0]).toBe(editIndividualAdminUrl);
|
|
694
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
695
|
+
expect(fetchArgs[0][1].body).toBe(formData);
|
|
696
|
+
});
|
|
697
|
+
});
|
|
698
|
+
|
|
699
|
+
describe("getSelfTests", () => {
|
|
700
|
+
it("dispatches request, load, and success", async () => {
|
|
701
|
+
const dispatch = jest.fn();
|
|
702
|
+
const collectionSelfTestURL = "/admin/collection_self_tests";
|
|
703
|
+
const selfTestData = "selfTestData";
|
|
704
|
+
fetcher.testData = {
|
|
705
|
+
ok: true,
|
|
706
|
+
status: 200,
|
|
707
|
+
json: () =>
|
|
708
|
+
new Promise<any>((resolve, _reject) => {
|
|
709
|
+
resolve(selfTestData);
|
|
710
|
+
}),
|
|
711
|
+
};
|
|
712
|
+
fetcher.resolve = true;
|
|
713
|
+
|
|
714
|
+
const data = await actions.getSelfTests(`${collectionSelfTestURL}/1`)(
|
|
715
|
+
dispatch
|
|
716
|
+
);
|
|
717
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
718
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
719
|
+
`${ActionCreator.GET_SELF_TESTS}_${ActionCreator.REQUEST}`
|
|
720
|
+
);
|
|
721
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
722
|
+
`${ActionCreator.GET_SELF_TESTS}_${ActionCreator.SUCCESS}`
|
|
723
|
+
);
|
|
724
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
725
|
+
`${ActionCreator.GET_SELF_TESTS}_${ActionCreator.LOAD}`
|
|
726
|
+
);
|
|
727
|
+
expect(data).toStrictEqual(selfTestData);
|
|
728
|
+
});
|
|
729
|
+
});
|
|
730
|
+
|
|
731
|
+
describe("runSelfTests", () => {
|
|
732
|
+
it("dispatches request and success", async () => {
|
|
733
|
+
const collectionUrl = "/admin/collection_self_tests/";
|
|
734
|
+
const collectionSelfTestURL = `${collectionUrl}/1`;
|
|
735
|
+
const dispatch = jest.fn();
|
|
736
|
+
|
|
737
|
+
fetchMock.mock(collectionSelfTestURL, "server response");
|
|
738
|
+
|
|
739
|
+
await actions.runSelfTests(collectionSelfTestURL)(dispatch);
|
|
740
|
+
const fetchArgs = fetchMock.calls();
|
|
741
|
+
|
|
742
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
743
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
744
|
+
`${ActionCreator.RUN_SELF_TESTS}_${ActionCreator.REQUEST}`
|
|
745
|
+
);
|
|
746
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
747
|
+
`${ActionCreator.RUN_SELF_TESTS}_${ActionCreator.SUCCESS}`
|
|
748
|
+
);
|
|
749
|
+
expect(fetchMock.called()).toBe(true);
|
|
750
|
+
expect(fetchArgs[0][0]).toBe(collectionSelfTestURL);
|
|
751
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
752
|
+
});
|
|
753
|
+
});
|
|
754
|
+
|
|
755
|
+
describe("patronLookup", () => {
|
|
756
|
+
it("dispatches request, success, and load", async () => {
|
|
757
|
+
const formData = new (window as any).FormData();
|
|
758
|
+
formData.append("test", "test");
|
|
759
|
+
const dispatch = jest.fn();
|
|
760
|
+
// prettier-ignore
|
|
761
|
+
const response = "{\"id\": \"test\", \"name\": \"test\"}";
|
|
762
|
+
|
|
763
|
+
fetchMock.mock("/nypl/admin/manage_patrons", response);
|
|
764
|
+
|
|
765
|
+
await actions.patronLookup(formData, "nypl")(dispatch);
|
|
766
|
+
const fetchArgs = fetchMock.calls();
|
|
767
|
+
|
|
768
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
769
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
770
|
+
`${ActionCreator.PATRON_LOOKUP}_${ActionCreator.REQUEST}`
|
|
771
|
+
);
|
|
772
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
773
|
+
`${ActionCreator.PATRON_LOOKUP}_${ActionCreator.SUCCESS}`
|
|
774
|
+
);
|
|
775
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
776
|
+
`${ActionCreator.PATRON_LOOKUP}_${ActionCreator.LOAD}`
|
|
777
|
+
);
|
|
778
|
+
expect(dispatch.mock.calls[2][0].data).toStrictEqual(
|
|
779
|
+
JSON.parse(response)
|
|
780
|
+
);
|
|
781
|
+
expect(fetchMock.called()).toBe(true);
|
|
782
|
+
expect(fetchArgs[0][0]).toBe("/nypl/admin/manage_patrons");
|
|
783
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
784
|
+
expect(fetchArgs[0][1].body).toBe(formData);
|
|
785
|
+
});
|
|
786
|
+
});
|
|
787
|
+
|
|
788
|
+
describe("resetAdobeId", () => {
|
|
789
|
+
it("dispatches request and success", async () => {
|
|
790
|
+
const formData = new (window as any).FormData();
|
|
791
|
+
const dispatch = jest.fn();
|
|
792
|
+
|
|
793
|
+
fetchMock.mock(
|
|
794
|
+
"/nypl/admin/manage_patrons/reset_adobe_id",
|
|
795
|
+
"server response"
|
|
796
|
+
);
|
|
797
|
+
|
|
798
|
+
const data = await actions.resetAdobeId(formData, "nypl")(dispatch);
|
|
799
|
+
const fetchArgs = fetchMock.calls();
|
|
800
|
+
|
|
801
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
802
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
803
|
+
`${ActionCreator.RESET_ADOBE_ID}_${ActionCreator.REQUEST}`
|
|
804
|
+
);
|
|
805
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
806
|
+
`${ActionCreator.RESET_ADOBE_ID}_${ActionCreator.SUCCESS}`
|
|
807
|
+
);
|
|
808
|
+
expect(fetchMock.called()).toBe(true);
|
|
809
|
+
expect(fetchArgs[0][0]).toBe("/nypl/admin/manage_patrons/reset_adobe_id");
|
|
810
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
811
|
+
expect(fetchArgs[0][1].body).toBe(formData);
|
|
812
|
+
expect(data.status).toBe(200);
|
|
813
|
+
});
|
|
814
|
+
});
|
|
815
|
+
|
|
816
|
+
describe("clearPatronData", () => {
|
|
817
|
+
it("dispatches load", () => {
|
|
818
|
+
const dispatch = jest.fn();
|
|
819
|
+
|
|
820
|
+
actions.clearPatronData()(dispatch);
|
|
821
|
+
|
|
822
|
+
expect(dispatch.mock.calls.length).toBe(1);
|
|
823
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
824
|
+
`${ActionCreator.CLEAR_PATRON_DATA}_${ActionCreator.LOAD}`
|
|
825
|
+
);
|
|
826
|
+
expect(dispatch.mock.calls[0][0].data).toBe(null);
|
|
827
|
+
});
|
|
828
|
+
});
|
|
829
|
+
|
|
830
|
+
describe("fetchMoreCustomListEntries", () => {
|
|
831
|
+
it("dispatches request and load", async () => {
|
|
832
|
+
const dispatch = jest.fn();
|
|
833
|
+
|
|
834
|
+
const getState = jest.fn().mockReturnValue({
|
|
835
|
+
editor: {
|
|
836
|
+
customListDetails: {
|
|
837
|
+
data: {
|
|
838
|
+
nextPageUrl: "url",
|
|
839
|
+
},
|
|
840
|
+
isFetchingMoreEntries: false,
|
|
841
|
+
},
|
|
842
|
+
},
|
|
843
|
+
});
|
|
844
|
+
|
|
845
|
+
const customListDetailsData = {
|
|
846
|
+
title: "custom list",
|
|
847
|
+
};
|
|
848
|
+
fetcher.testData = customListDetailsData;
|
|
849
|
+
fetcher.resolve = true;
|
|
850
|
+
|
|
851
|
+
// FIXME: This is a bit of a hack that requires knowing that the implementation of
|
|
852
|
+
// fetchMoreCustomListEntries calls dispatch internally on another action creator.
|
|
853
|
+
// These tests should all be refactored at some point to account for this case.
|
|
854
|
+
const outerDispatch = (action) => action(dispatch);
|
|
855
|
+
|
|
856
|
+
const data = await actions.fetchMoreCustomListEntries()(
|
|
857
|
+
outerDispatch,
|
|
858
|
+
getState
|
|
859
|
+
);
|
|
860
|
+
|
|
861
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
862
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
863
|
+
`${ActionCreator.CUSTOM_LIST_DETAILS_MORE}_${ActionCreator.REQUEST}`
|
|
864
|
+
);
|
|
865
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
866
|
+
`${ActionCreator.CUSTOM_LIST_DETAILS_MORE}_${ActionCreator.SUCCESS}`
|
|
867
|
+
);
|
|
868
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
869
|
+
`${ActionCreator.CUSTOM_LIST_DETAILS_MORE}_${ActionCreator.LOAD}`
|
|
870
|
+
);
|
|
871
|
+
expect(data).toStrictEqual(customListDetailsData);
|
|
872
|
+
});
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
describe("fetchSitewideAnnouncements", () => {
|
|
876
|
+
it("dispatches request, load, and success", async () => {
|
|
877
|
+
const dispatch = jest.fn();
|
|
878
|
+
const sitewideAnnouncementsData = "sitewide announcements";
|
|
879
|
+
fetcher.testData = {
|
|
880
|
+
ok: true,
|
|
881
|
+
status: 200,
|
|
882
|
+
json: () =>
|
|
883
|
+
new Promise<any>((resolve) => {
|
|
884
|
+
resolve(sitewideAnnouncementsData);
|
|
885
|
+
}),
|
|
886
|
+
};
|
|
887
|
+
fetcher.resolve = true;
|
|
888
|
+
|
|
889
|
+
const data = await actions.fetchSitewideAnnouncements()(dispatch);
|
|
890
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
891
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
892
|
+
`${ActionCreator.SITEWIDE_ANNOUNCEMENTS}_${ActionCreator.REQUEST}`
|
|
893
|
+
);
|
|
894
|
+
expect(dispatch.mock.calls[0][0].url).toBe("/admin/announcements");
|
|
895
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
896
|
+
`${ActionCreator.SITEWIDE_ANNOUNCEMENTS}_${ActionCreator.SUCCESS}`
|
|
897
|
+
);
|
|
898
|
+
expect(dispatch.mock.calls[2][0].type).toBe(
|
|
899
|
+
`${ActionCreator.SITEWIDE_ANNOUNCEMENTS}_${ActionCreator.LOAD}`
|
|
900
|
+
);
|
|
901
|
+
expect(data).toStrictEqual(sitewideAnnouncementsData);
|
|
902
|
+
});
|
|
903
|
+
});
|
|
904
|
+
|
|
905
|
+
describe("editSitewideAnnouncements", () => {
|
|
906
|
+
it("dispatches request and success", async () => {
|
|
907
|
+
const editSitewideAnnouncementsUrl = "/admin/announcements";
|
|
908
|
+
const dispatch = jest.fn();
|
|
909
|
+
const formData = new (window as any).FormData();
|
|
910
|
+
formData.append("announcements", "[]");
|
|
911
|
+
|
|
912
|
+
fetchMock.mock(editSitewideAnnouncementsUrl, "server response");
|
|
913
|
+
|
|
914
|
+
await actions.editSitewideAnnouncements(formData)(dispatch);
|
|
915
|
+
const fetchArgs = fetchMock.calls();
|
|
916
|
+
|
|
917
|
+
expect(dispatch.mock.calls.length).toBe(3);
|
|
918
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
919
|
+
`${ActionCreator.EDIT_SITEWIDE_ANNOUNCEMENTS}_${ActionCreator.REQUEST}`
|
|
920
|
+
);
|
|
921
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
922
|
+
`${ActionCreator.EDIT_SITEWIDE_ANNOUNCEMENTS}_${ActionCreator.SUCCESS}`
|
|
923
|
+
);
|
|
924
|
+
expect(fetchMock.called()).toBe(true);
|
|
925
|
+
expect(fetchArgs[0][0]).toBe(editSitewideAnnouncementsUrl);
|
|
926
|
+
expect(fetchArgs[0][1].method).toBe("POST");
|
|
927
|
+
expect(fetchArgs[0][1].body).toBe(formData);
|
|
928
|
+
});
|
|
929
|
+
});
|
|
930
|
+
|
|
931
|
+
describe("openCustomListEditor", () => {
|
|
932
|
+
it("dispatches CUSTOM_LIST_DETAILS_CLEAR and OPEN_CUSTOM_LIST_EDITOR", async () => {
|
|
933
|
+
const dispatch = jest.fn();
|
|
934
|
+
|
|
935
|
+
const getState = () => ({
|
|
936
|
+
editor: {
|
|
937
|
+
customLists: {
|
|
938
|
+
data: {
|
|
939
|
+
foo: "bar",
|
|
940
|
+
},
|
|
941
|
+
},
|
|
942
|
+
},
|
|
943
|
+
});
|
|
944
|
+
|
|
945
|
+
await actions.openCustomListEditor("list_id")(dispatch, getState);
|
|
946
|
+
|
|
947
|
+
expect(dispatch.mock.calls.length).toBe(2);
|
|
948
|
+
|
|
949
|
+
expect(dispatch.mock.calls[0][0].type).toBe(
|
|
950
|
+
`${ActionCreator.CUSTOM_LIST_DETAILS}_${ActionCreator.CLEAR}`
|
|
951
|
+
);
|
|
952
|
+
|
|
953
|
+
expect(dispatch.mock.calls[1][0].type).toBe(
|
|
954
|
+
ActionCreator.OPEN_CUSTOM_LIST_EDITOR
|
|
955
|
+
);
|
|
956
|
+
expect(dispatch.mock.calls[1][0].id).toBe("list_id");
|
|
957
|
+
expect(dispatch.mock.calls[1][0].data).toStrictEqual(
|
|
958
|
+
getState().editor.customLists.data
|
|
959
|
+
);
|
|
960
|
+
});
|
|
961
|
+
});
|
|
962
|
+
});
|