Skip to content
Snippets Groups Projects
Unverified Commit d53b0a7a authored by Ryan Laurie's avatar Ryan Laurie Committed by GitHub
Browse files

Consolidate sharing e2e specs (#43514)

parent fea8f89a
No related branches found
No related tags found
No related merge requests found
Showing
with 583 additions and 1444 deletions
import {
ORDERS_QUESTION_ID,
ORDERS_DASHBOARD_ID,
} from "e2e/support/cypress_sample_instance_data";
import {
describeEE,
restore,
setupSMTP,
sidebar,
visitQuestion,
visitDashboard,
setTokenFeatures,
} from "e2e/support/helpers";
const allowedDomain = "metabase.test";
const deniedDomain = "metabase.example";
const deniedEmail = `mailer@${deniedDomain}`;
const subscriptionError = `You're only allowed to email subscriptions to addresses ending in ${allowedDomain}`;
const alertError = `You're only allowed to email alerts to addresses ending in ${allowedDomain}`;
describeEE(
"scenarios > sharing > approved domains (EE)",
{ tags: "@external" },
() => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
setTokenFeatures("all");
setupSMTP();
setAllowedDomains();
});
it("should validate approved email domains for a question alert", () => {
visitQuestion(ORDERS_QUESTION_ID);
cy.icon("bell").click();
cy.button("Set up an alert").click();
cy.findByRole("heading", { name: "Email" })
.closest("li")
.within(() => {
addEmailRecipient(deniedEmail);
cy.findByText(alertError);
});
cy.button("Done").should("be.disabled");
});
it("should validate approved email domains for a dashboard subscription (metabase#17977)", () => {
visitDashboard(ORDERS_DASHBOARD_ID);
cy.icon("subscription").click();
cy.findByRole("heading", { name: "Email it" }).click();
sidebar().within(() => {
addEmailRecipient(deniedEmail);
// Reproduces metabase#17977
cy.button("Send email now").should("be.disabled");
cy.button("Done").should("be.disabled");
cy.findByText(subscriptionError);
});
});
},
);
function addEmailRecipient(email) {
cy.findByRole("textbox").click().type(`${email}`).blur();
}
function setAllowedDomains() {
cy.request("PUT", "/api/setting/subscription-allowed-domains", {
value: allowedDomain,
});
}
import {
restore,
downloadAndAssert,
runNativeQuery,
} from "e2e/support/helpers";
const testCases = ["csv", "xlsx"];
describe("issue 10803", () => {
beforeEach(() => {
cy.intercept("POST", "/api/dataset").as("dataset");
restore();
cy.signInAsAdmin();
cy.createNativeQuestion(
{
name: "10803",
native: {
query:
"SELECT cast(parsedatetime('2026-06-03', 'yyyy-MM-dd') AS timestamp) AS \"birth_date\", cast(parsedatetime('2026-06-03 23:41:23', 'yyyy-MM-dd HH:mm:ss') AS timestamp) AS \"created_at\"",
},
},
{ visitQuestion: true, wrapId: true },
);
});
testCases.forEach(fileType => {
it(`should format the date properly for ${fileType} in saved questions (metabase#10803)`, () => {
cy.get("@questionId").then(questionId => {
downloadAndAssert(
{ fileType, questionId, logResults: true, raw: true },
testWorkbookDatetimes,
);
});
});
it(`should format the date properly for ${fileType} in unsaved questions`, () => {
// Add a space at the end of the query to make it "dirty"
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.contains(/open editor/i).click();
cy.get(".ace_editor").type("{movetoend} ");
runNativeQuery();
downloadAndAssert({ fileType, raw: true }, testWorkbookDatetimes);
});
function testWorkbookDatetimes(sheet) {
expect(sheet["A1"].v).to.eq("birth_date");
expect(sheet["B1"].v).to.eq("created_at");
// Excel and CSV will have different formats
if (fileType === "csv") {
expect(sheet["A2"].v).to.eq("June 3, 2026, 12:00 AM");
expect(sheet["B2"].v).to.eq("June 3, 2026, 11:41 PM");
} else if (fileType === "xlsx") {
// We tell the xlsx library to read raw and not parse dates
// So for the _date_ format we expect an integer
// And for timestamp, we expect a float
expect(sheet["A2"].v).to.eq(46176);
expect(sheet["B2"].v).to.eq(46176.98707175926);
}
}
});
});
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
import { restore, downloadAndAssert, visitQuestion } from "e2e/support/helpers";
const { ORDERS, ORDERS_ID } = SAMPLE_DATABASE;
const questionDetails = {
name: "18219",
query: {
"source-table": ORDERS_ID,
aggregation: [["count"]],
breakout: [["field", ORDERS.CREATED_AT, { "temporal-unit": "year" }]],
},
};
const testCases = ["csv", "xlsx"];
describe.skip("issue 18219", () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
});
testCases.forEach(fileType => {
it("should format temporal units on export (metabase#18219)", () => {
cy.createQuestion(questionDetails).then(
({ body: { id: questionId } }) => {
visitQuestion(questionId);
cy.findByText("Created At: Year");
cy.findByText("2022");
cy.findByText("744");
downloadAndAssert({ fileType, questionId, raw: true }, assertion);
},
);
});
function assertion(sheet) {
expect(sheet["A1"].v).to.eq("Created At: Year");
if (fileType === "csv") {
expect(sheet["A2"].v).to.eq("2022");
}
if (fileType === "xlsx") {
/**
* Depending on how we end up solving this issue,
* the following assertion on the cell type might not be correct.
* It's very likely we'll format temporal breakouts as strings.
* I.e. we have to take into account Q1, Q2, etc.
*/
// expect(A2.t).to.eq("n");
/**
* Because of the excel date format, we cannot assert on the raw value `v`.
* Rather, we have to do it on the parsed value `w`.
*/
expect(sheet["A2"].w).to.eq("2022");
}
}
});
});
import { SAMPLE_DB_ID } from "e2e/support/cypress_data";
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
import {
restore,
visitQuestionAdhoc,
downloadAndAssert,
} from "e2e/support/helpers";
const { REVIEWS, REVIEWS_ID, PRODUCTS, PRODUCTS_ID } = SAMPLE_DATABASE;
/**
* This question might seem a bit overwhelming at the first sight.
* The whole point of this repro was to try to cover as much of the old syntax as possible.
* We want to make sure it still works when loaded into a new(er) Metabase version.
*/
const questionDetails = {
dataset_query: {
database: SAMPLE_DB_ID,
type: "query",
query: {
"source-table": REVIEWS_ID,
joins: [
{
fields: [["joined-field", "Products", ["field-id", PRODUCTS.TITLE]]],
"source-table": PRODUCTS_ID,
condition: [
"=",
["field-id", REVIEWS.PRODUCT_ID],
["joined-field", "Products", ["field-id", PRODUCTS.ID]],
],
alias: "Products",
},
],
filter: ["and", ["=", ["field-id", REVIEWS.RATING], 4]],
"order-by": [
["asc", ["joined-field", "Products", ["field-id", PRODUCTS.TITLE]]],
],
fields: [
["field-id", REVIEWS.ID],
["field-id", REVIEWS.REVIEWER],
],
limit: 5,
},
},
display: "table",
visualization_settings: {
column_settings: {
[`["ref",["field",${REVIEWS.ID},null]]`]: {
column_title: "MOD:ID",
},
[`["ref",["field",${REVIEWS.REVIEWER},null]]`]: {
column_title: "MOD:Reviewer",
},
[`["ref",["field",${PRODUCTS.TITLE},null]]`]: {
column_title: "MOD:Title",
},
},
// Reorder columns
"table.columns": [
{
name: "TITLE",
fieldRef: ["joined-field", "Products", ["field-id", PRODUCTS.TITLE]],
enabled: true,
},
{
name: "ID",
fieldRef: ["field-id", REVIEWS.ID],
enabled: true,
},
{
name: "REVIEWER",
fieldRef: ["field-id", REVIEWS.REVIEWER],
enabled: true,
},
],
},
};
const testCases = ["csv", "xlsx"];
testCases.forEach(fileType => {
describe("issue 18382", () => {
beforeEach(() => {
// TODO: Please remove this line when issue gets fixed
cy.skipOn(fileType === "csv");
restore();
cy.signInAsAdmin();
visitQuestionAdhoc(questionDetails);
});
it(`should handle the old syntax in downloads for ${fileType} (metabase#18382)`, () => {
downloadAndAssert({ fileType }, assertion);
});
});
});
function assertion(sheet) {
expect(sheet["A1"].v).to.eq("MOD:Title");
expect(sheet["B1"].v).to.eq("MOD:ID");
expect(sheet["C1"].v).to.eq("MOD:Reviewer");
expect(sheet["A2"].v).to.eq("Aerodynamic Concrete Bench");
}
import { SAMPLE_DB_ID } from "e2e/support/cypress_data";
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
import {
restore,
visitQuestionAdhoc,
downloadAndAssert,
visitQuestion,
} from "e2e/support/helpers";
const { ORDERS, ORDERS_ID, PRODUCTS } = SAMPLE_DATABASE;
const query = { "source-table": ORDERS_ID, limit: 5 };
const questionDetails = {
dataset_query: {
type: "query",
query,
database: SAMPLE_DB_ID,
},
};
const testCases = ["csv", "xlsx"];
describe("issue 18440", () => {
beforeEach(() => {
cy.intercept("POST", "/api/card").as("saveQuestion");
restore();
cy.signInAsAdmin();
// Remap Product ID -> Product Title
cy.request("POST", `/api/field/${ORDERS.PRODUCT_ID}/dimension`, {
name: "Product ID",
type: "external",
human_readable_field_id: PRODUCTS.TITLE,
});
});
testCases.forEach(fileType => {
it(`export should include a column with remapped values for ${fileType} (metabase#18440-1)`, () => {
visitQuestionAdhoc(questionDetails);
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Product ID");
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Awesome Concrete Shoes");
downloadAndAssert({ fileType }, assertion);
});
it(`export should include a column with remapped values for ${fileType} for a saved question (metabase#18440-2)`, () => {
cy.createQuestion({ query }).then(({ body: { id } }) => {
visitQuestion(id);
cy.findByText("Product ID");
cy.findByText("Awesome Concrete Shoes");
downloadAndAssert({ fileType, questionId: id }, assertion);
});
});
});
});
function assertion(sheet) {
expect(sheet["C1"].v).to.eq("Product ID");
expect(sheet["C2"].v).to.eq("Awesome Concrete Shoes");
}
import { SAMPLE_DB_ID } from "e2e/support/cypress_data";
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
import {
restore,
visitQuestionAdhoc,
downloadAndAssert,
} from "e2e/support/helpers";
const { ORDERS, ORDERS_ID, PRODUCTS } = SAMPLE_DATABASE;
const questionDetails = {
dataset_query: {
type: "query",
query: { "source-table": ORDERS_ID, limit: 2 },
database: SAMPLE_DB_ID,
},
visualization_settings: {
column_settings: {
[`["ref",["field",${ORDERS.PRODUCT_ID},null]]`]: {
column_title: "Foo",
},
},
},
};
describe("issue 18573", () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
// Remap Product ID -> Product Title
cy.request("POST", `/api/field/${ORDERS.PRODUCT_ID}/dimension`, {
name: "Product ID",
type: "external",
human_readable_field_id: PRODUCTS.TITLE,
});
});
it("for the remapped columns, it should preserve renamed column name in exports for xlsx (metabase#18573)", () => {
visitQuestionAdhoc(questionDetails);
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Foo");
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Awesome Concrete Shoes");
downloadAndAssert({ fileType: "xlsx" }, assertion);
});
});
function assertion(sheet) {
expect(sheet["C1"].v).to.eq("Foo");
expect(sheet["C2"].v).to.eq("Awesome Concrete Shoes");
}
import { SAMPLE_DB_ID } from "e2e/support/cypress_data";
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
import {
restore,
downloadAndAssert,
visitQuestionAdhoc,
} from "e2e/support/helpers";
const { ORDERS, ORDERS_ID, PRODUCTS } = SAMPLE_DATABASE;
const questionDetails = {
dataset_query: {
database: SAMPLE_DB_ID,
query: {
"source-table": ORDERS_ID,
aggregation: [["count"]],
breakout: [
["field", ORDERS.CREATED_AT, { "temporal-unit": "month-of-year" }],
["field", PRODUCTS.CATEGORY, { "source-field": ORDERS.PRODUCT_ID }],
],
limit: 2,
},
type: "query",
},
display: "line",
};
describe("issue 18729", () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
});
["csv", "xlsx"].forEach(fileType => {
it(`should properly format the 'X of Y'dates in ${fileType} exports (metabase#18729)`, () => {
visitQuestionAdhoc(questionDetails);
downloadAndAssert({ fileType }, assertion);
});
});
});
function assertion(sheet) {
// It currently says only "Created At", but that is already covered in an issue #18219.
// TODO: When 18219 gets fixed, uncomment the following assertion and delete the `contain` one.
// expect(sheet["A1"].v).to.eq("Created At: Month of year");
expect(sheet["A1"].v).to.contain("Created At");
// Based on how this issue gets resolved, the following assertions might need to change!
expect(sheet["A2"].v).to.eq(1);
expect(sheet["A2"].t).to.eq("n");
// Parsed values are always in the form of a string
expect(sheet["A2"].w).to.eq("1");
}
import { restore, downloadAndAssert, visitQuestion } from "e2e/support/helpers";
const questionDetails = {
name: "19889",
native: {
query: 'select 1 "column a", 2 "column b", 3 "column c"',
},
};
const testCases = ["csv", "xlsx"];
describe("issue 19889", () => {
beforeEach(() => {
cy.intercept("POST", "/api/dataset").as("dataset");
restore();
cy.signInAsAdmin();
cy.createNativeQuestion(questionDetails, {
loadMetadata: true,
wrapId: true,
});
// Reorder columns a and b
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("column a").trigger("mousedown", 0, 0).wait(100); //Don't force the first interaction. This ensures things are actually visible to start moving
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("column a")
.trigger("mousemove", 10, 10, { force: true })
.wait(100);
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("column a")
.trigger("mousemove", 100, 0, { force: true })
.wait(100);
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("column a")
.trigger("mouseup", 100, 0, { force: true })
.wait(100);
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Started from").click(); // Give DOM some time to update
});
testCases.forEach(fileType => {
it("should order columns correctly in unsaved native query exports", () => {
downloadAndAssert({ fileType, raw: true }, sheet => {
expect(sheet["A1"].v).to.equal("column b");
expect(sheet["B1"].v).to.equal("column a");
expect(sheet["C1"].v).to.equal("column c");
});
});
it("should order columns correctly in saved native query exports", () => {
saveAndOverwrite();
cy.get("@questionId").then(questionId => {
downloadAndAssert({ fileType, questionId, raw: true }, sheet => {
expect(sheet["A1"].v).to.equal("column b");
expect(sheet["B1"].v).to.equal("column a");
expect(sheet["C1"].v).to.equal("column c");
});
});
});
it("should order columns correctly in saved native query exports when the query was modified but not re-run before save (#19889)", () => {
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.contains(/open editor/i).click();
cy.get(".ace_editor").type(
'{selectall}select 1 "column x", 2 "column y", 3 "column c"',
);
saveAndOverwrite();
cy.get("@questionId").then(questionId => {
visitQuestion(questionId);
downloadAndAssert({ fileType, questionId, raw: true }, sheet => {
expect(sheet["A1"].v).to.equal("column x");
expect(sheet["B1"].v).to.equal("column y");
expect(sheet["C1"].v).to.equal("column c");
});
});
});
});
});
function saveAndOverwrite() {
cy.findByText("Save").click();
cy.findByTestId("save-question-modal").within(modal => {
cy.findByText("Save").click();
});
}
import { restore, downloadAndAssert } from "e2e/support/helpers";
const questionDetails = {
name: "28834",
native: {
query: 'select 1 "column a"',
},
};
describe("metabase#28834", () => {
// I have a test for saved native questions in `QueryBuilder.unit.spec.tsx`.
// Initially, this test was planned as a unit test, but with some technical
// difficulties, I've decided to test with Cypress instead.
beforeEach(() => {
cy.intercept("POST", "/api/dataset").as("dataset");
restore();
cy.signInAsAdmin();
cy.createNativeQuestion(questionDetails, {
loadMetadata: true,
wrapId: true,
});
cy.findByTestId("query-builder-main").findByText("Open Editor").click();
cy.get(".ace_editor").should("be.visible").type(', select 2 "column b"');
});
it("should be able to export unsaved native query results as CSV even after the query has changed", () => {
const fileType = "csv";
downloadAndAssert({ fileType, raw: true }, sheet => {
expect(sheet["A1"].v).to.equal("column a");
expect(sheet["A2"].v).to.equal("1");
expect(sheet["A3"]).to.be.undefined;
});
});
it("should be able to export unsaved native query results as XLSX even after the query has changed", () => {
const fileType = "xlsx";
downloadAndAssert({ fileType, raw: true }, sheet => {
expect(sheet["A1"].v).to.equal("column a");
expect(sheet["A2"].v).to.equal(1);
expect(sheet["A3"]).to.be.undefined;
});
});
});
import { SAMPLE_DB_ID } from "e2e/support/cypress_data";
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
import {
restore,
downloadAndAssert,
runNativeQuery,
visitQuestion,
visitQuestionAdhoc,
} from "e2e/support/helpers";
const { ORDERS, ORDERS_ID, REVIEWS, REVIEWS_ID, PRODUCTS, PRODUCTS_ID } =
SAMPLE_DATABASE;
describe("issue 10803", () => {
const testCases = ["csv", "xlsx"];
beforeEach(() => {
cy.intercept("POST", "/api/dataset").as("dataset");
restore();
cy.signInAsAdmin();
cy.createNativeQuestion(
{
name: "10803",
native: {
query:
"SELECT cast(parsedatetime('2026-06-03', 'yyyy-MM-dd') AS timestamp) AS \"birth_date\", cast(parsedatetime('2026-06-03 23:41:23', 'yyyy-MM-dd HH:mm:ss') AS timestamp) AS \"created_at\"",
},
},
{ visitQuestion: true, wrapId: true },
);
});
testCases.forEach(fileType => {
it(`should format the date properly for ${fileType} in saved questions (metabase#10803)`, () => {
cy.get("@questionId").then(questionId => {
downloadAndAssert(
{ fileType, questionId, logResults: true, raw: true },
testWorkbookDatetimes,
);
});
});
it(`should format the date properly for ${fileType} in unsaved questions`, () => {
// Add a space at the end of the query to make it "dirty"
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.contains(/open editor/i).click();
cy.get(".ace_editor").type("{movetoend} ");
runNativeQuery();
downloadAndAssert({ fileType, raw: true }, testWorkbookDatetimes);
});
function testWorkbookDatetimes(sheet) {
expect(sheet["A1"].v).to.eq("birth_date");
expect(sheet["B1"].v).to.eq("created_at");
// Excel and CSV will have different formats
if (fileType === "csv") {
expect(sheet["A2"].v).to.eq("June 3, 2026, 12:00 AM");
expect(sheet["B2"].v).to.eq("June 3, 2026, 11:41 PM");
} else if (fileType === "xlsx") {
// We tell the xlsx library to read raw and not parse dates
// So for the _date_ format we expect an integer
// And for timestamp, we expect a float
expect(sheet["A2"].v).to.eq(46176);
expect(sheet["B2"].v).to.eq(46176.98707175926);
}
}
});
});
describe.skip("issue 18219", () => {
const questionDetails = {
name: "18219",
query: {
"source-table": ORDERS_ID,
aggregation: [["count"]],
breakout: [["field", ORDERS.CREATED_AT, { "temporal-unit": "year" }]],
},
};
const testCases = ["csv", "xlsx"];
beforeEach(() => {
restore();
cy.signInAsAdmin();
});
testCases.forEach(fileType => {
it("should format temporal units on export (metabase#18219)", () => {
cy.createQuestion(questionDetails).then(
({ body: { id: questionId } }) => {
visitQuestion(questionId);
cy.findByText("Created At: Year");
cy.findByText("2022");
cy.findByText("744");
downloadAndAssert({ fileType, questionId, raw: true }, assertion);
},
);
});
function assertion(sheet) {
expect(sheet["A1"].v).to.eq("Created At: Year");
if (fileType === "csv") {
expect(sheet["A2"].v).to.eq("2022");
}
if (fileType === "xlsx") {
/**
* Depending on how we end up solving this issue,
* the following assertion on the cell type might not be correct.
* It's very likely we'll format temporal breakouts as strings.
* I.e. we have to take into account Q1, Q2, etc.
*/
// expect(A2.t).to.eq("n");
/**
* Because of the excel date format, we cannot assert on the raw value `v`.
* Rather, we have to do it on the parsed value `w`.
*/
expect(sheet["A2"].w).to.eq("2022");
}
}
});
});
describe("issue 18382", () => {
/**
* This question might seem a bit overwhelming at the first sight.
* The whole point of this repro was to try to cover as much of the old syntax as possible.
* We want to make sure it still works when loaded into a new(er) Metabase version.
*/
function assertion(sheet) {
expect(sheet["A1"].v).to.eq("MOD:Title");
expect(sheet["B1"].v).to.eq("MOD:ID");
expect(sheet["C1"].v).to.eq("MOD:Reviewer");
expect(sheet["A2"].v).to.eq("Aerodynamic Concrete Bench");
}
const questionDetails = {
dataset_query: {
database: SAMPLE_DB_ID,
type: "query",
query: {
"source-table": REVIEWS_ID,
joins: [
{
fields: [
["joined-field", "Products", ["field-id", PRODUCTS.TITLE]],
],
"source-table": PRODUCTS_ID,
condition: [
"=",
["field-id", REVIEWS.PRODUCT_ID],
["joined-field", "Products", ["field-id", PRODUCTS.ID]],
],
alias: "Products",
},
],
filter: ["and", ["=", ["field-id", REVIEWS.RATING], 4]],
"order-by": [
["asc", ["joined-field", "Products", ["field-id", PRODUCTS.TITLE]]],
],
fields: [
["field-id", REVIEWS.ID],
["field-id", REVIEWS.REVIEWER],
],
limit: 5,
},
},
display: "table",
visualization_settings: {
column_settings: {
[`["ref",["field",${REVIEWS.ID},null]]`]: {
column_title: "MOD:ID",
},
[`["ref",["field",${REVIEWS.REVIEWER},null]]`]: {
column_title: "MOD:Reviewer",
},
[`["ref",["field",${PRODUCTS.TITLE},null]]`]: {
column_title: "MOD:Title",
},
},
// Reorder columns
"table.columns": [
{
name: "TITLE",
fieldRef: ["joined-field", "Products", ["field-id", PRODUCTS.TITLE]],
enabled: true,
},
{
name: "ID",
fieldRef: ["field-id", REVIEWS.ID],
enabled: true,
},
{
name: "REVIEWER",
fieldRef: ["field-id", REVIEWS.REVIEWER],
enabled: true,
},
],
},
};
const testCases = ["csv", "xlsx"];
beforeEach(() => {
restore();
cy.signInAsAdmin();
visitQuestionAdhoc(questionDetails);
});
testCases.forEach(fileType => {
it(`should handle the old syntax in downloads for ${fileType} (metabase#18382)`, () => {
// TODO: Please remove this line when issue gets fixed
cy.skipOn(fileType === "csv");
downloadAndAssert({ fileType }, assertion);
});
});
});
describe("issue 18440", () => {
const query = { "source-table": ORDERS_ID, limit: 5 };
const questionDetails = {
dataset_query: {
type: "query",
query,
database: SAMPLE_DB_ID,
},
};
const testCases = ["csv", "xlsx"];
function assertion(sheet) {
expect(sheet["C1"].v).to.eq("Product ID");
expect(sheet["C2"].v).to.eq("Awesome Concrete Shoes");
}
beforeEach(() => {
cy.intercept("POST", "/api/card").as("saveQuestion");
restore();
cy.signInAsAdmin();
// Remap Product ID -> Product Title
cy.request("POST", `/api/field/${ORDERS.PRODUCT_ID}/dimension`, {
name: "Product ID",
type: "external",
human_readable_field_id: PRODUCTS.TITLE,
});
});
testCases.forEach(fileType => {
it(`export should include a column with remapped values for ${fileType} (metabase#18440-1)`, () => {
visitQuestionAdhoc(questionDetails);
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Product ID");
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Awesome Concrete Shoes");
downloadAndAssert({ fileType }, assertion);
});
it(`export should include a column with remapped values for ${fileType} for a saved question (metabase#18440-2)`, () => {
cy.createQuestion({ query }).then(({ body: { id } }) => {
visitQuestion(id);
cy.findByText("Product ID");
cy.findByText("Awesome Concrete Shoes");
downloadAndAssert({ fileType, questionId: id }, assertion);
});
});
});
});
describe("issue 18573", () => {
const questionDetails = {
dataset_query: {
type: "query",
query: { "source-table": ORDERS_ID, limit: 2 },
database: SAMPLE_DB_ID,
},
visualization_settings: {
column_settings: {
[`["ref",["field",${ORDERS.PRODUCT_ID},null]]`]: {
column_title: "Foo",
},
},
},
};
function assertion(sheet) {
expect(sheet["C1"].v).to.eq("Foo");
expect(sheet["C2"].v).to.eq("Awesome Concrete Shoes");
}
beforeEach(() => {
restore();
cy.signInAsAdmin();
// Remap Product ID -> Product Title
cy.request("POST", `/api/field/${ORDERS.PRODUCT_ID}/dimension`, {
name: "Product ID",
type: "external",
human_readable_field_id: PRODUCTS.TITLE,
});
});
it("for the remapped columns, it should preserve renamed column name in exports for xlsx (metabase#18573)", () => {
visitQuestionAdhoc(questionDetails);
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Foo");
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Awesome Concrete Shoes");
downloadAndAssert({ fileType: "xlsx" }, assertion);
});
});
describe("issue 18729", () => {
const questionDetails = {
dataset_query: {
database: SAMPLE_DB_ID,
query: {
"source-table": ORDERS_ID,
aggregation: [["count"]],
breakout: [
["field", ORDERS.CREATED_AT, { "temporal-unit": "month-of-year" }],
["field", PRODUCTS.CATEGORY, { "source-field": ORDERS.PRODUCT_ID }],
],
limit: 2,
},
type: "query",
},
display: "line",
};
function assertion(sheet) {
// It currently says only "Created At", but that is already covered in an issue #18219.
// TODO: When 18219 gets fixed, uncomment the following assertion and delete the `contain` one.
// expect(sheet["A1"].v).to.eq("Created At: Month of year");
expect(sheet["A1"].v).to.contain("Created At");
// Based on how this issue gets resolved, the following assertions might need to change!
expect(sheet["A2"].v).to.eq(1);
expect(sheet["A2"].t).to.eq("n");
// Parsed values are always in the form of a string
expect(sheet["A2"].w).to.eq("1");
}
beforeEach(() => {
restore();
cy.signInAsAdmin();
});
["csv", "xlsx"].forEach(fileType => {
it(`should properly format the 'X of Y'dates in ${fileType} exports (metabase#18729)`, () => {
visitQuestionAdhoc(questionDetails);
downloadAndAssert({ fileType }, assertion);
});
});
});
describe("issue 19889", () => {
const questionDetails = {
name: "19889",
native: {
query: 'select 1 "column a", 2 "column b", 3 "column c"',
},
};
const testCases = ["csv", "xlsx"];
function saveAndOverwrite() {
cy.findByText("Save").click();
cy.findByTestId("save-question-modal").within(modal => {
cy.findByText("Save").click();
});
}
beforeEach(() => {
cy.intercept("POST", "/api/dataset").as("dataset");
restore();
cy.signInAsAdmin();
cy.createNativeQuestion(questionDetails, {
loadMetadata: true,
wrapId: true,
});
// Reorder columns a and b
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("column a").trigger("mousedown", 0, 0).wait(100); //Don't force the first interaction. This ensures things are actually visible to start moving
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("column a")
.trigger("mousemove", 10, 10, { force: true })
.wait(100);
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("column a")
.trigger("mousemove", 100, 0, { force: true })
.wait(100);
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("column a")
.trigger("mouseup", 100, 0, { force: true })
.wait(100);
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Started from").click(); // Give DOM some time to update
});
testCases.forEach(fileType => {
it("should order columns correctly in unsaved native query exports", () => {
downloadAndAssert({ fileType, raw: true }, sheet => {
expect(sheet["A1"].v).to.equal("column b");
expect(sheet["B1"].v).to.equal("column a");
expect(sheet["C1"].v).to.equal("column c");
});
});
it("should order columns correctly in saved native query exports", () => {
saveAndOverwrite();
cy.get("@questionId").then(questionId => {
downloadAndAssert({ fileType, questionId, raw: true }, sheet => {
expect(sheet["A1"].v).to.equal("column b");
expect(sheet["B1"].v).to.equal("column a");
expect(sheet["C1"].v).to.equal("column c");
});
});
});
it("should order columns correctly in saved native query exports when the query was modified but not re-run before save (#19889)", () => {
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.contains(/open editor/i).click();
cy.get(".ace_editor").type(
'{selectall}select 1 "column x", 2 "column y", 3 "column c"',
);
saveAndOverwrite();
cy.get("@questionId").then(questionId => {
visitQuestion(questionId);
downloadAndAssert({ fileType, questionId, raw: true }, sheet => {
expect(sheet["A1"].v).to.equal("column x");
expect(sheet["B1"].v).to.equal("column y");
expect(sheet["C1"].v).to.equal("column c");
});
});
});
});
});
describe("metabase#28834", () => {
const questionDetails = {
name: "28834",
native: {
query: 'select 1 "column a"',
},
};
// I have a test for saved native questions in `QueryBuilder.unit.spec.tsx`.
// Initially, this test was planned as a unit test, but with some technical
// difficulties, I've decided to test with Cypress instead.
beforeEach(() => {
cy.intercept("POST", "/api/dataset").as("dataset");
restore();
cy.signInAsAdmin();
cy.createNativeQuestion(questionDetails, {
loadMetadata: true,
wrapId: true,
});
cy.findByTestId("query-builder-main").findByText("Open Editor").click();
cy.get(".ace_editor").should("be.visible").type(', select 2 "column b"');
});
it("should be able to export unsaved native query results as CSV even after the query has changed", () => {
const fileType = "csv";
downloadAndAssert({ fileType, raw: true }, sheet => {
expect(sheet["A1"].v).to.equal("column a");
expect(sheet["A2"].v).to.equal("1");
expect(sheet["A3"]).to.be.undefined;
});
});
it("should be able to export unsaved native query results as XLSX even after the query has changed", () => {
const fileType = "xlsx";
downloadAndAssert({ fileType, raw: true }, sheet => {
expect(sheet["A1"].v).to.equal("column a");
expect(sheet["A2"].v).to.equal(1);
expect(sheet["A3"]).to.be.undefined;
});
});
});
import { SAMPLE_DB_ID } from "e2e/support/cypress_data";
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
import {
ORDERS_QUESTION_ID,
ORDERS_DASHBOARD_ID,
} from "e2e/support/cypress_sample_instance_data";
import {
restore,
modal,
setActionsEnabledForDB,
createAction,
visitDashboardAndCreateTab,
describeEE,
setupSMTP,
sidebar,
visitQuestion,
visitDashboard,
setTokenFeatures,
} from "e2e/support/helpers";
const { ORDERS_ID } = SAMPLE_DATABASE;
......@@ -267,3 +277,64 @@ describe("scenarios > admin > settings > public sharing", () => {
);
});
});
describeEE(
"scenarios > sharing > approved domains (EE)",
{ tags: "@external" },
() => {
const allowedDomain = "metabase.test";
const deniedDomain = "metabase.example";
const deniedEmail = `mailer@${deniedDomain}`;
const subscriptionError = `You're only allowed to email subscriptions to addresses ending in ${allowedDomain}`;
const alertError = `You're only allowed to email alerts to addresses ending in ${allowedDomain}`;
function addEmailRecipient(email) {
cy.findByRole("textbox").click().type(`${email}`).blur();
}
function setAllowedDomains() {
cy.request("PUT", "/api/setting/subscription-allowed-domains", {
value: allowedDomain,
});
}
beforeEach(() => {
restore();
cy.signInAsAdmin();
setTokenFeatures("all");
setupSMTP();
setAllowedDomains();
});
it("should validate approved email domains for a question alert", () => {
visitQuestion(ORDERS_QUESTION_ID);
cy.icon("bell").click();
cy.button("Set up an alert").click();
cy.findByRole("heading", { name: "Email" })
.closest("li")
.within(() => {
addEmailRecipient(deniedEmail);
cy.findByText(alertError);
});
cy.button("Done").should("be.disabled");
});
it("should validate approved email domains for a dashboard subscription (metabase#17977)", () => {
visitDashboard(ORDERS_DASHBOARD_ID);
cy.icon("subscription").click();
cy.findByRole("heading", { name: "Email it" }).click();
sidebar().within(() => {
addEmailRecipient(deniedEmail);
// Reproduces metabase#17977
cy.button("Send email now").should("be.disabled");
cy.button("Done").should("be.disabled");
cy.findByText(subscriptionError);
});
});
},
);
import { USERS } from "e2e/support/cypress_data";
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
import {
ADMIN_USER_ID,
ORDERS_DASHBOARD_DASHCARD_ID,
ORDERS_DASHBOARD_ID,
ORDERS_QUESTION_ID,
} from "e2e/support/cypress_sample_instance_data";
import {
restore,
setupSMTP,
visitDashboard,
getFullName,
sidebar,
popover,
visitQuestion,
} from "e2e/support/helpers";
const { ORDERS, ORDERS_ID, PEOPLE } = SAMPLE_DATABASE;
const { admin } = USERS;
const { first_name, last_name } = admin;
describe("issue 17657", () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
createSubscriptionWithoutRecipients();
});
it("frontend should gracefully handle the case of a subscription without a recipient (metabase#17657)", () => {
visitDashboard(ORDERS_DASHBOARD_ID);
cy.icon("subscription").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText(/^Emailed monthly/).click();
sidebar().within(() => {
cy.button("Done").should("be.disabled");
});
// Open the popover with all users
cy.findByPlaceholderText("Enter user names or email addresses").click();
// Pick admin as a recipient
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText(`${first_name} ${last_name}`).click();
sidebar().within(() => {
cy.button("Done").should("not.be.disabled");
});
});
});
function createSubscriptionWithoutRecipients() {
cy.request("POST", "/api/pulse", {
name: "Orders in a dashboard",
cards: [
{
id: ORDERS_QUESTION_ID,
collection_id: null,
description: null,
display: "table",
name: "Orders",
include_csv: false,
include_xls: false,
dashboard_card_id: 1,
dashboard_id: ORDERS_DASHBOARD_ID,
parameter_mappings: [],
},
],
channels: [
{
channel_type: "email",
enabled: true,
// Since the fix (https://github.com/metabase/metabase/pull/17668), this is not even possible to do in the UI anymore.
// Backend still doesn't do this validation so we're making sure the FE handles the case of missing recipients gracefully.
recipients: [],
details: {},
schedule_type: "monthly",
schedule_day: "mon",
schedule_hour: 8,
schedule_frame: "first",
},
],
skip_if_empty: false,
collection_id: null,
parameters: [],
dashboard_id: ORDERS_DASHBOARD_ID,
});
}
describe("issue 17658", { tags: "@external" }, () => {
beforeEach(() => {
cy.intercept("PUT", "/api/pulse/*").as("deletePulse");
restore();
cy.signInAsAdmin();
setupSMTP();
moveDashboardToCollection("First collection");
});
it("should delete dashboard subscription from any collection (metabase#17658)", () => {
visitDashboard(ORDERS_DASHBOARD_ID);
cy.icon("subscription").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText(/^Emailed monthly/).click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Delete this subscription").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText(/^This dashboard will no longer be emailed to/).click();
cy.button("Delete").click();
cy.wait("@deletePulse").then(({ response }) => {
expect(response.body.cause).not.to.exist;
expect(response.statusCode).not.to.eq(500);
});
cy.button("Delete").should("not.exist");
});
});
function moveDashboardToCollection(collectionName) {
const { first_name, last_name, email } = admin;
cy.request("GET", "/api/collection/tree?tree=true").then(
({ body: collections }) => {
const { id } = collections.find(
collection => collection.name === collectionName,
);
// Move dashboard
cy.request("PUT", `/api/dashboard/${ORDERS_DASHBOARD_ID}`, {
collection_id: id,
});
// Create subscription
cy.request("POST", "/api/pulse", {
name: "Orders in a dashboard",
cards: [
{
id: ORDERS_QUESTION_ID,
collection_id: null,
description: null,
display: "table",
name: "Orders",
include_csv: false,
include_xls: false,
dashboard_card_id: ORDERS_DASHBOARD_DASHCARD_ID,
dashboard_id: ORDERS_DASHBOARD_ID,
parameter_mappings: [],
},
],
channels: [
{
channel_type: "email",
enabled: true,
recipients: [
{
id: ADMIN_USER_ID,
email,
first_name,
last_name,
common_name: getFullName(admin),
},
],
details: {},
schedule_type: "monthly",
schedule_day: "mon",
schedule_hour: 8,
schedule_frame: "first",
},
],
skip_if_empty: false,
collection_id: id,
parameters: [],
dashboard_id: ORDERS_DASHBOARD_ID,
});
},
);
}
describe("issue 17547", () => {
const questionDetails = {
query: {
"source-table": ORDERS_ID,
breakout: [
["field", ORDERS.CREATED_AT, { "temporal-unit": "month" }],
["field", PEOPLE.SOURCE, { "source-field": ORDERS.USER_ID }],
],
aggregation: [["count"]],
},
display: "area",
};
beforeEach(() => {
restore();
cy.signInAsAdmin();
cy.createQuestion(questionDetails).then(({ body: { id: questionId } }) => {
setUpAlert(questionId);
visitQuestion(questionId);
});
});
it("editing an alert should not delete it (metabase#17547)", () => {
cy.icon("bell").click();
popover().within(() => {
cy.findByText("Daily, 12:00 PM");
cy.findByText("Edit").click();
});
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("AM").click();
cy.button("Save changes").click();
cy.wait("@alertQuery");
cy.icon("bell").click();
popover().within(() => {
cy.findByText("Daily, 12:00 AM");
});
});
});
function setUpAlert(questionId) {
cy.request("POST", "/api/alert", {
channels: [
{
schedule_type: "daily",
schedule_hour: 12,
channel_type: "slack",
schedule_frame: null,
recipients: [],
details: { channel: "#work" },
pulse_id: 1,
id: 1,
schedule_day: null,
enabled: true,
},
],
alert_condition: "rows",
name: null,
creator_id: ADMIN_USER_ID,
card: { id: questionId, include_csv: true, include_xls: false },
alert_first_only: false,
skip_if_empty: true,
parameters: [],
dashboard_id: null,
}).then(({ body: { id: alertId } }) => {
cy.intercept("PUT", `/api/alert/${alertId}`).as("alertQuery");
});
}
describe("issue 16108", () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
});
it("should display a tooltip for CTA icons on an individual question (metabase#16108)", () => {
visitQuestion(ORDERS_QUESTION_ID);
cy.icon("download").realHover();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Download full results");
cy.icon("bell").realHover();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Get alerts");
cy.icon("share").realHover();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Sharing");
});
});
import { ORDERS_DASHBOARD_ID } from "e2e/support/cypress_sample_instance_data";
import {
restore,
popover,
setupSMTP,
visitDashboard,
sendEmailAndAssert,
sidebar,
} from "e2e/support/helpers";
describe("issue 18009", { tags: "@external" }, () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
setupSMTP();
cy.signIn("nodata");
});
it("nodata user should be able to create and receive an email subscription without errors (metabase#18009)", () => {
visitDashboard(ORDERS_DASHBOARD_ID);
cy.findByLabelText("subscriptions").click();
sidebar()
.findByPlaceholderText("Enter user names or email addresses")
.click();
popover()
.contains(/^No Data/)
.click();
// Click anywhere to close the popover that covers the "Send email now" button
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("To:").click();
sendEmailAndAssert(email => {
expect(email.html).not.to.include(
"An error occurred while displaying this card.",
);
expect(email.html).to.include("37.65");
});
});
});
import { USERS } from "e2e/support/cypress_data";
import { ORDERS_DASHBOARD_ID } from "e2e/support/cypress_sample_instance_data";
import {
restore,
editDashboard,
saveDashboard,
setupSMTP,
visitDashboard,
sendEmailAndAssert,
modal,
} from "e2e/support/helpers";
const {
admin: { first_name, last_name },
} = USERS;
describe("issue 18344", { tags: "@external" }, () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
setupSMTP();
// Rename the question
visitDashboard(ORDERS_DASHBOARD_ID);
editDashboard();
// Open visualization options
cy.findByTestId("dashcard").realHover();
cy.icon("palette").click();
modal().within(() => {
cy.findByDisplayValue("Orders").type("Foo").blur();
cy.button("Done").click();
});
saveDashboard();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("OrdersFoo");
});
it("subscription should not include original question name when it's been renamed in the dashboard (metabase#18344)", () => {
// Send a test email subscription
cy.icon("subscription").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Email it").click();
cy.findByPlaceholderText("Enter user names or email addresses").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText(`${first_name} ${last_name}`).click();
// Click this just to close the popover that is blocking the "Send email now" button
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("To:").click();
sendEmailAndAssert(email => {
expect(email.html).to.include("OrdersFoo");
});
});
});
import { USERS } from "e2e/support/cypress_data";
import {
restore,
setupSMTP,
visitQuestion,
visitDashboard,
sendEmailAndAssert,
} from "e2e/support/helpers";
const {
admin: { first_name, last_name },
} = USERS;
const questionDetails = {
name: "18352",
native: {
query: "SELECT 'foo', 1 UNION ALL SELECT 'bar', 2",
},
};
describe("issue 18352", { tags: "@external" }, () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
setupSMTP();
cy.createNativeQuestionAndDashboard({ questionDetails }).then(
({ body: { card_id, dashboard_id } }) => {
visitQuestion(card_id);
visitDashboard(dashboard_id);
},
);
});
it("should send the card with the INT64 values (metabase#18352)", () => {
cy.icon("subscription").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Email it").click();
cy.findByPlaceholderText("Enter user names or email addresses").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText(`${first_name} ${last_name}`).click();
// Click this just to close the popover that is blocking the "Send email now" button
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("To:").click();
sendEmailAndAssert(({ html }) => {
expect(html).not.to.include(
"An error occurred while displaying this card.",
);
expect(html).to.include("foo");
expect(html).to.include("bar");
});
});
});
import { USERS, SAMPLE_DB_ID } from "e2e/support/cypress_data";
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
import {
describeEE,
popover,
restore,
setupSMTP,
sidebar,
visitDashboard,
clickSend,
setTokenFeatures,
} from "e2e/support/helpers";
const { admin } = USERS;
const { PRODUCTS_ID, PRODUCTS } = SAMPLE_DATABASE;
describeEE("issue 18669", { tags: "@external" }, () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
setTokenFeatures("all");
setupSMTP();
cy.createQuestionAndDashboard({ questionDetails, dashboardDetails }).then(
({ body: card }) => {
cy.editDashboardCard(card, getFilterMapping(card));
visitDashboard(card.dashboard_id);
},
);
});
it("should send a test email with non-default parameters (metabase#18669)", () => {
cy.icon("subscription").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Email it").click();
cy.findByPlaceholderText("Enter user names or email addresses")
.click()
.type(`${admin.first_name} ${admin.last_name}{enter}`)
.blur();
sidebar().within(() => {
cy.findByText("Doohickey").click();
});
popover().within(() => {
cy.findByText("Gizmo").click();
cy.button("Update filter").click();
});
clickSend();
});
});
const questionDetails = {
name: "Product count",
database: SAMPLE_DB_ID,
type: "query",
query: {
"source-table": PRODUCTS_ID,
aggregation: [["count"]],
},
};
const filterDetails = {
name: "Category",
slug: "category",
id: "c32a49e1",
type: "category",
default: ["Doohickey"],
};
const dashboardDetails = {
parameters: [filterDetails],
};
const getFilterMapping = card => ({
parameter_mappings: [
{
parameter_id: filterDetails.id,
card_id: card.card_id,
target: ["dimension", ["field", PRODUCTS.CATEGORY, null]],
},
],
});
import {
restore,
popover,
visitDashboard,
editDashboard,
setFilter,
openNewPublicLinkDropdown,
} from "e2e/support/helpers";
describe("issue 20393", () => {
beforeEach(() => {
cy.intercept("POST", "/api/dashboard/*/public_link").as("publicLink");
restore();
cy.signInAsAdmin();
});
it("should show public dashboards with nested cards mapped to parameters (metabase#20393)", () => {
createDashboardWithNestedCard();
editDashboard();
setFilter("Time", "All Options");
// map the date parameter to the card
cy.findByTestId("dashcard-container").contains("Select").click();
popover().contains("CREATED_AT").click();
// save the dashboard
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Save").click();
// open the sharing modal and enable sharing
openNewPublicLinkDropdown("dashboard");
// navigate to the public dashboard link
cy.wait("@publicLink").then(({ response: { body } }) => {
const { uuid } = body;
cy.signOut();
cy.visit(`/public/dashboard/${uuid}`);
});
// verify that the card is visible on the page
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Q2");
});
});
function createDashboardWithNestedCard() {
cy.createNativeQuestion({
name: "Q1",
native: { query: 'SELECT * FROM "ORDERS"', "template-tags": {} },
}).then(({ body }) =>
cy
.createQuestionAndDashboard({
questionDetails: {
name: "Q2",
query: { "source-table": `card__${body.id}` },
},
dashboardDetails: {
name: "Q2 in a dashboard",
},
})
.then(({ body: { dashboard_id } }) => visitDashboard(dashboard_id)),
);
}
import { USERS } from "e2e/support/cypress_data";
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
import {
restore,
visitDashboard,
editDashboard,
saveDashboard,
setupSMTP,
sendEmailAndAssert,
chartPathWithFillColor,
} from "e2e/support/helpers";
const { admin } = USERS;
const { ORDERS, ORDERS_ID, PRODUCTS, PRODUCTS_ID } = SAMPLE_DATABASE;
const q1Details = {
name: "21559-1",
query: {
"source-table": ORDERS_ID,
aggregation: [["avg", ["field", ORDERS.TOTAL, null]]],
},
display: "scalar",
};
const q2Details = {
name: "21559-2",
query: {
"source-table": PRODUCTS_ID,
aggregation: [["avg", ["field", PRODUCTS.PRICE, null]]],
},
display: "scalar",
};
describe("issue 21559", { tags: "@external" }, () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
setupSMTP();
cy.createQuestionAndDashboard({
questionDetails: q1Details,
}).then(({ body: { dashboard_id } }) => {
cy.createQuestion(q2Details);
visitDashboard(dashboard_id);
editDashboard();
});
});
it("should respect dashboard card visualization (metabase#21559)", () => {
cy.findByTestId("add-series-button").click({ force: true });
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText(q2Details.name).click();
cy.findByTestId("add-series-modal").button("Done").click();
// Make sure visualization changed to bars
chartPathWithFillColor("#A989C5").should("have.length", 1);
chartPathWithFillColor("#88BF4D").should("have.length", 1);
saveDashboard();
cy.icon("subscription").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Email it").click();
cy.findByPlaceholderText("Enter user names or email addresses")
.click()
.type(`${admin.first_name} ${admin.last_name}{enter}`)
.blur(); // blur is needed to close the popover
sendEmailAndAssert(email => {
expect(email.html).to.include("img"); // Bar chart is sent as img (inline attachment)
expect(email.html).not.to.include("80.52"); // Scalar displays its value in HTML
});
});
});
import {
restore,
popover,
visitDashboard,
saveDashboard,
editDashboard,
setFilter,
openNewPublicLinkDropdown,
} from "e2e/support/helpers";
const questionDetails = {
name: "22524 question",
native: {
query: "select * from people where city = {{city}}",
"template-tags": {
city: {
id: "6d077d39-a420-fd14-0b0b-a5eb611ce1e0",
name: "city",
"display-name": "City",
type: "text",
},
},
},
};
describe("issue 22524", () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
});
it("update dashboard cards when changing parameters on publicly shared dashboards (metabase#22524)", () => {
cy.createNativeQuestionAndDashboard({ questionDetails }).then(
({ body: { dashboard_id } }) => {
cy.intercept("POST", `/api/dashboard/${dashboard_id}/public_link`).as(
"publicLink",
);
visitDashboard(dashboard_id);
},
);
editDashboard();
setFilter("Text or Category", "Is");
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Select…").click();
popover().contains("City").click();
saveDashboard();
// Share dashboard
openNewPublicLinkDropdown("dashboard");
cy.wait("@publicLink").then(({ response: { body } }) => {
const { uuid } = body;
cy.signOut();
cy.visit(`/public/dashboard/${uuid}`);
});
// Set parameter value
cy.findByPlaceholderText("Text").clear().type("Rye{enter}");
// Check results
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("2-7900 Cuerno Verde Road");
});
});
import { USERS } from "e2e/support/cypress_data";
import { ORDERS_DASHBOARD_ID } from "e2e/support/cypress_sample_instance_data";
import {
describeEE,
editDashboard,
popover,
restore,
saveDashboard,
sendEmailAndVisitIt,
setTokenFeatures,
setupSMTP,
setFilter,
} from "e2e/support/helpers";
const { admin } = USERS;
describeEE("issue 24223", () => {
beforeEach(() => {
restore();
cy.signInAsAdmin();
setTokenFeatures("all");
setupSMTP();
});
it("should clear default filter", () => {
cy.visit(`/dashboard/${ORDERS_DASHBOARD_ID}`);
addParametersToDashboard();
cy.findByLabelText("subscriptions").click();
// eslint-disable-next-line no-unscoped-text-selectors -- deprecated usage
cy.findByText("Email it").click();
cy.findByPlaceholderText("Enter user names or email addresses")
.click()
.type(`${admin.first_name} ${admin.last_name}{enter}`)
.blur(); // blur is needed to close the popover
cy.wait(500); // we need to wait here for some reason for CI to pass
cy.findAllByText("Doohickey")
.last()
.closest("fieldset")
.icon("close")
.click();
cy.button("Done").click();
cy.get("[aria-label='Pulse Card']")
.findByText("Text contains is Awesome")
.click();
sendEmailAndVisitIt();
cy.get("table.header").within(() => {
cy.findByText("Text").should("not.exist");
cy.findByText("Awesome").parent().findByText("Text contains");
});
});
});
function addParametersToDashboard() {
editDashboard();
setFilter("Text or Category", "Is");
cy.findByText("Select…").click();
popover().findByText("Category").click();
cy.findByText("No default").click();
popover().within(() => {
cy.findByText("Doohickey").click();
cy.button("Add filter").click();
});
setFilter("Text or Category", "Contains", "Text contains");
cy.findByText("Select…").click();
popover().findByText("Title").click();
cy.findByText("No default").click();
popover().find("input").type("Awesome");
popover().button("Add filter").click();
saveDashboard();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment