replicas-list.cy.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. /// <reference types="cypress" />
  2. import { routeSelectors } from "../../support/routeSelectors";
  3. describe("Replicas list", () => {
  4. beforeEach(() => {
  5. cy.setProjectIdCookie();
  6. cy.mockAuth();
  7. cy.intercept(routeSelectors.ENDPOINTS, {
  8. fixture: "endpoints/endpoints.json",
  9. }).as("endpoints");
  10. });
  11. const waitForAll = () => {
  12. cy.waitMockAuth();
  13. cy.wait(["@endpoints"]);
  14. };
  15. it("renders empty list", () => {
  16. cy.intercept(routeSelectors.REPLICAS, {
  17. body: { replicas: [] },
  18. }).as("replicas");
  19. cy.visit("/replicas");
  20. waitForAll();
  21. cy.wait(["@replicas"]);
  22. cy.get("div[class^='MainList__EmptyListMessage']").should(
  23. "contain.text",
  24. "don't have any Replicas in this project"
  25. );
  26. cy.get("button").should("contain.text", "Create a Replica");
  27. });
  28. it("renders list with scheduled icon", () => {
  29. const scheduleAliases: string[] = [];
  30. let schedules: any[] = [];
  31. cy.loadFixtures(
  32. [
  33. "transfers/replicas",
  34. "transfers/schedules-enabled",
  35. "transfers/schedules-disabled",
  36. ],
  37. (results: any[]) => {
  38. const replicas = results[0].replicas;
  39. schedules = replicas.map((_, index) =>
  40. index % 2 === 0 ? results[1].schedules : results[2].schedules
  41. );
  42. for (const [index, replica] of replicas.entries()) {
  43. const scheduleAlias = `schedule-${index}`;
  44. cy.intercept(`**/coriolis/**/replicas/${replica.id}/schedules`, {
  45. body: {
  46. schedules: schedules[index],
  47. },
  48. }).as(scheduleAlias);
  49. scheduleAliases.push(`@${scheduleAlias}`);
  50. }
  51. }
  52. );
  53. cy.visit("/replicas");
  54. waitForAll();
  55. cy.wait(scheduleAliases);
  56. cy.get("div[class^='MainList__EmptyListMessage']").should("not.exist");
  57. for (const [index, schedule] of schedules.entries()) {
  58. const shouldHaveIcon = schedule.find(s => s.enabled);
  59. const scheduleImage = cy
  60. .get("div[class^='TransferListItem__StatusWrapper']")
  61. .eq(index)
  62. .get("div[class^='TransferListItem__ScheduleImage']");
  63. if (shouldHaveIcon) {
  64. scheduleImage.should("exist");
  65. } else {
  66. scheduleImage.should("not.exist");
  67. }
  68. }
  69. });
  70. it("filters list", () => {
  71. cy.intercept(routeSelectors.SCHEDULES, {
  72. fixture: "transfers/schedules-enabled.json",
  73. }).as("schedules");
  74. cy.visit("/replicas");
  75. waitForAll();
  76. cy.wait(["@schedules"]);
  77. cy.loadFixtures(["transfers/replicas"], (results: any[]) => {
  78. const replicas = results[0].replicas;
  79. cy.get("div[class^='MainListFilter__FilterItem']")
  80. .contains("Error")
  81. .click();
  82. cy.get("div[class^='MainList__NoResults']").should("exist");
  83. cy.get("div[class^='MainListFilter__FilterItem']")
  84. .contains("Completed")
  85. .click();
  86. cy.get("div[class^='TransferListItem__Wrapper']").should(
  87. "have.length",
  88. replicas.filter(r => r.last_execution_status === "COMPLETED").length
  89. );
  90. cy.get("div[class^='MainListFilter__FilterItem']")
  91. .contains("All")
  92. .click();
  93. cy.get("div[class^='TransferListItem__Wrapper']").should(
  94. "have.length",
  95. replicas.length
  96. );
  97. cy.get("div[class^='SearchButton__Wrapper']").click();
  98. cy.get("input[class*='SearchInput']").type("ol88");
  99. cy.get("div[class^='TransferListItem__Wrapper']").should(
  100. "have.length",
  101. replicas.filter(r => r.instances.find(i => i.includes("ol88"))).length
  102. );
  103. cy.get("div[class^='TextInput__Close']").click();
  104. cy.get("div[class^='TransferListItem__Wrapper']").should(
  105. "have.length",
  106. replicas.length
  107. );
  108. });
  109. });
  110. it("does bulk actions", () => {
  111. cy.intercept(routeSelectors.SCHEDULES, {
  112. fixture: "transfers/schedules-enabled.json",
  113. }).as("schedules");
  114. cy.visit("/replicas");
  115. waitForAll();
  116. cy.wait(["@schedules"]);
  117. cy.get("div[class*='TransferListItem__Checkbox']").eq(0).click();
  118. cy.get("div[class*='MainListFilter__SelectionText']").should(
  119. "contain.text",
  120. "1 of 2"
  121. );
  122. cy.get("div[class^='ActionDropdown__Wrapper']").click();
  123. cy.loadFixtures(["transfers/replicas"], (results: any[]) => {
  124. const replicas = results[0].replicas;
  125. cy.intercept(`**/coriolis/**/replicas/${replicas[0].id}`, {
  126. fixture: "transfers/replica-unexecuted",
  127. }).as("replica");
  128. cy.get("div[class^='ActionDropdown__ListItem']")
  129. .contains("Delete Replicas")
  130. .click();
  131. cy.wait(["@replica"]);
  132. cy.intercept("DELETE", `**/coriolis/**/replicas/${replicas[0].id}`, {
  133. fixture: "transfers/replica-unexecuted",
  134. }).as("delete-replica");
  135. cy.get("button").contains("Delete Replica").click();
  136. cy.wait(["@delete-replica"]);
  137. });
  138. });
  139. });