@thepalaceproject/circulation-admin 0.0.0-post.1

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.
Files changed (72) hide show
  1. package/.eslintrc +59 -0
  2. package/.node-version +1 -0
  3. package/.nvmrc +1 -0
  4. package/.prettierrc.json +10 -0
  5. package/.sass-lint.yml +37 -0
  6. package/CHANGELOG.md +946 -0
  7. package/README.md +155 -0
  8. package/dist/060b2710bdbbe3dfe48b58d59bd5f1fb.svg +288 -0
  9. package/dist/0db1520f47986b6c755a.svg +1 -0
  10. package/dist/1e59d2330b4c6deb84b3.ttf +0 -0
  11. package/dist/20fd1704ea223900efa9.woff2 +0 -0
  12. package/dist/4692b9ec53fd5972caa2.ttf +0 -0
  13. package/dist/5be1347c682810f199c7.eot +0 -0
  14. package/dist/6563aa3790be8329e4f2.svg +1 -0
  15. package/dist/82b1212e45a2bc35dd73.woff +0 -0
  16. package/dist/8b43027f47b20503057d.eot +0 -0
  17. package/dist/PalaceCollectionManagerLogo.svg +122 -0
  18. package/dist/be810be3a3e14c682a25.woff2 +0 -0
  19. package/dist/c1e38fd9e0e74ba58f7a2b77ef29fdd3.svg +2671 -0
  20. package/dist/circulation-admin.css +6841 -0
  21. package/dist/circulation-admin.js +2 -0
  22. package/dist/circulation-admin.js.LICENSE.txt +153 -0
  23. package/dist/f691f37e57f04c152e23.woff +0 -0
  24. package/jest.config.js +15 -0
  25. package/jest.polyfills.js +12 -0
  26. package/nightwatch.json +58 -0
  27. package/package.json +155 -0
  28. package/pull_request_template.md +22 -0
  29. package/requirements-ci.txt +1 -0
  30. package/testReporter.js +31 -0
  31. package/tests/__data__/statisticsApiResponseData.ts +327 -0
  32. package/tests/__mocks__/fileMock.js +1 -0
  33. package/tests/__mocks__/styleMock.js +1 -0
  34. package/tests/browser/README.md +19 -0
  35. package/tests/browser/assertions/noError.js +38 -0
  36. package/tests/browser/commands/goHome.js +13 -0
  37. package/tests/browser/commands/signIn.js +18 -0
  38. package/tests/browser/globals.js.sample +5 -0
  39. package/tests/browser/navigate.js +294 -0
  40. package/tests/browser/pages/book.js +21 -0
  41. package/tests/browser/pages/catalog.js +24 -0
  42. package/tests/browser/pages/login.js +11 -0
  43. package/tests/browser/redirect.js +104 -0
  44. package/tests/browser/signInFailure.js +22 -0
  45. package/tests/jest/README.md +6 -0
  46. package/tests/jest/api/admin.test.ts +60 -0
  47. package/tests/jest/businessRules/roleBasedAccess.test.ts +250 -0
  48. package/tests/jest/components/AdvancedSearchBuilder.test.tsx +38 -0
  49. package/tests/jest/components/BookEditor.test.tsx +240 -0
  50. package/tests/jest/components/CirculationEventsDownload.test.tsx +65 -0
  51. package/tests/jest/components/CustomLists.test.tsx +203 -0
  52. package/tests/jest/components/EditableInput.test.tsx +64 -0
  53. package/tests/jest/components/IndividualAdminEditForm.test.tsx +128 -0
  54. package/tests/jest/components/InventoryReportRequestModal.test.tsx +652 -0
  55. package/tests/jest/components/Lane.test.tsx +78 -0
  56. package/tests/jest/components/LaneEditor.test.tsx +148 -0
  57. package/tests/jest/components/ProtocolFormField.test.tsx +37 -0
  58. package/tests/jest/components/QuicksightDashboard.test.tsx +67 -0
  59. package/tests/jest/components/Stats.test.tsx +699 -0
  60. package/tests/jest/context/AppContext.test.tsx +113 -0
  61. package/tests/jest/features/book.test.ts +396 -0
  62. package/tests/jest/jest-setup.ts +1 -0
  63. package/tests/jest/sample/sample.test.js +3 -0
  64. package/tests/jest/testUtils/renderWithContext.tsx +38 -0
  65. package/tests/jest/testUtils/withProviders.tsx +92 -0
  66. package/tests/jest/utils/NoCacheDataFetcher.test.ts +75 -0
  67. package/tsconfig.json +25 -0
  68. package/tslint.json +56 -0
  69. package/webpack.common.js +72 -0
  70. package/webpack.dev-server.config.js +215 -0
  71. package/webpack.dev.config.js +9 -0
  72. package/webpack.prod.config.js +8 -0
@@ -0,0 +1,294 @@
1
+ const breadcrumbSelector = "ol.breadcrumb";
2
+ let loadingSelector;
3
+ let catalogPage;
4
+ let bookPage;
5
+
6
+ module.exports = {
7
+ /**
8
+ * Before any tests run, log in with the correct credentials.
9
+ */
10
+ before: (browser, done) => {
11
+ const { username, password } = browser.globals;
12
+ catalogPage = browser.page.catalog();
13
+ bookPage = browser.page.book();
14
+ loadingSelector = catalogPage.elements.loadingSelector;
15
+
16
+ browser
17
+ .resizeWindow(1200, 900)
18
+ .signIn(username, password)
19
+ .perform(() => {
20
+ done();
21
+ });
22
+ },
23
+
24
+ "navigate to the first lane and back": function(browser) {
25
+ const { laneSelector } = catalogPage.elements;
26
+ const { nthBreadcrumbSelector } = catalogPage;
27
+
28
+ browser
29
+ .goHome()
30
+ .url(function(result) {
31
+ let catalogUrl = result.value;
32
+ this.getAttribute(laneSelector, "href", function(result) {
33
+ let laneUrl = result.value;
34
+ this.getText(laneSelector, function(laneText) {
35
+ let laneTitle = laneText.value;
36
+
37
+ this.click(laneSelector)
38
+ .waitForElementNotPresent(loadingSelector, 5000)
39
+ .verify.noError()
40
+ .verify.urlEquals(laneUrl)
41
+ .verify.titleContains(laneTitle)
42
+ // when a lane selector is clicked, we go into another
43
+ // navigation level
44
+ .verify.elementPresent(nthBreadcrumbSelector(3))
45
+ .back()
46
+ .waitForElementNotPresent(loadingSelector, 5000)
47
+ .verify.urlEquals(catalogUrl)
48
+ .verify.elementNotPresent(nthBreadcrumbSelector(3));
49
+ });
50
+ });
51
+ });
52
+ },
53
+
54
+ "navigate to the first book in the first lane and back": function(browser) {
55
+ const {
56
+ bookSelector,
57
+ bookLinkTitleSelector
58
+ } = catalogPage.elements;
59
+ const { bookTitleSelector } = bookPage.elements;
60
+
61
+ browser
62
+ .goHome()
63
+ .url(function(result) {
64
+ let catalogUrl = result.value;
65
+ this.getAttribute(bookSelector, "href", function(result) {
66
+ let bookUrl = result.value;
67
+ this.getText(bookLinkTitleSelector, function(result) {
68
+ let bookTitle = result.value;
69
+ this
70
+ .click(bookSelector)
71
+ .waitForElementPresent(bookTitleSelector, 5000)
72
+ .verify.noError()
73
+ .verify.urlEquals(bookUrl)
74
+ .verify.titleContains(bookTitle)
75
+ .verify.containsText(bookTitleSelector, bookTitle)
76
+ .back()
77
+ .waitForElementNotPresent(loadingSelector, 5000)
78
+ .verify.urlEquals(catalogUrl)
79
+ .verify.elementNotPresent(bookTitleSelector);
80
+ });
81
+ });
82
+ });
83
+ },
84
+
85
+ "navigate to the first book, click through tabs, refresh page, go back": function(browser) {
86
+ const { bookSelector } = catalogPage.elements;
87
+ const {
88
+ bookTitleSelector,
89
+ titleInputSelector,
90
+ genreInputSelector,
91
+ coverInputSelector,
92
+ complaintInputSelector,
93
+ listInputSelector,
94
+ editTabSelector,
95
+ classificationsTabSelector,
96
+ coverTabSelector,
97
+ complaintsTabSelector,
98
+ listsTabSelector
99
+ } = bookPage.elements;
100
+
101
+ browser
102
+ .goHome()
103
+ .getAttribute(bookSelector, "href", function(result) {
104
+ let bookUrl = result.value;
105
+ this.getAttribute(bookSelector, "title", function(result) {
106
+ let bookTitle = result.value;
107
+ this
108
+ .click(bookSelector)
109
+ .waitForElementPresent(bookTitleSelector, 5000)
110
+ .verify.noError()
111
+ .verify.urlEquals(bookUrl)
112
+ .verify.containsText(bookTitleSelector, bookTitle)
113
+
114
+ // go to the edit tab
115
+ .click(editTabSelector)
116
+ .waitForElementPresent(titleInputSelector, 5000)
117
+ .verify.urlContains("tab/edit")
118
+ .verify.value(titleInputSelector, bookTitle)
119
+
120
+ // go to the classifications tab
121
+ .click(classificationsTabSelector)
122
+ .waitForElementPresent(genreInputSelector, 5000)
123
+ .verify.urlContains("tab/classifications")
124
+
125
+ // go to the image cover tab
126
+ .click(coverTabSelector)
127
+ .waitForElementPresent(coverInputSelector, 5000)
128
+ .verify.urlContains("tab/cover")
129
+
130
+ // go to the complaints tab
131
+ .click(complaintsTabSelector)
132
+ .waitForElementPresent(complaintInputSelector, 5000)
133
+ .verify.urlContains("tab/complaints")
134
+ .refresh()
135
+ .waitForElementPresent(complaintInputSelector, 5000)
136
+ .verify.urlContains("tab/complaints")
137
+ .verify.titleContains(bookTitle)
138
+
139
+ // go to the list tab
140
+ .click(listsTabSelector)
141
+ .waitForElementPresent(listInputSelector, 5000)
142
+ .verify.urlContains("tab/list")
143
+
144
+ // go back to the complaints tab
145
+ .back()
146
+ // go back to the cover tab
147
+ .back()
148
+ // go back to the classifications tab
149
+ .back()
150
+ // go back to the edit tab
151
+ .back()
152
+ // go back to the main details tab
153
+ .back()
154
+ .waitForElementPresent(bookTitleSelector, 5000)
155
+ .verify.urlEquals(bookUrl);
156
+ });
157
+ });
158
+ },
159
+
160
+ "navigate to top-level feeds": function(browser) {
161
+ const {
162
+ laneSelector,
163
+ complaintsSelector,
164
+ hiddenSelector
165
+ } = catalogPage.elements;
166
+ const { nthBreadcrumbSelector } = catalogPage;
167
+
168
+ browser
169
+ .goHome()
170
+ .getAttribute(complaintsSelector, "href", function(result) {
171
+ let complaintsUrl = result.value;
172
+ this.getText(complaintsSelector, function(result) {
173
+ let complaintsTitle = result.value;
174
+ this.getAttribute(hiddenSelector, "href", function(result) {
175
+ let hiddenUrl = result.value
176
+ this.getText(hiddenSelector, function(result) {
177
+ let hiddenTitle = result.value;
178
+ this.getText(laneSelector, function(result) {
179
+ let laneTitle = result.value;
180
+ this
181
+ // go to the first lane
182
+ .click(laneSelector)
183
+ .waitForElementNotPresent(loadingSelector, 5000)
184
+ .waitForElementPresent(nthBreadcrumbSelector(2), 5000)
185
+ .assert.noError()
186
+ .verify.containsText(nthBreadcrumbSelector(1), "All Books")
187
+ .verify.containsText(nthBreadcrumbSelector(2), "Book")
188
+ .verify.containsText(nthBreadcrumbSelector(3), laneTitle)
189
+
190
+ // go to the complaints page
191
+ .click(complaintsSelector)
192
+ .waitForElementNotPresent(loadingSelector, 5000)
193
+ .assert.noError()
194
+ .assert.containsText(nthBreadcrumbSelector(1), "All Books")
195
+ .assert.containsText(nthBreadcrumbSelector(2), complaintsTitle)
196
+ .verify.urlEquals(complaintsUrl)
197
+
198
+ // go to the hidden books page
199
+ .click(hiddenSelector)
200
+ .waitForElementNotPresent(loadingSelector, 5000)
201
+ .assert.noError()
202
+ .assert.containsText(nthBreadcrumbSelector(1), "All Books")
203
+ .assert.containsText(nthBreadcrumbSelector(2), hiddenTitle)
204
+ .verify.urlEquals(hiddenUrl);
205
+ });
206
+ });
207
+ });
208
+ });
209
+ });
210
+ },
211
+
212
+ "navigate to dashboard and back to catalog": function(browser) {
213
+ const {
214
+ catalogSelector,
215
+ dashboardSelector,
216
+ circulationLibraryStatsSelector,
217
+ circulationAllStatsSelector,
218
+ } = catalogPage.elements;
219
+ const { nthBreadcrumbSelector } = catalogPage;
220
+
221
+ browser
222
+ .goHome()
223
+ .getAttribute(nthBreadcrumbSelector(1), "title", function(result) {
224
+ let libraryName = result.value;
225
+ this.getAttribute(catalogSelector, "href", function(result) {
226
+ let catalogUrl = result.value;
227
+ this.getAttribute(dashboardSelector, "href", function(result) {
228
+ let dashboardUrl = result.value
229
+ this
230
+ // go to the dashboard
231
+ .click(dashboardSelector)
232
+ .waitForElementNotPresent(loadingSelector, 5000)
233
+ .assert.noError()
234
+ .verify.elementPresent(circulationLibraryStatsSelector)
235
+ .verify.elementPresent(circulationAllStatsSelector)
236
+ .verify.titleContains("Palace Collection Manager - Dashboard")
237
+
238
+ // click the main navigation link
239
+ .click(catalogSelector)
240
+ .waitForElementNotPresent(loadingSelector, 5000)
241
+ .assert.noError()
242
+ .verify.elementPresent(nthBreadcrumbSelector(1))
243
+ .verify.urlEquals(catalogUrl)
244
+ .verify.titleContains(`Palace Collection Manager - ${libraryName}`);
245
+ });
246
+ });
247
+ });
248
+ },
249
+
250
+ "navigate to two different book detail pages": function(browser) {
251
+ const {
252
+ laneSelector,
253
+ firstBookSelector,
254
+ secondBookSelector
255
+ } = catalogPage.elements;
256
+ const { bookTitleSelector } = bookPage.elements;
257
+ const { nthBreadcrumbSelector } = catalogPage;
258
+
259
+ browser
260
+ .goHome()
261
+
262
+ // go to the first book
263
+ .click(firstBookSelector)
264
+ .waitForElementNotPresent(loadingSelector, 5000)
265
+ .waitForElementPresent(bookTitleSelector, 5000)
266
+ .getText(bookTitleSelector, function(result) {
267
+ let firstTitle = result.value;
268
+
269
+ this
270
+ // go back to the catalog
271
+ .click(nthBreadcrumbSelector(1))
272
+ .waitForElementNotPresent(loadingSelector, 5000)
273
+ .waitForElementPresent(secondBookSelector, 5000)
274
+
275
+ // go to the second book
276
+ .click(secondBookSelector)
277
+ .waitForElementNotPresent(loadingSelector, 5000)
278
+ .waitForElementPresent(bookTitleSelector, 50000)
279
+
280
+ // making sure that we are on a new book
281
+ .getText(bookTitleSelector, function(result) {
282
+ let secondTitle = result.value;
283
+ this.assert.notEqual(firstTitle, secondTitle);
284
+ });
285
+ });
286
+ },
287
+
288
+ /**
289
+ * Correctly end the selenium server and tests
290
+ */
291
+ after: (browser) => {
292
+ browser.end();
293
+ }
294
+ };
@@ -0,0 +1,21 @@
1
+ // Page Object for a book page
2
+ module.exports = {
3
+ elements: {
4
+ // Elements found on each tab
5
+ bookTitleSelector: ".book-details .title",
6
+ titleInputSelector: "input[name='title']",
7
+ genreInputSelector: "select[name='genre']",
8
+ // 2nd child because the first is a label
9
+ genreSecondOptionSelector: "select[name='genre'] option:nth-child(2)",
10
+ coverInputSelector: "input[name='cover_url']",
11
+ complaintInputSelector: "select[name='type']",
12
+ listInputSelector: "input[name='list']",
13
+ // Tab selectors
14
+ detailsTabSelector: "ul.nav-tabs li:nth-child(1) a",
15
+ editTabSelector: "ul.nav-tabs li:nth-child(2) a",
16
+ classificationsTabSelector: "ul.nav-tabs li:nth-child(3) a",
17
+ coverTabSelector: "ul.nav-tabs li:nth-child(4) a",
18
+ complaintsTabSelector: "ul.nav-tabs li:nth-child(5) a",
19
+ listsTabSelector: "ul.nav-tabs li:nth-child(6) a",
20
+ }
21
+ };
@@ -0,0 +1,24 @@
1
+ // Page Object for the catalog
2
+ module.exports = {
3
+ elements: {
4
+ loadingSelector: ".loading",
5
+ laneSelector: "li:first-child .lane h2 a",
6
+ bookSelector: ".lane-books li:first-child a",
7
+ bookLinkTitleSelector: ".lane-books li:first-child a .title",
8
+ catalogSelector: "ul.nav li:nth-child(1) a",
9
+ complaintsSelector: "ul.nav li:nth-child(2) a",
10
+ hiddenSelector: "ul.nav li:nth-child(3) a",
11
+ dashboardSelector: "ul.nav li:nth-child(6) a",
12
+ circulationLibraryStatsSelector: ".library-stats:nth-child(1) h2",
13
+ circulationAllStatsSelector: ".library-stats:nth-child(2) h2",
14
+ firstBookSelector: "li:nth-child(1) .book a",
15
+ secondBookSelector: "li:nth-child(2) .book a",
16
+ },
17
+ commands: [
18
+ {
19
+ nthBreadcrumbSelector: function(n) {
20
+ return `ol.breadcrumb li:nth-child(${n})`
21
+ }
22
+ }
23
+ ]
24
+ };
@@ -0,0 +1,11 @@
1
+ // Page Object for the login page
2
+ module.exports = {
3
+ url: function() {
4
+ return this.api.globals.homeUrl;
5
+ },
6
+ elements: {
7
+ username: "input[type='text']",
8
+ password: "input[type='password']",
9
+ submit: "button[type='submit']"
10
+ }
11
+ };
@@ -0,0 +1,104 @@
1
+ const http = require('follow-redirects').http
2
+
3
+ const fetchGroupPage = (browser) => {
4
+ return new Promise((resolve, reject) => {
5
+ http.get({
6
+ host: "localhost",
7
+ port: 6500,
8
+ path: "/groups/"
9
+ }, (response) => {
10
+ let body = "";
11
+
12
+ response.on("data", (chunk) => {
13
+ body += chunk;
14
+ });
15
+
16
+ response.on("error", (err) => {
17
+ reject(err);
18
+ });
19
+
20
+ response.on("end", () => {
21
+ resolve(body);
22
+ });
23
+ });
24
+ });
25
+ }
26
+ const getAdminBookUrlAndTitle = (body, browser) => {
27
+ const bookTitle = body.match(/<entry [\s\S]+?<title>([^<]+)<\/title>/i)[1];
28
+ const link = body.match(/<link [^>]*rel="alternate[^>]+\/>/i)[0];
29
+ const id = body.match(/<id>[\s\S]+?<\/id>/i)[0];
30
+ const lib = id.match(/\/[\w]+/i)[0]; // includes forward slash
31
+ const bookUrl = link.match(/href="([^"]+)"/)[1];
32
+ const entryBaseUrl = browser.globals.homeUrl.replace("/admin/web/", lib + "/works");
33
+
34
+ // transform the book url into an admin book url
35
+ const adminBookUrl =
36
+ browser.globals.homeUrl + "collection" + lib + "/book" + lib +
37
+ encodeURIComponent(
38
+ bookUrl.replace(entryBaseUrl, "")
39
+ );
40
+
41
+ return { adminBookUrl, bookTitle };
42
+ };
43
+ const getAdminListUrl = (body, browser) => {
44
+ const listBaseUrl = `${browser.globals.homeUrl}lists`;
45
+ const id = body.match(/<id>[\s\S]+?<\/id>/i)[0];
46
+ const libraryName = id.match(/\/[\w]+/i)[0]; // includes forward slash
47
+
48
+ return `${listBaseUrl}${libraryName}`;
49
+ };
50
+ let body;
51
+ let loginPage;
52
+ let loadingSelector;
53
+
54
+ module.exports = {
55
+ beforeEach: (browser, done) => {
56
+ loginPage = browser.page.login();
57
+ loadingSelector = browser.page.catalog().elements.loadingSelector;
58
+
59
+ fetchGroupPage(browser)
60
+ .then(data => {
61
+ body = data
62
+ done();
63
+ });
64
+ },
65
+
66
+ "attempt to view the admin list page before signing in": (browser) => {
67
+ const adminListUrl = getAdminListUrl(body, browser);
68
+ const { username, password, submit } = loginPage.elements;
69
+
70
+ // Go to the admin list page, get redirected to the login page with the
71
+ // redirect in the url, log in successfully, then go to the admin list page
72
+ browser
73
+ .url(adminListUrl)
74
+ .waitForElementVisible(username, 1000)
75
+ .assert.urlContains("redirect=" + encodeURIComponent(adminListUrl))
76
+ .setValue(username, browser.globals.username)
77
+ .setValue(password, browser.globals.password)
78
+ .click(submit)
79
+ .waitForElementVisible(loadingSelector, 1000)
80
+ .assert.urlContains(adminListUrl);
81
+ },
82
+
83
+ // TODO: Update once flask has been updated on the server
84
+ // "attempt to view a book page before signing in": (browser) => {
85
+ // const { adminBookUrl, bookTitle } = getAdminBookUrlAndTitle(body, browser);
86
+ // const { username, password, submit } = loginPage.elements;
87
+ // const { bookTitleSelector } = browser.page.book().elements;
88
+
89
+ // browser
90
+ // .url(adminBookUrl)
91
+ // .waitForElementVisible(username, 1000)
92
+ // .verify.urlContains("redirect=" + encodeURIComponent(adminBookUrl))
93
+ // .setValue(username, browser.globals.username)
94
+ // .setValue(password, browser.globals.password)
95
+ // .click(submit)
96
+ // .waitForElementVisible(loadingSelector, 1000)
97
+ // .verify.containsText(bookTitleSelector, bookTitle)
98
+ // .assert.urlContains(adminBookUrl);
99
+ // },
100
+
101
+ afterEach: (browser) => {
102
+ browser.end();
103
+ }
104
+ };
@@ -0,0 +1,22 @@
1
+ module.exports = {
2
+
3
+ /**
4
+ * The log in error page contains a simple message and a link to go back
5
+ * to the log in page.
6
+ */
7
+ "go to the error page with bad log in credentials": (browser) => {
8
+ const errorMessage = "p";
9
+ const tryAgainButton = "a";
10
+
11
+ browser
12
+ .resizeWindow(1200, 900)
13
+ .signIn("bad email", "bad password")
14
+ .waitForElementVisible("body", 10000)
15
+ .expect.element(errorMessage).text.to.contain("401 ERROR");
16
+
17
+ browser
18
+ .assert.attributeContains(tryAgainButton, "href", "/admin/sign_in");
19
+
20
+ browser.end();
21
+ }
22
+ };
@@ -0,0 +1,6 @@
1
+ # Jest Unit Tests
2
+
3
+ This directory contains unit tests that run using jest. The directory structure should mirror that of the `src` tree.
4
+
5
+ To run these tests, use the command `npm run test-jest`. These tests are executed along with the older mocha-based tests when `npm test` is run.
6
+ To run a single test file, use the command `npm run test-jest-file [filename]`.
@@ -0,0 +1,60 @@
1
+ import {
2
+ DEFAULT_BASE_ENDPOINT_URL,
3
+ getInventoryReportInfo,
4
+ requestInventoryReport,
5
+ } from "../../../src/api/admin";
6
+ import * as fetchMock from "fetch-mock-jest";
7
+
8
+ const sampleInfoResponseData = { collections: [] };
9
+ const sampleGenerateResponseData = { message: "some message" };
10
+
11
+ const testAlternateBaseUrl = "/test/base/url";
12
+ const libraryKey = "short-name";
13
+
14
+ const testEndpoints = ({
15
+ title,
16
+ baseEndpointUrl: baseEndpointUrl = undefined,
17
+ expectedUrl = DEFAULT_BASE_ENDPOINT_URL,
18
+ }) => {
19
+ describe(title, () => {
20
+ beforeEach(() => {
21
+ fetchMock
22
+ .get("*", { body: sampleInfoResponseData, status: 200 })
23
+ .post("*", { body: sampleGenerateResponseData, status: 202 });
24
+ });
25
+
26
+ afterEach(() => {
27
+ fetchMock.mockReset();
28
+ });
29
+
30
+ it("requests inventory report information", async () => {
31
+ const response = await getInventoryReportInfo({
32
+ library: libraryKey,
33
+ baseEndpointUrl,
34
+ });
35
+ expect(response).toStrictEqual(sampleInfoResponseData);
36
+ expect(fetchMock).toHaveBeenCalledWith(expectedUrl);
37
+ });
38
+
39
+ it("requests report generation via a post to the endpoint", async () => {
40
+ const response = await requestInventoryReport({
41
+ library: libraryKey,
42
+ baseEndpointUrl,
43
+ });
44
+ expect(response).toStrictEqual(sampleGenerateResponseData);
45
+ expect(fetchMock).toHaveBeenCalledWith(expectedUrl, { method: "POST" });
46
+ });
47
+ });
48
+ };
49
+
50
+ describe("Inventory report API", () => {
51
+ testEndpoints({
52
+ title: "default endpoints",
53
+ expectedUrl: `${DEFAULT_BASE_ENDPOINT_URL}/${libraryKey}`,
54
+ });
55
+ testEndpoints({
56
+ title: "alternative test endpoints",
57
+ baseEndpointUrl: testAlternateBaseUrl,
58
+ expectedUrl: `${testAlternateBaseUrl}/${libraryKey}`,
59
+ });
60
+ });