feature/IO-3587-Commision-Cut - Additional Testing / Test Harness improvements
This commit is contained in:
140
client/tests/e2e/commission-based-cut.e2e.js
Normal file
140
client/tests/e2e/commission-based-cut.e2e.js
Normal file
@@ -0,0 +1,140 @@
|
||||
/* eslint-disable */
|
||||
|
||||
import { expect, test } from "@playwright/test";
|
||||
import { acceptEulaIfPresent, login } from "./utils/login";
|
||||
|
||||
async function openCommissionCutHarness(page) {
|
||||
await page.goto("/manage/_test?fixture=commission-cut");
|
||||
await acceptEulaIfPresent(page);
|
||||
await expect(page.getByRole("heading", { name: "Commission Cut Test Harness" })).toBeVisible();
|
||||
}
|
||||
|
||||
test.describe("Commission-based cut", () => {
|
||||
test.skip(!process.env.TEST_USERNAME || !process.env.TEST_PASSWORD, "Requires TEST_USERNAME and TEST_PASSWORD.");
|
||||
|
||||
test("renders payout previews and completes Pay All from the commission-cut harness", async ({ page }) => {
|
||||
let calculateLaborCalls = 0;
|
||||
let payAllCalls = 0;
|
||||
|
||||
await login(page, {
|
||||
email: process.env.TEST_USERNAME,
|
||||
password: process.env.TEST_PASSWORD
|
||||
});
|
||||
|
||||
await page.route("**/payroll/calculatelabor", async (route) => {
|
||||
calculateLaborCalls += 1;
|
||||
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify([
|
||||
{
|
||||
employeeid: "emp-1",
|
||||
mod_lbr_ty: "LAA",
|
||||
expectedHours: 4,
|
||||
claimedHours: 1
|
||||
},
|
||||
{
|
||||
employeeid: "emp-2",
|
||||
mod_lbr_ty: "LAB",
|
||||
expectedHours: 2,
|
||||
claimedHours: 1
|
||||
}
|
||||
])
|
||||
});
|
||||
});
|
||||
|
||||
await page.route("**/payroll/payall", async (route) => {
|
||||
payAllCalls += 1;
|
||||
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify([{ id: "tt-1" }])
|
||||
});
|
||||
});
|
||||
|
||||
await openCommissionCutHarness(page);
|
||||
await expect(page.getByText("Claim Task Preview")).toBeVisible();
|
||||
await expect(page.getByRole("cell", { name: "Commission" })).toBeVisible();
|
||||
await expect(page.getByRole("cell", { name: "Hourly" })).toBeVisible();
|
||||
await expect(
|
||||
page.getByText(
|
||||
"There are currently 1.25 hours of repair lines that are unassigned. These hours are not including in the above calculations and must be paid manually."
|
||||
)
|
||||
).toBeVisible();
|
||||
|
||||
await expect(page.getByRole("button", { name: "Pay All" })).toBeVisible();
|
||||
await page.getByRole("button", { name: "Pay All" }).click();
|
||||
|
||||
await expect.poll(() => calculateLaborCalls).toBeGreaterThan(0);
|
||||
await expect.poll(() => payAllCalls).toBe(1);
|
||||
await expect(page.getByText("All hours paid out successfully.")).toBeVisible();
|
||||
});
|
||||
|
||||
test("shows the backend error when Pay All is rejected", async ({ page }) => {
|
||||
await login(page, {
|
||||
email: process.env.TEST_USERNAME,
|
||||
password: process.env.TEST_PASSWORD
|
||||
});
|
||||
|
||||
await page.route("**/payroll/calculatelabor", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify([
|
||||
{
|
||||
employeeid: "emp-1",
|
||||
mod_lbr_ty: "LAA",
|
||||
expectedHours: 4,
|
||||
claimedHours: 1
|
||||
}
|
||||
])
|
||||
});
|
||||
});
|
||||
|
||||
await page.route("**/payroll/payall", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify({
|
||||
success: false,
|
||||
error: "Not all hours have been assigned."
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
await openCommissionCutHarness(page);
|
||||
await page.getByRole("button", { name: "Pay All" }).click();
|
||||
|
||||
await expect(page.getByText("Error flagging hours. Not all hours have been assigned.")).toBeVisible();
|
||||
});
|
||||
|
||||
test("shows a negative labor difference when previously claimed hours exceed the current expected hours", async ({
|
||||
page
|
||||
}) => {
|
||||
await login(page, {
|
||||
email: process.env.TEST_USERNAME,
|
||||
password: process.env.TEST_PASSWORD
|
||||
});
|
||||
|
||||
await page.route("**/payroll/calculatelabor", async (route) => {
|
||||
await route.fulfill({
|
||||
status: 200,
|
||||
contentType: "application/json",
|
||||
body: JSON.stringify([
|
||||
{
|
||||
employeeid: "emp-1",
|
||||
mod_lbr_ty: "LAA",
|
||||
expectedHours: 2,
|
||||
claimedHours: 5
|
||||
}
|
||||
])
|
||||
});
|
||||
});
|
||||
|
||||
await openCommissionCutHarness(page);
|
||||
|
||||
await expect(page.locator("strong").filter({ hasText: "-3" }).first()).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,48 @@
|
||||
import { expect } from "@playwright/test";
|
||||
|
||||
const formatToday = () => {
|
||||
const today = new Date();
|
||||
const month = String(today.getMonth() + 1).padStart(2, "0");
|
||||
const day = String(today.getDate()).padStart(2, "0");
|
||||
const year = today.getFullYear();
|
||||
return `${month}/${day}/${year}`;
|
||||
};
|
||||
|
||||
export async function acceptEulaIfPresent(page) {
|
||||
const eulaDialog = page.getByRole("dialog", { name: "Terms and Conditions" });
|
||||
|
||||
const eulaVisible =
|
||||
(await eulaDialog.isVisible().catch(() => false)) ||
|
||||
(await eulaDialog
|
||||
.waitFor({
|
||||
state: "visible",
|
||||
timeout: 5000
|
||||
})
|
||||
.then(() => true)
|
||||
.catch(() => false));
|
||||
|
||||
if (!eulaVisible) {
|
||||
return;
|
||||
}
|
||||
|
||||
const markdownCard = page.locator(".eula-markdown-card");
|
||||
await markdownCard.evaluate((element) => {
|
||||
element.scrollTop = element.scrollHeight;
|
||||
element.dispatchEvent(new Event("scroll", { bubbles: true }));
|
||||
});
|
||||
|
||||
await page.getByRole("textbox", { name: "First Name" }).fill("Codex");
|
||||
await page.getByRole("textbox", { name: "Last Name" }).fill("Tester");
|
||||
await page.getByRole("textbox", { name: "Legal Business Name" }).fill("Codex QA");
|
||||
await page.getByRole("textbox", { name: "Date Accepted" }).fill(formatToday());
|
||||
await page.getByRole("checkbox", { name: "I accept the terms and conditions of this agreement." }).check();
|
||||
|
||||
const acceptButton = page.getByRole("button", { name: "Accept EULA" });
|
||||
await expect(acceptButton).toBeEnabled({ timeout: 10000 });
|
||||
await acceptButton.click();
|
||||
await expect(eulaDialog).not.toBeVisible({ timeout: 10000 });
|
||||
}
|
||||
|
||||
export async function login(page, { email, password }) {
|
||||
// Navigate to the login page
|
||||
await page.goto("/"); // Adjust if your login route differs (e.g., '/login')
|
||||
@@ -16,6 +59,8 @@ export async function login(page, { email, password }) {
|
||||
// Wait for navigation or success indicator (e.g., redirect to /manage/)
|
||||
await page.waitForURL(/\/manage\//, { timeout: 10000 }); // Adjust based on redirect
|
||||
|
||||
await acceptEulaIfPresent(page);
|
||||
|
||||
// Verify successful login (e.g., check for a dashboard element)
|
||||
await expect(page.locator("text=Manage")).toBeVisible(); // Adjust to your app’s post-login UI
|
||||
}
|
||||
|
||||
@@ -1,5 +1,45 @@
|
||||
import { afterEach } from "vitest";
|
||||
import { afterEach, vi } from "vitest";
|
||||
import { cleanup } from "@testing-library/react";
|
||||
import "@testing-library/jest-dom";
|
||||
|
||||
if (!window.matchMedia) {
|
||||
Object.defineProperty(window, "matchMedia", {
|
||||
writable: true,
|
||||
value: vi.fn().mockImplementation((query) => ({
|
||||
matches: false,
|
||||
media: query,
|
||||
onchange: null,
|
||||
addListener: vi.fn(),
|
||||
removeListener: vi.fn(),
|
||||
addEventListener: vi.fn(),
|
||||
removeEventListener: vi.fn(),
|
||||
dispatchEvent: vi.fn()
|
||||
}))
|
||||
});
|
||||
}
|
||||
|
||||
if (!window.ResizeObserver) {
|
||||
window.ResizeObserver = class ResizeObserver {
|
||||
observe() {}
|
||||
unobserve() {}
|
||||
disconnect() {}
|
||||
};
|
||||
}
|
||||
|
||||
if (!window.IntersectionObserver) {
|
||||
window.IntersectionObserver = class IntersectionObserver {
|
||||
observe() {}
|
||||
unobserve() {}
|
||||
disconnect() {}
|
||||
};
|
||||
}
|
||||
|
||||
if (!window.scrollTo) {
|
||||
window.scrollTo = vi.fn();
|
||||
}
|
||||
|
||||
if (!HTMLElement.prototype.scrollIntoView) {
|
||||
HTMLElement.prototype.scrollIntoView = vi.fn();
|
||||
}
|
||||
|
||||
afterEach(() => cleanup());
|
||||
|
||||
Reference in New Issue
Block a user