Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Page Object Model for Playwright tests #737

Merged
merged 16 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
23 changes: 23 additions & 0 deletions tests/e2e/fixtures/base.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { mergeTests, test as base } from "@playwright/test";
import { test as sarTest } from "./sar.ts";
import { test as wpTest } from "./wp.ts";
import StateHomePage from "../pages/stateHome.page";
import AdminHomePage from "../pages/adminHome.page";

type CustomFixtures = {
stateHomePage: StateHomePage;
adminHomePage: AdminHomePage;
};

export const baseTest = base.extend<CustomFixtures>({
stateHomePage: async ({ page }, use) => {
await use(new StateHomePage(page));
},
adminHomePage: async ({ page }, use) => {
await use(new AdminHomePage(page));
},
});

export const test = mergeTests(baseTest, sarTest, wpTest);

export { expect } from "@playwright/test";
12 changes: 12 additions & 0 deletions tests/e2e/fixtures/sar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { test as base } from "@playwright/test";
import { SARDashboardPage } from "../pages/sar/sarDashboard.page";

type SARFixtures = {
sarDashboard: SARDashboardPage;
};

export const test = base.extend<SARFixtures>({
sarDashboard: async ({ page }, use) => {
await use(new SARDashboardPage(page));
},
});
22 changes: 22 additions & 0 deletions tests/e2e/fixtures/wp.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { test as base } from "@playwright/test";
import { WPDashboardPage } from "../pages/wp/wpDashboard.page";
import { WPGeneralInformationPage } from "../pages/wp/wpGeneral.page";
import { WPReviewAndSubmitPage } from "../pages/wp/wpReviewAndSubmit.page";

type WPFixtures = {
wpDashboard: WPDashboardPage;
wpGeneralInformation: WPGeneralInformationPage;
wpReviewAndSubmit: WPReviewAndSubmitPage;
};

export const test = base.extend<WPFixtures>({
wpDashboard: async ({ page }, use) => {
await use(new WPDashboardPage(page));
},
wpGeneralInformation: async ({ page }, use) => {
await use(new WPGeneralInformationPage(page));
},
wpReviewAndSubmit: async ({ page }, use) => {
await use(new WPReviewAndSubmitPage(page));
},
});
27 changes: 12 additions & 15 deletions tests/e2e/home.spec.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,22 @@
import { test, expect } from "@playwright/test";
import { test, expect } from "./fixtures/base";
import { logInStateUser, logInAdminUser } from "./helpers";

test("Should see the correct home page as a state user", async ({ page }) => {
test("Should see the correct home page as a state user", async ({
page,
stateHomePage,
}) => {
await page.goto("/");
await logInStateUser(page);

await expect(
page.getByRole("button", { name: "Enter Work Plan online" })
).toBeVisible();
await expect(
page.getByRole("button", { name: "Enter SAR online" })
).toBeVisible();
await stateHomePage.isReady();
});

test("Should see the correct home page as an admin user", async ({ page }) => {
test("Should see the correct home page as an admin user", async ({
page,
adminHomePage,
}) => {
await page.goto("/");
await logInAdminUser(page);

await expect(
page.getByRole("combobox", {
name: "List of states, including District of Columbia and Puerto Rico",
})
).toBeVisible();
await adminHomePage.isReady();
await expect(adminHomePage.dropdown).toBeVisible();
});
41 changes: 41 additions & 0 deletions tests/e2e/pages/adminHome.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Locator, Page } from "@playwright/test";
import BasePage from "./base.page";

export default class AdminHomePage extends BasePage {
public path = "/";

readonly page: Page;
readonly title: Locator;
readonly dropdown: Locator;

constructor(page: Page) {
super(page);
this.page = page;
this.title = page.getByRole("heading", {
name: "View State/Territory Reports",
});
this.dropdown = page.getByRole("combobox", {
name: "List of states, including District of Columbia and Puerto Rico",
});
}

public async selectWP() {
await this.page.getByRole("radio", { name: "MFP Work Plan" }).click();
}

public async selectSAR() {
await this.page
.getByRole("radio", {
name: "MFP Semi-Annual Progress Report (SAR)",
})
.click();
}

public async goToDashboard() {
await this.page
.getByRole("button", {
name: "Go to Report Dashboard",
})
.click();
}
}
27 changes: 27 additions & 0 deletions tests/e2e/pages/base.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { expect, Locator, Page } from "@playwright/test";

export default class BasePage {
public path = "/";

readonly page: Page;
readonly title: Locator;
readonly continueButton: Locator;
readonly previousButton: Locator;

constructor(page: Page) {
this.page = page;
this.title = page.getByRole("heading", {
name: "Money Follows the Person",
});
this.continueButton = page.getByRole("button", { name: "Continue" });
this.previousButton = page.getByRole("button", { name: "Previous" });
}

public async goto() {
await this.page.goto(this.path);
}

public async isReady() {
return expect(this.title).toBeVisible();
}
}
58 changes: 58 additions & 0 deletions tests/e2e/pages/sar/sarDashboard.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { expect, Locator, Page } from "@playwright/test";
import BasePage from "../base.page";
import { firstPeriod, stateAbbreviation, stateName } from "../../helpers";
import { currentYear } from "../../../seeds/helpers";

export class SARDashboardPage extends BasePage {
public path = "/sar/";
jessabean marked this conversation as resolved.
Show resolved Hide resolved

readonly page: Page;
readonly title: Locator;
readonly createButton: Locator;
readonly modal: Locator;
readonly associatedWP: Locator;
readonly firstReport: Locator;

constructor(page: Page) {
super(page);
this.page = page;
this.title = this.page.getByRole("heading", {
name: `${stateName} MFP Semi-Annual Progress Report (SAR)`,
});
this.createButton = this.page.getByRole("button", {
name: "Add new MFP SAR submission",
});
this.modal = this.page.getByRole("dialog");
this.associatedWP = this.modal.getByRole("textbox", {
name: "Associated MFP Work Plan",
});
this.firstReport = this.page
.getByRole("row", {
name: `${stateName} MFP SAR ${currentYear} - Period ${firstPeriod}`,
})
.first();
}

public async isReady() {
await this.title.isVisible();
await this.page.waitForResponse(
(response) =>
response.url().includes("/reports/SAR/PR") && response.status() == 200
jessabean marked this conversation as resolved.
Show resolved Hide resolved
);
const table = this.page.getByRole("table");

return expect(table).toContainText("Submission name");
}

public async getReports() {
await this.page.waitForResponse(`**/reports/SAR/${stateAbbreviation}`);
}

public async createNewSAR() {
const radioNo = this.modal.getByRole("radio", { name: "No" });
jessabean marked this conversation as resolved.
Show resolved Hide resolved
const saveButton = this.modal.getByRole("button", { name: "Save" });

await radioNo.click();
await saveButton.click();
}
}
23 changes: 23 additions & 0 deletions tests/e2e/pages/stateHome.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Locator, Page } from "@playwright/test";
import BasePage from "./base.page";

export default class StateHomePage extends BasePage {
public path = "/";

readonly page: Page;
readonly title: Locator;
readonly wpButton: Locator;
readonly sarButton: Locator;

constructor(page: Page) {
super(page);
this.page = page;
this.title = page.getByRole("heading", {
name: "Money Follows the Person (MFP) Portal",
});
this.wpButton = page.getByRole("button", {
name: "Enter Work Plan online",
});
this.sarButton = page.getByRole("button", { name: "Enter SAR online" });
}
}
72 changes: 72 additions & 0 deletions tests/e2e/pages/wp/wpDashboard.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { expect, Locator, Page } from "@playwright/test";
import BasePage from "../base.page";
import {
firstPeriod,
secondPeriod,
stateAbbreviation,
stateName,
} from "../../helpers";
import { currentYear } from "../../../seeds/helpers";

export class WPDashboardPage extends BasePage {
public path = "/wp";

readonly page: Page;
readonly title: Locator;
readonly createButton: Locator;
readonly copyoverButton: Locator;
readonly modal: Locator;
readonly firstReport: Locator;
readonly copiedReport: Locator;
readonly submittedReport: Locator;

constructor(page: Page) {
super(page);
this.page = page;
this.title = this.page.getByRole("heading", {
name: `${stateName} MFP Work Plan`,
});
this.createButton = this.page.getByRole("button", {
name: "Start MFP Work Plan",
});
this.copyoverButton = this.page.getByRole("button", {
name: "Continue MFP Work Plan for next Period",
});
this.modal = this.page.getByRole("dialog");

this.firstReport = this.page
.getByRole("row", {
name: `${stateName} MFP Work Plan ${currentYear} - Period ${firstPeriod}`,
})
.first();
this.copiedReport = this.page.getByRole("row", {
name: `${stateName} MFP Work Plan ${currentYear} - Period ${secondPeriod}`,
});
this.submittedReport = this.page
.getByRole("row", { name: "Submitted" })
.last();
}

public async isReady() {
await this.title.isVisible();
await this.page.waitForResponse(
(response) =>
response.url().includes("/reports/WP/PR") && response.status() == 200
jessabean marked this conversation as resolved.
Show resolved Hide resolved
);
const table = this.page.getByRole("table");

return expect(table).toContainText("Submission name");
}

public async getReports() {
await this.page.waitForResponse(`**/reports/WP/${stateAbbreviation}`);
}

public async createNewWP() {
await this.modal.getByLabel(`${currentYear}`).click();
await this.modal
.getByLabel(`First reporting period (January 1 - June 30)`)
.click();
await this.modal.getByRole("button", { name: "Start new" }).click();
}
}
19 changes: 19 additions & 0 deletions tests/e2e/pages/wp/wpGeneral.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { Locator, Page } from "@playwright/test";
import BasePage from "../base.page";

export class WPGeneralInformationPage extends BasePage {
public path = "/wp/general-information";

readonly page: Page;
readonly title: Locator;
readonly continueButton: Locator;
readonly disclosure: Locator;

constructor(page: Page) {
super(page);
this.page = page;
this.title = page.getByRole("heading", { name: "General Information" });
this.continueButton = page.getByRole("button", { name: "Continue" });
jessabean marked this conversation as resolved.
Show resolved Hide resolved
this.disclosure = page.getByText("PRA Disclosure Statement");
}
}
31 changes: 31 additions & 0 deletions tests/e2e/pages/wp/wpReviewAndSubmit.page.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Locator, Page } from "@playwright/test";
import BasePage from "../base.page";

export class WPReviewAndSubmitPage extends BasePage {
public path = "/wp/review-and-submit";

readonly page: Page;
readonly title: Locator;
readonly reviewPDFButton: Locator;
readonly submitButton: Locator;
readonly approveButton: Locator;
readonly unlockButton: Locator;
readonly approveModal: Locator;

constructor(page: Page) {
super(page);
this.page = page;
this.title = page.getByRole("heading", { name: "Review & Submit" });
this.reviewPDFButton = page.getByRole("button", { name: "Review PDF" });
this.approveButton = page.getByRole("button", { name: "Approve" });
this.unlockButton = page.getByRole("button", { name: "Unlock" });
this.approveModal = page.getByRole("dialog", {
name: "Are you sure you want to approve this MFP Work Plan?",
});
}

public async approveReport() {
await this.approveModal.getByRole("textbox").fill("APPROVE");
await this.approveModal.getByRole("button", { name: "Approve" }).click();
}
}
Loading
Loading