Skip to content
This repository was archived by the owner on Sep 3, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion data/dispatch-sample-data.dump
Original file line number Diff line number Diff line change
Expand Up @@ -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
\.


Expand Down Expand Up @@ -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);


--
Expand Down
6 changes: 6 additions & 0 deletions tests/static/e2e/fixtures/dispatch-fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<DispatchFixtures>({
Expand All @@ -24,6 +26,10 @@ export const test = base.extend<DispatchFixtures>({
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)
Expand Down
64 changes: 64 additions & 0 deletions tests/static/e2e/pages/report-event-page.ts
Original file line number Diff line number Diff line change
@@ -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
Comment thread
whitdog47 marked this conversation as resolved.

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(),
Comment thread
whitdog47 marked this conversation as resolved.
])
}

async reportEvent(description: string, urgent: boolean = false) {
await this.goto()
// give time for default project to settle
await this.page.waitForTimeout(3000)
Comment thread
whitdog47 marked this conversation as resolved.
await this.addDescription(description)
if (urgent) {
await this.urgentCheckbox.click()
}
await this.page.waitForTimeout(1500)
Comment thread
whitdog47 marked this conversation as resolved.
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)
}
Comment thread
whitdog47 marked this conversation as resolved.
}
90 changes: 90 additions & 0 deletions tests/static/e2e/report-event.spec.ts
Original file line number Diff line number Diff line change
@@ -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.",
Comment thread
whitdog47 marked this conversation as resolved.
})
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-")
})
})
1 change: 1 addition & 0 deletions tests/static/e2e/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export enum Routes {
Incidents = "/incidents",
ReportIncident = "/incidents/report",
ReportCase = "/cases/report",
ReportEvent = "/events/report",
}
Loading