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

Add basic implicit actions e2e tests (#28476)

* add basic implicit action e2e tests

* DRY up the actions tests
parent 16f8a527
No related branches found
No related tags found
No related merge requests found
......@@ -304,6 +304,7 @@ class DashboardHeader extends Component {
<Tooltip key="add-action-button" tooltip={t`Add action button`}>
<DashboardHeaderButton
onClick={() => this.onAddAction()}
aria-label={t`Add action`}
data-metabase-event={`Dashboard;Add Action Button`}
>
<Icon name="click" size={18} />
......
import { capitalize } from "inflection";
import { SAMPLE_DB_ID } from "__support__/e2e/cypress_data";
export function enableActionsForDB(dbId = SAMPLE_DB_ID) {
return cy.request("PUT", `/api/database/${dbId}`, {
settings: {
......@@ -18,3 +18,31 @@ export function fillActionQuery(query) {
export function createAction(actionDetails) {
return cy.request("POST", "/api/action", actionDetails);
}
/**
* create a single implicit action of the given kind for the given model
*
* @param {Object} actionParams
* @param {"create" | "update" | "delete "} actionParams.kind
* @param {number} actionParams.model_id
*/
export function createImplicitAction({ model_id, kind }) {
return createAction({
kind: `row/${kind}`,
name: capitalize(kind),
type: "implicit",
model_id,
});
}
/**
* create all implicit actions for the given model
*
* @param {object} actionParams
* @param {number} actionParams.model_id
*/
export function createImplicitActions({ modelId }) {
createImplicitAction({ modelId, kind: "create" });
createImplicitAction({ modelId, kind: "update" });
createImplicitAction({ modelId, kind: "delete" });
}
......@@ -22,6 +22,7 @@ export function editDashboard() {
export function saveDashboard() {
cy.findByText("Save").click();
cy.findByText("You're editing this dashboard.").should("not.exist");
cy.wait(1); // this is stupid but necessary to due to the dashboard resizing and detaching elements
}
export function checkFilterLabelAndValue(label, value) {
......
......@@ -8,11 +8,19 @@ import {
visitDashboard,
editDashboard,
saveDashboard,
modal,
setFilter,
sidebar,
popover,
filterWidget,
createImplicitAction,
} from "__support__/e2e/helpers";
import { WRITABLE_DB_ID } from "__support__/e2e/cypress_data";
import { addWidgetStringFilter } from "../native-filters/helpers/e2e-field-filter-helpers";
const TEST_TABLE = "scoreboard_actions";
const MODEL_NAME = "Test Action Model";
["mysql", "postgres"].forEach(dialect => {
describe(
......@@ -26,6 +34,11 @@ const TEST_TABLE = "scoreboard_actions";
);
cy.intercept("GET", "/api/action?model-id=*").as("getActions");
cy.intercept(
"GET",
"/api/dashboard/*/dashcard/*/execute?parameters=*",
).as("executePrefetch");
cy.intercept("POST", "/api/dashboard/*/dashcard/*/execute").as(
"executeAPI",
);
......@@ -64,31 +77,43 @@ const TEST_TABLE = "scoreboard_actions";
cy.findByPlaceholderText("My new fantastic action").type("Add Zebras");
cy.findByText("Create").click();
cy.createDashboard({ name: `action packed dash` }).then(
({ body: { id: dashboardId } }) => {
visitDashboard(dashboardId);
},
);
createDashboardWithActionButton({
actionName: "Add Zebras",
});
cy.button("Add Zebras").click();
cy.wait("@executeAPI");
editDashboard();
cy.icon("click").click();
cy.get("aside").within(() => {
cy.button("Pick an action").click();
queryWritableDB(
`SELECT * FROM ${TEST_TABLE} WHERE team_name = 'Zany Zebras'`,
dialect,
).then(result => {
expect(result.rows.length).to.equal(1);
});
});
cy.findByRole("dialog").within(() => {
cy.findByText("Test Model").click();
cy.findByText("Add Zebras").click();
cy.button("Done").click();
it("adds an implicit create action to a dashboard and runs it", () => {
createModelFromTable(TEST_TABLE);
cy.get("@modelId").then(id => {
createImplicitAction({
kind: "create",
model_id: id,
});
});
createDashboardWithActionButton({
actionName: "Create",
});
saveDashboard();
cy.button("Create").click();
// this keeps the test from flaking because it's confused about the detached
// edit-mode button
cy.findByText(/^Edited a few seconds ago/).should("not.be.visible");
modal().within(() => {
cy.findByPlaceholderText("team_name").type("Zany Zebras");
cy.findByPlaceholderText("score").type("44");
cy.button("Click Me").click();
cy.button("Save").click();
});
cy.wait("@executeAPI");
......@@ -97,6 +122,97 @@ const TEST_TABLE = "scoreboard_actions";
dialect,
).then(result => {
expect(result.rows.length).to.equal(1);
expect(result.rows[0].score).to.equal(44);
});
});
it("adds an implicit update action to a dashboard and runs it", () => {
const actionName = "Update";
createModelFromTable(TEST_TABLE);
cy.get("@modelId").then(id => {
createImplicitAction({
kind: "update",
model_id: id,
});
});
createDashboardWithActionButton({
actionName,
idFilter: true,
});
filterWidget().click();
addWidgetStringFilter("5");
cy.button(actionName).click();
cy.wait("@executePrefetch");
// let's check that the existing values are pre-filled correctly
modal().within(() => {
cy.findByPlaceholderText("team_name")
.should("have.value", "Energetic Elephants")
.clear()
.type("Emotional Elephants");
cy.findByPlaceholderText("score")
.should("have.value", "30")
.clear()
.type("88");
cy.button("Update").click();
});
cy.wait("@executeAPI");
queryWritableDB(
`SELECT * FROM ${TEST_TABLE} WHERE team_name = 'Emotional Elephants'`,
dialect,
).then(result => {
expect(result.rows.length).to.equal(1);
expect(result.rows[0].score).to.equal(88);
});
});
it("adds an implicit delete action to a dashboard and runs it", () => {
queryWritableDB(
`SELECT * FROM ${TEST_TABLE} WHERE team_name = 'Cuddly Cats'`,
dialect,
).then(result => {
expect(result.rows.length).to.equal(1);
expect(result.rows[0].id).to.equal(3);
});
createModelFromTable(TEST_TABLE);
cy.get("@modelId").then(id => {
createImplicitAction({
kind: "delete",
model_id: id,
});
});
createDashboardWithActionButton({
actionName: "Delete",
});
cy.button("Delete").click();
modal().within(() => {
cy.findByPlaceholderText("id").type("3");
cy.button("Delete").click();
});
cy.wait("@executeAPI");
queryWritableDB(
`SELECT * FROM ${TEST_TABLE} WHERE team_name = 'Cuddly Cats'`,
dialect,
).then(result => {
expect(result.rows.length).to.equal(0);
});
});
},
......@@ -108,7 +224,7 @@ const createModelFromTable = tableName => {
cy.createQuestion(
{
database: WRITABLE_DB_ID,
name: "Test Model",
name: MODEL_NAME,
query: {
"source-table": tableId,
},
......@@ -121,3 +237,52 @@ const createModelFromTable = tableName => {
);
});
};
function createDashboardWithActionButton({
actionName,
modelName = MODEL_NAME,
idFilter = false,
}) {
cy.createDashboard({ name: "action packed dashboard" }).then(
({ body: { id: dashboardId } }) => {
visitDashboard(dashboardId);
},
);
editDashboard();
if (idFilter) {
setFilter("ID");
sidebar().within(() => {
cy.button("Done").click();
});
}
cy.button("Add action").click();
cy.get("aside").within(() => {
cy.findByPlaceholderText("Button text").clear().type(actionName);
cy.button("Pick an action").click();
});
cy.findByRole("dialog").within(() => {
cy.findByText(modelName).click();
cy.findByText(actionName).click();
});
if (idFilter) {
cy.findByRole("dialog").within(() => {
cy.findAllByText(/ask the user/i)
.first()
.click();
});
popover().within(() => {
cy.findByText("ID").click();
});
}
cy.findByRole("dialog").within(() => {
cy.button("Done").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