* 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>
308 lines
8.7 KiB
TypeScript
308 lines
8.7 KiB
TypeScript
const { H } = cy;
|
|
import {
|
|
ORDERS_BY_YEAR_QUESTION_ID,
|
|
ORDERS_DASHBOARD_DASHCARD_ID,
|
|
ORDERS_DASHBOARD_ID,
|
|
} from "e2e/support/cypress_sample_instance_data";
|
|
|
|
/** These tests are about the `downloads` flag for public dashboards and questions.
|
|
* Unless the product changes, these should test the same things as `embed-resource-downloads.cy.spec.ts`
|
|
*/
|
|
|
|
describe("Public dashboards/questions downloads (results and pdf)", () => {
|
|
beforeEach(() => {
|
|
H.resetSnowplow();
|
|
cy.deleteDownloadsFolder();
|
|
});
|
|
|
|
describe("Public dashboards", () => {
|
|
let publicLink: string;
|
|
|
|
before(() => {
|
|
H.restore("default");
|
|
cy.signInAsAdmin();
|
|
H.activateToken("pro-self-hosted");
|
|
|
|
cy.visit(`/dashboard/${ORDERS_DASHBOARD_ID}`);
|
|
|
|
H.openSharingMenu("Create a public link");
|
|
|
|
H.popover()
|
|
.findByTestId("public-link-input")
|
|
.should("contain.value", "/public/")
|
|
.invoke("val")
|
|
.then((url) => {
|
|
// Unjustified type cast. FIXME
|
|
publicLink = url as string;
|
|
});
|
|
|
|
cy.signOut();
|
|
});
|
|
|
|
afterEach(() => {
|
|
H.expectNoBadSnowplowEvents();
|
|
});
|
|
|
|
it("#downloads=false should disable both PDF downloads and dashcard results downloads", () => {
|
|
cy.visit(`${publicLink}#downloads=false`);
|
|
waitLoading();
|
|
|
|
cy.findByRole("heading", { name: "Orders in a dashboard" }).should(
|
|
"be.visible",
|
|
);
|
|
H.getDashboardCard()
|
|
.findAllByTestId("cell-data")
|
|
.should("have.length.above", 0);
|
|
|
|
cy.findByRole("button", { name: "Download as PDF" }).should("not.exist");
|
|
|
|
// we should not have any dashcard action in a public/embed scenario, so the menu should not be there
|
|
H.getEmbeddedDashboardCardMenu().should("not.exist");
|
|
});
|
|
|
|
it("#downloads=pdf should enable only PDF downloads and allow downloading a public dashboard as PDF", () => {
|
|
cy.visit(`${publicLink}#downloads=pdf`);
|
|
waitLoading();
|
|
|
|
cy.get("header")
|
|
.findByRole("button", { name: "Download as PDF" })
|
|
.should("exist");
|
|
H.getDashboardCard()
|
|
.findAllByTestId("cell-data")
|
|
.should("have.length.above", 0);
|
|
H.getEmbeddedDashboardCardMenu().should("not.exist");
|
|
|
|
cy.get("header")
|
|
.findByRole("button", { name: "Download as PDF" })
|
|
.click();
|
|
|
|
cy.verifyDownload("Orders in a dashboard.pdf");
|
|
|
|
H.expectUnstructuredSnowplowEvent({
|
|
event: "dashboard_pdf_exported",
|
|
dashboard_id: 0,
|
|
dashboard_accessed_via: "public-link",
|
|
});
|
|
});
|
|
|
|
it("should enable both downloads by default, allow downloading a public dashcard as CSV, and #downloads=results should enable only dashcard results downloads", () => {
|
|
cy.visit(publicLink);
|
|
waitLoading();
|
|
|
|
cy.get("header")
|
|
.findByRole("button", { name: "Download as PDF" })
|
|
.should("exist");
|
|
|
|
const uuid = publicLink.split("/").at(-1);
|
|
|
|
H.downloadAndAssert({
|
|
publicUuid: uuid,
|
|
fileType: "csv",
|
|
questionId: ORDERS_BY_YEAR_QUESTION_ID,
|
|
isDashboard: true,
|
|
isEmbed: true,
|
|
dashcardId: ORDERS_DASHBOARD_DASHCARD_ID,
|
|
});
|
|
|
|
H.expectUnstructuredSnowplowEvent({
|
|
event: "download_results_clicked",
|
|
resource_type: "dashcard",
|
|
accessed_via: "public-link",
|
|
export_type: "csv",
|
|
});
|
|
|
|
cy.visit(`${publicLink}#downloads=results`);
|
|
cy.reload();
|
|
waitLoading();
|
|
|
|
H.getDashboardCard()
|
|
.findAllByTestId("cell-data")
|
|
.should("have.length.above", 0);
|
|
cy.get("header")
|
|
.findByRole("button", { name: "Download as PDF" })
|
|
.should("not.exist");
|
|
|
|
H.main().realHover();
|
|
H.getEmbeddedDashboardCardMenu().click();
|
|
cy.findByLabelText("Download results").should("be.visible");
|
|
});
|
|
|
|
it("#downloads=results, pdf should handle whitespace between parameters", () => {
|
|
cy.visit(`${publicLink}#downloads=results, pdf`);
|
|
waitLoading();
|
|
|
|
cy.get("header")
|
|
.findByRole("button", { name: "Download as PDF" })
|
|
.should("exist");
|
|
|
|
H.main().realHover();
|
|
H.getEmbeddedDashboardCardMenu().click();
|
|
cy.findByLabelText("Download results").should("be.visible");
|
|
});
|
|
});
|
|
|
|
describe("Public questions", () => {
|
|
let publicLink: string;
|
|
|
|
before(() => {
|
|
H.restore("default");
|
|
cy.signInAsAdmin();
|
|
H.activateToken("pro-self-hosted");
|
|
|
|
cy.visit(`/question/${ORDERS_BY_YEAR_QUESTION_ID}`);
|
|
|
|
H.openSharingMenu("Create a public link");
|
|
|
|
H.popover()
|
|
.findByTestId("public-link-input")
|
|
.should("contain.value", "/public/")
|
|
.invoke("val")
|
|
.then((url) => {
|
|
// Unjustified type cast. FIXME
|
|
publicLink = url as string;
|
|
});
|
|
|
|
cy.signOut();
|
|
});
|
|
|
|
it("#downloads=false should disable result downloads", () => {
|
|
cy.visit(`${publicLink}#downloads=false`);
|
|
waitLoading();
|
|
|
|
H.echartsContainer().should("be.visible");
|
|
H.main().realHover();
|
|
cy.findByRole("button", { name: "Download results" }).should("not.exist");
|
|
});
|
|
|
|
it("should be able to download the question as PNG", () => {
|
|
cy.visit(`${publicLink}`);
|
|
waitLoading();
|
|
|
|
cy.findByRole("button", { name: "Download results" }).click();
|
|
H.popover().within(() => {
|
|
cy.findByText(".png").click();
|
|
cy.findByTestId("download-results-button").click();
|
|
});
|
|
|
|
cy.verifyDownload(".png", { contains: true });
|
|
|
|
H.expectUnstructuredSnowplowEvent({
|
|
event: "download_results_clicked",
|
|
resource_type: "question",
|
|
accessed_via: "public-link",
|
|
export_type: "png",
|
|
});
|
|
});
|
|
|
|
it("#downloads=results should enable result downloads and allow downloading a public card as CSV", () => {
|
|
cy.visit(`${publicLink}#downloads=results`);
|
|
waitLoading();
|
|
|
|
H.main().realHover();
|
|
cy.findByLabelText("Download results").should("be.visible");
|
|
|
|
const uuid = publicLink.split("/").at(-1);
|
|
|
|
H.downloadAndAssert({
|
|
publicUuid: uuid,
|
|
fileType: "csv",
|
|
questionId: ORDERS_BY_YEAR_QUESTION_ID,
|
|
isDashboard: false,
|
|
isEmbed: true,
|
|
});
|
|
|
|
H.expectUnstructuredSnowplowEvent({
|
|
event: "download_results_clicked",
|
|
resource_type: "question",
|
|
accessed_via: "public-link",
|
|
export_type: "csv",
|
|
});
|
|
});
|
|
});
|
|
|
|
describe("Public questions with parameters", () => {
|
|
before(() => {
|
|
H.restore("default");
|
|
cy.signInAsAdmin();
|
|
H.activateToken("pro-self-hosted");
|
|
|
|
H.createNativeQuestion(
|
|
{
|
|
native: {
|
|
query: "SELECT * FROM orders WHERE TOTAL > {{ minimum }}",
|
|
|
|
"template-tags": {
|
|
minimum: {
|
|
id: "930e4001",
|
|
name: "minimum",
|
|
"display-name": "Minimum",
|
|
type: "number",
|
|
default: "10",
|
|
},
|
|
},
|
|
},
|
|
parameters: [
|
|
{
|
|
id: "930e4001",
|
|
slug: "minimum",
|
|
name: "minimum",
|
|
type: "number",
|
|
default: 10,
|
|
target: ["variable", ["template-tag", "minimum"]],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
visitQuestion: true,
|
|
},
|
|
);
|
|
|
|
H.openSharingMenu("Create a public link");
|
|
|
|
H.popover()
|
|
.findByTestId("public-link-input")
|
|
.should("contain.value", "/public/")
|
|
.invoke("val")
|
|
.then((url) => {
|
|
if (typeof url === "string") {
|
|
cy.signOut();
|
|
cy.visit(url);
|
|
}
|
|
});
|
|
});
|
|
|
|
it("should not pass all the parameters to the public link", () => {
|
|
waitLoading();
|
|
|
|
H.main().realHover();
|
|
cy.findByLabelText("Download results").should("be.visible");
|
|
|
|
cy.location("pathname").then((pathname) => {
|
|
const uuid = pathname.split("/").at(-1);
|
|
|
|
H.downloadAndAssert({
|
|
publicUuid: uuid,
|
|
fileType: "csv",
|
|
isDashboard: false,
|
|
isEmbed: true,
|
|
});
|
|
|
|
cy.get<{ request: Request }>("@fileDownload").then(({ request }) => {
|
|
const url = new URL(request.url);
|
|
const parameters = JSON.parse(
|
|
url.searchParams.get("parameters") ?? "[]",
|
|
);
|
|
|
|
cy.wrap(parameters).should("have.length", 1);
|
|
cy.wrap(parameters[0]).should("have.property", "id");
|
|
cy.wrap(parameters[0]).should("have.property", "value");
|
|
cy.wrap(parameters[0]).should("not.have.property", "type");
|
|
cy.wrap(parameters[0]).should("not.have.property", "target");
|
|
});
|
|
});
|
|
});
|
|
});
|
|
});
|
|
|
|
const waitLoading = () => H.main().findByText("Loading...").should("not.exist");
|