@thepalaceproject/circulation-admin 1.43.0-post.8 → 1.43.0-post.9
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/package.json +1 -1
- 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/CatalogServices.test.tsx +63 -0
- package/tests/jest/components/CirculationEventsDownloadForm.test.tsx +41 -0
- package/tests/jest/components/CustomListSearch.test.tsx +275 -0
- package/tests/jest/components/CustomListsSidebar.test.tsx +251 -0
- package/tests/jest/components/DiagnosticsTabContainer.test.tsx +147 -0
- package/tests/jest/components/ErrorMessage.test.tsx +97 -0
- package/tests/jest/components/Footer.test.tsx +141 -0
- package/tests/jest/components/LanguageField.test.tsx +40 -0
- package/tests/jest/components/LoadButton.test.tsx +49 -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/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/TabContainer.test.tsx +68 -0
- package/tests/jest/components/Timestamp.test.tsx +74 -0
- package/tests/jest/components/WithEditButton.test.tsx +55 -0
- package/tests/jest/components/WithRemoveButton.test.tsx +95 -0
- package/tests/jest/index.test.tsx +50 -0
- package/tests/jest/components/AdvancedSearchBuilder.test.tsx +0 -38
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
4
|
+
import { DndProvider } from "react-dnd";
|
|
5
|
+
import { HTML5Backend } from "react-dnd-html5-backend";
|
|
6
|
+
import AdvancedSearchValueFilter from "../../../src/components/AdvancedSearchValueFilter";
|
|
7
|
+
import {
|
|
8
|
+
fields,
|
|
9
|
+
operators,
|
|
10
|
+
} from "../../../src/components/AdvancedSearchBuilder";
|
|
11
|
+
|
|
12
|
+
describe("AdvancedSearchValueFilter", () => {
|
|
13
|
+
let onMove;
|
|
14
|
+
let onRemove;
|
|
15
|
+
let onSelect;
|
|
16
|
+
let query;
|
|
17
|
+
|
|
18
|
+
const renderFilter = (props = {}) =>
|
|
19
|
+
render(
|
|
20
|
+
<DndProvider backend={HTML5Backend}>
|
|
21
|
+
<AdvancedSearchValueFilter
|
|
22
|
+
query={query}
|
|
23
|
+
onMove={onMove}
|
|
24
|
+
onSelect={onSelect}
|
|
25
|
+
onRemove={onRemove}
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
</DndProvider>
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
onMove = jest.fn();
|
|
33
|
+
onRemove = jest.fn();
|
|
34
|
+
onSelect = jest.fn();
|
|
35
|
+
|
|
36
|
+
query = {
|
|
37
|
+
id: "91",
|
|
38
|
+
key: "title",
|
|
39
|
+
op: "eq",
|
|
40
|
+
value: "foo",
|
|
41
|
+
};
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should render the field label, operator symbol, and value of the query", () => {
|
|
45
|
+
renderFilter();
|
|
46
|
+
|
|
47
|
+
const expectedField = `${
|
|
48
|
+
fields.find((field) => field.value === "title")?.label
|
|
49
|
+
}`;
|
|
50
|
+
const expectedOperator = `${
|
|
51
|
+
operators.find((op) => op.value === "eq")?.symbol
|
|
52
|
+
}`;
|
|
53
|
+
const filterLabelText = `${expectedField} ${expectedOperator} foo`;
|
|
54
|
+
|
|
55
|
+
expect(screen.getByText(filterLabelText)).toBeInTheDocument();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("should apply the selected class when selected is true", () => {
|
|
59
|
+
const { container } = renderFilter({ selected: true });
|
|
60
|
+
|
|
61
|
+
expect(
|
|
62
|
+
container.querySelector(".advanced-search-value-filter")
|
|
63
|
+
).toHaveClass("selected");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("should not apply the selected class when readOnly is true", () => {
|
|
67
|
+
const { container } = renderFilter({ readOnly: true, selected: true });
|
|
68
|
+
|
|
69
|
+
expect(
|
|
70
|
+
container.querySelector(".advanced-search-value-filter")
|
|
71
|
+
).not.toHaveClass("selected");
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("should render a remove button", () => {
|
|
75
|
+
renderFilter();
|
|
76
|
+
|
|
77
|
+
const button = screen.getByRole("button");
|
|
78
|
+
|
|
79
|
+
expect(button).toHaveTextContent("×");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("should not render a remove button when readOnly is true", () => {
|
|
83
|
+
renderFilter({ readOnly: true });
|
|
84
|
+
|
|
85
|
+
expect(screen.queryByRole("button")).not.toBeInTheDocument();
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("should call onRemove when the remove button is clicked", async () => {
|
|
89
|
+
const user = userEvent.setup();
|
|
90
|
+
renderFilter();
|
|
91
|
+
|
|
92
|
+
await user.click(screen.getByRole("button"));
|
|
93
|
+
|
|
94
|
+
expect(onRemove).toHaveBeenCalledTimes(1);
|
|
95
|
+
expect(onRemove).toHaveBeenCalledWith("91");
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("should call onSelect when clicked", async () => {
|
|
99
|
+
const user = userEvent.setup();
|
|
100
|
+
const { container } = renderFilter();
|
|
101
|
+
|
|
102
|
+
await user.click(container.querySelector(".advanced-search-value-filter"));
|
|
103
|
+
|
|
104
|
+
expect(onSelect).toHaveBeenCalledTimes(1);
|
|
105
|
+
expect(onSelect).toHaveBeenCalledWith("91");
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("should call onSelect when the space bar is depressed", async () => {
|
|
109
|
+
const user = userEvent.setup();
|
|
110
|
+
const { container } = renderFilter();
|
|
111
|
+
|
|
112
|
+
// The filter is a focusable treeitem; focus it and press space, as a
|
|
113
|
+
// keyboard user would.
|
|
114
|
+
const item = container.querySelector(
|
|
115
|
+
".advanced-search-value-filter"
|
|
116
|
+
) as HTMLElement;
|
|
117
|
+
item.focus();
|
|
118
|
+
await user.keyboard(" ");
|
|
119
|
+
|
|
120
|
+
expect(onSelect).toHaveBeenCalledTimes(1);
|
|
121
|
+
expect(onSelect).toHaveBeenCalledWith("91");
|
|
122
|
+
});
|
|
123
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { screen, within } from "@testing-library/react";
|
|
3
|
+
import { CatalogServices } from "../../../src/components/CatalogServices";
|
|
4
|
+
import renderWithContext from "../testUtils/renderWithContext";
|
|
5
|
+
import { defaultFeatureFlags } from "../../../src/utils/featureFlags";
|
|
6
|
+
|
|
7
|
+
describe("CatalogServices", () => {
|
|
8
|
+
const data = {
|
|
9
|
+
catalog_services: [
|
|
10
|
+
{
|
|
11
|
+
id: 2,
|
|
12
|
+
protocol: "test protocol",
|
|
13
|
+
settings: {
|
|
14
|
+
test_setting: "test setting",
|
|
15
|
+
},
|
|
16
|
+
libraries: [
|
|
17
|
+
{
|
|
18
|
+
short_name: "nypl",
|
|
19
|
+
test_library_setting: "test library setting",
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
name: "nypl catalog",
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
protocols: [
|
|
26
|
+
{
|
|
27
|
+
name: "test protocol",
|
|
28
|
+
label: "test protocol label",
|
|
29
|
+
settings: [],
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
allLibraries: [
|
|
33
|
+
{
|
|
34
|
+
short_name: "nypl",
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const config = { csrfToken: "token", featureFlags: defaultFeatureFlags };
|
|
40
|
+
|
|
41
|
+
it("shows catalog service list", () => {
|
|
42
|
+
renderWithContext(
|
|
43
|
+
<CatalogServices
|
|
44
|
+
data={data}
|
|
45
|
+
fetchData={jest.fn()}
|
|
46
|
+
editItem={jest.fn().mockResolvedValue(undefined)}
|
|
47
|
+
csrfToken="token"
|
|
48
|
+
isFetching={false}
|
|
49
|
+
/>,
|
|
50
|
+
config
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const items = screen.getAllByRole("listitem");
|
|
54
|
+
expect(items).toHaveLength(1);
|
|
55
|
+
expect(items[0]).toHaveTextContent("nypl catalog: test protocol label");
|
|
56
|
+
|
|
57
|
+
const editLink = within(items[0]).getByRole("link");
|
|
58
|
+
expect(editLink).toHaveAttribute(
|
|
59
|
+
"href",
|
|
60
|
+
"/admin/web/config/catalogServices/edit/2"
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { render, screen, within } from "@testing-library/react";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
4
|
+
|
|
5
|
+
import CirculationEventsDownloadForm from "../../../src/components/CirculationEventsDownloadForm";
|
|
6
|
+
|
|
7
|
+
describe("CirculationEventsDownloadForm", () => {
|
|
8
|
+
let hide: jest.Mock;
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
hide = jest.fn();
|
|
12
|
+
render(<CirculationEventsDownloadForm show={true} hide={hide} />);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it("renders start date and end date inputs", () => {
|
|
16
|
+
// The modal renders into a portal, so query the whole document.
|
|
17
|
+
const dates =
|
|
18
|
+
document.querySelectorAll<HTMLInputElement>("input[type='date']");
|
|
19
|
+
expect(dates).toHaveLength(2);
|
|
20
|
+
expect(dates[0].name).toBe("dateStart");
|
|
21
|
+
expect(dates[1].name).toBe("dateEnd");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("renders download and close buttons", async () => {
|
|
25
|
+
const user = userEvent.setup();
|
|
26
|
+
|
|
27
|
+
expect(
|
|
28
|
+
screen.getByRole("button", { name: "Download" })
|
|
29
|
+
).toBeInTheDocument();
|
|
30
|
+
|
|
31
|
+
// The modal header's dismiss control is also labeled "Close" (its visible
|
|
32
|
+
// "×" is aria-hidden), so scope to the footer for the reusable Close button.
|
|
33
|
+
const footer = document.querySelector<HTMLElement>(".modal-footer");
|
|
34
|
+
const closeButton = within(footer).getByRole("button", { name: "Close" });
|
|
35
|
+
expect(closeButton).toBeInTheDocument();
|
|
36
|
+
|
|
37
|
+
await user.click(closeButton);
|
|
38
|
+
|
|
39
|
+
expect(hide).toHaveBeenCalledTimes(1);
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { render, screen, within } from "@testing-library/react";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
4
|
+
import CustomListSearch from "../../../src/components/CustomListSearch";
|
|
5
|
+
|
|
6
|
+
describe("CustomListSearch", () => {
|
|
7
|
+
const library = {
|
|
8
|
+
uuid: "uuid",
|
|
9
|
+
name: "name",
|
|
10
|
+
short_name: "short_name",
|
|
11
|
+
settings: {
|
|
12
|
+
large_collections: ["eng", "fre", "spa"],
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const entryPoints = ["All", "Book", "Audio"];
|
|
17
|
+
|
|
18
|
+
const searchParams = {
|
|
19
|
+
entryPoint: "all",
|
|
20
|
+
terms: "foo bar",
|
|
21
|
+
sort: "title",
|
|
22
|
+
language: "English",
|
|
23
|
+
advanced: {
|
|
24
|
+
include: {
|
|
25
|
+
query: null,
|
|
26
|
+
selectedQueryId: null,
|
|
27
|
+
clearFilters: null,
|
|
28
|
+
},
|
|
29
|
+
exclude: {
|
|
30
|
+
query: null,
|
|
31
|
+
selectedQueryId: null,
|
|
32
|
+
clearFilters: null,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const languages = {
|
|
38
|
+
eng: ["English"],
|
|
39
|
+
spa: ["Spanish", "Castilian"],
|
|
40
|
+
fre: ["French"],
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const renderSearch = (
|
|
44
|
+
overrides: Partial<React.ComponentProps<typeof CustomListSearch>> = {}
|
|
45
|
+
) =>
|
|
46
|
+
render(
|
|
47
|
+
<CustomListSearch
|
|
48
|
+
entryPoints={entryPoints}
|
|
49
|
+
isOwner={true}
|
|
50
|
+
languages={languages}
|
|
51
|
+
library={library}
|
|
52
|
+
listId="123"
|
|
53
|
+
search={jest.fn()}
|
|
54
|
+
searchParams={searchParams}
|
|
55
|
+
updateAutoUpdate={jest.fn()}
|
|
56
|
+
updateSearchParam={jest.fn()}
|
|
57
|
+
{...overrides}
|
|
58
|
+
/>
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
it("renders a radio button for each entry point", () => {
|
|
62
|
+
const { container } = renderSearch();
|
|
63
|
+
const entryPointsSection =
|
|
64
|
+
container.querySelector<HTMLElement>(".entry-points");
|
|
65
|
+
|
|
66
|
+
const radios = within(entryPointsSection).getAllByRole("radio");
|
|
67
|
+
expect(radios).toHaveLength(3);
|
|
68
|
+
|
|
69
|
+
const all = within(entryPointsSection).getByRole("radio", { name: "All" });
|
|
70
|
+
expect(all).toHaveAttribute("name", "entry-points-selection");
|
|
71
|
+
expect(all).toHaveAttribute("value", "All");
|
|
72
|
+
expect(all).toBeEnabled();
|
|
73
|
+
expect(all).toBeChecked();
|
|
74
|
+
|
|
75
|
+
const book = within(entryPointsSection).getByRole("radio", {
|
|
76
|
+
name: "Book",
|
|
77
|
+
});
|
|
78
|
+
expect(book).toHaveAttribute("name", "entry-points-selection");
|
|
79
|
+
expect(book).toHaveAttribute("value", "Book");
|
|
80
|
+
expect(book).toBeEnabled();
|
|
81
|
+
expect(book).not.toBeChecked();
|
|
82
|
+
|
|
83
|
+
const audio = within(entryPointsSection).getByRole("radio", {
|
|
84
|
+
name: "Audio",
|
|
85
|
+
});
|
|
86
|
+
expect(audio).toHaveAttribute("name", "entry-points-selection");
|
|
87
|
+
expect(audio).toHaveAttribute("value", "Audio");
|
|
88
|
+
expect(audio).toBeEnabled();
|
|
89
|
+
expect(audio).not.toBeChecked();
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("disables the entry point radio buttons when isOwner is false", () => {
|
|
93
|
+
const { container } = renderSearch({ isOwner: false });
|
|
94
|
+
const entryPointsSection =
|
|
95
|
+
container.querySelector<HTMLElement>(".entry-points");
|
|
96
|
+
|
|
97
|
+
within(entryPointsSection)
|
|
98
|
+
.getAllByRole("radio")
|
|
99
|
+
.forEach((radio) => expect(radio).toBeDisabled());
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
it("calls updateSearchParam when an entry point radio button is changed", async () => {
|
|
103
|
+
const user = userEvent.setup();
|
|
104
|
+
const updateSearchParam = jest.fn();
|
|
105
|
+
const { container } = renderSearch({ updateSearchParam });
|
|
106
|
+
const entryPointsSection =
|
|
107
|
+
container.querySelector<HTMLElement>(".entry-points");
|
|
108
|
+
|
|
109
|
+
await user.click(
|
|
110
|
+
within(entryPointsSection).getByRole("radio", { name: "Audio" })
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
expect(updateSearchParam).toHaveBeenCalledTimes(1);
|
|
114
|
+
expect(updateSearchParam).toHaveBeenCalledWith("entryPoint", "Audio");
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("renders a radio button for each sort option", () => {
|
|
118
|
+
const { container } = renderSearch();
|
|
119
|
+
const sortSection = container.querySelector<HTMLElement>(".search-options");
|
|
120
|
+
|
|
121
|
+
const radios = within(sortSection).getAllByRole("radio");
|
|
122
|
+
expect(radios).toHaveLength(3);
|
|
123
|
+
|
|
124
|
+
const relevance = within(sortSection).getByRole("radio", {
|
|
125
|
+
name: "Relevance",
|
|
126
|
+
});
|
|
127
|
+
expect(relevance).toHaveAttribute("name", "sort-selection");
|
|
128
|
+
expect(relevance).toHaveAttribute("value", "");
|
|
129
|
+
expect(relevance).toBeEnabled();
|
|
130
|
+
expect(relevance).not.toBeChecked();
|
|
131
|
+
|
|
132
|
+
const title = within(sortSection).getByRole("radio", { name: "Title" });
|
|
133
|
+
expect(title).toHaveAttribute("name", "sort-selection");
|
|
134
|
+
expect(title).toHaveAttribute("value", "title");
|
|
135
|
+
expect(title).toBeEnabled();
|
|
136
|
+
expect(title).toBeChecked();
|
|
137
|
+
|
|
138
|
+
const author = within(sortSection).getByRole("radio", { name: "Author" });
|
|
139
|
+
expect(author).toHaveAttribute("name", "sort-selection");
|
|
140
|
+
expect(author).toHaveAttribute("value", "author");
|
|
141
|
+
expect(author).toBeEnabled();
|
|
142
|
+
expect(author).not.toBeChecked();
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it("disables the sort option radio buttons when isOwner is false", () => {
|
|
146
|
+
const { container } = renderSearch({ isOwner: false });
|
|
147
|
+
const sortSection = container.querySelector<HTMLElement>(".search-options");
|
|
148
|
+
|
|
149
|
+
within(sortSection)
|
|
150
|
+
.getAllByRole("radio")
|
|
151
|
+
.forEach((radio) => expect(radio).toBeDisabled());
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it("calls updateSearchParam when a sort radio button is changed", async () => {
|
|
155
|
+
const user = userEvent.setup();
|
|
156
|
+
const updateSearchParam = jest.fn();
|
|
157
|
+
const { container } = renderSearch({ updateSearchParam });
|
|
158
|
+
const sortSection = container.querySelector<HTMLElement>(".search-options");
|
|
159
|
+
|
|
160
|
+
await user.click(
|
|
161
|
+
within(sortSection).getByRole("radio", { name: "Author" })
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
expect(updateSearchParam).toHaveBeenCalledTimes(1);
|
|
165
|
+
expect(updateSearchParam).toHaveBeenCalledWith("sort", "author");
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("calls addAdvSearchQuery and search when mounted if there is a startingTitle", () => {
|
|
169
|
+
const addAdvSearchQuery = jest.fn();
|
|
170
|
+
const search = jest.fn();
|
|
171
|
+
|
|
172
|
+
renderSearch({ startingTitle: "test", addAdvSearchQuery, search });
|
|
173
|
+
|
|
174
|
+
expect(addAdvSearchQuery).toHaveBeenCalledTimes(1);
|
|
175
|
+
expect(addAdvSearchQuery).toHaveBeenCalledWith("include", {
|
|
176
|
+
key: "title",
|
|
177
|
+
op: "eq",
|
|
178
|
+
value: "test",
|
|
179
|
+
});
|
|
180
|
+
expect(search).toHaveBeenCalledTimes(1);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
describe("when showAutoUpdate is false", () => {
|
|
184
|
+
it("does not render radio buttons for auto update on and off", () => {
|
|
185
|
+
const { container } = renderSearch();
|
|
186
|
+
|
|
187
|
+
expect(container.querySelector(".auto-update")).toBeNull();
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe("when showAutoUpdate is true", () => {
|
|
192
|
+
it("renders radio buttons for auto update on and off", () => {
|
|
193
|
+
const { container } = renderSearch({
|
|
194
|
+
showAutoUpdate: true,
|
|
195
|
+
listId: null,
|
|
196
|
+
});
|
|
197
|
+
const autoSection = container.querySelector<HTMLElement>(".auto-update");
|
|
198
|
+
|
|
199
|
+
const radios = within(autoSection).getAllByRole("radio");
|
|
200
|
+
expect(radios).toHaveLength(2);
|
|
201
|
+
|
|
202
|
+
const on = within(autoSection).getByRole("radio", {
|
|
203
|
+
name: "Automatically update this list",
|
|
204
|
+
});
|
|
205
|
+
expect(on).toHaveAttribute("name", "auto-update");
|
|
206
|
+
expect(on).toBeEnabled();
|
|
207
|
+
|
|
208
|
+
const off = within(autoSection).getByRole("radio", {
|
|
209
|
+
name: "Manually select titles",
|
|
210
|
+
});
|
|
211
|
+
expect(off).toHaveAttribute("name", "auto-update");
|
|
212
|
+
expect(off).toBeEnabled();
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
it("disables the radio buttons for auto update when isOwner is false", () => {
|
|
216
|
+
const { container } = renderSearch({
|
|
217
|
+
showAutoUpdate: true,
|
|
218
|
+
isOwner: false,
|
|
219
|
+
listId: null,
|
|
220
|
+
});
|
|
221
|
+
const autoSection = container.querySelector<HTMLElement>(".auto-update");
|
|
222
|
+
|
|
223
|
+
within(autoSection)
|
|
224
|
+
.getAllByRole("radio")
|
|
225
|
+
.forEach((radio) => expect(radio).toBeDisabled());
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it("disables the radio buttons for auto update when listId is not null", () => {
|
|
229
|
+
// isOwner: true keeps readOnly false, so listId is the only thing that can
|
|
230
|
+
// disable the radios — otherwise readOnly alone would, masking this path.
|
|
231
|
+
const { container } = renderSearch({
|
|
232
|
+
showAutoUpdate: true,
|
|
233
|
+
isOwner: true,
|
|
234
|
+
listId: "123",
|
|
235
|
+
});
|
|
236
|
+
const autoSection = container.querySelector<HTMLElement>(".auto-update");
|
|
237
|
+
|
|
238
|
+
within(autoSection)
|
|
239
|
+
.getAllByRole("radio")
|
|
240
|
+
.forEach((radio) => expect(radio).toBeDisabled());
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
it("calls updateAutoUpdate when an auto update radio button is changed", async () => {
|
|
244
|
+
const user = userEvent.setup();
|
|
245
|
+
// Clicking the currently-unchecked "on" radio reports true.
|
|
246
|
+
const updateAutoUpdateOn = jest.fn();
|
|
247
|
+
const { unmount } = renderSearch({
|
|
248
|
+
showAutoUpdate: true,
|
|
249
|
+
listId: null,
|
|
250
|
+
autoUpdate: false,
|
|
251
|
+
updateAutoUpdate: updateAutoUpdateOn,
|
|
252
|
+
});
|
|
253
|
+
await user.click(
|
|
254
|
+
screen.getByRole("radio", { name: "Automatically update this list" })
|
|
255
|
+
);
|
|
256
|
+
expect(updateAutoUpdateOn).toHaveBeenCalledTimes(1);
|
|
257
|
+
expect(updateAutoUpdateOn).toHaveBeenCalledWith(true);
|
|
258
|
+
unmount();
|
|
259
|
+
|
|
260
|
+
// Clicking the currently-unchecked "off" radio reports false.
|
|
261
|
+
const updateAutoUpdateOff = jest.fn();
|
|
262
|
+
renderSearch({
|
|
263
|
+
showAutoUpdate: true,
|
|
264
|
+
listId: null,
|
|
265
|
+
autoUpdate: true,
|
|
266
|
+
updateAutoUpdate: updateAutoUpdateOff,
|
|
267
|
+
});
|
|
268
|
+
await user.click(
|
|
269
|
+
screen.getByRole("radio", { name: "Manually select titles" })
|
|
270
|
+
);
|
|
271
|
+
expect(updateAutoUpdateOff).toHaveBeenCalledTimes(1);
|
|
272
|
+
expect(updateAutoUpdateOff).toHaveBeenCalledWith(false);
|
|
273
|
+
});
|
|
274
|
+
});
|
|
275
|
+
});
|