diff --git a/frontend/test/__support__/e2e/commands/api/question.js b/frontend/test/__support__/e2e/commands/api/question.js
index a9cd6d7a4c1ef88e6dfb00842a9b6e89eb9f1b88..a50bb86efeb07f2ffb0d34a86b4ac9d1727b9c09 100644
--- a/frontend/test/__support__/e2e/commands/api/question.js
+++ b/frontend/test/__support__/e2e/commands/api/question.js
@@ -1,51 +1,92 @@
+Cypress.Commands.add("createQuestion", (questionDetails, customOptions) => {
+  const { name, query } = questionDetails;
+
+  throwIfNotPresent(query);
+
+  logAction("Create a QB question", name);
+  question("query", questionDetails, customOptions);
+});
+
 Cypress.Commands.add(
-  "createQuestion",
-  ({
-    name = "card",
-    query = {},
-    display = "table",
-    database = 1,
-    visualization_settings = {},
-    collection_id = null,
-    collection_position = null,
-  } = {}) => {
-    cy.log(`Create a question: ${name}`);
-    cy.request("POST", "/api/card", {
-      name,
-      dataset_query: {
-        type: "query",
-        query,
-        database,
-      },
-      display,
-      visualization_settings,
-      collection_id,
-      collection_position,
-    });
+  "createNativeQuestion",
+  (questionDetails, customOptions) => {
+    const { name, native } = questionDetails;
+
+    throwIfNotPresent(native);
+
+    logAction("Create a native question", name);
+    question("native", questionDetails, customOptions);
   },
 );
 
-Cypress.Commands.add(
-  "createNativeQuestion",
-  ({
-    name = "native",
-    native = {},
-    display = "table",
+/**
+ *
+ * @param {("query"|"native")} type
+ *
+ * @param {object} questionDetails
+ * @param {string} [questionDetails.name="test question"]
+ * @param {object} questionDetails.native
+ * @param {object} questionDetails.query
+ * @param {number} [questionDetails.database=1]
+ * @param {string} [questionDetails.display="table"]
+ * @param {object} [questionDetails.visualization_settings={}]
+ * @param {number} [questionDetails.collection_id] - Parent collection in which to store this question.
+ * @param {number} [questionDetails.collection_position] - used on the frontend to determine whether the question is pinned or not.
+ *
+ * @param {object} customOptions
+ * @param {boolean} customOptions.loadMetadata - Whether to visit the question in order to load its metadata.
+ * @param {boolean} customOptions.visitQuestion - Whether to visit the question after the creation or not.
+ */
+function question(
+  type,
+  {
+    name = "test question",
+    native,
+    query,
     database = 1,
+    display = "table",
     visualization_settings = {},
-    collection_id = null,
-  } = {}) => {
-    cy.log(`Create a native question: ${name}`);
-    cy.request("POST", "/api/card", {
-      name,
-      collection_id,
-      dataset_query: {
-        type: "native",
-        native,
-        database,
-      },
-      display,
-      visualization_settings,
-    });
-  },
-);
+    collection_id,
+    collection_position,
+  } = {},
+  { loadMetadata = false, visitQuestion = false } = {},
+) {
+  cy.request("POST", "/api/card", {
+    name,
+    dataset_query: {
+      type,
+      [type]: type === "native" ? native : query,
+      database,
+    },
+    display,
+    visualization_settings,
+    collection_id,
+    collection_position,
+  }).then(({ body }) => {
+    if (loadMetadata || visitQuestion) {
+      cy.intercept("POST", `/api/card/${body.id}/query`).as("cardQuery");
+      cy.visit(`/question/${body.id}`);
+
+      // Wait for `result_metadata` to load
+      cy.wait("@cardQuery");
+    }
+  });
+}
+
+function throwIfNotPresent(param) {
+  if (!param) {
+    throw new Error(`Wrong key! Expected "query" or "native".`);
+  }
+}
+
+/**
+ *
+ * @param {string} title - A title used to log the Cypress action/request that follows it.
+ * @param {string} [questionName] - Optional question name.
+ */
+function logAction(title, questionName) {
+  const fullTitle = `${title}: ${questionName}`;
+  const message = questionName ? fullTitle : title;
+
+  cy.log(message);
+}
diff --git a/frontend/test/metabase/scenarios/binning/sql.cy.spec.js b/frontend/test/metabase/scenarios/binning/sql.cy.spec.js
index b9fc40370718e7c8fe0252056f6b8898c8439969..755b3ed428b718e725581b3eb05df43851b1ff38 100644
--- a/frontend/test/metabase/scenarios/binning/sql.cy.spec.js
+++ b/frontend/test/metabase/scenarios/binning/sql.cy.spec.js
@@ -1,26 +1,20 @@
 import { restore, popover } from "__support__/e2e/cypress";
 
+const questionDetails = {
+  name: "SQL Binning",
+  native: {
+    query:
+      "SELECT ORDERS.CREATED_AT, ORDERS.TOTAL, PEOPLE.LONGITUDE FROM ORDERS JOIN PEOPLE ON orders.user_id = people.id",
+  },
+};
+
 describe("scenarios > binning > from a saved sql question", () => {
   beforeEach(() => {
-    cy.intercept("POST", "/api/card/*/query").as("cardQuery");
     cy.intercept("POST", "/api/dataset").as("dataset");
 
     restore();
     cy.signInAsAdmin();
-    cy.createNativeQuestion({
-      name: "SQL Binning",
-      native: {
-        query:
-          "SELECT ORDERS.CREATED_AT, ORDERS.TOTAL, PEOPLE.LONGITUDE FROM ORDERS JOIN PEOPLE ON orders.user_id = people.id",
-      },
-    }).then(({ body }) => {
-      /**
-       * We need to visit the question and to wait for the result metadata to load first.
-       * Please see: https://github.com/metabase/metabase/pull/16707#issuecomment-866126310
-       */
-      cy.visit(`/question/${body.id}`);
-      cy.wait("@cardQuery");
-    });
+    cy.createNativeQuestion(questionDetails, { loadMetadata: true });
   });
 
   context("via simple question", () => {
diff --git a/frontend/test/metabase/scenarios/question/new.cy.spec.js b/frontend/test/metabase/scenarios/question/new.cy.spec.js
index 517436b1748eccdf632009ba68682ceade40ad2c..462655059164883cdc874b7743720846a407217c 100644
--- a/frontend/test/metabase/scenarios/question/new.cy.spec.js
+++ b/frontend/test/metabase/scenarios/question/new.cy.spec.js
@@ -375,7 +375,7 @@ describe("scenarios > question > new", () => {
     });
 
     it("should display timeseries filter and granularity widgets at the bottom of the screen (metabase#11183)", () => {
-      cy.createQuestion({
+      const questionDetails = {
         name: "11183",
         query: {
           "source-table": ORDERS_ID,
@@ -385,14 +385,10 @@ describe("scenarios > question > new", () => {
           ],
         },
         display: "line",
-      }).then(({ body: { id: QUESTION_ID } }) => {
-        cy.server();
-        cy.route("POST", `/api/card/${QUESTION_ID}/query`).as("cardQuery");
+      };
 
-        cy.visit(`/question/${QUESTION_ID}`);
-      });
+      cy.createQuestion(questionDetails, { visitQuestion: true });
 
-      cy.wait("@cardQuery");
       cy.log("Reported missing in v0.33.1");
       cy.get(".AdminSelect")
         .as("select")