From 95b0bdfd1e573659efc485cba2eae6f7a8ee712b Mon Sep 17 00:00:00 2001 From: Nemanja Glumac <31325167+nemanjaglumac@users.noreply.github.com> Date: Sun, 10 Apr 2022 14:43:34 +0200 Subject: [PATCH] [E2E] Embedded dashboard with linked filters connected to a GUI question (#21529) --- .../embedding-linked-filters.cy.spec.js | 227 +++++++++++++++++- .../embedding/embedding-linked-filters.js | 70 +++++- 2 files changed, 285 insertions(+), 12 deletions(-) diff --git a/frontend/test/metabase/scenarios/embedding/embedding-linked-filters.cy.spec.js b/frontend/test/metabase/scenarios/embedding/embedding-linked-filters.cy.spec.js index 583b4f05a0c..5c2b1cc3001 100644 --- a/frontend/test/metabase/scenarios/embedding/embedding-linked-filters.cy.spec.js +++ b/frontend/test/metabase/scenarios/embedding/embedding-linked-filters.cy.spec.js @@ -6,9 +6,12 @@ import { } from "__support__/e2e/cypress"; import { - questionDetails, - dashboardDetails, - mapParameters, + nativeQuestionDetails, + nativeDashboardDetails, + mapNativeDashboardParameters, + guiQuestion, + guiDashboard, + mapGUIDashboardParameters, } from "./embedding-linked-filters"; describe("scenarios > embedding > dashboard > linked filters (metabase#13639, metabase#13868)", () => { @@ -20,12 +23,12 @@ describe("scenarios > embedding > dashboard > linked filters (metabase#13639, me context("SQL question with field filters", () => { beforeEach(() => { cy.createNativeQuestionAndDashboard({ - questionDetails, - dashboardDetails, + questionDetails: nativeQuestionDetails, + dashboardDetails: nativeDashboardDetails, }).then(({ body: { id, card_id, dashboard_id } }) => { cy.wrap(dashboard_id).as("dashboardId"); - mapParameters({ id, card_id, dashboard_id }); + mapNativeDashboardParameters({ id, card_id, dashboard_id }); // Enable embedding for this dashboard with both the city and state filters enabled cy.request("PUT", `/api/dashboard/${dashboard_id}`, { @@ -47,8 +50,9 @@ describe("scenarios > embedding > dashboard > linked filters (metabase#13639, me visitEmbeddedPage(payload); }); - cy.findByRole("heading", { name: dashboardDetails.name }); - cy.get(".Card").contains(questionDetails.name); + + cy.findByRole("heading", { name: nativeDashboardDetails.name }); + cy.get(".Card").contains(nativeQuestionDetails.name); cy.get(".bar").should("have.length", 49); @@ -237,6 +241,205 @@ describe("scenarios > embedding > dashboard > linked filters (metabase#13639, me cy.location("search").should("eq", "?city=Anchorage"); }); }); + + context("GUI question in the dashboard", () => { + beforeEach(() => { + cy.createQuestionAndDashboard({ + questionDetails: guiQuestion, + dashboardDetails: guiDashboard, + }).then(({ body: { id, card_id, dashboard_id } }) => { + cy.wrap(dashboard_id).as("guiDashboardId"); + + mapGUIDashboardParameters(id, card_id, dashboard_id); + + cy.request("PUT", `/api/dashboard/${dashboard_id}`, { + embedding_params: { + id_filter: "enabled", + category: "enabled", + }, + enable_embedding: true, + }); + }); + }); + + it("works when both filters are enabled and their values are set through UI", () => { + cy.get("@guiDashboardId").then(dashboard_id => { + const payload = { + resource: { dashboard: dashboard_id }, + params: {}, + }; + + visitEmbeddedPage(payload); + }); + + // ID filter already comes with the default value + cy.location("search").should("eq", "?id_filter=1"); + + // But it should still be editable, and that's why we see two filter widgets + filterWidget() + .should("have.length", 2) + .contains("Category") + .click(); + + popover().within(() => { + cy.findByText("Gizmo").click(); + cy.findByText("Doohickey").should("not.exist"); + cy.findByText("Gadget").should("not.exist"); + cy.findByText("Widget").should("not.exist"); + + cy.button("Add filter").click(); + }); + + cy.location("search").should("eq", "?id_filter=1&category=Gizmo"); + + cy.findByTestId("table-row") + .should("have.length", 1) + .and("contain", "Gizmo"); + }); + + it("works when main filter's value is set through URL", () => { + cy.get("@guiDashboardId").then(dashboard_id => { + const payload = { + resource: { dashboard: dashboard_id }, + params: {}, + }; + + cy.log("Make sure we can override the default value"); + visitEmbeddedPage(payload, { setFilters: "id_filter=4" }); + + cy.location("search").should("eq", "?id_filter=4"); + + filterWidget() + .should("have.length", 2) + .contains("Category") + .click(); + + popover().within(() => { + cy.findByText("Doohickey").click(); + cy.findByText("Gizmo").should("not.exist"); + cy.findByText("Gadget").should("not.exist"); + cy.findByText("Widget").should("not.exist"); + + cy.button("Add filter").click(); + }); + + cy.location("search").should("eq", "?id_filter=4&category=Doohickey"); + + cy.findByTestId("table-row") + .should("have.length", 1) + .and("contain", "Doohickey"); + + cy.log("Make sure we can set multiple values"); + visitEmbeddedPage(payload, { + setFilters: "id_filter=4&id_filter=29&category=Widget", + }); + + filterWidget() + .should("have.length", 2) + .and("contain", "2 selections") + .and("contain", "Widget"); + + cy.findByTestId("table-row") + .should("have.length", 1) + .and("contain", "Widget") + .and("contain", "Durable Steel Toucan"); + + removeValueForFilter("Category"); + + cy.findAllByTestId("table-row") + .should("have.length", 2) + .and("contain", "Widget") + .and("contain", "Doohickey") + .and("contain", "Durable Steel Toucan"); + + cy.findByText("2 selections").click(); + + // Remove one of the previously set filter values + popover() + .findByText("29") + .closest("li") + .find(".Icon-close") + .click(); + cy.button("Update filter").click(); + + cy.findByTestId("table-row") + .should("have.length", 1) + .and("contain", "Doohickey"); + + openFilterOptions("Category"); + + popover().within(() => { + cy.findByText("Doohickey"); + cy.findByText("Gizmo").should("not.exist"); + cy.findByText("Gadget").should("not.exist"); + cy.findByText("Widget").should("not.exist"); + }); + }); + }); + + it("works when the default filter is hidden", () => { + cy.get("@guiDashboardId").then(dashboard_id => { + const payload = { + resource: { dashboard: dashboard_id }, + params: {}, + }; + + visitEmbeddedPage(payload, { + hideFilters: "id_filter", + }); + }); + + cy.findByTestId("table-row") + .should("have.length", 1) + .and("contain", "Gizmo"); + + filterWidget() + .should("have.length", 1) + .and("contain", "Category") + .click(); + + popover().within(() => { + cy.findByText("Gizmo"); + cy.findByText("Doohickey").should("not.exist"); + cy.findByText("Gadget").should("not.exist"); + cy.findByText("Widget").should("not.exist"); + }); + }); + + it("works when the default filter is locked", () => { + cy.get("@guiDashboardId").then(dashboard_id => { + cy.request("PUT", `/api/dashboard/${dashboard_id}`, { + embedding_params: { + id_filter: "locked", + category: "enabled", + }, + }); + + const payload = { + resource: { dashboard: dashboard_id }, + params: { id_filter: [1] }, + }; + + visitEmbeddedPage(payload); + }); + + cy.findByTestId("table-row") + .should("have.length", 1) + .and("contain", "Gizmo"); + + filterWidget() + .should("have.length", 1) + .and("contain", "Category") + .click(); + + popover().within(() => { + cy.findByText("Gizmo"); + cy.findByText("Doohickey").should("not.exist"); + cy.findByText("Gadget").should("not.exist"); + cy.findByText("Widget").should("not.exist"); + }); + }); + }); }); function openFilterOptions(name) { @@ -265,3 +468,11 @@ function assertOnXYAxisLabels({ xLabel, yLabel } = {}) { function getXAxisValues() { return cy.get(".axis.x .tick"); } + +function removeValueForFilter(label) { + cy.get("legend") + .contains(label) + .closest("fieldset") + .find(".Icon-close") + .click(); +} diff --git a/frontend/test/metabase/scenarios/embedding/embedding-linked-filters.js b/frontend/test/metabase/scenarios/embedding/embedding-linked-filters.js index 5bb78c3e320..ddf120de8b9 100644 --- a/frontend/test/metabase/scenarios/embedding/embedding-linked-filters.js +++ b/frontend/test/metabase/scenarios/embedding/embedding-linked-filters.js @@ -1,8 +1,8 @@ import { SAMPLE_DATABASE } from "__support__/e2e/cypress_sample_database"; -const { PEOPLE } = SAMPLE_DATABASE; +const { PEOPLE, PRODUCTS, PRODUCTS_ID } = SAMPLE_DATABASE; -export const questionDetails = { +export const nativeQuestionDetails = { name: "Count of People by State (SQL)", native: { query: @@ -44,12 +44,16 @@ const cityFilter = { filteringParameters: [stateFilter.id], }; -export const dashboardDetails = { +export const nativeDashboardDetails = { name: "Embedding Dashboard With Linked Filters", parameters: [stateFilter, cityFilter], }; -export function mapParameters({ id, card_id, dashboard_id } = {}) { +export function mapNativeDashboardParameters({ + id, + card_id, + dashboard_id, +} = {}) { return cy.request("PUT", `/api/dashboard/${dashboard_id}/cards`, { cards: [ { @@ -75,3 +79,61 @@ export function mapParameters({ id, card_id, dashboard_id } = {}) { ], }); } + +export const guiQuestion = { + query: { "source-table": PRODUCTS_ID }, +}; + +const idFilter = { + name: "ID Filter", + slug: "id_filter", + id: "fde6db8b", + type: "id", + sectionId: "id", + default: [1], +}; + +const categoryFilter = { + name: "Category", + slug: "category", + id: "e8ff3175", + type: "string/=", + sectionId: "string", + filteringParameters: ["fde6db8b"], +}; + +export const guiDashboard = { + name: "Dashboard With GUI question", + parameters: [idFilter, categoryFilter], +}; + +export function mapGUIDashboardParameters(id, card_id, dashboard_id) { + const parameter_mappings = [ + { + parameter_id: idFilter.id, + card_id, + target: ["dimension", ["field", PRODUCTS.ID, null]], + }, + { + parameter_id: categoryFilter.id, + card_id, + target: ["dimension", ["field", PRODUCTS.CATEGORY, null]], + }, + ]; + + cy.request("PUT", `/api/dashboard/${dashboard_id}/cards`, { + cards: [ + { + id, + card_id, + row: 0, + col: 0, + sizeX: 10, + sizeY: 8, + series: [], + visualization_settings: {}, + parameter_mappings, + }, + ], + }); +} -- GitLab