DashboardTopEndpoints.spec.tsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /*
  2. Copyright (C) 2023 Cloudbase Solutions SRL
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. import React from "react";
  15. import { Endpoint } from "@src/@types/Endpoint";
  16. import { MigrationItem, TransferItem } from "@src/@types/MainItem";
  17. import { fireEvent, render } from "@testing-library/react";
  18. import TestUtils from "@tests/TestUtils";
  19. import DashboardTopEndpoints from "./DashboardTopEndpoints";
  20. jest.mock("react-router-dom", () => ({ Link: "a" }));
  21. type BuildType<T extends "replica" | "migration"> = T extends "replica"
  22. ? TransferItem
  23. : MigrationItem;
  24. const buildItem = <T extends "replica" | "migration">(
  25. type: T,
  26. origin_endpoint_id: string,
  27. destination_endpoint_id: string
  28. ): BuildType<T> => {
  29. const item = {
  30. id: "",
  31. type,
  32. name: "",
  33. created_at: new Date().toISOString(),
  34. updated_at: new Date().toISOString(),
  35. origin_endpoint_id,
  36. destination_endpoint_id,
  37. notes: "",
  38. origin_minion_pool_id: null,
  39. destination_minion_pool_id: null,
  40. instances: [""],
  41. info: {},
  42. destination_environment: {},
  43. source_environment: {},
  44. transfer_result: null,
  45. last_execution_status: "",
  46. user_id: "",
  47. };
  48. return item as BuildType<T>;
  49. };
  50. const buildEndpoint = (id: string): Endpoint => ({
  51. id,
  52. name: `${id}-name`,
  53. description: "",
  54. type: "openstack",
  55. created_at: new Date().toISOString(),
  56. mapped_regions: [],
  57. connection_info: {},
  58. });
  59. const replicas: DashboardTopEndpoints["props"]["transfers"] = [
  60. buildItem("replica", "a", "b"),
  61. buildItem("replica", "a", "b"),
  62. buildItem("replica", "c", "d"),
  63. ];
  64. const migrations: DashboardTopEndpoints["props"]["migrations"] = [
  65. buildItem("migration", "e", "f"),
  66. buildItem("migration", "e", "f"),
  67. buildItem("migration", "e", "f"),
  68. ];
  69. const endpoints: DashboardTopEndpoints["props"]["endpoints"] = [
  70. buildEndpoint("a"),
  71. buildEndpoint("b"),
  72. buildEndpoint("c"),
  73. buildEndpoint("d"),
  74. buildEndpoint("e"),
  75. buildEndpoint("f"),
  76. ];
  77. describe("DashboardTopEndpoints", () => {
  78. const defaultProps: DashboardTopEndpoints["props"] = {
  79. transfers: replicas,
  80. migrations,
  81. endpoints,
  82. style: {},
  83. loading: false,
  84. onNewClick: jest.fn(),
  85. };
  86. it("should display a loading state", () => {
  87. render(
  88. <DashboardTopEndpoints
  89. {...defaultProps}
  90. transfers={[]}
  91. migrations={[]}
  92. endpoints={[]}
  93. loading={true}
  94. />
  95. );
  96. expect(TestUtils.select("StatusImage__Image")).toBeTruthy();
  97. });
  98. it("should display no data message", () => {
  99. render(
  100. <DashboardTopEndpoints
  101. {...defaultProps}
  102. transfers={[]}
  103. migrations={[]}
  104. endpoints={[]}
  105. />
  106. );
  107. expect(TestUtils.select("DashboardTopEndpoints__NoItems")).toBeTruthy();
  108. });
  109. it("should trigger onNewClick when New Endpoint button is clicked", () => {
  110. const onNewClickMock = jest.fn();
  111. render(
  112. <DashboardTopEndpoints
  113. {...defaultProps}
  114. onNewClick={onNewClickMock}
  115. transfers={[]}
  116. migrations={[]}
  117. endpoints={[]}
  118. />
  119. );
  120. fireEvent.click(
  121. TestUtils.select("DashboardTopEndpoints__NoItems")?.querySelector(
  122. "button"
  123. )!
  124. );
  125. expect(onNewClickMock).toHaveBeenCalledTimes(1);
  126. });
  127. it("should display the chart with data", () => {
  128. render(<DashboardTopEndpoints {...defaultProps} />);
  129. expect(
  130. TestUtils.select("DashboardTopEndpoints__ChartWrapper")
  131. ).toBeTruthy();
  132. expect(
  133. TestUtils.selectAll(
  134. "DashboardTopEndpoints__LegendLabel-"
  135. )[0].attributes.getNamedItem("to")?.value
  136. ).toBe("/endpoints/e");
  137. expect(
  138. TestUtils.selectAll("DashboardTopEndpoints__LegendLabel-")[1].textContent
  139. ).toBe("f-name");
  140. });
  141. it("should call calculateGroupedEndpoints when component receives new props", () => {
  142. const calculateGroupedEndpointsSpy = jest.spyOn(
  143. DashboardTopEndpoints.prototype,
  144. "calculateGroupedEndpoints"
  145. );
  146. const { rerender } = render(<DashboardTopEndpoints {...defaultProps} />);
  147. const newProps = {
  148. ...defaultProps,
  149. replicas: [],
  150. migrations: [],
  151. endpoints: [],
  152. };
  153. rerender(<DashboardTopEndpoints {...newProps} />);
  154. expect(calculateGroupedEndpointsSpy).toHaveBeenCalledWith(newProps);
  155. expect(calculateGroupedEndpointsSpy).toHaveBeenCalledTimes(2);
  156. });
  157. it("should handle mouse over and update state", () => {
  158. const setStateSpy = jest
  159. .spyOn(DashboardTopEndpoints.prototype, "setState")
  160. .mockImplementationOnce(() => {});
  161. const instance = new DashboardTopEndpoints(defaultProps);
  162. instance.chartRef = document.createElement("div");
  163. const groupedEndpoint = {
  164. endpoint: endpoints[0],
  165. replicasCount: 1,
  166. migrationsCount: 2,
  167. value: 3,
  168. };
  169. instance.handleMouseOver(groupedEndpoint, 10, 10);
  170. expect(setStateSpy).toHaveBeenCalledWith({
  171. groupedEndpoint,
  172. tooltipPosition: { x: 26, y: -22 },
  173. });
  174. });
  175. it("should handle mouse over and not update state if there's no chartRef", () => {
  176. const setStateSpy = jest
  177. .spyOn(DashboardTopEndpoints.prototype, "setState")
  178. .mockImplementationOnce(() => {});
  179. const instance = new DashboardTopEndpoints(defaultProps);
  180. instance.chartRef = null;
  181. const groupedEndpoint = {
  182. endpoint: endpoints[0],
  183. replicasCount: 1,
  184. migrationsCount: 2,
  185. value: 3,
  186. };
  187. instance.handleMouseOver(groupedEndpoint, 10, 10);
  188. expect(setStateSpy).not.toHaveBeenCalled();
  189. });
  190. it("should handle mouse leave and update state", () => {
  191. const setStateSpy = jest
  192. .spyOn(DashboardTopEndpoints.prototype, "setState")
  193. .mockImplementationOnce(() => {});
  194. const instance = new DashboardTopEndpoints(defaultProps);
  195. instance.handleMouseLeave();
  196. expect(setStateSpy).toHaveBeenCalledWith({
  197. groupedEndpoint: null,
  198. });
  199. });
  200. });