Files
metabase/e2e/test/scenarios/sharing/public-question.cy.spec.js
Chris Vandoodewaard 519834f9ee Consolidate sharing e2e tests (#83657)
* 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>
2026-10-06 17:39:59 -04:00

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);
});
};