* Remove duplicate public sharing e2e tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Merge sharing reproductions e2e tests that share setup Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Merge downloads e2e tests that share setup Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Merge public sharing e2e tests that share setup Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Repair downloads e2e tests that cannot fail Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Repair sharing reproductions e2e tests that cannot fail Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Drop unused setup in sharing reproductions e2e tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Remove duplicate subscriptions e2e tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Repair public sharing e2e tests that cannot fail Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Drop unused setup in downloads e2e tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Drop unused setup in public sharing e2e tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Remove duplicate alert e2e tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Merge alert e2e tests that share setup Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Repair alert e2e tests that cannot fail Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Drop unused setup in alert e2e tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Remove duplicate public sharing e2e tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Merge subscriptions e2e tests that share setup Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Repair subscriptions e2e tests that cannot fail Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Drop unused setup in subscriptions e2e tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Fold public dashboard link creation e2e test into 20393 repro Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fold 30314 subscription cancel e2e test into 14117 test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Fold 16108 tooltip e2e test into download format test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Merge public sharing e2e tests that share setup Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Place merged 18352 card below the Orders card Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Type a name before Escape in the 24629 subscriptions e2e test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Repair public sharing e2e tests that cannot fail Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Tag sharing e2e tests that need maildev as external Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Drop unused setup in public sharing e2e tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Fix popover check after Escape in dashboard downloads e2e test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Keep the webhook channel in the 12349 alert e2e test Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Tighten subscriptions e2e checks found in parity review Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Tighten sharing reproductions e2e checks found in parity review Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Restore admin and UI-created link coverage in public sharing e2e tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011Jc2P2sKm39MghfKPxCSiv * Fix 7 sharing e2e failures from CI * Restore 48402 coverage and merge more sharing e2e tests - Restore the metabase#48402 delete-alert step in the 12349 test and check the delete modal - Make 18669 check the email filter value and 21559 check the card image - Merge public dashboard download flag tests with the real downloads - Merge static-viz, branding, and default-filter subscription tests - Merge dashboard PDF and PNG download tests and check download parameters - Merge the two background=false public dashboard tests Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Address review on sharing e2e consolidation Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Fix sharing e2e CI failures Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
239 lines
7.1 KiB
JavaScript
239 lines
7.1 KiB
JavaScript
const { H } = cy;
|
|
|
|
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
|
|
|
|
const { PEOPLE, ORDERS_ID } = SAMPLE_DATABASE;
|
|
|
|
const questionData = {
|
|
name: "Parameterized Public Question",
|
|
native: {
|
|
query: "SELECT * FROM PEOPLE WHERE {{birthdate}} AND {{source}} limit 5",
|
|
"template-tags": {
|
|
birthdate: {
|
|
id: "08c5ea9d-1579-3503-37f1-cbe4d29e6a28",
|
|
name: "birthdate",
|
|
"display-name": "Birthdate",
|
|
type: "dimension",
|
|
dimension: ["field", PEOPLE.BIRTH_DATE, null],
|
|
"widget-type": "date/all-options",
|
|
default: "past30years",
|
|
},
|
|
source: {
|
|
id: "37eb6fa2-3677-91d3-6be0-c5dd9113c672",
|
|
name: "source",
|
|
"display-name": "Source",
|
|
type: "dimension",
|
|
dimension: ["field", PEOPLE.SOURCE, null],
|
|
"widget-type": "string/=",
|
|
default: "Affiliate",
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
const PUBLIC_QUESTION_REGEX =
|
|
/\/public\/question\/[0-9a-fA-F]{8}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{4}\b-[0-9a-fA-F]{12}$/;
|
|
|
|
const USERS = {
|
|
"admin user": () => cy.signInAsAdmin(),
|
|
"user with no permissions": () => cy.signIn("none"),
|
|
};
|
|
|
|
describe("scenarios > public > question", () => {
|
|
beforeEach(() => {
|
|
cy.intercept("GET", "/api/public/card/*/query?*").as("publicQuery");
|
|
|
|
H.restore();
|
|
cy.signInAsAdmin();
|
|
});
|
|
|
|
it("adds filters to url as get params and renders the results correctly (metabase#7120, metabase#17033, metabase#21993)", () => {
|
|
H.createNativeQuestion(questionData).then(({ body: { id } }) => {
|
|
H.visitQuestion(id);
|
|
|
|
// Make sure metadata fully loaded before we continue
|
|
cy.findByTestId("visualization-root").should("be.visible");
|
|
|
|
H.openNewPublicLinkDropdown("card");
|
|
|
|
// Although we already have API helper `visitPublicQuestion`,
|
|
// it makes sense to use the UI here in order to check that the
|
|
// generated url originally doesn't include query params
|
|
visitPublicURL();
|
|
|
|
// On page load, query params are added
|
|
cy.location("search").should("include", "source=Affiliate");
|
|
cy.location("search").should("include", "birthdate=past30years");
|
|
|
|
H.filterWidget().contains("Previous 30 years");
|
|
H.filterWidget().contains("Affiliate");
|
|
|
|
cy.wait("@publicQuery");
|
|
|
|
cy.findAllByTestId("cell-data").should("contain.text", "Affiliate");
|
|
|
|
// Make sure we can download the public question (metabase#21993)
|
|
cy.get("@uuid").then((publicUuid) => {
|
|
H.main().realHover();
|
|
|
|
H.downloadAndAssert({ fileType: "xlsx", questionId: id, publicUuid });
|
|
});
|
|
});
|
|
});
|
|
|
|
Object.entries(USERS).map(([userType, setUser]) =>
|
|
describe(`${userType}`, () => {
|
|
it("should be able to view public questions", () => {
|
|
H.createNativeQuestion(questionData).then(({ body: { id } }) => {
|
|
cy.request("POST", `/api/card/${id}/public_link`).then(
|
|
({ body: { uuid } }) => {
|
|
setUser();
|
|
cy.visit(`/public/question/${uuid}`);
|
|
|
|
cy.location("search").should("include", "source=Affiliate");
|
|
cy.location("search").should("include", "birthdate=past30years");
|
|
|
|
H.filterWidget().contains("Previous 30 years");
|
|
H.filterWidget().contains("Affiliate");
|
|
|
|
cy.findByTestId("visualization-root").should("be.visible");
|
|
},
|
|
);
|
|
});
|
|
});
|
|
}),
|
|
);
|
|
|
|
it("should be able to view public questions with snippets and card template tags", () => {
|
|
H.createNativeQuestion({
|
|
name: "Nested Question",
|
|
native: {
|
|
query: "SELECT * FROM PEOPLE LIMIT 5",
|
|
},
|
|
}).then(({ body: { id: nestedQuestionId } }) => {
|
|
H.startNewNativeQuestion({ display: "table" });
|
|
|
|
// Create a snippet
|
|
cy.icon("snippet").click();
|
|
cy.findByTestId("sidebar-content").findByText("Create snippet").click();
|
|
|
|
H.modal().within(() => {
|
|
cy.findByLabelText(
|
|
"Enter some SQL here so you can reuse it later",
|
|
).type("'test'");
|
|
cy.findByLabelText("Give your snippet a name").type("string 'test'");
|
|
cy.findByText("Save").click();
|
|
});
|
|
|
|
H.NativeEditor.type("{moveToStart}select ");
|
|
H.NativeEditor.type(`{moveToEnd}, * from {{#${nestedQuestionId}`);
|
|
|
|
H.saveQuestion(
|
|
"test question",
|
|
{ wrapId: true },
|
|
{
|
|
path: ["Our analytics"],
|
|
},
|
|
);
|
|
});
|
|
|
|
cy.get("@questionId").then((id) => {
|
|
H.createPublicQuestionLink(id).then(({ body: { uuid } }) => {
|
|
cy.signOut();
|
|
cy.signInAsNormalUser().then(() => {
|
|
cy.visit(`/public/question/${uuid}`);
|
|
cy.get("[data-testid=cell-data]").contains("test");
|
|
// Check the name of the first person in the PEOPLE table
|
|
cy.get("[data-testid=cell-data]").contains("Hudson Borer");
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
it("should support #theme=dark (metabase#65731)", () => {
|
|
const questionName = "Orders Theme Test";
|
|
H.createQuestion({
|
|
name: questionName,
|
|
query: {
|
|
"source-table": ORDERS_ID,
|
|
},
|
|
}).then(({ body: { id } }) => {
|
|
H.visitPublicQuestion(id, {
|
|
hash: {
|
|
theme: "dark",
|
|
},
|
|
});
|
|
});
|
|
|
|
cy.log("dark theme should have white text");
|
|
cy.findByRole("heading", {
|
|
name: questionName,
|
|
}).should("have.css", "color", "rgba(255, 255, 255, 0.95)");
|
|
});
|
|
});
|
|
|
|
describe("scenarios [EE] > public > question", () => {
|
|
beforeEach(() => {
|
|
cy.intercept("GET", "/api/public/card/*/query?*").as("publicQuery");
|
|
|
|
H.restore();
|
|
cy.signInAsAdmin();
|
|
H.activateToken("pro-self-hosted");
|
|
});
|
|
|
|
it("should allow to set locale from the `#locale` hash parameter (metabase#50182)", () => {
|
|
H.createNativeQuestion(
|
|
{
|
|
name: "Native question with a parameter",
|
|
native: {
|
|
query:
|
|
"select '2025-2-11'::DATE as date, {{some_parameter}} as some_parameter ",
|
|
"template-tags": {
|
|
some_parameter: {
|
|
type: "text",
|
|
name: "some_parameter",
|
|
id: "1e0806a0-155b-4e24-80bc-c050720201d0",
|
|
"display-name": "Some Parameter",
|
|
default: "some default value",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{ wrapId: true },
|
|
);
|
|
|
|
// We don't have a de-CH.json file, so it should fallback to de.json, see metabase#51039 for more details
|
|
cy.intercept("GET", "**/locale-de-json*.js").as("deLocale");
|
|
|
|
cy.get("@questionId").then((id) => {
|
|
H.visitPublicQuestion(id, {
|
|
params: {
|
|
some_parameter: "some_value",
|
|
},
|
|
hash: {
|
|
locale: "de-CH",
|
|
},
|
|
});
|
|
});
|
|
|
|
cy.wait("@deLocale");
|
|
|
|
H.main().findByText("Februar 11, 2025");
|
|
|
|
cy.url().should("include", "locale=de");
|
|
});
|
|
});
|
|
|
|
const visitPublicURL = () => {
|
|
cy.findByTestId("public-link-input").should(($input) => {
|
|
// Copied URL has no get params
|
|
expect($input.val()).to.match(PUBLIC_QUESTION_REGEX);
|
|
});
|
|
cy.findByTestId("public-link-input")
|
|
.invoke("val")
|
|
.then((publicURL) => {
|
|
cy.signOut();
|
|
cy.visit(publicURL);
|
|
});
|
|
};
|