@thepalaceproject/circulation-admin 1.43.0-post.9 → 1.44.0-post.10
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 +22 -10
- package/README.md +11 -5
- package/dist/circulation-admin.js +1 -1
- package/jest.config.js +11 -44
- package/package.json +1 -5
- package/tests/jest/components/AdvancedSearchBuilder.test.tsx +111 -0
- package/tests/jest/components/Announcement.test.tsx +76 -0
- package/tests/jest/components/AnnouncementForm.test.tsx +229 -0
- package/tests/jest/components/AnnouncementsSection.test.tsx +146 -0
- package/tests/jest/components/Autocomplete.test.tsx +67 -0
- package/tests/jest/components/BookCoverEditor.test.tsx +393 -0
- package/tests/jest/components/BookDetailsEditor.test.tsx +275 -0
- package/tests/jest/components/BookDetailsTabContainer.test.tsx +237 -0
- package/tests/jest/components/BookEditForm.test.tsx +352 -0
- package/tests/jest/components/BookEditor.test.tsx +20 -21
- package/tests/jest/components/CatalogPage.test.tsx +158 -0
- package/tests/jest/components/CatalogServices.test.tsx +38 -1
- package/tests/jest/components/ChangePasswordForm.test.tsx +163 -0
- package/tests/jest/components/Classifications.test.tsx +166 -0
- package/tests/jest/components/ClassificationsForm.test.tsx +458 -0
- package/tests/jest/components/ClassificationsTable.test.tsx +57 -0
- package/tests/jest/components/Collections.test.tsx +335 -7
- 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/ConfigTabContainer.test.tsx +196 -0
- package/tests/jest/components/ContextProvider.test.tsx +138 -0
- package/tests/jest/components/Contributors.test.tsx +157 -0
- package/tests/jest/components/CustomListEditor.test.tsx +367 -0
- package/tests/jest/components/CustomListEntriesEditor.test.tsx +1240 -0
- package/tests/jest/components/CustomLists.test.tsx +621 -4
- package/tests/jest/components/CustomListsForBook.test.tsx +353 -0
- package/tests/jest/components/DiagnosticsServiceTabs.test.tsx +141 -0
- package/tests/jest/components/DiagnosticsServiceType.test.tsx +75 -0
- package/tests/jest/components/DiscoveryServices.test.tsx +154 -7
- package/tests/jest/components/EditableConfigList.test.tsx +598 -7
- package/tests/jest/components/EditableInput.test.tsx +250 -1
- package/tests/jest/components/EditorField.test.tsx +95 -0
- package/tests/jest/components/GenreForm.test.tsx +152 -0
- package/tests/jest/components/Header.test.tsx +421 -0
- package/tests/jest/components/IndividualAdminEditForm.test.tsx +506 -1
- package/tests/jest/components/IndividualAdmins.test.tsx +124 -8
- package/tests/jest/components/InputList.test.tsx +493 -0
- package/tests/jest/components/Lane.test.tsx +132 -10
- package/tests/jest/components/LaneCustomListsEditor.test.tsx +450 -0
- package/tests/jest/components/LaneEditor.test.tsx +377 -9
- package/tests/jest/components/Lanes.test.tsx +446 -0
- package/tests/jest/components/LanesSidebar.test.tsx +621 -0
- package/tests/jest/components/Libraries.test.tsx +48 -0
- package/tests/jest/components/LibraryEditForm.test.tsx +383 -0
- package/tests/jest/components/LibraryRegistration.test.tsx +354 -0
- package/tests/jest/components/LibraryRegistrationForm.test.tsx +203 -0
- package/tests/jest/components/MetadataServices.test.tsx +37 -1
- package/tests/jest/components/NeighborhoodAnalyticsForm.test.tsx +167 -0
- package/tests/jest/components/PairedMenus.test.tsx +220 -0
- package/tests/jest/components/PatronAuthServices.test.tsx +114 -0
- package/tests/jest/components/ProtocolFormField.test.tsx +443 -7
- package/tests/jest/components/ResetAdobeId.test.tsx +302 -0
- package/tests/jest/components/SelfTests.test.tsx +601 -0
- package/tests/jest/components/SelfTestsTabContainer.test.tsx +216 -0
- package/tests/jest/components/ServiceEditForm.test.tsx +1092 -0
- package/tests/jest/components/SitewideAnnouncements.test.tsx +134 -0
- package/tests/jest/components/Stats.test.tsx +0 -7
- package/tests/jest/components/TextWithEditMode.test.tsx +218 -0
- package/tests/jest/components/ToolTip.test.tsx +46 -0
- package/tests/jest/components/TroubleshootingCategoryPage.test.tsx +69 -0
- package/tests/jest/components/TroubleshootingPage.test.tsx +94 -0
- package/tests/jest/features/book.test.ts +75 -80
- package/tests/jest/fixtures/classificationsData.ts +45 -0
- package/tests/jest/fixtures/genreData.ts +811 -0
- package/tests/jest/README.md +0 -6
- package/tests/jest/legacy-setup.ts +0 -13
- 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
|
+
});
|