@thepalaceproject/circulation-admin 0.4.2 → 0.5.0
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/.nvmrc +1 -0
- package/CHANGELOG.md +12 -0
- package/README.md +1 -1
- package/dist/{89889688147bd7575d6327160d64e760.svg → 060b2710bdbbe3dfe48b58d59bd5f1fb.svg} +0 -0
- package/dist/0db1520f47986b6c755a.svg +1 -0
- package/dist/{b06871f281fee6b241d60582ae9369b9.ttf → 1e59d2330b4c6deb84b340635ed36249.ttf} +0 -0
- package/dist/45eb1d236a736caa24dd.woff2 +1 -0
- package/dist/4c6f1cd9993ba8a53b8e.ttf +1 -0
- package/dist/5e9505a87e4d8ecb2017.eot +1 -0
- package/dist/6563aa3790be8329e4f2.svg +1 -0
- package/dist/7a065a1c0cb2d586cecb.woff +1 -0
- package/dist/7d6ec71e2466a9fd777f.woff2 +1 -0
- package/dist/{674f50d287a8c48dc19ba404d20fe713.eot → 8b43027f47b20503057dfbbaa9401fef.eot} +0 -0
- package/dist/{912ec66d7572ff821749319396470bde.svg → c1e38fd9e0e74ba58f7a2b77ef29fdd3.svg} +0 -0
- package/dist/circulation-admin.css +4 -4
- package/dist/circulation-admin.js +2 -397
- package/dist/circulation-admin.js.LICENSE.txt +125 -0
- package/dist/dec4ea00820558e24672.ttf +1 -0
- package/dist/e5c0c62d732823225aaa.eot +1 -0
- package/dist/f34ea237f268661e9d00.woff +1 -0
- package/jest.config.js +6 -0
- package/nightwatch.json +3 -3
- package/package.json +47 -30
- package/tests/{README.md → browser/README.md} +3 -0
- package/tests/jest/README.md +6 -0
- package/tests/jest/components/AdvancedSearchBuilder.test.tsx +39 -0
- package/tests/jest/components/EditableInput.test.tsx +64 -0
- package/tests/jest/components/IndividualAdminEditForm.test.tsx +126 -0
- package/tests/jest/components/Lane.test.tsx +78 -0
- package/tests/jest/components/LaneEditor.test.tsx +148 -0
- package/tests/jest/jest-setup.ts +1 -0
- package/tests/jest/sample/sample.test.js +3 -0
- package/tests/jest/testUtils/renderWithContext.tsx +36 -0
- package/tsconfig.json +8 -4
- package/webpack.common.js +9 -5
- package/webpack.dev-server.config.js +1 -1
- package/webpack.dev.config.js +1 -1
- package/webpack.prod.config.js +1 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import EditableInput from "../../../src/components/EditableInput";
|
|
4
|
+
|
|
5
|
+
describe("EditableInput", () => {
|
|
6
|
+
it("renders an accessible description if a description prop is supplied and a label prop is supplied", () => {
|
|
7
|
+
const label = "input1";
|
|
8
|
+
const description = "this is a field";
|
|
9
|
+
|
|
10
|
+
render(
|
|
11
|
+
<EditableInput
|
|
12
|
+
label={label}
|
|
13
|
+
optionalText={false}
|
|
14
|
+
description={description}
|
|
15
|
+
/>
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const textbox = screen.getByRole("textbox", { name: label });
|
|
19
|
+
|
|
20
|
+
expect(textbox).toHaveAccessibleDescription(description);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
it("renders an accessible description if a description prop is supplied and a label prop is not supplied", () => {
|
|
24
|
+
const description = "this is a field";
|
|
25
|
+
|
|
26
|
+
render(<EditableInput optionalText={false} description={description} />);
|
|
27
|
+
|
|
28
|
+
const textbox = screen.getByRole("textbox");
|
|
29
|
+
|
|
30
|
+
expect(textbox).toHaveAccessibleDescription(description);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
it("renders an accessible description if optionalText is true", () => {
|
|
34
|
+
render(<EditableInput optionalText={true} />);
|
|
35
|
+
|
|
36
|
+
const textbox = screen.getByRole("textbox");
|
|
37
|
+
|
|
38
|
+
expect(textbox).toHaveAccessibleDescription(/optional/i);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it("associates accessible descriptions with the correct inputs when multiple instances are present", () => {
|
|
42
|
+
const descriptions = ["desc 1", "desc 2", "desc 3"];
|
|
43
|
+
|
|
44
|
+
render(
|
|
45
|
+
<div>
|
|
46
|
+
<EditableInput optionalText={false} description={descriptions[0]} />
|
|
47
|
+
<EditableInput optionalText={false} />
|
|
48
|
+
<EditableInput optionalText={false} />
|
|
49
|
+
<EditableInput optionalText={false} description={descriptions[1]} />
|
|
50
|
+
<EditableInput optionalText={false} description={descriptions[2]} />
|
|
51
|
+
<EditableInput optionalText={false} />
|
|
52
|
+
</div>
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
const textboxes = screen.getAllByRole("textbox");
|
|
56
|
+
|
|
57
|
+
expect(textboxes[0]).toHaveAccessibleDescription(descriptions[0]);
|
|
58
|
+
expect(textboxes[1]).toHaveAccessibleDescription("");
|
|
59
|
+
expect(textboxes[2]).toHaveAccessibleDescription("");
|
|
60
|
+
expect(textboxes[3]).toHaveAccessibleDescription(descriptions[1]);
|
|
61
|
+
expect(textboxes[4]).toHaveAccessibleDescription(descriptions[2]);
|
|
62
|
+
expect(textboxes[5]).toHaveAccessibleDescription("");
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { screen } from "@testing-library/react";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
4
|
+
import IndividualAdminEditForm from "../../../src/components/IndividualAdminEditForm";
|
|
5
|
+
import renderWithContext from "../testUtils/renderWithContext";
|
|
6
|
+
|
|
7
|
+
describe("IndividualAdminEditForm", () => {
|
|
8
|
+
it("clears the role checkboxes after save", async () => {
|
|
9
|
+
const user = userEvent.setup();
|
|
10
|
+
|
|
11
|
+
const contextProviderProps = {
|
|
12
|
+
csrfToken: "",
|
|
13
|
+
roles: [
|
|
14
|
+
{
|
|
15
|
+
role: "system",
|
|
16
|
+
},
|
|
17
|
+
],
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const props = {
|
|
21
|
+
data: {
|
|
22
|
+
allLibraries: [
|
|
23
|
+
{
|
|
24
|
+
name: "Alpha",
|
|
25
|
+
short_name: "alpha",
|
|
26
|
+
uuid: "a3247ce9-9639-426b-bb09-82e9cb4cf44b",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: "Beta",
|
|
30
|
+
short_name: "beta",
|
|
31
|
+
uuid: "da80cd40-7a87-41db-a789-5f1e87732aeb",
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: "Gamma",
|
|
35
|
+
short_name: "gamma",
|
|
36
|
+
uuid: "15f32675-73f5-46f3-91f4-837b933bc7b1",
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
disabled: false,
|
|
41
|
+
listDataKey: "",
|
|
42
|
+
urlBase: "",
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const { rerender } = renderWithContext(
|
|
46
|
+
<IndividualAdminEditForm {...props} />,
|
|
47
|
+
contextProviderProps
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
const systemAdminCheckbox = screen.getByRole("checkbox", {
|
|
51
|
+
name: /^system admin$/i,
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const allAdminCheckbox = screen.getByRole("checkbox", {
|
|
55
|
+
name: /^administrator$/i,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const allUserCheckbox = screen.getByRole("checkbox", {
|
|
59
|
+
name: /^user$/i,
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const alphaAdminCheckbox = screen.getByRole("checkbox", {
|
|
63
|
+
name: /administrator of alpha/i,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const alphaUserCheckbox = screen.getByRole("checkbox", {
|
|
67
|
+
name: /user of alpha/i,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const betaAdminCheckbox = screen.getByRole("checkbox", {
|
|
71
|
+
name: /administrator of beta/i,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
const betaUserCheckbox = screen.getByRole("checkbox", {
|
|
75
|
+
name: /user of beta/i,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const gammaAdminCheckbox = screen.getByRole("checkbox", {
|
|
79
|
+
name: /administrator of gamma/i,
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const gammaUserCheckbox = screen.getByRole("checkbox", {
|
|
83
|
+
name: /user of gamma/i,
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
expect(systemAdminCheckbox).not.toBeChecked();
|
|
87
|
+
|
|
88
|
+
await user.click(systemAdminCheckbox);
|
|
89
|
+
|
|
90
|
+
expect(systemAdminCheckbox).toBeChecked();
|
|
91
|
+
|
|
92
|
+
expect(allAdminCheckbox).toBeChecked();
|
|
93
|
+
expect(allUserCheckbox).toBeChecked();
|
|
94
|
+
|
|
95
|
+
expect(alphaAdminCheckbox).toBeChecked();
|
|
96
|
+
expect(alphaUserCheckbox).toBeChecked();
|
|
97
|
+
|
|
98
|
+
expect(betaAdminCheckbox).toBeChecked();
|
|
99
|
+
expect(betaUserCheckbox).toBeChecked();
|
|
100
|
+
|
|
101
|
+
expect(gammaAdminCheckbox).toBeChecked();
|
|
102
|
+
expect(gammaUserCheckbox).toBeChecked();
|
|
103
|
+
|
|
104
|
+
const nextProps = {
|
|
105
|
+
...props,
|
|
106
|
+
// Existence of the responseBody prop indicates that the form was just saved.
|
|
107
|
+
responseBody: "some response",
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
rerender(<IndividualAdminEditForm {...nextProps} />);
|
|
111
|
+
|
|
112
|
+
expect(systemAdminCheckbox).not.toBeChecked();
|
|
113
|
+
|
|
114
|
+
expect(allAdminCheckbox).not.toBeChecked();
|
|
115
|
+
expect(allUserCheckbox).not.toBeChecked();
|
|
116
|
+
|
|
117
|
+
expect(alphaAdminCheckbox).not.toBeChecked();
|
|
118
|
+
expect(alphaUserCheckbox).not.toBeChecked();
|
|
119
|
+
|
|
120
|
+
expect(betaAdminCheckbox).not.toBeChecked();
|
|
121
|
+
expect(betaUserCheckbox).not.toBeChecked();
|
|
122
|
+
|
|
123
|
+
expect(gammaAdminCheckbox).not.toBeChecked();
|
|
124
|
+
expect(gammaUserCheckbox).not.toBeChecked();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import { stub } from "sinon";
|
|
4
|
+
import { LaneData } from "../../../src/interfaces";
|
|
5
|
+
import Lane from "../../../src/components/Lane";
|
|
6
|
+
|
|
7
|
+
// Mock the Link component from React Router, so we can verify that it gets rendered with the
|
|
8
|
+
// expected props. This serves as an example of how to do something analogous to Enzyme's shallow
|
|
9
|
+
// rendering, when we don't want/need to render the whole component tree down to HTML elements to
|
|
10
|
+
// test something. This technique is useful for testing components in isolation (unit testing),
|
|
11
|
+
// instead of the integration testing that RTL focuses on.
|
|
12
|
+
|
|
13
|
+
jest.mock("react-router", () => ({
|
|
14
|
+
...jest.requireActual("react-router"),
|
|
15
|
+
Link: (props) => (
|
|
16
|
+
<div data-testid="Link" data-to={props.to}>
|
|
17
|
+
{props.children}
|
|
18
|
+
</div>
|
|
19
|
+
),
|
|
20
|
+
}));
|
|
21
|
+
|
|
22
|
+
const renderLanes = stub();
|
|
23
|
+
const toggleLaneVisibility = stub();
|
|
24
|
+
|
|
25
|
+
function createLaneData(displayName: string, isAutomated: boolean): LaneData {
|
|
26
|
+
return {
|
|
27
|
+
id: 1,
|
|
28
|
+
display_name: displayName,
|
|
29
|
+
visible: true,
|
|
30
|
+
count: 5,
|
|
31
|
+
sublanes: [],
|
|
32
|
+
// The absence/presence of custom list ids determines if a lane is automated or custom.
|
|
33
|
+
custom_list_ids: isAutomated ? [] : [1],
|
|
34
|
+
inherit_parent_restrictions: true,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
describe("Lane", () => {
|
|
39
|
+
it("renders an edit link on a custom lane", () => {
|
|
40
|
+
const laneData = createLaneData("Custom Lane", false);
|
|
41
|
+
|
|
42
|
+
render(
|
|
43
|
+
<Lane
|
|
44
|
+
lane={laneData}
|
|
45
|
+
active={false}
|
|
46
|
+
library="test_library"
|
|
47
|
+
orderChanged={false}
|
|
48
|
+
renderLanes={renderLanes}
|
|
49
|
+
toggleLaneVisibility={toggleLaneVisibility}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const editLink = screen.getAllByTestId("Link")[0];
|
|
54
|
+
|
|
55
|
+
expect(editLink).toHaveAttribute("data-to", expect.stringMatching(/edit/i));
|
|
56
|
+
expect(editLink).toHaveTextContent(/edit/i);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("renders an edit link on an automated lane", async () => {
|
|
60
|
+
const laneData = createLaneData("Automated Lane", true);
|
|
61
|
+
|
|
62
|
+
render(
|
|
63
|
+
<Lane
|
|
64
|
+
lane={laneData}
|
|
65
|
+
active={false}
|
|
66
|
+
library="test_library"
|
|
67
|
+
orderChanged={false}
|
|
68
|
+
renderLanes={renderLanes}
|
|
69
|
+
toggleLaneVisibility={toggleLaneVisibility}
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const editLink = screen.getAllByTestId("Link")[0];
|
|
74
|
+
|
|
75
|
+
expect(editLink).toHaveAttribute("data-to", expect.stringMatching(/edit/i));
|
|
76
|
+
expect(editLink).toHaveTextContent(/edit/i);
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import { stub } from "sinon";
|
|
4
|
+
import { LaneData } from "../../../src/interfaces";
|
|
5
|
+
import LaneEditor from "../../../src/components/LaneEditor";
|
|
6
|
+
|
|
7
|
+
// Mock the LaneCustomListsEditor so we can verify that it is or isn't rendered. This serves as an
|
|
8
|
+
// example of how to do something analogous to Enzyme's shallow rendering, when we don't want/need
|
|
9
|
+
// to render the whole component tree down to HTML elements to test something. This technique is
|
|
10
|
+
// useful for testing components in isolation (unit testing), instead of the integration testing
|
|
11
|
+
// that RTL focuses on.
|
|
12
|
+
|
|
13
|
+
jest.mock("../../../src/components/LaneCustomListsEditor", () => ({
|
|
14
|
+
__esModule: true,
|
|
15
|
+
default: (props) => <div data-testid="LaneCustomListsEditor" />,
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
const customListsData = [
|
|
19
|
+
{ id: 1, name: "list 1", entries: [], is_owner: true, is_shared: false },
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
const editLane = stub().returns(
|
|
23
|
+
new Promise<void>((resolve) => resolve())
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const deleteLane = stub().returns(
|
|
27
|
+
new Promise<void>((resolve) => resolve())
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
const toggleLaneVisibility = stub();
|
|
31
|
+
|
|
32
|
+
function createLaneData(displayName: string, isAutomated: boolean): LaneData {
|
|
33
|
+
return {
|
|
34
|
+
id: 1,
|
|
35
|
+
display_name: displayName,
|
|
36
|
+
visible: true,
|
|
37
|
+
count: 5,
|
|
38
|
+
sublanes: [
|
|
39
|
+
{
|
|
40
|
+
id: 2,
|
|
41
|
+
display_name: `Sublane of ${displayName}`,
|
|
42
|
+
visible: true,
|
|
43
|
+
count: 3,
|
|
44
|
+
sublanes: [],
|
|
45
|
+
custom_list_ids: [1],
|
|
46
|
+
inherit_parent_restrictions: false,
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
// The absence/presence of custom list ids determines if a lane is automated or custom.
|
|
50
|
+
custom_list_ids: isAutomated ? [] : [1],
|
|
51
|
+
inherit_parent_restrictions: true,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
describe("LaneEditor", () => {
|
|
56
|
+
describe("for a custom lane", () => {
|
|
57
|
+
const laneData = createLaneData("Custom Lane", false);
|
|
58
|
+
|
|
59
|
+
beforeEach(() => {
|
|
60
|
+
render(
|
|
61
|
+
<LaneEditor
|
|
62
|
+
library="library"
|
|
63
|
+
lane={laneData}
|
|
64
|
+
customLists={customListsData}
|
|
65
|
+
editOrCreate="edit"
|
|
66
|
+
editLane={editLane}
|
|
67
|
+
deleteLane={deleteLane}
|
|
68
|
+
findParentOfLane={stub().returns(laneData)}
|
|
69
|
+
toggleLaneVisibility={toggleLaneVisibility}
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("renders a delete button", () => {
|
|
75
|
+
expect(screen.getByRole("button", { name: /delete/i })).not.toBeNull();
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("renders an inherit parent restrictions checkbox", () => {
|
|
79
|
+
expect(
|
|
80
|
+
screen.getByRole("checkbox", {
|
|
81
|
+
name: /inherit restrictions from parent/i,
|
|
82
|
+
})
|
|
83
|
+
).not.toBeNull();
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("renders a custom lists editor", () => {
|
|
87
|
+
expect(screen.getByTestId("LaneCustomListsEditor")).not.toBeNull();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
describe("for an automated lane", () => {
|
|
92
|
+
const laneData = createLaneData("Automated Lane", true);
|
|
93
|
+
|
|
94
|
+
beforeEach(() => {
|
|
95
|
+
render(
|
|
96
|
+
<LaneEditor
|
|
97
|
+
library="library"
|
|
98
|
+
lane={laneData}
|
|
99
|
+
customLists={customListsData}
|
|
100
|
+
editOrCreate="edit"
|
|
101
|
+
editLane={editLane}
|
|
102
|
+
deleteLane={deleteLane}
|
|
103
|
+
findParentOfLane={stub().returns(laneData)}
|
|
104
|
+
toggleLaneVisibility={toggleLaneVisibility}
|
|
105
|
+
/>
|
|
106
|
+
);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it("does not render a delete button", () => {
|
|
110
|
+
expect(screen.queryByRole("button", { name: /delete/i })).toBeNull();
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("does not render an inherit parent restrictions checkbox", () => {
|
|
114
|
+
expect(
|
|
115
|
+
screen.queryByRole("checkbox", {
|
|
116
|
+
name: /inherit restrictions from parent/i,
|
|
117
|
+
})
|
|
118
|
+
).toBeNull();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("does not render a custom lists editor", () => {
|
|
122
|
+
expect(screen.queryByTestId("LaneCustomListsEditor")).toBeNull();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it("renders an explanation that the lane contents can't be edited", () => {
|
|
126
|
+
expect(screen.getByText(/contents cannot be edited/i)).not.toBeNull();
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
it("doesn't render a custom lists editor while a lane is being loaded for editing", () => {
|
|
131
|
+
const laneData = null;
|
|
132
|
+
|
|
133
|
+
render(
|
|
134
|
+
<LaneEditor
|
|
135
|
+
library="library"
|
|
136
|
+
lane={laneData}
|
|
137
|
+
customLists={customListsData}
|
|
138
|
+
editOrCreate="edit"
|
|
139
|
+
editLane={editLane}
|
|
140
|
+
deleteLane={deleteLane}
|
|
141
|
+
findParentOfLane={stub().returns(laneData)}
|
|
142
|
+
toggleLaneVisibility={toggleLaneVisibility}
|
|
143
|
+
/>
|
|
144
|
+
);
|
|
145
|
+
|
|
146
|
+
expect(screen.queryByTestId("LaneCustomListsEditor")).toBeNull();
|
|
147
|
+
});
|
|
148
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { render, RenderOptions, RenderResult } from "@testing-library/react";
|
|
3
|
+
import ContextProvider, {
|
|
4
|
+
ContextProviderProps,
|
|
5
|
+
} from "../../../src/components/ContextProvider";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Renders a given React element, wrapped in a ContextProvider. The resulting rerender function is
|
|
9
|
+
* also wrapped, so that rerenders will have the identical context.
|
|
10
|
+
*
|
|
11
|
+
* @param ui The element to render
|
|
12
|
+
* @param contextProviderProps Props to pass to the ContextProvider wrapper
|
|
13
|
+
* @param renderOptions Options to pass through to the RTL render function
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
export default function renderWithContext(
|
|
17
|
+
ui: React.ReactElement,
|
|
18
|
+
contextProviderProps: ContextProviderProps,
|
|
19
|
+
renderOptions?: Omit<RenderOptions, "queries">
|
|
20
|
+
): RenderResult {
|
|
21
|
+
const renderResult = render(
|
|
22
|
+
<ContextProvider {...contextProviderProps}>{ui}</ContextProvider>,
|
|
23
|
+
renderOptions
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
const rerenderWithContext = (ui) => {
|
|
27
|
+
return renderResult.rerender(
|
|
28
|
+
<ContextProvider {...contextProviderProps}>{ui}</ContextProvider>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
...renderResult,
|
|
34
|
+
rerender: rerenderWithContext,
|
|
35
|
+
};
|
|
36
|
+
}
|
package/tsconfig.json
CHANGED
|
@@ -5,17 +5,21 @@
|
|
|
5
5
|
"target": "es5",
|
|
6
6
|
"outDir": "lib",
|
|
7
7
|
"lib": ["es2019", "dom"],
|
|
8
|
-
"rootDir": "
|
|
9
|
-
|
|
8
|
+
"rootDir": ".",
|
|
9
|
+
// Mocha and jest are both used in this project. Certain globals are declared by both,
|
|
10
|
+
// such as describe, it, and test. Setting skipLibCheck to true prevents typescript from
|
|
11
|
+
// erroring when it sees duplicate variable declarations with different types.
|
|
12
|
+
"skipLibCheck": true,
|
|
13
|
+
"types": ["mocha", "node", "jest", "@testing-library/jest-dom"],
|
|
10
14
|
"jsx": "react"
|
|
11
15
|
},
|
|
12
16
|
"exclude": [
|
|
13
17
|
"lib",
|
|
14
18
|
"node_modules",
|
|
15
|
-
"tests"
|
|
19
|
+
"tests/browser"
|
|
16
20
|
],
|
|
17
21
|
"typedocOptions": {
|
|
18
|
-
"
|
|
22
|
+
"entryPointStrategy": "expand",
|
|
19
23
|
"out": "docs"
|
|
20
24
|
}
|
|
21
25
|
}
|
package/webpack.common.js
CHANGED
|
@@ -3,7 +3,6 @@ const path = require("path");
|
|
|
3
3
|
const CleanWebpackPlugin = require("clean-webpack-plugin");
|
|
4
4
|
const webpack = require("webpack");
|
|
5
5
|
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
|
|
6
|
-
const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
|
|
7
6
|
const TerserPlugin = require("terser-webpack-plugin");
|
|
8
7
|
const CopyPlugin = require("copy-webpack-plugin");
|
|
9
8
|
/* eslint-enable @typescript-eslint/no-var-requires */
|
|
@@ -22,7 +21,7 @@ module.exports = {
|
|
|
22
21
|
new CleanWebpackPlugin(),
|
|
23
22
|
// jsdom is needed for server rendering, but causes errors
|
|
24
23
|
// in the browser even if it is never used, so we ignore it:
|
|
25
|
-
new webpack.IgnorePlugin(/jsdom$/),
|
|
24
|
+
new webpack.IgnorePlugin({ resourceRegExp: /jsdom$/ }),
|
|
26
25
|
// Extract separate css file.
|
|
27
26
|
new MiniCssExtractPlugin({ filename: "circulation-admin.css" }),
|
|
28
27
|
// Set a local global variable in the app that will be used only
|
|
@@ -47,18 +46,23 @@ module.exports = {
|
|
|
47
46
|
{
|
|
48
47
|
test: /\.tsx?$/,
|
|
49
48
|
exclude: [/node_modules/],
|
|
50
|
-
|
|
49
|
+
use: ["ts-loader"],
|
|
51
50
|
},
|
|
52
51
|
{
|
|
53
52
|
test: /\.(ttf|woff|eot|svg|png|woff2|gif|jpg)(\?[\s\S]+)?$/,
|
|
54
|
-
|
|
53
|
+
use: ["url-loader?limit=100000"],
|
|
55
54
|
},
|
|
56
55
|
],
|
|
57
56
|
},
|
|
58
57
|
resolve: {
|
|
59
|
-
extensions: [".ts", ".tsx", ".js", ".scss"],
|
|
60
58
|
alias: {
|
|
61
59
|
react: path.resolve("./node_modules/react"),
|
|
62
60
|
},
|
|
61
|
+
extensions: [".ts", ".tsx", ".js", ".scss"],
|
|
62
|
+
fallback: {
|
|
63
|
+
"stream": require.resolve("stream-browserify"),
|
|
64
|
+
"timers": require.resolve("timers-browserify"),
|
|
65
|
+
"url": require.resolve("url")
|
|
66
|
+
}
|
|
63
67
|
},
|
|
64
68
|
};
|
package/webpack.dev.config.js
CHANGED
package/webpack.prod.config.js
CHANGED