@openshift-migration-advisor/shared-components 0.28.0-9da6a7613f16 → 0.28.0-cc35dd2cf135
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/dist/charts/MigrationDonutChart.d.ts.map +1 -1
- package/dist/charts/MigrationDonutChart.js +8 -4
- package/dist/report/OsUpgradeRecommendationPopover.d.ts.map +1 -1
- package/dist/report/OsUpgradeRecommendationPopover.js +1 -7
- package/dist/report/ReportExportMenu.d.ts +1 -0
- package/dist/report/ReportExportMenu.d.ts.map +1 -1
- package/dist/report/ReportExportMenu.js +38 -4
- package/dist/report/StorageOverview.d.ts.map +1 -1
- package/dist/report/StorageOverview.js +13 -1
- package/dist/report/VMMigrationStatus.d.ts +33 -0
- package/dist/report/VMMigrationStatus.d.ts.map +1 -0
- package/dist/report/VMMigrationStatus.js +129 -0
- package/dist/report/index.d.ts +2 -1
- package/dist/report/index.d.ts.map +1 -1
- package/dist/report/index.js +1 -0
- package/dist/report/reportExportOptions.d.ts +13 -2
- package/dist/report/reportExportOptions.d.ts.map +1 -1
- package/dist/report/reportExportOptions.js +13 -5
- package/package.json +1 -1
- package/src/charts/MigrationDonutChart.tsx +18 -6
- package/src/charts/__tests__/MigrationDonutChart.test.tsx +53 -0
- package/src/report/OsUpgradeRecommendationPopover.tsx +0 -8
- package/src/report/ReportExportMenu.tsx +69 -13
- package/src/report/StorageOverview.tsx +18 -1
- package/src/report/VMMigrationStatus.tsx +358 -0
- package/src/report/__tests__/StorageOverview.test.tsx +44 -0
- package/src/report/__tests__/VMMigrationStatus.test.tsx +178 -0
- package/src/report/index.ts +7 -0
- package/src/report/reportExportOptions.ts +28 -5
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import "@testing-library/jest-dom";
|
|
2
|
+
import { cleanup, render, screen } from "@testing-library/react";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
4
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
import type { MigrationDonutChartProps } from "../../charts/MigrationDonutChart.js";
|
|
6
|
+
import { chartColorFailure, chartColorSuccess } from "../constants.js";
|
|
7
|
+
import { VMMigrationStatus } from "../VMMigrationStatus.js";
|
|
8
|
+
|
|
9
|
+
const donutProps = vi.hoisted(() => ({
|
|
10
|
+
current: null as MigrationDonutChartProps | null,
|
|
11
|
+
}));
|
|
12
|
+
|
|
13
|
+
vi.mock("../../charts/MigrationDonutChart.js", () => ({
|
|
14
|
+
MigrationDonutChart: (props: MigrationDonutChartProps): JSX.Element => {
|
|
15
|
+
donutProps.current = props;
|
|
16
|
+
return (
|
|
17
|
+
<div data-testid="migration-donut">
|
|
18
|
+
{props.title} {props.subTitle}
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
},
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
donutProps.current = null;
|
|
26
|
+
cleanup();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const renderedDonut = (): MigrationDonutChartProps => {
|
|
30
|
+
const props = donutProps.current;
|
|
31
|
+
if (!props) {
|
|
32
|
+
throw new Error("expected a migration-status donut to render");
|
|
33
|
+
}
|
|
34
|
+
return props;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const selectView = async (name: string): Promise<void> => {
|
|
38
|
+
const user = userEvent.setup();
|
|
39
|
+
await user.click(
|
|
40
|
+
screen.getByRole("button", { name: "No issues vs with issues" }),
|
|
41
|
+
);
|
|
42
|
+
await user.click(screen.getByRole("menuitem", { name }));
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
describe("VMMigrationStatus", () => {
|
|
46
|
+
it("shows the empty state when there are no VMs", () => {
|
|
47
|
+
render(<VMMigrationStatus data={{ migratable: 0, nonMigratable: 0 }} />);
|
|
48
|
+
|
|
49
|
+
expect(screen.getByText("VM Migration Status")).toBeInTheDocument();
|
|
50
|
+
expect(
|
|
51
|
+
screen.getByText("Migration status data not collected"),
|
|
52
|
+
).toBeInTheDocument();
|
|
53
|
+
expect(screen.queryByTestId("migration-donut")).not.toBeInTheDocument();
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
it("renders the migratable vs not-ready donut", () => {
|
|
57
|
+
render(<VMMigrationStatus data={{ migratable: 7, nonMigratable: 3 }} />);
|
|
58
|
+
|
|
59
|
+
expect(screen.getByTestId("migration-donut")).toHaveTextContent("10 VMs");
|
|
60
|
+
|
|
61
|
+
const props = renderedDonut();
|
|
62
|
+
expect(props.data.map((slice) => [slice.name, slice.count])).toEqual([
|
|
63
|
+
["Migratable", 7],
|
|
64
|
+
["Not ready for migration", 3],
|
|
65
|
+
]);
|
|
66
|
+
expect(props.legend).toEqual({
|
|
67
|
+
Migratable: chartColorSuccess,
|
|
68
|
+
"Not ready for migration": chartColorFailure,
|
|
69
|
+
});
|
|
70
|
+
expect(props.legendVariant).toBe("html");
|
|
71
|
+
expect(props.subTitleColor).toBe(
|
|
72
|
+
"var(--pf-t--global--text--color--subtle)",
|
|
73
|
+
);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it("drills down into readiness when a donut slice is clicked", () => {
|
|
77
|
+
const onReadinessSelect = vi.fn();
|
|
78
|
+
render(
|
|
79
|
+
<VMMigrationStatus
|
|
80
|
+
data={{ migratable: 7, nonMigratable: 3 }}
|
|
81
|
+
onReadinessSelect={onReadinessSelect}
|
|
82
|
+
/>,
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const props = renderedDonut();
|
|
86
|
+
const [migratable, notReady] = props.data;
|
|
87
|
+
if (!migratable || !notReady) {
|
|
88
|
+
throw new Error("expected both readiness slices");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
props.onItemClick?.(migratable);
|
|
92
|
+
expect(onReadinessSelect).toHaveBeenLastCalledWith(true);
|
|
93
|
+
|
|
94
|
+
props.onItemClick?.(notReady);
|
|
95
|
+
expect(onReadinessSelect).toHaveBeenLastCalledWith(false);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("forwards the center-title click", () => {
|
|
99
|
+
const onTitleClick = vi.fn();
|
|
100
|
+
render(
|
|
101
|
+
<VMMigrationStatus
|
|
102
|
+
data={{ migratable: 1, nonMigratable: 0 }}
|
|
103
|
+
onTitleClick={onTitleClick}
|
|
104
|
+
/>,
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
renderedDonut().onTitleClick?.();
|
|
108
|
+
expect(onTitleClick).toHaveBeenCalledTimes(1);
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
it("renders the issue breakdown bars in category order", async () => {
|
|
112
|
+
render(
|
|
113
|
+
<VMMigrationStatus
|
|
114
|
+
data={{ migratable: 1, nonMigratable: 9 }}
|
|
115
|
+
issuesBreakdown={{
|
|
116
|
+
critical: 3,
|
|
117
|
+
error: 2,
|
|
118
|
+
warning: 5,
|
|
119
|
+
information: 1,
|
|
120
|
+
advisory: 0,
|
|
121
|
+
}}
|
|
122
|
+
/>,
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
await selectView("With issues breakdown");
|
|
126
|
+
|
|
127
|
+
expect(screen.queryByTestId("migration-donut")).not.toBeInTheDocument();
|
|
128
|
+
expect(screen.getByTitle("Critical: 3 VMs")).toBeInTheDocument();
|
|
129
|
+
expect(screen.getByTitle("Warning: 5 VMs")).toBeInTheDocument();
|
|
130
|
+
expect(screen.getByTitle("Advisory: 0 VMs")).toBeInTheDocument();
|
|
131
|
+
expect(
|
|
132
|
+
screen.getByText(/Totals may exceed the unique VM count/),
|
|
133
|
+
).toBeInTheDocument();
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("drills down into a concern category when a bar is clicked", async () => {
|
|
137
|
+
const onCategorySelect = vi.fn();
|
|
138
|
+
render(
|
|
139
|
+
<VMMigrationStatus
|
|
140
|
+
data={{ migratable: 1, nonMigratable: 9 }}
|
|
141
|
+
issuesBreakdown={{
|
|
142
|
+
critical: 3,
|
|
143
|
+
error: 2,
|
|
144
|
+
warning: 5,
|
|
145
|
+
information: 1,
|
|
146
|
+
advisory: 0,
|
|
147
|
+
}}
|
|
148
|
+
onCategorySelect={onCategorySelect}
|
|
149
|
+
/>,
|
|
150
|
+
);
|
|
151
|
+
|
|
152
|
+
await selectView("With issues breakdown");
|
|
153
|
+
await userEvent.setup().click(screen.getByTitle("Warning: 5 VMs"));
|
|
154
|
+
|
|
155
|
+
expect(onCategorySelect).toHaveBeenCalledWith("Warning");
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
it("shows the breakdown empty state when no issue data was collected", async () => {
|
|
159
|
+
render(<VMMigrationStatus data={{ migratable: 1, nonMigratable: 9 }} />);
|
|
160
|
+
|
|
161
|
+
await selectView("With issues breakdown");
|
|
162
|
+
|
|
163
|
+
expect(
|
|
164
|
+
screen.getByText("Issues breakdown data not collected"),
|
|
165
|
+
).toBeInTheDocument();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("passes the chart legend variant through", () => {
|
|
169
|
+
render(
|
|
170
|
+
<VMMigrationStatus
|
|
171
|
+
legendVariant="chart"
|
|
172
|
+
data={{ migratable: 1, nonMigratable: 1 }}
|
|
173
|
+
/>,
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
expect(renderedDonut().legendVariant).toBe("chart");
|
|
177
|
+
});
|
|
178
|
+
});
|
package/src/report/index.ts
CHANGED
|
@@ -192,7 +192,9 @@ export {
|
|
|
192
192
|
export { ReportTable, type ReportTableProps } from "./ReportTable.js";
|
|
193
193
|
export {
|
|
194
194
|
type ReportExportOption,
|
|
195
|
+
type ReportExportSection,
|
|
195
196
|
type StandardReportExportHandlers,
|
|
197
|
+
type StandardReportExportOptionsConfig,
|
|
196
198
|
standardReportExportOptions,
|
|
197
199
|
} from "./reportExportOptions.js";
|
|
198
200
|
export {
|
|
@@ -211,6 +213,11 @@ export {
|
|
|
211
213
|
VCenterClusterDetails,
|
|
212
214
|
type VCenterClusterDetailsProps,
|
|
213
215
|
} from "./VCenterClusterDetails.js";
|
|
216
|
+
export {
|
|
217
|
+
type IssuesBreakdownLike,
|
|
218
|
+
VMMigrationStatus,
|
|
219
|
+
type VMMigrationStatusProps,
|
|
220
|
+
} from "./VMMigrationStatus.js";
|
|
214
221
|
export {
|
|
215
222
|
VmPowerStates,
|
|
216
223
|
type VmPowerStatesProps,
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
export interface ReportExportSection {
|
|
2
|
+
id: string;
|
|
3
|
+
label: string;
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
export interface ReportExportOption {
|
|
2
7
|
key: string;
|
|
3
8
|
label: string;
|
|
4
9
|
description?: string;
|
|
5
10
|
onSelect: () => void;
|
|
6
11
|
isDisabled?: boolean;
|
|
12
|
+
/** When set, the menu groups rows and shows `label` as the group heading. */
|
|
13
|
+
section?: ReportExportSection;
|
|
7
14
|
}
|
|
8
15
|
|
|
9
16
|
export interface StandardReportExportHandlers {
|
|
@@ -12,22 +19,38 @@ export interface StandardReportExportHandlers {
|
|
|
12
19
|
onExportHtml?: () => void;
|
|
13
20
|
}
|
|
14
21
|
|
|
22
|
+
export type StandardReportExportOptionsConfig = StandardReportExportHandlers & {
|
|
23
|
+
/** Dropdown group label for PDF / HTML / PNG. Default: `"Assessment report"`. */
|
|
24
|
+
assessmentSectionLabel?: string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const DEFAULT_ASSESSMENT_SECTION: ReportExportSection = {
|
|
28
|
+
id: "assessment-report",
|
|
29
|
+
label: "Assessment report",
|
|
30
|
+
};
|
|
31
|
+
|
|
15
32
|
/**
|
|
16
|
-
*
|
|
33
|
+
* Optional helper for chart-based assessment downloads. Omit a handler to hide
|
|
34
|
+
* that format. Override `assessmentSectionLabel` if product copy differs per app.
|
|
17
35
|
*/
|
|
18
36
|
export const standardReportExportOptions = ({
|
|
19
37
|
onExportPdf,
|
|
20
38
|
onExportPng,
|
|
21
39
|
onExportHtml,
|
|
22
|
-
|
|
40
|
+
assessmentSectionLabel,
|
|
41
|
+
}: StandardReportExportOptionsConfig): ReportExportOption[] => {
|
|
42
|
+
const section: ReportExportSection = assessmentSectionLabel
|
|
43
|
+
? { ...DEFAULT_ASSESSMENT_SECTION, label: assessmentSectionLabel }
|
|
44
|
+
: DEFAULT_ASSESSMENT_SECTION;
|
|
45
|
+
|
|
23
46
|
const options: ReportExportOption[] = [];
|
|
24
47
|
|
|
25
48
|
if (onExportPdf) {
|
|
26
49
|
options.push({
|
|
27
50
|
key: "pdf",
|
|
28
51
|
label: "PDF",
|
|
29
|
-
description: "Export the report as a PDF",
|
|
30
52
|
onSelect: onExportPdf,
|
|
53
|
+
section,
|
|
31
54
|
});
|
|
32
55
|
}
|
|
33
56
|
|
|
@@ -35,8 +58,8 @@ export const standardReportExportOptions = ({
|
|
|
35
58
|
options.push({
|
|
36
59
|
key: "html",
|
|
37
60
|
label: "HTML",
|
|
38
|
-
description: "Export the report as HTML",
|
|
39
61
|
onSelect: onExportHtml,
|
|
62
|
+
section,
|
|
40
63
|
});
|
|
41
64
|
}
|
|
42
65
|
|
|
@@ -44,8 +67,8 @@ export const standardReportExportOptions = ({
|
|
|
44
67
|
options.push({
|
|
45
68
|
key: "png",
|
|
46
69
|
label: "PNG",
|
|
47
|
-
description: "Download all charts as PNG files",
|
|
48
70
|
onSelect: onExportPng,
|
|
71
|
+
section,
|
|
49
72
|
});
|
|
50
73
|
}
|
|
51
74
|
|