657 lines
21 KiB
JavaScript
657 lines
21 KiB
JavaScript
const { H } = cy;
|
|
import { SAMPLE_DATABASE } from "e2e/support/cypress_sample_database";
|
|
import {
|
|
ORDERS_BY_YEAR_QUESTION_ID,
|
|
ORDERS_COUNT_QUESTION_ID,
|
|
ORDERS_DASHBOARD_ID,
|
|
ORDERS_QUESTION_ID,
|
|
SECOND_COLLECTION_ID,
|
|
} from "e2e/support/cypress_sample_instance_data";
|
|
|
|
const { ORDERS, ORDERS_ID, PRODUCTS, PRODUCTS_ID } = SAMPLE_DATABASE;
|
|
|
|
describe("scenarios > question > saved", () => {
|
|
beforeEach(() => {
|
|
H.restore();
|
|
cy.signInAsNormalUser();
|
|
cy.intercept("POST", "api/card").as("cardCreate");
|
|
});
|
|
|
|
it("view and filter saved question", () => {
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
cy.findAllByText("Orders"); // question and table name appears
|
|
|
|
// capture the view header height in the saved state to assert it does not
|
|
// change after the question transitions to ad-hoc (UXW-3751)
|
|
let savedHeaderHeight;
|
|
cy.findByTestId("qb-header")
|
|
.invoke("outerHeight")
|
|
.then((h) => {
|
|
savedHeaderHeight = h;
|
|
});
|
|
|
|
// filter to only orders with quantity=100
|
|
H.tableHeaderClick("Quantity");
|
|
H.popover().findByText("Filter by this column").click();
|
|
H.selectFilterOperator("Equal to");
|
|
H.popover().within(() => {
|
|
cy.findByPlaceholderText("Search the list").type("100");
|
|
cy.findByText("100").click();
|
|
cy.findByText("Add filter").click();
|
|
});
|
|
// eslint-disable-next-line metabase/no-unscoped-text-selectors -- deprecated usage
|
|
cy.findByText("Quantity is equal to 100");
|
|
// eslint-disable-next-line metabase/no-unscoped-text-selectors -- deprecated usage
|
|
cy.findByText("Showing 2 rows"); // query updated
|
|
|
|
// view header height should be unchanged in the ad-hoc state
|
|
cy.findByTestId("qb-header")
|
|
.invoke("outerHeight")
|
|
.should((h) => {
|
|
expect(h).to.equal(savedHeaderHeight);
|
|
});
|
|
|
|
// check that save will give option to replace
|
|
// eslint-disable-next-line metabase/no-unscoped-text-selectors -- deprecated usage
|
|
cy.findByText("Save").click();
|
|
cy.findByTestId("save-question-modal").within(() => {
|
|
cy.findByText('Replace original question, "Orders"');
|
|
cy.findByText("Save as new question");
|
|
cy.findByText("Cancel").click();
|
|
});
|
|
|
|
// click "Started from Orders" and check that the original question is restored
|
|
// eslint-disable-next-line metabase/no-unscoped-text-selectors -- deprecated usage
|
|
cy.findByText("Started from").within(() => cy.findByText("Orders").click());
|
|
// eslint-disable-next-line metabase/no-unscoped-text-selectors -- deprecated usage
|
|
cy.findByText("Showing first 2,000 rows"); // query updated
|
|
// eslint-disable-next-line metabase/no-unscoped-text-selectors -- deprecated usage
|
|
cy.findByText("Started from").should("not.exist");
|
|
// eslint-disable-next-line metabase/no-unscoped-text-selectors -- deprecated usage
|
|
cy.findByText("Quantity is equal to 100").should("not.exist");
|
|
});
|
|
|
|
it("should duplicate a saved question into a collection", () => {
|
|
cy.intercept("POST", "/api/card").as("cardCreate");
|
|
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
|
|
H.openQuestionActions();
|
|
H.popover().within(() => {
|
|
cy.findByText("Duplicate").click();
|
|
});
|
|
|
|
H.modal().within(() => {
|
|
cy.findByLabelText("Name").should("have.value", "Orders - Duplicate");
|
|
cy.findByText("Duplicate").click();
|
|
cy.wait("@cardCreate");
|
|
});
|
|
|
|
cy.findByTestId("qb-header-left-side").within(() => {
|
|
cy.findByDisplayValue("Orders - Duplicate");
|
|
});
|
|
});
|
|
|
|
it("should duplicate a saved question into a dashboard", () => {
|
|
cy.intercept("POST", "/api/card").as("cardCreate");
|
|
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
|
|
H.openQuestionActions();
|
|
H.popover().within(() => {
|
|
cy.findByText("Duplicate").click();
|
|
});
|
|
|
|
H.modal().within(() => {
|
|
cy.findByLabelText("Name").should("have.value", "Orders - Duplicate");
|
|
cy.findByLabelText(/Where do you want to save this/).click();
|
|
});
|
|
|
|
H.entityPickerModal().within(() => {
|
|
cy.findByText("Select a collection or dashboard").should("exist");
|
|
cy.findByText("Orders in a dashboard").click();
|
|
cy.findByRole("button", { name: "Select this dashboard" }).click();
|
|
});
|
|
H.entityPickerModal().should("not.exist");
|
|
|
|
H.modal().within(() => {
|
|
cy.findByText("Duplicate").click();
|
|
cy.wait("@cardCreate");
|
|
});
|
|
|
|
cy.url().should("include", "/dashboard/");
|
|
cy.location("hash").should("not.include", "scrollTo");
|
|
H.dashboardCards().findByText("Orders - Duplicate").should("be.visible");
|
|
});
|
|
|
|
it("should duplicate a saved question to a collection created on the go", () => {
|
|
cy.intercept("POST", "/api/card").as("cardCreate");
|
|
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
|
|
H.openQuestionActions();
|
|
H.popover().within(() => {
|
|
cy.findByText("Duplicate").click();
|
|
});
|
|
|
|
H.modal().within(() => {
|
|
cy.findByLabelText("Name").should("have.value", "Orders - Duplicate");
|
|
cy.findByTestId("dashboard-and-collection-picker-button").click();
|
|
});
|
|
|
|
H.entityPickerModal().findByText("New collection").click();
|
|
|
|
const NEW_COLLECTION = "My New collection";
|
|
H.collectionOnTheGoModal().then(() => {
|
|
cy.findByPlaceholderText("My new collection").type(NEW_COLLECTION);
|
|
cy.findByText("Create").click();
|
|
});
|
|
|
|
H.entityPickerModal()
|
|
.button(/Select/)
|
|
.click();
|
|
|
|
H.modal().within(() => {
|
|
cy.findByLabelText("Name").should("have.value", "Orders - Duplicate");
|
|
cy.findByTestId("dashboard-and-collection-picker-button").should(
|
|
"have.text",
|
|
NEW_COLLECTION,
|
|
);
|
|
cy.button("Duplicate").click();
|
|
cy.wait("@cardCreate");
|
|
});
|
|
|
|
cy.findByTestId("qb-header-left-side").within(() => {
|
|
cy.findByDisplayValue("Orders - Duplicate");
|
|
});
|
|
|
|
cy.get("header").findByText(NEW_COLLECTION);
|
|
});
|
|
|
|
it("should not add scrollbar to duplicate modal if question name is long (metabase#53364)", () => {
|
|
H.createQuestion(
|
|
{
|
|
name: "A".repeat(240),
|
|
query: {
|
|
"source-table": ORDERS_ID,
|
|
},
|
|
},
|
|
{ visitQuestion: true },
|
|
);
|
|
H.openQuestionActions();
|
|
H.popover().findByText("Duplicate").click();
|
|
|
|
H.modal().should(($el) => {
|
|
const $modal = $el[0];
|
|
expect($modal.clientWidth).to.be.equal($modal.scrollWidth);
|
|
});
|
|
});
|
|
|
|
it("should revert a saved question to a previous version", () => {
|
|
cy.intercept("PUT", "/api/card/**").as("updateQuestion");
|
|
cy.intercept("POST", "/api/revision/revert").as("revertRevision");
|
|
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
H.questionInfoButton().click();
|
|
|
|
H.sidesheet().within(() => {
|
|
cy.findByPlaceholderText("Add description")
|
|
.type("This is a question")
|
|
.blur();
|
|
|
|
cy.wait("@updateQuestion");
|
|
|
|
cy.findByRole("tab", { name: "History" }).click();
|
|
cy.findByText(/added a description/i);
|
|
|
|
cy.findByTestId("question-revert-button").click();
|
|
// The revert mutation invalidates the revision list. On fetch
|
|
// (microtask resolution) clicking the History tab before that
|
|
// invalidation lands shows the pre-revert entries — the new
|
|
// "reverted to an earlier version" row is then never found within
|
|
// Cypress's default 4s. Wait for the revert request before
|
|
// re-entering History.
|
|
cy.wait("@revertRevision");
|
|
|
|
cy.findByRole("tab", { name: "History" }).click();
|
|
cy.findByText(/reverted to an earlier version/i);
|
|
cy.findByText(/This is a question/i).should("not.exist");
|
|
|
|
// Simulate a backend failure on revert and confirm we surface
|
|
// the error message as a toast (UXW-310).
|
|
cy.intercept("POST", "/api/revision/revert", {
|
|
statusCode: 500,
|
|
body: { message: "Cannot revert: missing card" },
|
|
}).as("failedRevert");
|
|
|
|
cy.findAllByTestId("question-revert-button").first().click();
|
|
cy.wait("@failedRevert");
|
|
});
|
|
|
|
H.undoToast().should("contain.text", "Cannot revert: missing card");
|
|
});
|
|
|
|
it("should show collection breadcrumbs for a saved question in the root collection", () => {
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
// eslint-disable-next-line metabase/no-unscoped-text-selectors -- deprecated usage
|
|
H.appBar().within(() => cy.findByText("Our analytics").click());
|
|
|
|
// eslint-disable-next-line metabase/no-unscoped-text-selectors -- deprecated usage
|
|
cy.findByText("Orders").should("be.visible");
|
|
});
|
|
|
|
it("should show collection breadcrumbs for a saved question in a non-root collection", () => {
|
|
cy.request("PUT", `/api/card/${ORDERS_QUESTION_ID}`, {
|
|
collection_id: SECOND_COLLECTION_ID,
|
|
});
|
|
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
// eslint-disable-next-line metabase/no-unscoped-text-selectors -- deprecated usage
|
|
H.appBar().within(() => cy.findByText("Second collection").click());
|
|
|
|
// eslint-disable-next-line metabase/no-unscoped-text-selectors -- deprecated usage
|
|
cy.findByText("Orders").should("be.visible");
|
|
});
|
|
|
|
it("should show dashboard breadcrumbs for a saved question in a dashboard", () => {
|
|
cy.request("PUT", `/api/card/${ORDERS_QUESTION_ID}`, {
|
|
dashboard_id: ORDERS_DASHBOARD_ID,
|
|
});
|
|
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
H.appBar().within(() => {
|
|
cy.findByText("Our analytics").should("exist");
|
|
cy.log("should be able to navigate to the parent dashboard");
|
|
cy.findByText("Orders in a dashboard").should("exist").click();
|
|
});
|
|
|
|
cy.log(
|
|
"should have dashboard info disappear when navigating away from question",
|
|
);
|
|
H.appBar().within(() => {
|
|
cy.findByText("Our analytics").should("exist");
|
|
cy.findByText("Orders in a dashboard").should("not.exist");
|
|
});
|
|
|
|
// eslint-disable-next-line metabase/no-unscoped-text-selectors -- deprecated usage
|
|
cy.findByText("Orders").should("be.visible");
|
|
});
|
|
|
|
it("should show the question lineage when a saved question is changed", () => {
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
|
|
H.summarize();
|
|
H.rightSidebar().within(() => {
|
|
cy.findByText("Quantity").click();
|
|
cy.button("Done").click();
|
|
});
|
|
|
|
H.appBar().within(() => {
|
|
cy.findByText("Started from").should("be.visible");
|
|
cy.findByText("Orders").click();
|
|
cy.findByText("Started from").should("not.exist");
|
|
});
|
|
});
|
|
|
|
it("'read-only' user should be able to resize column width (metabase#9772)", () => {
|
|
cy.signIn("readonly");
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
|
|
cy.findAllByTestId("header-cell")
|
|
.filter(":contains(Tax)")
|
|
.as("headerCell")
|
|
.should("be.visible")
|
|
.then(($cell) => {
|
|
cy.wrap($cell[0].getBoundingClientRect().width).as("originalWidth");
|
|
});
|
|
|
|
const moveX = 100;
|
|
|
|
// The TanStack resize handle re-renders while the grid measures itself, so a
|
|
// single drag is occasionally lost or only partially applied and the column
|
|
// never grows enough. Re-run the (idempotent, gte-checked) drag until the
|
|
// column has actually widened, turning a dropped drag into a non-event.
|
|
cy.get("@originalWidth").then((originalWidth) => {
|
|
const minWidth = originalWidth + moveX * 0.6;
|
|
|
|
const dragUntilResized = (attemptsLeft) => {
|
|
cy.findByTestId("resize-handle-TAX").trigger("mousedown", {
|
|
button: 0,
|
|
clientX: 0,
|
|
clientY: 0,
|
|
});
|
|
cy.get("body")
|
|
.trigger("mousemove", { clientX: moveX / 2, clientY: 0 })
|
|
.trigger("mousemove", { clientX: moveX, clientY: 0 })
|
|
.trigger("mouseup", { button: 0, clientX: moveX, clientY: 0 });
|
|
|
|
cy.get("@headerCell").then(($cell) => {
|
|
const width = $cell[0].getBoundingClientRect().width;
|
|
if (width < minWidth && attemptsLeft > 0) {
|
|
dragUntilResized(attemptsLeft - 1);
|
|
}
|
|
});
|
|
};
|
|
|
|
dragUntilResized(4);
|
|
|
|
cy.get("@headerCell").should(($cell) => {
|
|
expect($cell[0].getBoundingClientRect().width).to.be.gte(minWidth);
|
|
});
|
|
});
|
|
});
|
|
|
|
it("should always be possible to view the full title text of the saved question", () => {
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
cy.findByTestId("saved-question-header-title")
|
|
.as("savedQuestionTitle")
|
|
.should("be.visible")
|
|
.clear()
|
|
.type(
|
|
"Space, the final frontier. These are the voyages of the Starship Enterprise.",
|
|
)
|
|
.blur();
|
|
|
|
cy.get("@savedQuestionTitle")
|
|
.should("be.visible")
|
|
.should(($el) => {
|
|
// clientHeight: height of the textarea
|
|
// scrollHeight: height of the text content, including content not visible on the screen
|
|
const heightDifference = $el[0].clientHeight - $el[0].scrollHeight;
|
|
expect(heightDifference).to.eq(0);
|
|
});
|
|
});
|
|
|
|
it("should not show '- Modified' suffix after we click 'Save' on a new model (metabase#42773)", () => {
|
|
cy.log("Use UI to create a model based on the Products table");
|
|
cy.visit("/model/new");
|
|
cy.findByTestId("new-model-options")
|
|
.findByText("Use the notebook editor")
|
|
.click();
|
|
|
|
H.miniPicker().within(() => {
|
|
cy.findByText("Sample Database").click();
|
|
cy.findByText("Products").click();
|
|
});
|
|
|
|
cy.findByTestId("dataset-edit-bar").button("Save").click();
|
|
|
|
cy.findByTestId("save-question-modal").within(() => {
|
|
cy.button("Save").click();
|
|
cy.wait("@cardCreate");
|
|
// It is important to have extremely short timeout in order to catch the issue
|
|
cy.findByDisplayValue("Products - Modified", { timeout: 10 }).should(
|
|
"not.exist",
|
|
);
|
|
});
|
|
});
|
|
|
|
describe("with hidden tables", () => {
|
|
beforeEach(() => {
|
|
cy.signInAsAdmin();
|
|
});
|
|
|
|
const HIDDEN_TYPES = ["hidden", "technical", "cruft"];
|
|
|
|
function hideTable({ name, id, visibilityType }) {
|
|
// Since v56 it's no longer possible to specify the reason (e.g. "technical" or "cruft")
|
|
// for hiding the table via UI.
|
|
// We still want to support cases where visibility type has been set to such values in
|
|
// the past, so we simulate it with API call.
|
|
if (visibilityType === "technical" || visibilityType === "cruft") {
|
|
cy.request("PUT", `/api/table/${id}`, {
|
|
visibility_type: visibilityType,
|
|
});
|
|
} else {
|
|
H.DataModel.visit();
|
|
H.DataModel.TablePicker.getTable(name).click();
|
|
H.DataModel.TablePicker.getTable(name).button("Hide table").click();
|
|
}
|
|
}
|
|
|
|
HIDDEN_TYPES.forEach((visibilityType) => {
|
|
it(`should show a View-only tag when the source table is marked as ${visibilityType}`, () => {
|
|
hideTable({ name: "Orders", id: ORDERS_ID, visibilityType });
|
|
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
|
|
H.queryBuilderHeader()
|
|
.findByText("View-only")
|
|
.should("be.visible")
|
|
.realHover();
|
|
H.popover()
|
|
.findByText(
|
|
"One of the administrators hid the source table “Orders”, making this question view-only.",
|
|
)
|
|
.should("be.visible");
|
|
});
|
|
|
|
it(`should show a View-only tag when a joined table is marked as ${visibilityType}`, () => {
|
|
cy.signInAsAdmin();
|
|
hideTable({ name: "Products", id: PRODUCTS_ID, visibilityType });
|
|
H.createQuestion(
|
|
{
|
|
name: "Joined question",
|
|
query: {
|
|
"source-table": ORDERS_ID,
|
|
joins: [
|
|
{
|
|
"source-table": PRODUCTS_ID,
|
|
alias: "Orders",
|
|
condition: [
|
|
"=",
|
|
["field", ORDERS.PRODUCT_ID, null],
|
|
["field", PRODUCTS.ID, { "join-alias": "Products" }],
|
|
],
|
|
fields: "all",
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
visitQuestion: true,
|
|
},
|
|
);
|
|
H.queryBuilderHeader()
|
|
.findByText("View-only")
|
|
.should("be.visible")
|
|
.realHover();
|
|
H.popover()
|
|
.findByText(
|
|
"One of the administrators hid the source table “Products”, making this question view-only.",
|
|
)
|
|
.should("be.visible");
|
|
});
|
|
});
|
|
|
|
function moveQuestionTo(newCollectionName) {
|
|
H.openQuestionActions();
|
|
cy.findByTestId("move-button").click();
|
|
H.entityPickerModal().within(() => {
|
|
cy.findByText(newCollectionName).click();
|
|
cy.button("Move").click();
|
|
});
|
|
}
|
|
|
|
it("should show a View-only tag when one of the source cards is unavailable", () => {
|
|
H.createQuestion(
|
|
{
|
|
name: "Products Question + Orders",
|
|
query: {
|
|
"source-table": `card__${ORDERS_QUESTION_ID}`,
|
|
joins: [
|
|
{
|
|
"source-table": PRODUCTS_ID,
|
|
alias: "Orders Question",
|
|
fields: "all",
|
|
condition: [
|
|
"=",
|
|
["field", PRODUCTS.PRODUCT_ID, null],
|
|
["field", ORDERS.ID, { "join-alias": "Orders" }],
|
|
],
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
wrapId: true,
|
|
idAlias: "questionId",
|
|
},
|
|
);
|
|
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
moveQuestionTo(/Personal Collection/);
|
|
|
|
cy.signInAsNormalUser();
|
|
cy.get("@questionId").then(H.visitQuestion);
|
|
|
|
H.queryBuilderHeader().findByText("View-only").should("be.visible");
|
|
});
|
|
});
|
|
|
|
describe("with watermark", () => {
|
|
beforeEach(() => {
|
|
H.restore();
|
|
cy.signInAsAdmin();
|
|
H.activateToken("pro-self-hosted");
|
|
|
|
cy.intercept("/api/session/properties", (req) => {
|
|
req.continue((res) => {
|
|
res.body["token-features"].development_mode = true;
|
|
});
|
|
});
|
|
|
|
cy.request("PUT", `/api/card/${ORDERS_BY_YEAR_QUESTION_ID}`, {
|
|
collection_position: 1,
|
|
enable_embedding: true,
|
|
});
|
|
|
|
cy.request("PUT", `/api/dashboard/${ORDERS_DASHBOARD_ID}`, {
|
|
enable_embedding: true,
|
|
});
|
|
});
|
|
|
|
it("should show questions with a watermark when in dev mode whereever we show visualizations", () => {
|
|
H.visitQuestion(ORDERS_QUESTION_ID);
|
|
|
|
cy.findByTestId("development-watermark").should("exist");
|
|
|
|
H.appBar()
|
|
.findByRole("link", { name: /Our analytics/i })
|
|
.click();
|
|
|
|
cy.findByTestId("collection-table")
|
|
.findByRole("link", { name: /Orders in a dashboard/i })
|
|
.click();
|
|
cy.findAllByTestId("development-watermark").should(
|
|
"have.length.above",
|
|
0,
|
|
);
|
|
|
|
H.visitEmbeddedPage({
|
|
resource: { dashboard: ORDERS_DASHBOARD_ID },
|
|
params: {},
|
|
});
|
|
|
|
cy.findAllByTestId("development-watermark").should(
|
|
"have.length.greaterThan",
|
|
0,
|
|
);
|
|
|
|
H.visitEmbeddedPage({
|
|
resource: { question: ORDERS_BY_YEAR_QUESTION_ID },
|
|
params: {},
|
|
});
|
|
|
|
cy.findAllByTestId("development-watermark").should(
|
|
"have.length.greaterThan",
|
|
0,
|
|
);
|
|
|
|
//Need to sign in to generate the public link for the orders question
|
|
cy.signInAsAdmin();
|
|
|
|
H.visitPublicQuestion(ORDERS_QUESTION_ID);
|
|
cy.findAllByTestId("development-watermark").should(
|
|
"have.length.above",
|
|
0,
|
|
);
|
|
|
|
//Need to sign in to generate the public link for the orders dashboard
|
|
cy.signInAsAdmin();
|
|
|
|
H.visitPublicDashboard(ORDERS_DASHBOARD_ID);
|
|
cy.findAllByTestId("development-watermark").should(
|
|
"have.length.above",
|
|
0,
|
|
);
|
|
});
|
|
});
|
|
});
|
|
|
|
//http://127.0.0.1:9080/api/session/00000000-0000-0000-0000-000000000000/requests
|
|
|
|
// Ensure the webhook tester docker container is running
|
|
// docker run -p 127.0.0.1:9080:8080/tcp tarampampam/webhook-tester:1.1.0 serve --create-session 00000000-0000-0000-0000-000000000000
|
|
describe(
|
|
"scenarios > question > saved > alerts",
|
|
{ tags: ["@external"] },
|
|
|
|
() => {
|
|
const firstWebhookName = "E2E Test Webhook";
|
|
const secondWebhookName = "Toucan Hook";
|
|
|
|
beforeEach(() => {
|
|
H.resetWebhookTester();
|
|
H.restore();
|
|
cy.signInAsAdmin();
|
|
H.setupSMTP();
|
|
|
|
cy.request("POST", "/api/channel", {
|
|
name: firstWebhookName,
|
|
description: "All aboard the Metaboat",
|
|
type: "channel/http",
|
|
details: {
|
|
url: H.WEBHOOK_TEST_URL,
|
|
"auth-method": "none",
|
|
"fe-form-type": "none",
|
|
},
|
|
});
|
|
|
|
cy.request("POST", "/api/channel", {
|
|
name: secondWebhookName,
|
|
description: "Quack!",
|
|
type: "channel/http",
|
|
details: {
|
|
url: H.WEBHOOK_TEST_URL,
|
|
"auth-method": "none",
|
|
"fe-form-type": "none",
|
|
},
|
|
});
|
|
});
|
|
|
|
it("should allow you to enable a webhook alert", () => {
|
|
H.visitQuestion(ORDERS_COUNT_QUESTION_ID);
|
|
cy.findByLabelText("Move, trash, and more…").click();
|
|
H.popover().findByText("Create an alert").click();
|
|
|
|
H.modal().findByText("New alert").should("be.visible");
|
|
H.removeNotificationHandlerChannel("Email");
|
|
H.addNotificationHandlerChannel(secondWebhookName, {
|
|
hasNoChannelsAdded: true,
|
|
});
|
|
H.selectScheduleTime();
|
|
H.modal().button("Done").click();
|
|
|
|
cy.findByLabelText("Move, trash, and more…").click();
|
|
H.popover().findByText("Edit alerts").click();
|
|
H.modal()
|
|
.findByText(/Created by you/)
|
|
.should("be.exist")
|
|
.click();
|
|
|
|
H.modal().findByText(secondWebhookName).should("be.visible");
|
|
});
|
|
},
|
|
);
|