From 2aad9b407bc5ba3d24edd0ae0c8deec3a21743e9 Mon Sep 17 00:00:00 2001
From: Kamil Mielnik <kamil@kamilmielnik.com>
Date: Mon, 19 Aug 2024 16:14:31 +0700
Subject: [PATCH] Refactor e2e JavaScript API commands to TypeScript function
 helpers (#46934)

* Remove unused file

* Refactor getCurrentUser command to a TS function util

* Refactor createAlert command to a TS function util

* Refactor createModerationReview command to a TS function util

* Reuse createModerationReview

* Refactor createPulse command to a TS function util

* Remove references to deleted files

* Improve typing
---
 e2e/support/commands.js                       |  4 ---
 e2e/support/commands/api/alert.js             | 20 --------------
 e2e/support/commands/api/dashboard.ts         | 26 -------------------
 e2e/support/commands/api/moderation.js        | 13 ----------
 e2e/support/commands/api/pulse.js             | 13 ----------
 e2e/support/commands/api/user.js              |  3 ---
 e2e/support/helpers/api/createAlert.ts        | 22 ++++++++++++++++
 .../helpers/api/createModerationReview.ts     | 21 +++++++++++++++
 e2e/support/helpers/api/createPulse.ts        | 22 ++++++++++++++++
 e2e/support/helpers/api/getCurrentUser.ts     |  5 ++++
 e2e/support/helpers/api/index.ts              |  4 +++
 e2e/test/scenarios/admin-2/people.cy.spec.js  | 21 ++++++++-------
 .../onboarding/notifications.cy.spec.js       | 19 ++++++++------
 .../content-verification.cy.spec.js           | 19 +++++++-------
 .../application-permissions.cy.spec.js        | 15 ++++++-----
 .../search/recently-viewed.cy.spec.js         | 21 ++++++++-------
 .../search/search-filters.cy.spec.js          |  7 ++---
 17 files changed, 130 insertions(+), 125 deletions(-)
 delete mode 100644 e2e/support/commands/api/alert.js
 delete mode 100644 e2e/support/commands/api/dashboard.ts
 delete mode 100644 e2e/support/commands/api/moderation.js
 delete mode 100644 e2e/support/commands/api/pulse.js
 delete mode 100644 e2e/support/commands/api/user.js
 create mode 100644 e2e/support/helpers/api/createAlert.ts
 create mode 100644 e2e/support/helpers/api/createModerationReview.ts
 create mode 100644 e2e/support/helpers/api/createPulse.ts
 create mode 100644 e2e/support/helpers/api/getCurrentUser.ts

diff --git a/e2e/support/commands.js b/e2e/support/commands.js
index ebf98680e49..68016517f60 100644
--- a/e2e/support/commands.js
+++ b/e2e/support/commands.js
@@ -2,11 +2,7 @@ import "./commands/ui/button";
 import "./commands/ui/icon";
 
 import "./commands/api/index";
-import "./commands/api/alert";
 import "./commands/api/dashboardCard";
-import "./commands/api/moderation";
-import "./commands/api/pulse";
-import "./commands/api/user";
 import "./commands/api/timeline";
 
 import "./commands/api/composite/createNativeQuestionAndDashboard";
diff --git a/e2e/support/commands/api/alert.js b/e2e/support/commands/api/alert.js
deleted file mode 100644
index afb9ddfcfe2..00000000000
--- a/e2e/support/commands/api/alert.js
+++ /dev/null
@@ -1,20 +0,0 @@
-Cypress.Commands.add(
-  "createAlert",
-  ({
-    card,
-    channels = [],
-    alert_condition = "rows",
-    alert_first_only = false,
-    alert_above_goal = false,
-  } = {}) => {
-    cy.log("Create an alert");
-
-    return cy.request("POST", "/api/alert", {
-      card,
-      channels,
-      alert_condition,
-      alert_first_only,
-      alert_above_goal,
-    });
-  },
-);
diff --git a/e2e/support/commands/api/dashboard.ts b/e2e/support/commands/api/dashboard.ts
deleted file mode 100644
index 6599910f001..00000000000
--- a/e2e/support/commands/api/dashboard.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { archiveDashboard, createDashboard } from "e2e/support/helpers";
-
-declare global {
-  namespace Cypress {
-    interface Chainable {
-      /**
-       * @deprecated Use function helper instead, i.e.
-       * ```
-       * import { archiveDashboard } from "e2e/support/helpers"
-       * ```
-       */
-      archiveDashboard: typeof archiveDashboard;
-
-      /**
-       * @deprecated Use function helper instead, i.e.
-       * ```
-       * import { createDashboard } from "e2e/support/helpers"
-       * ```
-       */
-      createDashboard: typeof createDashboard;
-    }
-  }
-}
-
-Cypress.Commands.add("archiveDashboard", archiveDashboard);
-Cypress.Commands.add("createDashboard", createDashboard);
diff --git a/e2e/support/commands/api/moderation.js b/e2e/support/commands/api/moderation.js
deleted file mode 100644
index 7666c4f9277..00000000000
--- a/e2e/support/commands/api/moderation.js
+++ /dev/null
@@ -1,13 +0,0 @@
-Cypress.Commands.add(
-  "createModerationReview",
-  ({ status, moderated_item_type, moderated_item_id }) => {
-    cy.log(
-      `Create a moderation review, status: ${status}, item type: ${moderated_item_type}, item id: ${moderated_item_id}`,
-    );
-    cy.request("POST", "/api/moderation-review", {
-      status,
-      moderated_item_id,
-      moderated_item_type,
-    });
-  },
-);
diff --git a/e2e/support/commands/api/pulse.js b/e2e/support/commands/api/pulse.js
deleted file mode 100644
index aecf9909b80..00000000000
--- a/e2e/support/commands/api/pulse.js
+++ /dev/null
@@ -1,13 +0,0 @@
-Cypress.Commands.add(
-  "createPulse",
-  ({ name = "Pulse", cards = [], channels = [], dashboard_id }) => {
-    cy.log("Create a pulse");
-
-    return cy.request("POST", "/api/pulse", {
-      name,
-      cards,
-      channels,
-      dashboard_id,
-    });
-  },
-);
diff --git a/e2e/support/commands/api/user.js b/e2e/support/commands/api/user.js
deleted file mode 100644
index f3baa26dbd2..00000000000
--- a/e2e/support/commands/api/user.js
+++ /dev/null
@@ -1,3 +0,0 @@
-Cypress.Commands.add("getCurrentUser", () => {
-  return cy.request("GET", "/api/user/current");
-});
diff --git a/e2e/support/helpers/api/createAlert.ts b/e2e/support/helpers/api/createAlert.ts
new file mode 100644
index 00000000000..2b95c0489b0
--- /dev/null
+++ b/e2e/support/helpers/api/createAlert.ts
@@ -0,0 +1,22 @@
+import type { Alert, CreateAlertRequest } from "metabase-types/api";
+
+export const createAlert = ({
+  card,
+  channels = [],
+  alert_condition = "rows",
+  alert_first_only = false,
+  alert_above_goal = false,
+}: Partial<CreateAlertRequest> &
+  Pick<CreateAlertRequest, "card">): Cypress.Chainable<
+  Cypress.Response<Alert>
+> => {
+  cy.log("Create an alert");
+
+  return cy.request<Alert>("POST", "/api/alert", {
+    card,
+    channels,
+    alert_condition,
+    alert_first_only,
+    alert_above_goal,
+  });
+};
diff --git a/e2e/support/helpers/api/createModerationReview.ts b/e2e/support/helpers/api/createModerationReview.ts
new file mode 100644
index 00000000000..0fa70d33a8f
--- /dev/null
+++ b/e2e/support/helpers/api/createModerationReview.ts
@@ -0,0 +1,21 @@
+import type { ModerationReview } from "metabase-types/api";
+
+export const createModerationReview = ({
+  status,
+  moderated_item_type,
+  moderated_item_id,
+}: {
+  status: "verified" | null;
+  moderated_item_type: "card";
+  moderated_item_id: number;
+}): Cypress.Chainable<Cypress.Response<ModerationReview>> => {
+  cy.log(
+    `Create a moderation review, status: ${status}, item type: ${moderated_item_type}, item id: ${moderated_item_id}`,
+  );
+
+  return cy.request<ModerationReview>("POST", "/api/moderation-review", {
+    status,
+    moderated_item_id,
+    moderated_item_type,
+  });
+};
diff --git a/e2e/support/helpers/api/createPulse.ts b/e2e/support/helpers/api/createPulse.ts
new file mode 100644
index 00000000000..591af7a51e8
--- /dev/null
+++ b/e2e/support/helpers/api/createPulse.ts
@@ -0,0 +1,22 @@
+import type {
+  CreateSubscriptionRequest,
+  DashboardSubscription,
+} from "metabase-types/api";
+
+export const createPulse = ({
+  name = "Pulse",
+  cards = [],
+  channels = [],
+  dashboard_id,
+}: Partial<CreateSubscriptionRequest>): Cypress.Chainable<
+  Cypress.Response<DashboardSubscription>
+> => {
+  cy.log("Create a pulse");
+
+  return cy.request<DashboardSubscription>("POST", "/api/pulse", {
+    name,
+    cards,
+    channels,
+    dashboard_id,
+  });
+};
diff --git a/e2e/support/helpers/api/getCurrentUser.ts b/e2e/support/helpers/api/getCurrentUser.ts
new file mode 100644
index 00000000000..eb1d0744ece
--- /dev/null
+++ b/e2e/support/helpers/api/getCurrentUser.ts
@@ -0,0 +1,5 @@
+import type { User } from "metabase-types/api";
+
+export const getCurrentUser = (): Cypress.Chainable<Cypress.Response<User>> => {
+  return cy.request<User>("GET", "/api/user/current");
+};
diff --git a/e2e/support/helpers/api/index.ts b/e2e/support/helpers/api/index.ts
index ee582d2d198..806ef1a4dad 100644
--- a/e2e/support/helpers/api/index.ts
+++ b/e2e/support/helpers/api/index.ts
@@ -2,18 +2,22 @@ export { addOrUpdateDashboardCard } from "./addOrUpdateDashboardCard";
 export { archiveCollection } from "./archiveCollection";
 export { archiveDashboard } from "./archiveDashboard";
 export { archiveQuestion } from "./archiveQuestion";
+export { createAlert } from "./createAlert";
 export { createApiKey } from "./createApiKey";
 export { createCollection } from "./createCollection";
 export { createDashboard } from "./createDashboard";
 export type { DashboardDetails } from "./createDashboard";
 export { createDashboardWithTabs } from "./createDashboardWithTabs";
+export { createModerationReview } from "./createModerationReview";
 export { createNativeQuestion } from "./createNativeQuestion";
 export type { NativeQuestionDetails } from "./createNativeQuestion";
+export { createPulse } from "./createPulse";
 export { createQuestion } from "./createQuestion";
 export type {
   QuestionDetails,
   StructuredQuestionDetails,
 } from "./createQuestion";
 export { createQuestionAndDashboard } from "./createQuestionAndDashboard";
+export { getCurrentUser } from "./getCurrentUser";
 export { remapDisplayValueToFK } from "./remapDisplayValueToFK";
 export { updateDashboardCards } from "./updateDashboardCards";
diff --git a/e2e/test/scenarios/admin-2/people.cy.spec.js b/e2e/test/scenarios/admin-2/people.cy.spec.js
index 42fcc5a93b9..dd7b58c68cb 100644
--- a/e2e/test/scenarios/admin-2/people.cy.spec.js
+++ b/e2e/test/scenarios/admin-2/people.cy.spec.js
@@ -3,18 +3,21 @@ import _ from "underscore";
 import { USERS, USER_GROUPS } from "e2e/support/cypress_data";
 import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
 import {
-  NORMAL_USER_ID,
   COLLECTION_GROUP_ID,
+  NORMAL_USER_ID,
 } from "e2e/support/cypress_sample_instance_data";
 import {
-  restore,
-  modal,
-  popover,
-  setupSMTP,
+  createAlert,
+  createApiKey,
+  createPulse,
   describeEE,
+  getCurrentUser,
   getFullName,
+  modal,
+  popover,
+  restore,
   setTokenFeatures,
-  createApiKey,
+  setupSMTP,
 } from "e2e/support/helpers";
 
 const { sandboxed, normal, admin, nodata, nocollection } = USERS;
@@ -531,12 +534,12 @@ describeEE("scenarios > admin > people", () => {
   });
 
   it("should unsubscribe a user from all subscriptions and alerts", () => {
-    cy.getCurrentUser().then(({ body: { id: user_id } }) => {
+    getCurrentUser().then(({ body: { id: user_id } }) => {
       cy.createQuestionAndDashboard({
         questionDetails: getQuestionDetails(),
       }).then(({ body: { card_id, dashboard_id } }) => {
-        cy.createAlert(getAlertDetails({ user_id, card_id }));
-        cy.createPulse(getPulseDetails({ card_id, dashboard_id }));
+        createAlert(getAlertDetails({ user_id, card_id }));
+        createPulse(getPulseDetails({ card_id, dashboard_id }));
       });
     });
 
diff --git a/e2e/test/scenarios/onboarding/notifications.cy.spec.js b/e2e/test/scenarios/onboarding/notifications.cy.spec.js
index 7e29b828381..1cff087919c 100644
--- a/e2e/test/scenarios/onboarding/notifications.cy.spec.js
+++ b/e2e/test/scenarios/onboarding/notifications.cy.spec.js
@@ -1,6 +1,11 @@
 import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
-import { restore } from "e2e/support/helpers/e2e-setup-helpers";
-import { modal } from "e2e/support/helpers/e2e-ui-elements-helpers";
+import {
+  createAlert,
+  createPulse,
+  getCurrentUser,
+  modal,
+  restore,
+} from "e2e/support/helpers";
 
 const { ORDERS_ID } = SAMPLE_DATABASE;
 
@@ -61,14 +66,12 @@ describe("scenarios > account > notifications", () => {
   describe("alerts", () => {
     beforeEach(() => {
       cy.signInAsAdmin().then(() => {
-        cy.getCurrentUser().then(({ body: { id: admin_id } }) => {
+        getCurrentUser().then(({ body: { id: admin_id } }) => {
           cy.signInAsNormalUser().then(() => {
-            cy.getCurrentUser().then(({ body: { id: user_id } }) => {
+            getCurrentUser().then(({ body: { id: user_id } }) => {
               cy.createQuestion(getQuestionDetails()).then(
                 ({ body: { id: card_id } }) => {
-                  cy.createAlert(
-                    getAlertDetails({ card_id, user_id, admin_id }),
-                  );
+                  createAlert(getAlertDetails({ card_id, user_id, admin_id }));
                 },
               );
             });
@@ -149,7 +152,7 @@ describe("scenarios > account > notifications", () => {
         cy.createQuestionAndDashboard({
           questionDetails: getQuestionDetails(),
         }).then(({ body: { card_id, dashboard_id } }) => {
-          cy.createPulse(getPulseDetails({ card_id, dashboard_id }));
+          createPulse(getPulseDetails({ card_id, dashboard_id }));
         });
       });
     });
diff --git a/e2e/test/scenarios/organization/content-verification.cy.spec.js b/e2e/test/scenarios/organization/content-verification.cy.spec.js
index 223245bedc0..a7caf228dc7 100644
--- a/e2e/test/scenarios/organization/content-verification.cy.spec.js
+++ b/e2e/test/scenarios/organization/content-verification.cy.spec.js
@@ -1,16 +1,17 @@
 import { ORDERS_COUNT_QUESTION_ID } from "e2e/support/cypress_sample_instance_data";
 import {
+  closeCommandPalette,
+  commandPalette,
+  commandPaletteSearch,
+  createModerationReview,
   describeEE,
-  restore,
-  visitQuestion,
+  openCommandPalette,
   openQuestionActions,
+  popover,
   questionInfoButton,
+  restore,
   setTokenFeatures,
-  popover,
-  openCommandPalette,
-  commandPalette,
-  closeCommandPalette,
-  commandPaletteSearch,
+  visitQuestion,
 } from "e2e/support/helpers";
 
 describeEE("scenarios > premium > content verification", () => {
@@ -151,7 +152,7 @@ describeEE("scenarios > premium > content verification", () => {
 
     describe("non-admin user", () => {
       beforeEach(() => {
-        cy.createModerationReview({
+        createModerationReview({
           status: "verified",
           moderated_item_type: "card",
           moderated_item_id: ORDERS_COUNT_QUESTION_ID,
@@ -200,7 +201,7 @@ describeEE("scenarios > premium > content verification", () => {
   context("token expired or removed", () => {
     beforeEach(() => {
       setTokenFeatures("all");
-      cy.createModerationReview({
+      createModerationReview({
         status: "verified",
         moderated_item_type: "card",
         moderated_item_id: ORDERS_COUNT_QUESTION_ID,
diff --git a/e2e/test/scenarios/permissions/application-permissions.cy.spec.js b/e2e/test/scenarios/permissions/application-permissions.cy.spec.js
index 5873ab8851d..158508909cb 100644
--- a/e2e/test/scenarios/permissions/application-permissions.cy.spec.js
+++ b/e2e/test/scenarios/permissions/application-permissions.cy.spec.js
@@ -1,20 +1,21 @@
 import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
 import {
-  ORDERS_QUESTION_ID,
   ORDERS_DASHBOARD_ID,
+  ORDERS_QUESTION_ID,
 } from "e2e/support/cypress_sample_instance_data";
 import {
-  restore,
-  modal,
+  createPulse,
   describeEE,
+  modal,
   modifyPermission,
-  visitQuestion,
-  visitDashboard,
+  popover,
+  restore,
   setTokenFeatures,
   setupSMTP,
   sidebar,
-  popover,
   undoToast,
+  visitDashboard,
+  visitQuestion,
 } from "e2e/support/helpers";
 
 const { ORDERS_ID } = SAMPLE_DATABASE;
@@ -227,7 +228,7 @@ function createSubscription(user_id) {
       },
     },
   }).then(({ body: { card_id, dashboard_id } }) => {
-    cy.createPulse({
+    createPulse({
       name: "Subscription",
       dashboard_id,
       cards: [
diff --git a/e2e/test/scenarios/search/recently-viewed.cy.spec.js b/e2e/test/scenarios/search/recently-viewed.cy.spec.js
index 479cc45d9d1..8349f97e0a3 100644
--- a/e2e/test/scenarios/search/recently-viewed.cy.spec.js
+++ b/e2e/test/scenarios/search/recently-viewed.cy.spec.js
@@ -1,19 +1,20 @@
 import {
-  ORDERS_QUESTION_ID,
   ORDERS_DASHBOARD_ID,
+  ORDERS_QUESTION_ID,
 } from "e2e/support/cypress_sample_instance_data";
 import {
-  restore,
-  visitQuestion,
-  visitDashboard,
-  openPeopleTable,
+  commandPalette,
+  createModerationReview,
   describeEE,
-  setTokenFeatures,
-  popover,
   entityPickerModal,
-  visitFullAppEmbeddingUrl,
   openCommandPalette,
-  commandPalette,
+  openPeopleTable,
+  popover,
+  restore,
+  setTokenFeatures,
+  visitDashboard,
+  visitFullAppEmbeddingUrl,
+  visitQuestion,
 } from "e2e/support/helpers";
 
 describe("search > recently viewed", () => {
@@ -142,7 +143,7 @@ describeEE("search > recently viewed > enterprise features", () => {
     cy.signInAsAdmin();
     setTokenFeatures("all");
 
-    cy.request("POST", "/api/moderation-review", {
+    createModerationReview({
       status: "verified",
       moderated_item_id: ORDERS_QUESTION_ID,
       moderated_item_type: "card",
diff --git a/e2e/test/scenarios/search/search-filters.cy.spec.js b/e2e/test/scenarios/search/search-filters.cy.spec.js
index 6f2489dfd88..08a529db5d3 100644
--- a/e2e/test/scenarios/search/search-filters.cy.spec.js
+++ b/e2e/test/scenarios/search/search-filters.cy.spec.js
@@ -2,12 +2,14 @@ import { SAMPLE_DB_ID } from "e2e/support/cypress_data";
 import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
 import {
   ADMIN_USER_ID,
+  FIRST_COLLECTION_ID,
   NORMAL_USER_ID,
   ORDERS_COUNT_QUESTION_ID,
-  FIRST_COLLECTION_ID,
 } from "e2e/support/cypress_sample_instance_data";
 import {
+  commandPaletteSearch,
   createAction,
+  createModerationReview,
   describeEE,
   expectSearchResultContent,
   popover,
@@ -15,7 +17,6 @@ import {
   setActionsEnabledForDB,
   setTokenFeatures,
   summarize,
-  commandPaletteSearch,
 } from "e2e/support/helpers";
 import { createModelIndex } from "e2e/support/helpers/e2e-model-index-helper";
 
@@ -871,7 +872,7 @@ describe("scenarios > search", () => {
     describeEE("verified filter", () => {
       beforeEach(() => {
         setTokenFeatures("all");
-        cy.createModerationReview({
+        createModerationReview({
           status: "verified",
           moderated_item_type: "card",
           moderated_item_id: ORDERS_COUNT_QUESTION_ID,
-- 
GitLab