From 28ab027592b26baf4e95c52c3fa5d0de3a6f43a9 Mon Sep 17 00:00:00 2001 From: Alexander Polyankin <alexander.polyankin@metabase.com> Date: Fri, 8 Mar 2024 15:13:44 +0200 Subject: [PATCH] Extract column e2e (#39770) --- .../column_extract_drill.cy.spec.js | 153 ++++++++++++++++++ .../TableInteractive/TableInteractive.jsx | 4 +- 2 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 e2e/test/scenarios/visualizations-tabular/drillthroughs/column_extract_drill.cy.spec.js diff --git a/e2e/test/scenarios/visualizations-tabular/drillthroughs/column_extract_drill.cy.spec.js b/e2e/test/scenarios/visualizations-tabular/drillthroughs/column_extract_drill.cy.spec.js new file mode 100644 index 00000000000..8b3b3cdee77 --- /dev/null +++ b/e2e/test/scenarios/visualizations-tabular/drillthroughs/column_extract_drill.cy.spec.js @@ -0,0 +1,153 @@ +import _ from "underscore"; + +import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database"; +import { + enterCustomColumnDetails, + getNotebookStep, + openNotebook, + openOrdersTable, + popover, + restore, + visualize, +} from "e2e/support/helpers"; + +const { ORDERS, ORDERS_ID } = SAMPLE_DATABASE; + +const DATE_CASES = [ + { + option: "Hour of day", + value: "21", + }, + { + option: "Day of month", + value: "11", + }, + { + option: "Day of week", + value: "Tuesday", + }, + { + option: "Month of year", + value: "Feb", + }, + { + option: "Quarter of year", + value: "Q1", + }, + { + option: "Year", + value: "2,025", + }, +]; + +const DATE_QUESTION = { + query: { + "source-table": ORDERS_ID, + aggregation: [ + ["min", ["field", ORDERS.CREATED_AT, { "base-type": "type/DateTime" }]], + ], + breakout: [ + [ + "field", + ORDERS.CREATED_AT, + { "base-type": "type/DateTime", "temporal-unit": "month" }, + ], + ], + limit: 1, + }, +}; + +describe("extract action", () => { + beforeEach(() => { + restore(); + cy.signInAsAdmin(); + }); + + describe("date columns", () => { + describe("should add a date expression for each option", () => { + DATE_CASES.forEach(({ option, value }) => { + it(option, () => { + openOrdersTable({ limit: 1 }); + extractColumnAndCheck({ + column: "Created At", + option, + value, + }); + }); + }); + }); + + it("should add an expression based on a breakout column", () => { + cy.createQuestion(DATE_QUESTION, { visitQuestion: true }); + extractColumnAndCheck({ + column: "Created At: Month", + option: "Month of year", + value: "Apr", + }); + }); + + it("should add an expression based on an aggregation column", () => { + cy.createQuestion(DATE_QUESTION, { visitQuestion: true }); + extractColumnAndCheck({ + column: "Min of Created At: Default", + option: "Year", + value: "2,022", + }); + }); + + it("should handle duplicate expression names", () => { + openOrdersTable({ limit: 1 }); + extractColumnAndCheck({ + column: "Created At", + option: "Hour of day", + newColumn: "Hour of day", + }); + extractColumnAndCheck({ + column: "Created At", + option: "Hour of day", + newColumn: "Hour of day_2", + }); + }); + + it("should be able to modify the expression in the notebook editor", () => { + openOrdersTable({ limit: 1 }); + extractColumnAndCheck({ + column: "Created At", + option: "Year", + value: "2,025", + }); + openNotebook(); + getNotebookStep("expression").findByText("Year").click(); + enterCustomColumnDetails({ formula: "+ 2" }); + popover().button("Update").click(); + visualize(); + cy.findByRole("gridcell", { name: "2,027" }).should("be.visible"); + }); + + it("should use current user locale for string expressions", () => { + cy.request("GET", "/api/user/current").then(({ body: user }) => { + cy.request("PUT", `/api/user/${user.id}`, { locale: "de" }); + }); + openOrdersTable({ limit: 1 }); + extractColumnAndCheck({ + column: "Created At", + option: "Tag der Woche", + value: "Dienstag", + }); + }); + }); +}); + +function extractColumnAndCheck({ column, option, newColumn = option, value }) { + const requestAlias = _.uniqueId("dataset"); + cy.intercept("POST", "/api/dataset").as(requestAlias); + cy.findByRole("columnheader", { name: column }).click(); + popover().findByText("Extract day, month…").click(); + popover().findByText(option).click(); + cy.wait(`@${requestAlias}`); + + cy.findByRole("columnheader", { name: newColumn }).should("be.visible"); + if (value) { + cy.findByRole("gridcell", { name: value }).should("be.visible"); + } +} diff --git a/frontend/src/metabase/visualizations/components/TableInteractive/TableInteractive.jsx b/frontend/src/metabase/visualizations/components/TableInteractive/TableInteractive.jsx index fdd5bb9f07a..36650a5372c 100644 --- a/frontend/src/metabase/visualizations/components/TableInteractive/TableInteractive.jsx +++ b/frontend/src/metabase/visualizations/components/TableInteractive/TableInteractive.jsx @@ -753,7 +753,6 @@ class TableInteractive extends Component { }} > <HeaderCell - data-testid={isVirtual ? undefined : "header-cell"} ref={e => (this.headerRefs[columnIndex] = e)} style={{ ...style, @@ -776,6 +775,9 @@ class TableInteractive extends Component { "justify-end": isRightAligned, }, )} + role="columnheader" + aria-label={columnTitle} + data-testid={isVirtual ? undefined : "header-cell"} onClick={ // only use the onClick if not draggable since it's also handled in Draggable's onStop isClickable && !isDraggable -- GitLab