/*
Copyright (C) 2023 Cloudbase Solutions SRL
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
import React from "react";
import { Endpoint } from "@src/@types/Endpoint";
import { MigrationItem, TransferItem } from "@src/@types/MainItem";
import { fireEvent, render } from "@testing-library/react";
import TestUtils from "@tests/TestUtils";
import DashboardTopEndpoints from "./DashboardTopEndpoints";
jest.mock("react-router-dom", () => ({ Link: "a" }));
type BuildType = T extends "replica"
? TransferItem
: MigrationItem;
const buildItem = (
type: T,
origin_endpoint_id: string,
destination_endpoint_id: string
): BuildType => {
const item = {
id: "",
type,
name: "",
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
origin_endpoint_id,
destination_endpoint_id,
notes: "",
origin_minion_pool_id: null,
destination_minion_pool_id: null,
instances: [""],
info: {},
destination_environment: {},
source_environment: {},
transfer_result: null,
last_execution_status: "",
user_id: "",
};
return item as BuildType;
};
const buildEndpoint = (id: string): Endpoint => ({
id,
name: `${id}-name`,
description: "",
type: "openstack",
created_at: new Date().toISOString(),
mapped_regions: [],
connection_info: {},
});
const replicas: DashboardTopEndpoints["props"]["transfers"] = [
buildItem("replica", "a", "b"),
buildItem("replica", "a", "b"),
buildItem("replica", "c", "d"),
];
const migrations: DashboardTopEndpoints["props"]["migrations"] = [
buildItem("migration", "e", "f"),
buildItem("migration", "e", "f"),
buildItem("migration", "e", "f"),
];
const endpoints: DashboardTopEndpoints["props"]["endpoints"] = [
buildEndpoint("a"),
buildEndpoint("b"),
buildEndpoint("c"),
buildEndpoint("d"),
buildEndpoint("e"),
buildEndpoint("f"),
];
describe("DashboardTopEndpoints", () => {
const defaultProps: DashboardTopEndpoints["props"] = {
transfers: replicas,
migrations,
endpoints,
style: {},
loading: false,
onNewClick: jest.fn(),
};
it("should display a loading state", () => {
render(
);
expect(TestUtils.select("StatusImage__Image")).toBeTruthy();
});
it("should display no data message", () => {
render(
);
expect(TestUtils.select("DashboardTopEndpoints__NoItems")).toBeTruthy();
});
it("should trigger onNewClick when New Endpoint button is clicked", () => {
const onNewClickMock = jest.fn();
render(
);
fireEvent.click(
TestUtils.select("DashboardTopEndpoints__NoItems")?.querySelector(
"button"
)!
);
expect(onNewClickMock).toHaveBeenCalledTimes(1);
});
it("should display the chart with data", () => {
render();
expect(
TestUtils.select("DashboardTopEndpoints__ChartWrapper")
).toBeTruthy();
expect(
TestUtils.selectAll(
"DashboardTopEndpoints__LegendLabel-"
)[0].attributes.getNamedItem("to")?.value
).toBe("/endpoints/e");
expect(
TestUtils.selectAll("DashboardTopEndpoints__LegendLabel-")[1].textContent
).toBe("f-name");
});
it("should call calculateGroupedEndpoints when component receives new props", () => {
const calculateGroupedEndpointsSpy = jest.spyOn(
DashboardTopEndpoints.prototype,
"calculateGroupedEndpoints"
);
const { rerender } = render();
const newProps = {
...defaultProps,
replicas: [],
migrations: [],
endpoints: [],
};
rerender();
expect(calculateGroupedEndpointsSpy).toHaveBeenCalledWith(newProps);
expect(calculateGroupedEndpointsSpy).toHaveBeenCalledTimes(2);
});
it("should handle mouse over and update state", () => {
const setStateSpy = jest
.spyOn(DashboardTopEndpoints.prototype, "setState")
.mockImplementationOnce(() => {});
const instance = new DashboardTopEndpoints(defaultProps);
instance.chartRef = document.createElement("div");
const groupedEndpoint = {
endpoint: endpoints[0],
replicasCount: 1,
migrationsCount: 2,
value: 3,
};
instance.handleMouseOver(groupedEndpoint, 10, 10);
expect(setStateSpy).toHaveBeenCalledWith({
groupedEndpoint,
tooltipPosition: { x: 26, y: -22 },
});
});
it("should handle mouse over and not update state if there's no chartRef", () => {
const setStateSpy = jest
.spyOn(DashboardTopEndpoints.prototype, "setState")
.mockImplementationOnce(() => {});
const instance = new DashboardTopEndpoints(defaultProps);
instance.chartRef = null;
const groupedEndpoint = {
endpoint: endpoints[0],
replicasCount: 1,
migrationsCount: 2,
value: 3,
};
instance.handleMouseOver(groupedEndpoint, 10, 10);
expect(setStateSpy).not.toHaveBeenCalled();
});
it("should handle mouse leave and update state", () => {
const setStateSpy = jest
.spyOn(DashboardTopEndpoints.prototype, "setState")
.mockImplementationOnce(() => {});
const instance = new DashboardTopEndpoints(defaultProps);
instance.handleMouseLeave();
expect(setStateSpy).toHaveBeenCalledWith({
groupedEndpoint: null,
});
});
});