From c607ce23c49714b56d96e08df22b80a5c9f74f9f Mon Sep 17 00:00:00 2001
From: "Damon P. Cortesi" <d.lifehacker@gmail.com>
Date: Wed, 18 Nov 2020 22:42:37 -0800
Subject: [PATCH] Enable enterprise cypress tests on release branch (#13809)

* Enable enterprise cypress tests (#13756)

* Get auditing.cy.spec to pass

* Skip custom drill through tests until we replace them

* A few updates to the whitelabel test case:
- Move custom colors into constant variable to reference throughout
- remove some 'it' blocks we didn't need to speed up tests
- Remove a few 'wait's
- Restructure tests to be a bit more in line with best practices

* Update the snippet permissions test:
- Create test for just creating snippet as admin
- Create test for inability to create snippet as user by default
- Quarantine the user snippet creation test

* Rename sandboxes

* Replace legacy ENABLE_ENTERPRISE_EDITION env variable with MB_EDITION

* Add MB_EDITION env variable to Cypress test run

* Fix admin settings `auth` cypress test (#13841) [ci skip]

* Fix `snippet` Cypress test for CI (#13843)

- related: https://github.com/metabase/metabase-enterprise/issues/543

Co-authored-by: Nemanja Glumac <31325167+nemanjaglumac@users.noreply.github.com>
---
 .circleci/config.yml                          |   1 +
 .../audit/auditing.cy.spec.js                 |  48 ++--
 .../drill_through.cy.spec.js                  |  11 +-
 .../formatting/whitelabel.cy.spec.js          | 218 ++++++++++--------
 .../sandboxes.cy.spec.js                      |   0
 .../snippets/snippet-permissions.cy.spec.js   | 119 ++++++++--
 frontend/test/__runner__/backend.js           |   2 +-
 frontend/test/__runner__/run_cypress_tests.js |   2 +-
 .../admin/settings/settings.cy.spec.js        |  21 +-
 .../scenarios/question/snippets.cy.spec.js    |   9 +-
 10 files changed, 264 insertions(+), 167 deletions(-)
 rename enterprise/frontend/test/metabase-enterprise/{formatting => sandboxes}/sandboxes.cy.spec.js (100%)

diff --git a/.circleci/config.yml b/.circleci/config.yml
index 291fcc74408..a6fb47de302 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -692,6 +692,7 @@ jobs:
       <<: *Params
     executor: << parameters.e >>
     environment:
+      MB_EDITION: << parameters.edition >>
       CYPRESS_GROUP:  << parameters.cypress-group >>
       DISPLAY: ""
     steps:
diff --git a/enterprise/frontend/test/metabase-enterprise/audit/auditing.cy.spec.js b/enterprise/frontend/test/metabase-enterprise/audit/auditing.cy.spec.js
index 6b94fd1c3bd..65a40b49730 100644
--- a/enterprise/frontend/test/metabase-enterprise/audit/auditing.cy.spec.js
+++ b/enterprise/frontend/test/metabase-enterprise/audit/auditing.cy.spec.js
@@ -62,23 +62,20 @@ export function generateDashboards(users) {
 }
 
 describeWithToken("audit > auditing", () => {
-  before(restore);
   const users = ["admin", "normal"];
+  before(() => {
+    restore();
+    generateQuestions(users);
+    generateDashboards(users);
+  });
 
   describe("Generate data to audit", () => {
     beforeEach(signOut);
 
-    it("should create questions and dashboards", () => {
-      generateQuestions(users);
-      generateDashboards(users);
-    });
-
     it("should view a dashboard", () => {
       signIn("nodata");
       cy.visit("/collection/root?type=dashboard");
-      cy.wait(3000)
-        .findByText(users[1] + " test dash")
-        .click();
+      cy.findByText(users[1] + " test dash").click();
 
       cy.findByText("This dashboard is looking empty.");
       cy.findByText("My personal collection").should("not.exist");
@@ -87,18 +84,14 @@ describeWithToken("audit > auditing", () => {
     it("should view old question and new question", () => {
       signIn("nodata");
       cy.visit("/collection/root?type");
-      cy.wait(2000)
-        .findByText("Orders, Count")
-        .click();
+      cy.findByText("Orders, Count").click();
 
       cy.findByText("18,760");
 
       cy.visit("/collection/root?type");
-      cy.wait(2000)
-        .findByText(users[0] + " test q")
-        .click();
+      cy.findByText(users[0] + " test q").click();
 
-      cy.findByText("ID");
+      cy.get('[placeholder="ID"]');
     });
 
     it("should download a question", () => {
@@ -124,13 +117,20 @@ describeWithToken("audit > auditing", () => {
     it("should load the Overview tab", () => {
       cy.visit("/admin/audit/members/overview");
 
+      // We haven't created any new members yet so this should be empty
       cy.findByText("Active members and new members per day");
       cy.findByText("No results!");
-      cy.wait(1000)
-        .get(".LineAreaBarChart")
+
+      // Wait for both of the charts to show up
+      cy.get(".dc-chart").should("have.length", 2);
+
+      // For queries viewed, we have 2 users that haven't viewed anything
+      cy.get(".LineAreaBarChart")
         .first()
         .find("[width='0']")
         .should("have.length", 2);
+
+      // For queries created, we have 3 users that haven't created anything
       cy.get("svg")
         .last()
         .find("[width='0']")
@@ -183,7 +183,7 @@ describeWithToken("audit > auditing", () => {
       // Overview tab
       cy.visit("/admin/audit/schemas/overview");
       cy.get("svg").should("have.length", 2);
-      cy.wait(1000).findAllByText("Sample Dataset PUBLIC");
+      cy.findAllByText("Sample Dataset PUBLIC");
       cy.findAllByText("No results!").should("not.exist");
 
       // All schemas tab
@@ -197,7 +197,7 @@ describeWithToken("audit > auditing", () => {
       cy.visit("/admin/audit/tables/overview");
       cy.findByText("Most-queried tables");
       cy.findAllByText("No results!").should("not.exist");
-      cy.wait(1000).findAllByText("Sample Dataset PUBLIC ORDERS");
+      cy.findAllByText("Sample Dataset PUBLIC ORDERS");
 
       // *** Will fail when code below works again
       cy.findAllByText("Sample Dataset PUBLIC PRODUCTS").should("not.exist");
@@ -237,9 +237,7 @@ describeWithToken("audit > auditing", () => {
       // All questions tab
       cy.visit("/admin/audit/questions/all");
       cy.findByPlaceholderText("Question name");
-      cy.wait(1000)
-        .findAllByText("Sample Dataset")
-        .should("have.length", 5);
+      cy.findAllByText("Sample Dataset").should("have.length", 5);
       cy.findByText("normal test q");
       cy.findByText("Orders, Count, Grouped by Created At (year)");
       cy.findByText("4").should("not.exist");
@@ -275,9 +273,7 @@ describeWithToken("audit > auditing", () => {
 
       // All downloads tab
       cy.visit("/admin/audit/downloads/all");
-      cy.wait(2000)
-        .findByText("No results")
-        .should("not.exist");
+      cy.findByText("No results").should("not.exist");
       cy.get("tr")
         .last()
         .children()
diff --git a/enterprise/frontend/test/metabase-enterprise/custom_drill_through/drill_through.cy.spec.js b/enterprise/frontend/test/metabase-enterprise/custom_drill_through/drill_through.cy.spec.js
index 7ec27eb7dee..f0f4a93a723 100644
--- a/enterprise/frontend/test/metabase-enterprise/custom_drill_through/drill_through.cy.spec.js
+++ b/enterprise/frontend/test/metabase-enterprise/custom_drill_through/drill_through.cy.spec.js
@@ -1,12 +1,7 @@
-import {
-  signIn,
-  signInAsAdmin,
-  restore,
-  modal,
-  describeWithToken,
-} from "__support__/cypress";
+import { signIn, signInAsAdmin, restore, modal } from "__support__/cypress";
 
-describeWithToken("drill through", () => {
+// Drill-through support has been replaced with custom dashboard destinations
+describe.skip("drill through", () => {
   before(restore);
 
   beforeEach(signInAsAdmin);
diff --git a/enterprise/frontend/test/metabase-enterprise/formatting/whitelabel.cy.spec.js b/enterprise/frontend/test/metabase-enterprise/formatting/whitelabel.cy.spec.js
index 68bef57adaf..10752a10d4d 100644
--- a/enterprise/frontend/test/metabase-enterprise/formatting/whitelabel.cy.spec.js
+++ b/enterprise/frontend/test/metabase-enterprise/formatting/whitelabel.cy.spec.js
@@ -7,15 +7,20 @@ import {
   describeWithToken,
 } from "../../../../../frontend/test/__support__/cypress";
 
-const main_color = {
-  // brown - button, links, chart
-  hex: "8B572A",
-  rgb: "(139, 87, 42)",
+// Define colors that we use for whitelabeling
+// If rbg values exist, it's because we explicit test those
+const colors = {
+  primary: { hex: "8B572A", rgb: [139, 87, 42] },
+  nav: { hex: "284E07", rgb: [40, 78, 7] },
+  accent1: { hex: "417505" },
+  accent2: { hex: "7ED321" },
+  additional1: { hex: "B8E986" },
+  additional2: { hex: "50E3C2" },
+  additional3: { hex: "4A90E2" },
+  additional4: { hex: "082CBE" },
+  additional5: { hex: "F8E71C", rgb: [248, 231, 28] },
 };
 
-//green - nav bar
-const header_color = "rgb(40, 78, 7)";
-
 function changeThemeColor(location, colorhex) {
   cy.get("td")
     .eq(location)
@@ -40,40 +45,35 @@ function checkLogo() {
 describeWithToken("formatting > whitelabel", () => {
   before(restore);
 
-  describe("Changes to company name work", () => {
-    beforeEach(signOut);
-
-    it("should change company name", () => {
-      signInAsAdmin();
-      cy.visit("/admin/settings/whitelabel");
-      cy.findByPlaceholderText("Metabase")
-        .clear()
-        .type("Test Co");
-      // *** In html, is not text, only value
-      cy.findByText("Application Name").click();
-
-      cy.findByText("Saved");
-      cy.get("input").should("have.value", "Test Co");
-    });
-
-    it("should show new name on activity page as admin", () => {
-      signInAsAdmin();
-      cy.visit("/activity");
-      cy.findByText("Test Co is up and running.");
-      cy.findByText("Metabase is up and running.").should("not.exist");
-    });
-
-    it("should show new name when logged out", () => {
-      cy.visit("/");
-      cy.wait(2000).findByText("Sign in to Test Co");
-    });
-
-    it("should show new name on activity page as user", () => {
-      signInAsNormalUser();
-      cy.visit("/activity");
-      cy.findByText("Test Co is up and running.");
-      cy.findByText("Metabase is up and running.").should("not.exist");
-    });
+  it("should be able to change company name", () => {
+    signInAsAdmin();
+    cy.visit("/admin/settings/whitelabel");
+    cy.findByPlaceholderText("Metabase")
+      .clear()
+      .type("Test Co");
+    // *** In html, is not text, only value
+    cy.findByText("Application Name").click();
+
+    cy.findByText("Saved");
+    cy.get("input").should("have.value", "Test Co");
+    cy.log("Company name has been updated");
+
+    cy.log("New company show show up on activity page");
+    // signInAsAdmin();
+    cy.visit("/activity");
+    cy.findByText("Test Co is up and running.");
+    cy.findByText("Metabase is up and running.").should("not.exist");
+
+    cy.log("New company should show up when logged out");
+    signOut();
+    cy.visit("/");
+    cy.findByText("Sign in to Test Co");
+
+    cy.log("new company should show up as a normal user");
+    signInAsNormalUser();
+    cy.visit("/activity");
+    cy.findByText("Test Co is up and running.");
+    cy.findByText("Metabase is up and running.").should("not.exist");
   });
 
   describe("Changes to theme colors work", () => {
@@ -82,7 +82,7 @@ describeWithToken("formatting > whitelabel", () => {
       cy.visit("/admin/settings/whitelabel");
 
       // Select color with squares
-      changeThemeColor(1, main_color.hex);
+      changeThemeColor(1, colors.primary.hex);
 
       // Select color by entering rgb
       cy.get("td")
@@ -92,25 +92,25 @@ describeWithToken("formatting > whitelabel", () => {
         .find("input")
         .eq(1)
         .clear()
-        .type("40");
+        .type(colors.nav.rgb[0]);
       cy.get(".sketch-picker")
         .find("input")
         .eq(2)
         .clear()
-        .type("78");
+        .type(colors.nav.rgb[1]);
       cy.get(".sketch-picker")
         .find("input")
         .eq(3)
         .clear()
-        .type("7");
+        .type(colors.nav.rgb[2]);
       cy.findByText("Done").click();
 
       // Select colors with squares
-      changeThemeColor(9, "417505");
-      changeThemeColor(13, "7ED321");
-      changeThemeColor(17, "B8E986");
-      changeThemeColor(21, "50E3C2");
-      changeThemeColor(25, "4A90E2");
+      changeThemeColor(9, colors.accent1.hex);
+      changeThemeColor(13, colors.accent2.hex);
+      changeThemeColor(17, colors.additional1.hex);
+      changeThemeColor(21, colors.additional2.hex);
+      changeThemeColor(25, colors.additional3.hex);
 
       // Select color by typing hex code
       cy.get("td")
@@ -120,48 +120,74 @@ describeWithToken("formatting > whitelabel", () => {
         .find("input")
         .first()
         .clear()
-        .type("082CBE");
+        .type(colors.additional4.hex);
       cy.findByText("Done").click();
 
-      changeThemeColor(33, "F8E71C");
+      changeThemeColor(33, colors.additional5.hex);
 
       cy.get(".Icon-close").should("have.length", 10);
     });
 
-    it("should show color changes on admin's dashboard", () => {
-      signInAsAdmin();
-      cy.visit("/");
-      cy.get(`[style='background-color: ${header_color};']`);
-    });
-
-    it("should show color changes when signed out", () => {
+    it("should show color changes", () => {
       signOut();
       cy.visit("/");
-      cy.get(
-        `[style='width: 16px; height: 16px; background-color: rgb${main_color.rgb}; border: 2px solid rgb${main_color.rgb};']`,
+      cy.contains("Sign in");
+
+      // Note that if we have modified the logo, the entire background turns the brand color.
+      // But if we _haven't_, as is the case now, then the existing logo is branded
+      // As is the "Remember me" and "Sign in" inputs
+      cy.get(".Icon").should(
+        "have.css",
+        "color",
+        `rgb(${colors.primary.rgb.join(", ")})`,
       );
-    });
 
-    it("should show color changes on user's dashboard", () => {
+      cy.findByLabelText("Email address").type("some@email.com");
+      cy.findByLabelText("Password").type("1234");
+      cy.get(".Button--primary").should(
+        "have.css",
+        "background-color",
+        `rgb(${colors.primary.rgb.join(", ")})`,
+      );
+
+      cy.log("Normal users should have a green header");
       signInAsNormalUser();
       cy.visit("/");
-      cy.get(`[style='background-color: ${header_color};']`);
+      cy.get(".Nav").should(
+        "have.css",
+        "background-color",
+        `rgb(${colors.nav.rgb.join(", ")})`,
+      );
+
+      cy.log(
+        "Admin users should also have a green header, but yellow in the admin panel",
+      );
+      signInAsAdmin();
+      cy.visit("/");
+      cy.get(".Nav").should(
+        "have.css",
+        "background-color",
+        `rgb(${colors.nav.rgb.join(", ")})`,
+      );
+      cy.visit("/admin");
+      cy.get(".Nav").should(
+        "have.css",
+        "background-color",
+        `rgb(${colors.additional5.rgb.join(", ")})`,
+      );
     });
 
     it.skip("should show color changes reflected in q visualizations (metabase-enterprise #470)", () => {
       // *** Test should pass when issue #470 is resolved
       signInAsNormalUser();
       openOrdersTable();
-      cy.wait(3000)
-        .findAllByText("Summarize")
+      cy.findAllByText("Summarize")
         .first()
         .click();
-      cy.wait(1000)
-        .findByText("Price")
-        .click();
+      cy.findByText("Price").click();
       cy.findByText("Done").click();
 
-      cy.get(`div[fill='#${main_color.hex};']`);
+      cy.get(`div[fill='#${colors.primary.hex};']`);
       cy.get(`rect[fill='#509EE3']`).should("not.exist");
     });
   });
@@ -210,36 +236,26 @@ describeWithToken("formatting > whitelabel", () => {
     });
   });
 
-  describe("Changes to favicon work", () => {
-    it("should add a favicon", () => {
-      signInAsAdmin();
-      cy.visit("/admin/settings/whitelabel");
-
-      cy.server();
-
-      cy.findByPlaceholderText("frontend_client/favicon.ico").type(
-        "https://cdn.ecosia.org/assets/images/ico/favicon.ico",
-      );
-      cy.get("ul")
-        .eq(2)
-        .click("right");
-      cy.wait(10).findByText("Saved");
-
-      checkFavicon();
-    });
-
-    it("should reflect favicon change in API", () => {
-      signInAsAdmin();
-      cy.visit("/");
-      checkFavicon();
-    });
-
-    it("should reflect favicon change in HTML", () => {
-      signInAsNormalUser();
-      cy.visit("/");
-      cy.get('head link[rel="icon"]')
-        .get('[href="https://cdn.ecosia.org/assets/images/ico/favicon.ico"]')
-        .should("have.length", 1);
-    });
+  it("should add a custom favicon", () => {
+    signInAsAdmin();
+    cy.visit("/admin/settings/whitelabel");
+
+    cy.server();
+
+    cy.findByPlaceholderText("frontend_client/favicon.ico").type(
+      "https://cdn.ecosia.org/assets/images/ico/favicon.ico",
+    );
+    cy.get("ul")
+      .eq(2)
+      .click("right");
+    cy.findByText("Saved");
+    checkFavicon();
+
+    cy.log("New favicon should show up in user's HTML");
+    signInAsNormalUser();
+    cy.visit("/");
+    cy.get('head link[rel="icon"]')
+      .get('[href="https://cdn.ecosia.org/assets/images/ico/favicon.ico"]')
+      .should("have.length", 1);
   });
 });
diff --git a/enterprise/frontend/test/metabase-enterprise/formatting/sandboxes.cy.spec.js b/enterprise/frontend/test/metabase-enterprise/sandboxes/sandboxes.cy.spec.js
similarity index 100%
rename from enterprise/frontend/test/metabase-enterprise/formatting/sandboxes.cy.spec.js
rename to enterprise/frontend/test/metabase-enterprise/sandboxes/sandboxes.cy.spec.js
diff --git a/enterprise/frontend/test/metabase-enterprise/snippets/snippet-permissions.cy.spec.js b/enterprise/frontend/test/metabase-enterprise/snippets/snippet-permissions.cy.spec.js
index 15c488a5439..e983cd27d41 100644
--- a/enterprise/frontend/test/metabase-enterprise/snippets/snippet-permissions.cy.spec.js
+++ b/enterprise/frontend/test/metabase-enterprise/snippets/snippet-permissions.cy.spec.js
@@ -10,7 +10,105 @@ import {
 
 describeWithToken("scenarios > question > snippets", () => {
   before(restore);
-  beforeEach(signInAsNormalUser);
+  beforeEach(signInAsAdmin);
+
+  it("can create a snippet", () => {
+    cy.visit("/question/new");
+    cy.contains("Native query").click();
+    cy.get(".Icon-snippet").click();
+    cy.contains("Create a snippet").click();
+    modal().within(() => {
+      cy.findByLabelText("Enter some SQL here so you can reuse it later").type(
+        "SELECT 'a snippet darkly'",
+      );
+      cy.findByLabelText("Give your snippet a name").type("night snippet");
+      cy.contains("Save").click();
+    });
+    cy.get(".Icon-play")
+      .first()
+      .click();
+    cy.get(".ScalarValue").contains("a snippet darkly");
+  });
+
+  it("can not create a snippet as a user by default", () => {
+    // Note that this is expected behavior, but a little weird because
+    // users have to be granted explicit access.
+    // See metabase-enterprise#543 for more details
+
+    signInAsNormalUser();
+
+    cy.request({
+      method: "POST",
+      url: "/api/native-query-snippet",
+      body: {
+        content: "SELECT 'a snippet in light'",
+        name: "light snippet",
+        collection_id: null,
+      },
+      failOnStatusCode: false,
+    }).then(resp => {
+      expect(resp.status).to.equal(403);
+    });
+  });
+
+  // [quarantine] because the popover click action is very flaky.
+  it.skip("can create a snippet once the admin has granted access", () => {
+    // See metabase-enterprise#543 for more details
+    // This is kind of a UX issue where the admin has to:
+    // - First create a snippet
+    // - Then grant All Users access to snippets
+
+    // create snippet via API
+    cy.request("POST", "/api/native-query-snippet", {
+      content: "SELECT 'a snippet darkly'",
+      name: "543 - admin snippet",
+      collection_id: null,
+    });
+
+    // Grant access
+    cy.visit("/question/new");
+    cy.contains("Native query").click();
+    cy.get(".Icon-snippet").click();
+
+    sidebar()
+      .find(".Icon-ellipsis")
+      .click({ force: true });
+    popover().within(() => cy.findByText("Change permissions").click());
+    modal().within(() => {
+      cy.findByText("Permissions for Top folder");
+      cy.contains("All Users");
+      cy.get(".ReactVirtualized__Grid .Icon-close")
+        .first()
+        .click();
+    });
+    // The click action is very flaky, sometimes it doesn't click the right thing
+    popover()
+      .contains("Grant Edit access")
+      .click();
+    modal()
+      .contains("Save")
+      .click();
+    // Now the user should be able to create a snippet
+    signInAsNormalUser();
+
+    cy.request({
+      method: "POST",
+      url: "/api/native-query-snippet",
+      body: {
+        content: "SELECT 'a snippet in light'",
+        name: "543 - user snippet",
+        collection_id: null,
+      },
+      failOnStatusCode: false,
+    }).then(resp => {
+      expect(resp.status).to.equal(200);
+    });
+
+    cy.reload();
+    cy.get(".Icon-snippet").click();
+    cy.contains("543 - admin snippet");
+    cy.contains("543 - user snippet");
+  });
 
   it("should let you create a snippet folder and move a snippet into it", () => {
     cy.visit("/question/new");
@@ -59,23 +157,4 @@ describeWithToken("scenarios > question > snippets", () => {
     cy.findByText("my favorite snippets").click();
     cy.findByText("snippet 1");
   });
-
-  it("should allow updating snippet folder permissions", () => {
-    signInAsAdmin();
-    cy.visit("/question/new");
-    cy.contains("Native query").click();
-    cy.get(".Icon-snippet").click();
-
-    sidebar()
-      .findByText("my favorite snippets")
-      .parent()
-      .parent()
-      .find(".Icon-ellipsis")
-      .click({ force: true });
-    popover().within(() => cy.findByText("Change permissions").click());
-    modal().within(() => {
-      cy.findByText("Permissions for this folder");
-    });
-    // TODO: incomplete
-  });
 });
diff --git a/frontend/test/__runner__/backend.js b/frontend/test/__runner__/backend.js
index 160ffe243cb..7c0ce9f0867 100644
--- a/frontend/test/__runner__/backend.js
+++ b/frontend/test/__runner__/backend.js
@@ -65,7 +65,7 @@ export const BackendResource = createSharedResource("BackendResource", {
             MB_JETTY_PORT: server.port,
             MB_ENABLE_TEST_ENDPOINTS: "true",
             MB_PREMIUM_EMBEDDING_TOKEN:
-              (process.env["ENABLE_ENTERPRISE_EDITION"] === "true" &&
+              (process.env["MB_EDITION"] === "ee" &&
                 process.env["ENTERPRISE_TOKEN"]) ||
               undefined,
           },
diff --git a/frontend/test/__runner__/run_cypress_tests.js b/frontend/test/__runner__/run_cypress_tests.js
index 8fcd9eab9f2..0dcd2e8ffe6 100644
--- a/frontend/test/__runner__/run_cypress_tests.js
+++ b/frontend/test/__runner__/run_cypress_tests.js
@@ -77,7 +77,7 @@ const init = async () => {
   // These env vars provide the token to the backend.
   // If they're not present, we skip some tests that depend on a valid token.
   const hasEnterpriseToken =
-    process.env["ENTERPRISE_TOKEN"] && process.env["ENABLE_ENTERPRISE_EDITION"];
+    process.env["ENTERPRISE_TOKEN"] && process.env["MB_EDITION"] === "ee";
 
   const cypressProcess = spawn(
     "yarn",
diff --git a/frontend/test/metabase/scenarios/admin/settings/settings.cy.spec.js b/frontend/test/metabase/scenarios/admin/settings/settings.cy.spec.js
index b703e6859af..86144543d27 100644
--- a/frontend/test/metabase/scenarios/admin/settings/settings.cy.spec.js
+++ b/frontend/test/metabase/scenarios/admin/settings/settings.cy.spec.js
@@ -46,10 +46,9 @@ describe("scenarios > admin > settings", () => {
     // Ported from `SettingsAuthenticationOptions.e2e.spec.js`
     // Google sign in
     cy.visit("/admin/settings/authentication");
-    cy.findByText("Sign in with Google");
-    cy.findAllByText("Configure")
-      .first()
-      .click();
+
+    configureAuth("Sign in with Google");
+
     cy.contains(
       "To allow users to sign in with Google you'll need to give Metabase a Google Developers console application client ID.",
     );
@@ -58,10 +57,9 @@ describe("scenarios > admin > settings", () => {
 
     // SSO
     cy.visit("/admin/settings/authentication");
-    cy.findByText("LDAP").click();
-    cy.findAllByText("Configure")
-      .last()
-      .click();
+
+    configureAuth("LDAP");
+
     cy.findByText("LDAP Authentication");
     cy.findByText("User Schema");
     cy.findByText("Save changes");
@@ -310,3 +308,10 @@ describe("scenarios > admin > settings", () => {
     });
   });
 });
+
+function configureAuth(providerTitle) {
+  cy.findByText(providerTitle)
+    .closest(".rounded.bordered")
+    .contains("Configure")
+    .click();
+}
diff --git a/frontend/test/metabase/scenarios/question/snippets.cy.spec.js b/frontend/test/metabase/scenarios/question/snippets.cy.spec.js
index b03e9e263d2..e291d86e13e 100644
--- a/frontend/test/metabase/scenarios/question/snippets.cy.spec.js
+++ b/frontend/test/metabase/scenarios/question/snippets.cy.spec.js
@@ -1,4 +1,4 @@
-import { signInAsNormalUser, restore, modal } from "__support__/cypress";
+import { signInAsAdmin, restore, modal } from "__support__/cypress";
 
 // HACK which lets us type (even very long words) without losing focus
 // this is needed for fields where autocomplete suggestions are enabled
@@ -12,9 +12,14 @@ function _clearAndIterativelyTypeUsingLabel(label, string) {
   }
 }
 
+// NOTE: - Had to change user role to "admin" on 2020-11-19.
+//       - Normal users don't have permission to create/edit snippets in `ee` version.
+//       - CI runs this test twice (both contexts), so it fails on `ee`.
+//       - There is a related issue: https://github.com/metabase/metabase-enterprise/issues/543
+// TODO: Once the above issue is (re)solved, change back to `signInAsNormalUser`
 describe("scenarios > question > snippets", () => {
   before(restore);
-  beforeEach(signInAsNormalUser);
+  beforeEach(signInAsAdmin);
 
   it("should let you create and use a snippet", () => {
     cy.visit("/question/new");
-- 
GitLab