diff --git a/data/dispatch-sample-data.dump b/data/dispatch-sample-data.dump index 7be0bb5b5854..4b7129b583b5 100644 --- a/data/dispatch-sample-data.dump +++ b/data/dispatch-sample-data.dump @@ -7891,6 +7891,7 @@ COPY dispatch_organization_default.case_priority (id, name, description, color, 1 Low Low priority #558b2f t t -1 \N 1 f 2 Medium Medium priority \N t f 2 \N 1 f 3 High High priority #b71c1c t f 3 \N 1 f +4 Critical Critical priority \N t f 4 \N 1 t \. @@ -9263,7 +9264,7 @@ SELECT pg_catalog.setval('dispatch_organization_default.case_id_seq', 1, true); -- Name: case_priority_id_seq; Type: SEQUENCE SET; Schema: dispatch_organization_default; Owner: postgres -- -SELECT pg_catalog.setval('dispatch_organization_default.case_priority_id_seq', 3, true); +SELECT pg_catalog.setval('dispatch_organization_default.case_priority_id_seq', 4, true); -- diff --git a/tests/static/e2e/fixtures/dispatch-fixtures.ts b/tests/static/e2e/fixtures/dispatch-fixtures.ts index ec55b0302f62..98a1b815eadd 100644 --- a/tests/static/e2e/fixtures/dispatch-fixtures.ts +++ b/tests/static/e2e/fixtures/dispatch-fixtures.ts @@ -3,12 +3,14 @@ import { AuthPage } from "../pages/auth-page" import { ReportIncidentPage } from "../pages/report-incident-page" import { ReportCasePage } from "../pages/report-case-page" import { IncidentsPage } from "../pages/incidents-page" +import { ReportEventPage } from "../pages/report-event-page" type DispatchFixtures = { authPage: AuthPage reportIncidentPage: ReportIncidentPage reportCasePage: ReportCasePage incidentsPage: IncidentsPage + reportEventPage: ReportEventPage } export const test = base.extend({ @@ -24,6 +26,10 @@ export const test = base.extend({ await use(new ReportCasePage(page)) }, + reportEventPage: async ({ page }, use) => { + await use(new ReportEventPage(page)) + }, + incidentsPage: async ({ page }, use) => { const incidentsPage = new IncidentsPage(page) await use(incidentsPage) diff --git a/tests/static/e2e/pages/report-event-page.ts b/tests/static/e2e/pages/report-event-page.ts new file mode 100644 index 000000000000..34ac5f77e874 --- /dev/null +++ b/tests/static/e2e/pages/report-event-page.ts @@ -0,0 +1,64 @@ +import { expect, Locator, Page } from "@playwright/test" +import { orgSlug, Routes } from "../routes" + +export class ReportEventPage { + readonly page: Page + readonly route: string + readonly reportHeader: Locator + readonly descriptionTextBox: Locator + readonly urgentCheckbox: Locator + readonly submitButton: Locator + readonly pageBorder: Locator + + constructor(page: Page) { + this.page = page + this.route = orgSlug + Routes.ReportEvent + this.reportHeader = page.getByText("Report a Security Event").first() + this.descriptionTextBox = page.getByLabel("Description", { exact: true }) + this.urgentCheckbox = page.getByLabel( + "URGENT: I need immediate help with this (the oncall will be paged)", + { exact: true } + ) + this.submitButton = page.getByRole("button", { name: "Submit" }) + this.pageBorder = this.page.locator("span").filter({ + hasText: "Security Events are an input", + }) + } + + async goto() { + await Promise.all([ + this.page.goto(this.route), + await this.page.waitForURL(this.route), + await expect(this.reportHeader).toBeVisible(), + ]) + } + + async reportEvent(description: string, urgent: boolean = false) { + await this.goto() + // give time for default project to settle + await this.page.waitForTimeout(3000) + await this.addDescription(description) + if (urgent) { + await this.urgentCheckbox.click() + } + await this.page.waitForTimeout(1500) + await this.resetPageView() + await Promise.all([ + await this.submitButton.click(), + await this.page.waitForLoadState("networkidle"), + ]) + } + + async addDescription(description: string) { + await this.descriptionTextBox.click() + await this.descriptionTextBox.fill(description) + } + + async resetPageView() { + // await this.pageBorder.click() + } + + async pageObjectModel(description: string, urgent: boolean = false) { + await this.reportEvent(description, urgent) + } +} diff --git a/tests/static/e2e/report-event.spec.ts b/tests/static/e2e/report-event.spec.ts new file mode 100644 index 000000000000..8bed2f52a772 --- /dev/null +++ b/tests/static/e2e/report-event.spec.ts @@ -0,0 +1,90 @@ +import register from "./utils/register" +import { test, expect } from "./fixtures/dispatch-fixtures" + +test.describe("Authenticated Dispatch App", () => { + test.beforeEach(async ({ authPage }) => { + await register(authPage) + }), + test("Should allow me to report an event", async ({ page, reportEventPage }) => { + /* The ability to report a case is one of the most critical + user stories in the Dispatch application. */ + + const description = "Security Event Test Created by Playwright" + const title = "Security Event Triage" + + await reportEventPage.reportEvent(description) + // Soft validate that we get redirected to the event submission form + const expectedURL = encodeURI( + `/default/events/report?project=default&title=${title}&description=${description}` + ) + // replace + with %20 + const pageURL = page.url().replace(/\+/g, "%20") + + await expect.soft(pageURL).toContain(expectedURL) + + // Soft validate that we receive the post-create resources form. + await expect + .soft( + page.getByText( + "This page will be populated with case resources as they are created (if available). If you have any questions, please feel free to review the Frequently Asked Questions (FAQ) document linked below, and/or reach out to the listed assignee." + ), + "'Case Resources' text visible on page after submission of a case." + ) + .toBeVisible() + + // Soft validate that the ticket link is present + const loc = page.getByRole("link", { + name: "Ticket Ticket for tracking purposes. It contains information and links to resources.", + }) + await expect + .soft(await loc.first().getAttribute("href")) + .toContain("default/cases/dispatch-default-default-") + }), + test("Should allow me to report an event with urgent flagged", async ({ + page, + reportEventPage, + }) => { + /* The ability to report a case is one of the most critical + user stories in the Dispatch application. */ + + const description = "Security Event Test Created by Playwright" + const title = "Security Event Triage" + + await reportEventPage.reportEvent(description, true) + // Soft validate that we get redirected to the case submission form + const expectedURL = encodeURI( + `/default/events/report?project=default&title=${title}&description=${description}` + ) + // replace + with %20 + const pageURL = page.url().replace(/\+/g, "%20") + + await expect.soft(pageURL).toContain(expectedURL) + + // Soft validate that we receive the post-create resources form. + await expect + .soft( + page.getByText( + "This page will be populated with case resources as they are created (if available). If you have any questions, please feel free to review the Frequently Asked Questions (FAQ) document linked below, and/or reach out to the listed assignee." + ), + "'Case Resources' text visible on page after submission of an event." + ) + .toBeVisible() + + // Validate that the Priority is set to 'Critical' + const priorityElement = page.getByText("Priority") + + const subtitleElement = priorityElement.locator( + 'xpath=following-sibling::div[contains(@class, "v-list-item-subtitle")]' + ) + await expect(subtitleElement).toBeVisible() + await expect(subtitleElement).toHaveText(/Critical/) + + // Soft validate that the ticket link is present + const loc = page.getByRole("link", { + name: "Ticket Ticket for tracking purposes. It contains information and links to resources.", + }) + await expect + .soft(await loc.first().getAttribute("href")) + .toContain("default/cases/dispatch-default-default-") + }) +}) diff --git a/tests/static/e2e/routes.ts b/tests/static/e2e/routes.ts index 76adf6f9b948..cd3a872fee68 100644 --- a/tests/static/e2e/routes.ts +++ b/tests/static/e2e/routes.ts @@ -7,4 +7,5 @@ export enum Routes { Incidents = "/incidents", ReportIncident = "/incidents/report", ReportCase = "/cases/report", + ReportEvent = "/events/report", }