@thepalaceproject/circulation-admin 1.11.0 → 1.12.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.
package/package.json
CHANGED
|
@@ -73,10 +73,12 @@
|
|
|
73
73
|
"@types/jest": "^29.2.6",
|
|
74
74
|
"@types/mocha": "^10.0.1",
|
|
75
75
|
"@types/node": "^18.11.14",
|
|
76
|
+
"@types/numeral": "^2.0.5",
|
|
76
77
|
"@types/prop-types": "^15.7.3",
|
|
77
78
|
"@types/react": "^16.14.6",
|
|
78
79
|
"@types/react-dom": "^16.9.8",
|
|
79
80
|
"@types/react-redux": "^7.1.16",
|
|
81
|
+
"@types/recharts": "^1.8.28",
|
|
80
82
|
"@types/redux-mock-store": "^1.0.3",
|
|
81
83
|
"@typescript-eslint/eslint-plugin": "^5.46.0",
|
|
82
84
|
"@typescript-eslint/parser": "^5.46.0",
|
|
@@ -139,5 +141,5 @@
|
|
|
139
141
|
"*.{js,jsx,ts,tsx,css,md}": "prettier --write",
|
|
140
142
|
"*.{js,css,md}": "prettier --write"
|
|
141
143
|
},
|
|
142
|
-
"version": "1.
|
|
144
|
+
"version": "1.12.0-post.1"
|
|
143
145
|
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { render } from "@testing-library/react";
|
|
3
|
+
import { CustomTooltip } from "../../../src/components/LibraryStats";
|
|
4
|
+
|
|
5
|
+
describe("Dashboard Statistics", () => {
|
|
6
|
+
// NB: This adds test to the already existing tests in:
|
|
7
|
+
// - `src/components/__tests__/Stats-test.tsx`.
|
|
8
|
+
// - `src/components/__tests__/LibraryStats-test.tsx`.
|
|
9
|
+
// - `src/components/__tests__/SingleStatListItem-test.tsx`.
|
|
10
|
+
//
|
|
11
|
+
// Those tests should eventually be migrated here and
|
|
12
|
+
// adapted to the Jest/React Testing Library paradigm.
|
|
13
|
+
|
|
14
|
+
describe("charting - custom tooltip", () => {
|
|
15
|
+
const defaultLabel = "Collection X";
|
|
16
|
+
const summaryInventory = {
|
|
17
|
+
availableTitles: 7953,
|
|
18
|
+
licensedTitles: 7974,
|
|
19
|
+
meteredLicenseTitles: 7974,
|
|
20
|
+
meteredLicensesAvailable: 75446,
|
|
21
|
+
meteredLicensesOwned: 301541,
|
|
22
|
+
openAccessTitles: 0,
|
|
23
|
+
titles: 7974,
|
|
24
|
+
unlimitedLicenseTitles: 0,
|
|
25
|
+
};
|
|
26
|
+
const perMediumInventory = {
|
|
27
|
+
Audio: {
|
|
28
|
+
availableTitles: 148,
|
|
29
|
+
licensedTitles: 165,
|
|
30
|
+
meteredLicenseTitles: 165,
|
|
31
|
+
meteredLicensesAvailable: 221,
|
|
32
|
+
meteredLicensesOwned: 392,
|
|
33
|
+
openAccessTitles: 0,
|
|
34
|
+
titles: 165,
|
|
35
|
+
unlimitedLicenseTitles: 0,
|
|
36
|
+
},
|
|
37
|
+
Book: {
|
|
38
|
+
availableTitles: 7805,
|
|
39
|
+
licensedTitles: 7809,
|
|
40
|
+
meteredLicenseTitles: 7809,
|
|
41
|
+
meteredLicensesAvailable: 75225,
|
|
42
|
+
meteredLicensesOwned: 301149,
|
|
43
|
+
openAccessTitles: 0,
|
|
44
|
+
titles: 7809,
|
|
45
|
+
unlimitedLicenseTitles: 0,
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
const defaultChartItemWithoutPerMediumInventory = {
|
|
49
|
+
name: defaultLabel,
|
|
50
|
+
...summaryInventory,
|
|
51
|
+
};
|
|
52
|
+
const defaultChartItemWithPerMediumInventory = {
|
|
53
|
+
...defaultChartItemWithoutPerMediumInventory,
|
|
54
|
+
_by_medium: perMediumInventory,
|
|
55
|
+
};
|
|
56
|
+
const defaultPayload = [
|
|
57
|
+
{
|
|
58
|
+
fill: "#606060",
|
|
59
|
+
dataKey: "meteredLicenseTitles",
|
|
60
|
+
name: "Metered License Titles",
|
|
61
|
+
color: "#606060",
|
|
62
|
+
value: 7974,
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
fill: "#404040",
|
|
66
|
+
dataKey: "unlimitedLicenseTitles",
|
|
67
|
+
name: "Unlimited License Titles",
|
|
68
|
+
color: "#404040",
|
|
69
|
+
value: 0,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
fill: "#202020",
|
|
73
|
+
dataKey: "openAccessTitles",
|
|
74
|
+
name: "Open Access Titles",
|
|
75
|
+
color: "#202020",
|
|
76
|
+
value: 0,
|
|
77
|
+
},
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
const populateTooltipProps = ({
|
|
81
|
+
active = true,
|
|
82
|
+
label = defaultLabel,
|
|
83
|
+
payload = [],
|
|
84
|
+
chartItem = undefined,
|
|
85
|
+
}) => {
|
|
86
|
+
const constructedChartItem = !chartItem
|
|
87
|
+
? chartItem
|
|
88
|
+
: {
|
|
89
|
+
...chartItem,
|
|
90
|
+
name: label,
|
|
91
|
+
};
|
|
92
|
+
const constructedPayload = payload.map((entry) => ({
|
|
93
|
+
...entry,
|
|
94
|
+
payload: constructedChartItem,
|
|
95
|
+
}));
|
|
96
|
+
return {
|
|
97
|
+
active,
|
|
98
|
+
label,
|
|
99
|
+
payload: constructedPayload,
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Helper function to test passing tests for a tooltip
|
|
105
|
+
*
|
|
106
|
+
* @param tooltipProps - passed to the <CustomTooltip /> component
|
|
107
|
+
* @param expectedInventoryItemText - the expected inventory item text content
|
|
108
|
+
*/
|
|
109
|
+
const expectPassingTestsForActiveTooltip = ({
|
|
110
|
+
tooltipProps,
|
|
111
|
+
expectedInventoryItemText,
|
|
112
|
+
}) => {
|
|
113
|
+
const { container, getByRole } = render(
|
|
114
|
+
<CustomTooltip {...tooltipProps} />
|
|
115
|
+
);
|
|
116
|
+
const tooltipContent = container.querySelector(".customTooltip");
|
|
117
|
+
|
|
118
|
+
const detail = tooltipContent.querySelector(".customTooltipDetail");
|
|
119
|
+
const detailChildren = detail.children;
|
|
120
|
+
const heading = getByRole("heading", { level: 1, name: "Collection X" });
|
|
121
|
+
const items = tooltipContent.querySelectorAll("p.customTooltipItem");
|
|
122
|
+
const divider = detail.querySelector("hr");
|
|
123
|
+
|
|
124
|
+
expect(heading).toHaveTextContent("Collection X");
|
|
125
|
+
|
|
126
|
+
// Eight (8) metrics in the following order.
|
|
127
|
+
expect(items).toHaveLength(8);
|
|
128
|
+
// The expected inventory item labels array should be the same length.
|
|
129
|
+
expect(expectedInventoryItemText).toHaveLength(items.length);
|
|
130
|
+
// And the items should contain at least the expected text.
|
|
131
|
+
Array.from(items).forEach((item, index) => {
|
|
132
|
+
expect(item).toHaveTextContent(expectedInventoryItemText[index]);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
// The heading should be at the top and the divider (`hr`)
|
|
136
|
+
// should be between the third and fourth statistics.
|
|
137
|
+
expect(detailChildren).toHaveLength(10);
|
|
138
|
+
expect(heading).toEqual(detailChildren[0]);
|
|
139
|
+
expect(items[0]).toEqual(detailChildren[1]);
|
|
140
|
+
expect(items[2]).toEqual(detailChildren[3]);
|
|
141
|
+
expect(divider).toEqual(detailChildren[4]);
|
|
142
|
+
expect(items[3]).toEqual(detailChildren[5]);
|
|
143
|
+
expect(items[7]).toEqual(detailChildren[9]);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
it("should not render when active is false", () => {
|
|
147
|
+
// Recharts sticks some extra props
|
|
148
|
+
const tooltipProps = populateTooltipProps({
|
|
149
|
+
active: false,
|
|
150
|
+
chartItem: defaultChartItemWithPerMediumInventory,
|
|
151
|
+
payload: defaultPayload,
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
const { container, getByRole } = render(
|
|
155
|
+
<CustomTooltip {...tooltipProps} />
|
|
156
|
+
);
|
|
157
|
+
const tooltipContent = container.querySelectorAll(".customTooltip");
|
|
158
|
+
|
|
159
|
+
expect(tooltipContent).toHaveLength(0);
|
|
160
|
+
});
|
|
161
|
+
it("should render when active is true", () => {
|
|
162
|
+
const tooltipProps = populateTooltipProps({
|
|
163
|
+
active: true,
|
|
164
|
+
chartItem: defaultChartItemWithoutPerMediumInventory,
|
|
165
|
+
payload: defaultPayload,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const expectedInventoryItemText = [
|
|
169
|
+
"Titles:",
|
|
170
|
+
"Available Titles:",
|
|
171
|
+
"Metered License Titles:",
|
|
172
|
+
"Licensed Titles:",
|
|
173
|
+
"Metered Licenses Available:",
|
|
174
|
+
"Metered Licenses Owned:",
|
|
175
|
+
"Open Access Titles:",
|
|
176
|
+
"Unlimited License Titles:",
|
|
177
|
+
];
|
|
178
|
+
|
|
179
|
+
expectPassingTestsForActiveTooltip({
|
|
180
|
+
tooltipProps,
|
|
181
|
+
expectedInventoryItemText,
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
it("should render without per-medium inventory", () => {
|
|
185
|
+
const tooltipProps = populateTooltipProps({
|
|
186
|
+
active: true,
|
|
187
|
+
chartItem: defaultChartItemWithoutPerMediumInventory,
|
|
188
|
+
payload: defaultPayload,
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
const expectedInventoryItemText = [
|
|
192
|
+
"Titles: 7,974",
|
|
193
|
+
"Available Titles: 7,953",
|
|
194
|
+
"Metered License Titles: 7,974",
|
|
195
|
+
"Licensed Titles: 7,974",
|
|
196
|
+
"Metered Licenses Available: 75,446",
|
|
197
|
+
"Metered Licenses Owned: 301,541",
|
|
198
|
+
"Open Access Titles: 0",
|
|
199
|
+
"Unlimited License Titles: 0",
|
|
200
|
+
];
|
|
201
|
+
|
|
202
|
+
expectPassingTestsForActiveTooltip({
|
|
203
|
+
tooltipProps,
|
|
204
|
+
expectedInventoryItemText,
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
it("should render additional detail with per-medium inventory", () => {
|
|
208
|
+
const tooltipProps = populateTooltipProps({
|
|
209
|
+
active: true,
|
|
210
|
+
chartItem: defaultChartItemWithPerMediumInventory,
|
|
211
|
+
payload: defaultPayload,
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
const expectedInventoryItemText = [
|
|
215
|
+
"Titles: 7,974 (Audio: 165, Book: 7,809)",
|
|
216
|
+
"Available Titles: 7,953 (Audio: 148, Book: 7,805)",
|
|
217
|
+
"Metered License Titles: 7,974 (Audio: 165, Book: 7,809)",
|
|
218
|
+
"Licensed Titles: 7,974 (Audio: 165, Book: 7,809)",
|
|
219
|
+
"Metered Licenses Available: 75,446 (Audio: 221, Book: 75,225)",
|
|
220
|
+
"Metered Licenses Owned: 301,541 (Audio: 392, Book: 301,149)",
|
|
221
|
+
"Open Access Titles: 0",
|
|
222
|
+
"Unlimited License Titles: 0",
|
|
223
|
+
];
|
|
224
|
+
|
|
225
|
+
expectPassingTestsForActiveTooltip({
|
|
226
|
+
tooltipProps,
|
|
227
|
+
expectedInventoryItemText,
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
});
|