@thepalaceproject/circulation-admin 1.43.0-post.9 → 1.44.0-post.3

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 (73) hide show
  1. package/CLAUDE.md +22 -10
  2. package/README.md +11 -5
  3. package/dist/circulation-admin.js +1 -1
  4. package/jest.config.js +11 -44
  5. package/package.json +1 -5
  6. package/tests/jest/components/AdvancedSearchBuilder.test.tsx +111 -0
  7. package/tests/jest/components/Announcement.test.tsx +76 -0
  8. package/tests/jest/components/AnnouncementForm.test.tsx +229 -0
  9. package/tests/jest/components/AnnouncementsSection.test.tsx +146 -0
  10. package/tests/jest/components/Autocomplete.test.tsx +67 -0
  11. package/tests/jest/components/BookCoverEditor.test.tsx +393 -0
  12. package/tests/jest/components/BookDetailsEditor.test.tsx +275 -0
  13. package/tests/jest/components/BookDetailsTabContainer.test.tsx +237 -0
  14. package/tests/jest/components/BookEditForm.test.tsx +352 -0
  15. package/tests/jest/components/BookEditor.test.tsx +20 -21
  16. package/tests/jest/components/CatalogPage.test.tsx +158 -0
  17. package/tests/jest/components/CatalogServices.test.tsx +38 -1
  18. package/tests/jest/components/ChangePasswordForm.test.tsx +163 -0
  19. package/tests/jest/components/Classifications.test.tsx +166 -0
  20. package/tests/jest/components/ClassificationsForm.test.tsx +458 -0
  21. package/tests/jest/components/ClassificationsTable.test.tsx +57 -0
  22. package/tests/jest/components/Collections.test.tsx +335 -7
  23. package/tests/jest/components/ColorPicker.test.tsx +58 -0
  24. package/tests/jest/components/ComplaintForm.test.tsx +171 -0
  25. package/tests/jest/components/Complaints.test.tsx +259 -0
  26. package/tests/jest/components/ConfigTabContainer.test.tsx +196 -0
  27. package/tests/jest/components/ContextProvider.test.tsx +138 -0
  28. package/tests/jest/components/Contributors.test.tsx +157 -0
  29. package/tests/jest/components/CustomListEditor.test.tsx +367 -0
  30. package/tests/jest/components/CustomListEntriesEditor.test.tsx +1240 -0
  31. package/tests/jest/components/CustomLists.test.tsx +621 -4
  32. package/tests/jest/components/CustomListsForBook.test.tsx +353 -0
  33. package/tests/jest/components/DiagnosticsServiceTabs.test.tsx +141 -0
  34. package/tests/jest/components/DiagnosticsServiceType.test.tsx +75 -0
  35. package/tests/jest/components/DiscoveryServices.test.tsx +154 -7
  36. package/tests/jest/components/EditableConfigList.test.tsx +598 -7
  37. package/tests/jest/components/EditableInput.test.tsx +250 -1
  38. package/tests/jest/components/EditorField.test.tsx +95 -0
  39. package/tests/jest/components/GenreForm.test.tsx +152 -0
  40. package/tests/jest/components/Header.test.tsx +421 -0
  41. package/tests/jest/components/IndividualAdminEditForm.test.tsx +506 -1
  42. package/tests/jest/components/IndividualAdmins.test.tsx +124 -8
  43. package/tests/jest/components/InputList.test.tsx +493 -0
  44. package/tests/jest/components/Lane.test.tsx +132 -10
  45. package/tests/jest/components/LaneCustomListsEditor.test.tsx +450 -0
  46. package/tests/jest/components/LaneEditor.test.tsx +377 -9
  47. package/tests/jest/components/Lanes.test.tsx +446 -0
  48. package/tests/jest/components/LanesSidebar.test.tsx +621 -0
  49. package/tests/jest/components/Libraries.test.tsx +48 -0
  50. package/tests/jest/components/LibraryEditForm.test.tsx +383 -0
  51. package/tests/jest/components/LibraryRegistration.test.tsx +354 -0
  52. package/tests/jest/components/LibraryRegistrationForm.test.tsx +203 -0
  53. package/tests/jest/components/MetadataServices.test.tsx +37 -1
  54. package/tests/jest/components/NeighborhoodAnalyticsForm.test.tsx +167 -0
  55. package/tests/jest/components/PairedMenus.test.tsx +220 -0
  56. package/tests/jest/components/PatronAuthServices.test.tsx +114 -0
  57. package/tests/jest/components/ProtocolFormField.test.tsx +443 -7
  58. package/tests/jest/components/ResetAdobeId.test.tsx +302 -0
  59. package/tests/jest/components/SelfTests.test.tsx +601 -0
  60. package/tests/jest/components/SelfTestsTabContainer.test.tsx +216 -0
  61. package/tests/jest/components/ServiceEditForm.test.tsx +1092 -0
  62. package/tests/jest/components/SitewideAnnouncements.test.tsx +134 -0
  63. package/tests/jest/components/Stats.test.tsx +0 -7
  64. package/tests/jest/components/TextWithEditMode.test.tsx +218 -0
  65. package/tests/jest/components/ToolTip.test.tsx +46 -0
  66. package/tests/jest/components/TroubleshootingCategoryPage.test.tsx +69 -0
  67. package/tests/jest/components/TroubleshootingPage.test.tsx +94 -0
  68. package/tests/jest/features/book.test.ts +75 -80
  69. package/tests/jest/fixtures/classificationsData.ts +45 -0
  70. package/tests/jest/fixtures/genreData.ts +811 -0
  71. package/tests/jest/README.md +0 -6
  72. package/tests/jest/legacy-setup.ts +0 -13
  73. package/tests/jest/legacyJsdomEnvironment.js +0 -49
@@ -0,0 +1,216 @@
1
+ import * as React from "react";
2
+ import * as PropTypes from "prop-types";
3
+ import { render, screen, waitFor } from "@testing-library/react";
4
+ import userEvent from "@testing-library/user-event";
5
+
6
+ import buildStore from "../../../src/store";
7
+
8
+ // Each active tab renders the connected SelfTestsCategory, which fetches on mount
9
+ // and recurses into the self-tests machinery. This container's behavior is which
10
+ // slice of the store each category gets and under what type/link name, so mock it
11
+ // to a marker echoing those. `data-items` names the slice's contents so passing
12
+ // the wrong category's items — or the whole items object — is visible.
13
+ jest.mock("../../../src/components/SelfTestsCategory", () => ({
14
+ __esModule: true,
15
+ default: (props: any) => (
16
+ <div
17
+ data-testid="self-tests-category"
18
+ data-type={props.type}
19
+ data-link-name={props.linkName}
20
+ data-items={
21
+ Array.isArray(props.items)
22
+ ? props.items.map((item: any) => item.name).join(",")
23
+ : `not-an-array:${typeof props.items}`
24
+ }
25
+ />
26
+ ),
27
+ }));
28
+
29
+ import { SelfTestsTabContainer } from "../../../src/components/SelfTestsTabContainer";
30
+
31
+ // SelfTestsTabContainer reads `router` and `pathFor` from legacy react-router
32
+ // context via static contextTypes (handleSelect calls router.push). Supply them
33
+ // through a tiny legacy-context provider.
34
+ class LegacyContextProvider extends React.Component<{
35
+ router: { push: jest.Mock };
36
+ pathFor: jest.Mock;
37
+ children: React.ReactNode;
38
+ }> {
39
+ static childContextTypes = {
40
+ router: PropTypes.object,
41
+ pathFor: PropTypes.func,
42
+ };
43
+ getChildContext() {
44
+ return { router: this.props.router, pathFor: this.props.pathFor };
45
+ }
46
+ render() {
47
+ return <>{this.props.children}</>;
48
+ }
49
+ }
50
+
51
+ describe("SelfTestsTabContainer", () => {
52
+ let goToTab: jest.Mock;
53
+ let fetchItems: jest.Mock;
54
+ let router: { push: jest.Mock };
55
+ let pathFor: jest.Mock;
56
+ let store;
57
+
58
+ const collections = [
59
+ {
60
+ id: 1,
61
+ name: "collection 1",
62
+ protocol: "protocol",
63
+ self_test_results: {
64
+ duration: 1.75,
65
+ start: "2018-08-07T19:34:54Z",
66
+ end: "2018-08-07T19:34:55Z",
67
+ results: [
68
+ {
69
+ duration: 0.000119,
70
+ end: "2018-08-07T19:34:54Z",
71
+ exception: null,
72
+ name: "Initial setup.",
73
+ result: null,
74
+ start: "2018-08-07T19:34:54Z",
75
+ success: true,
76
+ },
77
+ ],
78
+ },
79
+ },
80
+ ];
81
+
82
+ beforeEach(() => {
83
+ store = buildStore();
84
+ goToTab = jest.fn();
85
+ fetchItems = jest.fn();
86
+ router = { push: jest.fn() };
87
+ pathFor = jest.fn();
88
+ });
89
+
90
+ const element = (overrides = {}) => {
91
+ const props = {
92
+ store,
93
+ goToTab,
94
+ fetchItems,
95
+ tab: "collections",
96
+ items: { protocols: [], collections },
97
+ ...overrides,
98
+ };
99
+ return (
100
+ <LegacyContextProvider router={router} pathFor={pathFor}>
101
+ <SelfTestsTabContainer {...props} />
102
+ </LegacyContextProvider>
103
+ );
104
+ };
105
+
106
+ const renderContainer = (overrides = {}) => render(element(overrides));
107
+
108
+ it("renders a tab container", () => {
109
+ const { container } = renderContainer();
110
+ expect(container.firstChild).toHaveClass("tab-container");
111
+ });
112
+
113
+ it("renders tabs and defaults to showing the Collections tab", () => {
114
+ const { container } = renderContainer();
115
+ const tabs = container.querySelectorAll("ul.nav-tabs li");
116
+ expect(tabs).toHaveLength(3);
117
+
118
+ expect(tabs[0]).toHaveTextContent("Collections");
119
+ expect(tabs[0]).toHaveClass("active");
120
+
121
+ expect(tabs[1]).toHaveTextContent("Patron Authentication");
122
+ expect(tabs[1]).not.toHaveClass("active");
123
+
124
+ expect(tabs[2]).toHaveTextContent("Metadata Services");
125
+ expect(tabs[2]).not.toHaveClass("active");
126
+ });
127
+
128
+ it("renders tab content", () => {
129
+ const { container } = renderContainer();
130
+
131
+ // Only the collections data is present, so its category renders; the other
132
+ // two tabs fall back to a loading indicator.
133
+ const markers = screen.getAllByTestId("self-tests-category");
134
+ expect(markers).toHaveLength(1);
135
+ expect(markers[0]).toHaveAttribute("data-type", "collection");
136
+ expect(markers[0]).toHaveAttribute("data-link-name", "collections");
137
+ expect(markers[0]).toHaveAttribute("data-items", "collection 1");
138
+
139
+ expect(container.querySelectorAll(".loading")).toHaveLength(2);
140
+ });
141
+
142
+ it("calls fetchItems on mount", () => {
143
+ renderContainer();
144
+ expect(fetchItems).toHaveBeenCalled();
145
+ });
146
+
147
+ it("shows an error message", () => {
148
+ const { container, rerender } = renderContainer();
149
+ expect(container.querySelectorAll(".alert-danger")).toHaveLength(0);
150
+
151
+ rerender(
152
+ element({
153
+ fetchError: { status: 401, response: "error fetching diagnostics" },
154
+ })
155
+ );
156
+
157
+ expect(container.querySelectorAll(".alert-danger")).toHaveLength(3);
158
+ });
159
+
160
+ it("calls goToTab and pushes to the router when a tab is clicked", async () => {
161
+ renderContainer();
162
+
163
+ await userEvent.click(
164
+ screen.getByRole("link", { name: "Patron Authentication" })
165
+ );
166
+
167
+ expect(goToTab).toHaveBeenCalledTimes(1);
168
+ expect(goToTab).toHaveBeenCalledWith("patronAuthServices");
169
+ await waitFor(() =>
170
+ expect(router.push).toHaveBeenCalledWith(
171
+ "/admin/web/troubleshooting/self-tests/patronAuthServices"
172
+ )
173
+ );
174
+ });
175
+
176
+ it("switches tabs when the tab prop changes", () => {
177
+ const { container, rerender } = renderContainer();
178
+ let tabs = container.querySelectorAll("ul.nav-tabs li");
179
+ expect(tabs[0]).toHaveClass("active");
180
+ expect(tabs[1]).not.toHaveClass("active");
181
+
182
+ rerender(element({ tab: "patronAuthServices" }));
183
+
184
+ tabs = container.querySelectorAll("ul.nav-tabs li");
185
+ expect(tabs[0]).not.toHaveClass("active");
186
+ expect(tabs[1]).toHaveClass("active");
187
+ });
188
+
189
+ it("derives the store key, type, and link name for each category", () => {
190
+ // A category only renders once its store key holds items, so populate all
191
+ // three with distinctly named items: the key each category is looked up
192
+ // under is then observable in the items its marker receives.
193
+ renderContainer({
194
+ items: {
195
+ collections: [{ id: 1, name: "a collection" }],
196
+ patron_auth_services: [{ id: 2, name: "a patron auth service" }],
197
+ metadata_services: [{ id: 3, name: "a metadata service" }],
198
+ },
199
+ });
200
+
201
+ const markers = screen.getAllByTestId("self-tests-category");
202
+ expect(markers).toHaveLength(3);
203
+
204
+ expect(markers[0]).toHaveAttribute("data-type", "collection");
205
+ expect(markers[0]).toHaveAttribute("data-link-name", "collections");
206
+ expect(markers[0]).toHaveAttribute("data-items", "a collection");
207
+
208
+ expect(markers[1]).toHaveAttribute("data-type", "patron_auth_service");
209
+ expect(markers[1]).toHaveAttribute("data-link-name", "patronAuth");
210
+ expect(markers[1]).toHaveAttribute("data-items", "a patron auth service");
211
+
212
+ expect(markers[2]).toHaveAttribute("data-type", "metadata_service");
213
+ expect(markers[2]).toHaveAttribute("data-link-name", "metadata");
214
+ expect(markers[2]).toHaveAttribute("data-items", "a metadata service");
215
+ });
216
+ });