-
Anton Kulyk authored
* Skip repro for 10493 * Add repro for 44532 * Remove `ensureMetricsAndDimensions`
Anton Kulyk authored* Skip repro for 10493 * Add repro for 44532 * Remove `ensureMetricsAndDimensions`
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
reproductions-3.cy.spec.js 23.97 KiB
import { WRITABLE_DB_ID, SAMPLE_DB_ID } from "e2e/support/cypress_data";
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
import { NO_COLLECTION_PERSONAL_COLLECTION_ID } from "e2e/support/cypress_sample_instance_data";
import {
restore,
visualize,
openTable,
openOrdersTable,
popover,
modal,
summarize,
startNewQuestion,
entityPickerModal,
entityPickerModalTab,
questionInfoButton,
rightSidebar,
getNotebookStep,
visitQuestionAdhoc,
openNotebook,
queryBuilderHeader,
cartesianChartCircle,
filter,
moveColumnDown,
getDraggableElements,
resetTestTable,
getTable,
resyncDatabase,
createQuestion,
saveQuestion,
echartsContainer,
newButton,
appBar,
openProductsTable,
} from "e2e/support/helpers";
const { ORDERS, ORDERS_ID, PRODUCTS } = SAMPLE_DATABASE;
describe("issue 32625, issue 31635", () => {
const CC_NAME = "Is Promotion";
const QUESTION = {
dataset_query: {
type: "query",
database: SAMPLE_DB_ID,
query: {
"source-table": ORDERS_ID,
aggregation: [
"distinct",
["field", ORDERS.PRODUCT_ID, { "base-type": "type/Integer" }],
],
breakout: ["expression", CC_NAME],
expressions: {
[CC_NAME]: [
"case",
[[[">", ["field", ORDERS.DISCOUNT, null], 0], 1]],
{ default: 0 },
],
},
},
},
};
beforeEach(() => {
restore();
cy.signInAsAdmin();
});
it("should remove dependent clauses when a clause is removed (metabase#32625, metabase#31635)", () => {
visitQuestionAdhoc(QUESTION, { mode: "notebook" });
getNotebookStep("expression")
.findAllByTestId("notebook-cell-item")
.first()
.icon("close")
.click();
getNotebookStep("expression").should("not.exist");
getNotebookStep("summarize").findByText(CC_NAME).should("not.exist");
visualize();
cy.findByTestId("query-builder-main").within(() => {
cy.findByTestId("scalar-value").should("have.text", "200");
cy.findByText("There was a problem with your question").should(
"not.exist",
);
});
});
});
describe("issue 32964", () => {
const LONG_NAME = "A very long column name that will cause text overflow";
const QUESTION = {
dataset_query: {
type: "query",
database: SAMPLE_DB_ID,
query: {
"source-table": ORDERS_ID,
expressions: {
[LONG_NAME]: [
"*",
["field", SAMPLE_DATABASE.ORDERS.SUBTOTAL, null],
2,
],
},
aggregation: [["sum", ["expression", LONG_NAME]]],
breakout: [
[
"field",
SAMPLE_DATABASE.ORDERS.CREATED_AT,
{
"base-type": "type/DateTime",
"temporal-unit": "week",
},
],
],
},
},
};
beforeEach(() => {
restore();
cy.signInAsAdmin();
});
it("should not overflow chart settings sidebar with long column name (metabase#32964)", () => {
visitQuestionAdhoc(QUESTION);
cy.findByTestId("viz-settings-button").click();
cy.findByTestId("sidebar-left").within(([sidebar]) => {
const maxX = sidebar.getBoundingClientRect().right;
cy.findByText(`Sum of ${LONG_NAME}`).then(([el]) => {
const x = el.getBoundingClientRect().right;
expect(x).to.be.lessThan(maxX);
});
});
});
});
describe("issue 33079", () => {
const questionDetails = {
display: "line",
query: {
"source-table": ORDERS_ID,
aggregation: [["count"]],
breakout: [["field", ORDERS.CREATED_AT, { "temporal-unit": "month" }]],
},
};
beforeEach(() => {
restore();
cy.signInAsAdmin();
cy.intercept("POST", "/api/dataset").as("dataset");
cy.request("GET", "/api/user/current").then(({ body: user }) => {
cy.request("PUT", `/api/user/${user.id}`, { locale: "de" });
});
});
it("underlying records drill should work in a non-English locale (metabase#33079)", () => {
cy.createQuestion(questionDetails, { visitQuestion: true });
cartesianChartCircle().eq(1).click({ force: true });
popover()
.findByText(/Order/) // See these Orders
.click();
cy.wait("@dataset");
cy.findByTestId("question-row-count").should("contain", "19");
});
});
describe("issue 34414", () => {
const { INVOICES_ID } = SAMPLE_DATABASE;
const INVOICE_MODEL_DETAILS = {
name: "Invoices Model",
query: { "source-table": INVOICES_ID },
type: "model",
};
beforeEach(() => {
restore();
cy.signInAsNormalUser();
});
it("populate field values after re-adding filter on virtual table field (metabase#34414)", () => {
cy.createQuestion(INVOICE_MODEL_DETAILS).then(response => {
const modelId = response.body.id;
visitQuestionAdhoc({
dataset_query: {
type: "query",
database: SAMPLE_DB_ID,
query: { "source-table": `card__${modelId}` },
},
});
});
openNotebook();
filter({ mode: "notebook" });
popover().within(() => {
cy.findByText("Plan").click();
assertPlanFieldValues();
cy.log("Open filter again");
cy.findByLabelText("Back").click();
cy.log("Open plan field again");
cy.findByText("Plan").click();
assertPlanFieldValues();
});
});
});
function assertPlanFieldValues() {
cy.findByText("Basic").should("be.visible");
cy.findByText("Business").should("be.visible");
cy.findByText("Premium").should("be.visible");
}
describe("issue 38176", () => {
beforeEach(() => {
restore();
cy.signInAsNormalUser();
cy.intercept("PUT", "/api/card/**").as("updateQuestion");
});
it("restoring a question to a previous version should preserve the variables (metabase#38176)", () => {
cy.createNativeQuestion(
{
name: "38176",
native: {
query:
'SELECT "COUNTRY" from "ACCOUNTS" WHERE country = {{ country }} LIMIT 5',
"template-tags": {
country: {
type: "text",
id: "dd06cd10-596b-41d0-9d6e-94e98ceaf989",
name: "country",
"display-name": "Country",
},
},
},
},
{ visitQuestion: true },
);
cy.findByPlaceholderText("Country").type("NL");
cy.findByTestId("query-builder-main").button("Get Answer").click();
questionInfoButton().click();
rightSidebar().within(() => {
cy.findByText("History");
cy.findByPlaceholderText("Add description")
.type("This is a question")
.blur();
cy.wait("@updateQuestion");
cy.findByText(/added a description/i);
cy.findByTestId("question-revert-button").click();
cy.findByText(/reverted to an earlier version/i).should("be.visible");
});
cy.findAllByRole("gridcell").should("contain", "NL");
});
});
describe("issue 38354", { tags: "@external" }, () => {
const QUESTION_DETAILS = {
query: {
"source-table": ORDERS_ID,
limit: 5,
},
};
beforeEach(() => {
restore();
restore("postgres-12");
cy.signInAsAdmin();
cy.createQuestion(QUESTION_DETAILS, { visitQuestion: true });
});
it("should be possible to change source database (metabase#38354)", () => {
openNotebook();
getNotebookStep("data").findByTestId("data-step-cell").click();
entityPickerModal().within(() => {
cy.findByText("QA Postgres12").click();
cy.findByText("Orders").click();
});
// optimization: add a limit so that query runs faster
cy.button("Row limit").click();
getNotebookStep("limit").findByPlaceholderText("Enter a limit").type("5");
visualize();
cy.findByTestId("query-builder-main")
.findByText("There was a problem with your question")
.should("not.exist");
cy.get("[data-testid=cell-data]").should("contain", "37.65"); // assert visualization renders the data
});
});
describe("issue 39102", () => {
const questionDetails = {
name: "39102",
query: {
"source-query": {
"source-table": ORDERS_ID,
aggregation: ["count"],
breakout: [["field", ORDERS.CREATED_AT, { "temporal-unit": "year" }]],
},
filter: [">", ["field", "count", { "base-type": "type/Integer" }], 1000],
aggregation: ["count"],
},
type: "question",
};
beforeEach(() => {
restore();
cy.signInAsAdmin();
cy.intercept("POST", "/api/dataset").as("dataset");
});
it("should be able to preview a multi-stage query (metabase#39102)", () => {
cy.createQuestion(questionDetails, { visitQuestion: true });
openNotebook();
getNotebookStep("data", { stage: 0 }).icon("play").click();
cy.wait("@dataset");
cy.findByTestId("preview-root").within(() => {
cy.findByText("Tax").should("be.visible");
cy.icon("close").click();
});
getNotebookStep("summarize", { stage: 0 }).icon("play").click();
cy.wait("@dataset");
cy.findByTestId("preview-root").within(() => {
cy.findByText("Count").should("be.visible");
cy.findByText("3,610").should("be.visible");
cy.findByText("744").should("be.visible");
cy.icon("close").click();
});
getNotebookStep("filter", { stage: 1 }).icon("play").click();
cy.wait("@dataset");
cy.findByTestId("preview-root").within(() => {
cy.findByText("Count").should("be.visible");
cy.findByText("3,610").should("be.visible");
cy.findByText("744").should("not.exist");
cy.icon("close").click();
});
getNotebookStep("summarize", { stage: 1 }).icon("play").click();
cy.wait("@dataset");
cy.findByTestId("preview-root").within(() => {
cy.findByText("Count").should("be.visible");
cy.findByText("4").should("be.visible");
});
});
});
describe("issue 39795", () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
//If you comment out this post, then the test will pass.
cy.request("post", `/api/field/${ORDERS.PRODUCT_ID}/dimension`, {
human_readable_field_id: PRODUCTS.TITLE,
name: "Product ID",
type: "external",
});
});
it("should allow me to re-order even when a field is set with a different display value (metabase#39795)", () => {
visitQuestionAdhoc({
dataset_query: {
database: SAMPLE_DB_ID,
query: {
"source-table": ORDERS_ID,
},
type: "query",
},
});
cy.findByTestId("viz-settings-button").click();
moveColumnDown(getDraggableElements().first(), 2);
// We are not able to re-order because the dataset will also contain values a column for Product ID
// This causes the isValid() check to fire, and you are always forced into the default value for table.columns
getDraggableElements().eq(2).should("contain.text", "ID");
});
});
describe("issue 40176", () => {
const DIALECT = "postgres";
const TABLE = "uuid_pk_table";
beforeEach(() => {
restore(`${DIALECT}-writable`);
cy.signInAsAdmin();
resetTestTable({ type: DIALECT, table: TABLE });
resyncDatabase({
dbId: WRITABLE_DB_ID,
tableName: TABLE,
});
});
it(
"should allow filtering on UUID PK columns (metabase#40176)",
{ tags: "@external" },
() => {
getTable({ name: TABLE }).then(({ id: tableId }) => {
visitQuestionAdhoc({
display: "table",
dataset_query: {
database: WRITABLE_DB_ID,
query: {
"source-table": tableId,
},
type: "query",
},
});
});
openNotebook();
cy.findByTestId("action-buttons").findByText("Filter").click();
popover().within(() => {
cy.findByText("ID").click();
cy.findByLabelText("Filter value").type(
"a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11",
);
cy.button("Add filter").click();
});
visualize();
cy.findByTestId("question-row-count")
.findByText("Showing 1 row")
.should("be.visible");
},
);
});
describe("issue 40435", () => {
beforeEach(() => {
restore();
cy.signInAsNormalUser();
cy.intercept("PUT", "/api/card/*").as("updateCard");
});
it("should make new query columns visible by default (metabase#40435)", () => {
openOrdersTable();
openNotebook();
getNotebookStep("data").button("Pick columns").click();
popover().within(() => {
cy.findByText("Select none").click();
cy.findByText("User ID").click();
});
getNotebookStep("data").button("Pick columns").click();
visualize();
cy.findByTestId("viz-settings-button").click();
cy.findByTestId("sidebar-left").within(() => {
cy.findByTestId("ID-hide-button").click();
cy.findByTestId("ID-show-button").click();
});
saveQuestion();
openNotebook();
getNotebookStep("data").button("Pick columns").click();
popover().findByText("Product ID").click();
queryBuilderHeader().findByText("Save").click();
modal().last().findByText("Save").click();
cy.wait("@updateCard");
visualize();
cy.findByRole("columnheader", { name: "ID" }).should("be.visible");
cy.findByRole("columnheader", { name: "User ID" }).should("be.visible");
cy.findByRole("columnheader", { name: "Product ID" }).should("be.visible");
});
});
describe(
"issue 42010 -- Unable to filter by mongo id",
{ tags: "@mongo" },
() => {
beforeEach(() => {
restore("mongo-5");
cy.signInAsAdmin();
cy.intercept("POST", "/api/dataset").as("dataset");
cy.request(`/api/database/${WRITABLE_DB_ID}/schema/`).then(({ body }) => {
const tableId = body.find(table => table.name === "orders").id;
openTable({
database: WRITABLE_DB_ID,
table: tableId,
limit: 2,
});
});
cy.wait("@dataset");
});
it("should be possible to filter by Mongo _id column (metabase#40770, metabase#42010)", () => {
cy.get("#main-data-grid")
.findAllByRole("gridcell")
.first()
.then($cell => {
// Ids are non-deterministic so we have to obtain the id from the cell, and store its value.
const id = $cell.text();
cy.log(
"Scenario 1 - Make sure the simple mode filter is working correctly (metabase#40770)",
);
filter();
cy.findByRole("dialog").within(() => {
cy.findByPlaceholderText("Search by ID").type(id);
cy.button("Apply filters").click();
});
cy.findByTestId("question-row-count").should(
"have.text",
"Showing 1 row",
);
removeFilter();
cy.log(
"Scenario 2 - Make sure filter is working in the notebook editor (metabase#42010)",
);
openNotebook();
filter({ mode: "notebook" });
popover()
.findAllByRole("option")
.first()
.should("have.text", "ID")
.click();
cy.findByTestId("string-filter-picker").within(() => {
cy.findByLabelText("Filter operator").should("have.value", "Is");
cy.findByPlaceholderText("Search by ID").type(id);
cy.button("Add filter").click();
});
cy.findByTestId("step-filter-0-0").within(() => {
cy.findByText(`ID is ${id}`);
cy.log(
"Scenario 2.1 - Trigger the preview to make sure it reflects the filter correctly",
);
cy.icon("play").click();
});
// The preview should show only one row
const ordersColumns = 10;
cy.findByTestId("preview-root")
.get("#main-data-grid")
.findAllByTestId("cell-data")
.should("have.length.at.most", ordersColumns);
cy.log("Scenario 2.2 - Make sure we can visualize the data");
visualize();
cy.findByTestId("question-row-count").should(
"have.text",
"Showing 1 row",
);
});
});
},
);
function removeFilter() {
cy.findByTestId("filter-pill").findByLabelText("Remove").click();
cy.findByTestId("question-row-count").should("have.text", "Showing 2 rows");
}
describe("issue 42244", () => {
const COLUMN_NAME = "Created At".repeat(5);
beforeEach(() => {
restore();
cy.signInAsAdmin();
cy.request("PUT", `/api/field/${ORDERS.CREATED_AT}`, {
display_name: COLUMN_NAME,
});
});
it("should allow to change the temporal bucket when the column name is long (metabase#42244)", () => {
openOrdersTable({ mode: "notebook" });
summarize({ mode: "notebook" });
getNotebookStep("summarize")
.findByText("Pick a column to group by")
.click();
popover().within(() => {
cy.findByText(COLUMN_NAME).realHover();
cy.findByText("by month").should("be.visible").click();
});
popover().last().findByText("Year").click();
getNotebookStep("summarize")
.findByText(`${COLUMN_NAME}: Year`)
.should("be.visible");
});
});
describe("issue 42957", () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
});
it("does not show collections that contain models from different tabs (metabase#42957)", () => {
createQuestion({
name: "Model",
type: "model",
query: {
"source-table": ORDERS_ID,
},
});
cy.createCollection({ name: "Collection without models" }).then(
({ body: collection }) => {
cy.wrap(collection.id).as("collectionId");
},
);
cy.get("@collectionId").then(collectionId => {
createQuestion({
name: "Question",
type: "question",
query: {
"source-table": ORDERS_ID,
},
collection_id: collectionId,
});
});
startNewQuestion();
entityPickerModal().within(() => {
entityPickerModalTab("Models").click();
cy.findByText("Collection without models").should("not.exist");
});
});
});
describe.skip("issue 10493", () => {
beforeEach(() => {
restore();
cy.intercept("POST", "/api/dataset").as("dataset");
cy.signInAsAdmin();
});
it("should not reset chart axes after adding a new query stage (metabase#10493)", () => {
visitQuestionAdhoc({
display: "bar",
dataset_query: {
type: "query",
database: SAMPLE_DB_ID,
query: {
aggregation: [["count"]],
breakout: [
[
"field",
ORDERS.QUANTITY,
{ "base-type": "type/Integer", binning: { strategy: "default" } },
],
],
"source-table": ORDERS_ID,
},
},
});
filter();
modal().within(() => {
cy.findByText("Summaries").click();
cy.findByTestId("filter-column-Count").within(() => {
cy.findByPlaceholderText("Min").type("0");
cy.findByPlaceholderText("Max").type("30000");
});
cy.button("Apply filters").click();
});
cy.wait("@dataset");
echartsContainer().within(() => {
// y axis
cy.findByText("Count").should("exist");
cy.findByText("21,000").should("exist");
cy.findByText("3,000").should("exist");
// x axis
cy.findByText("Quantity").should("exist");
cy.findByText("25").should("exist");
cy.findByText("75").should("exist");
});
});
});
describe("issue 44071", () => {
const questionDetails = {
name: "Test",
query: { "source-table": ORDERS_ID },
collection_id: NO_COLLECTION_PERSONAL_COLLECTION_ID,
};
beforeEach(() => {
restore();
cy.signIn("nocollection");
createQuestion(questionDetails);
});
it("should be able to save questions based on another questions without collection access (metabase#44071)", () => {
cy.visit("/");
newButton("Question").click();
entityPickerModal().within(() => {
entityPickerModalTab("Saved questions").click();
cy.findByText(/Personal Collection/).click();
cy.findByText(questionDetails.name).click();
});
getNotebookStep("data")
.findByText(questionDetails.name)
.should("be.visible");
saveQuestion();
appBar()
.findByText(/Personal Collection/)
.should("be.visible");
});
});
describe("issue 44415", () => {
beforeEach(() => {
restore();
cy.signIn("admin");
createQuestion(
{
query: {
"source-table": ORDERS_ID,
filter: [
"and",
[
"not-null",
["field", ORDERS.DISCOUNT, { "base-type": "type/Float" }],
],
],
},
visualization_settings: {
"table.columns": [
{
name: "ID",
fieldRef: ["field", ORDERS.ID, null],
enabled: true,
},
{
name: "DISCOUNT",
fieldRef: ["field", ORDERS.DISCOUNT, null],
enabled: true,
},
],
},
},
{ wrapId: true },
);
});
it("should be able to edit a table question in the notebook editor before running its query (metabase#44415)", () => {
cy.get("@questionId").then(questionId =>
cy.visit(`/question/${questionId}/notebook`),
);
getNotebookStep("filter")
.findAllByTestId("notebook-cell-item")
.first()
.icon("close")
.click();
getNotebookStep("filter").should("not.exist");
visualize();
cy.findByTestId("qb-filters-panel").should("not.exist");
cy.get("@questionId").then(questionId => {
cy.url().should("not.include", `/question/${questionId}`);
cy.url().should("include", "question#");
});
});
});
describe("issue 44532", () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
openProductsTable();
});
it("should update chart metrics and dimensions with each added breakout (metabase #44532)", () => {
summarize();
rightSidebar()
.findByRole("listitem", { name: "Category" })
.button("Add dimension")
.click();
cy.wait("@dataset");
echartsContainer().within(() => {
cy.findByText("Count").should("exist"); // y-axis
cy.findByText("Category").should("exist"); // x-axis
// x-axis values
cy.findByText("Doohickey").should("exist");
cy.findByText("Gadget").should("exist");
cy.findByText("Gizmo").should("exist");
cy.findByText("Widget").should("exist");
});
rightSidebar()
.findByRole("listitem", { name: "Created At" })
.button("Add dimension")
.click();
cy.wait("@dataset");
cy.findByLabelText("Legend").within(() => {
cy.findByText("Doohickey").should("exist");
cy.findByText("Gadget").should("exist");
cy.findByText("Gizmo").should("exist");
cy.findByText("Widget").should("exist");
});
echartsContainer().within(() => {
cy.findByText("Count").should("exist"); // y-axis
cy.findByText("Created At").should("exist"); // x-axis
// x-axis values
cy.findByText("January 2023").should("exist");
cy.findByText("January 2024").should("exist");
cy.findByText("January 2025").should("exist");
// previous x-axis values
cy.findByText("Doohickey").should("not.exist");
cy.findByText("Gadget").should("not.exist");
cy.findByText("Gizmo").should("not.exist");
cy.findByText("Widget").should("not.exist");
});
rightSidebar().button("Done").click();
cy.wait("@dataset");
cy.findByLabelText("Legend").within(() => {
cy.findByText("Doohickey").should("exist");
cy.findByText("Gadget").should("exist");
cy.findByText("Gizmo").should("exist");
cy.findByText("Widget").should("exist");
});
echartsContainer().within(() => {
cy.findByText("Count").should("exist"); // y-axis
cy.findByText("Created At").should("exist"); // x-axis
// x-axis values
cy.findByText("January 2023").should("exist");
cy.findByText("January 2024").should("exist");
cy.findByText("January 2025").should("exist");
// previous x-axis values
cy.findByText("Doohickey").should("not.exist");
cy.findByText("Gadget").should("not.exist");
cy.findByText("Gizmo").should("not.exist");
cy.findByText("Widget").should("not.exist");
});
});
});