mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-02 22:43:23 +00:00
262 lines
8.2 KiB
TypeScript
262 lines
8.2 KiB
TypeScript
|
|
import { expect, test, type Page, type Route } from "@playwright/test";
|
|||
|
|
|
|||
|
|
const TEST_USER = {
|
|||
|
|
token: "vendor-visual-token",
|
|||
|
|
expiration: "2030-01-01T00:00:00.000Z",
|
|||
|
|
email: "admin@seahavenind.com",
|
|||
|
|
userRoles: "Admin",
|
|||
|
|
phoneNumber: "5551234567",
|
|||
|
|
fullname: "Vendor Visual Admin",
|
|||
|
|
id: "1",
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const activeVendors = [
|
|||
|
|
{
|
|||
|
|
Id: 1,
|
|||
|
|
CompanyId: 101,
|
|||
|
|
CompanyName: "Gateway Plumbing",
|
|||
|
|
ContactName: "Adam Whyte",
|
|||
|
|
Email: "dispatch@gateway.test",
|
|||
|
|
Phone: "314-555-0198",
|
|||
|
|
CompanyPhone: "314-555-0100",
|
|||
|
|
Address: "1 Market St",
|
|||
|
|
City: "St. Louis",
|
|||
|
|
State: "MO",
|
|||
|
|
Zip: "63101",
|
|||
|
|
TradeSpecialties: "Plumbing, Backflow Preventers",
|
|||
|
|
GoogleMapsUrl: "https://maps.google.com/gateway",
|
|||
|
|
Notes: "Preferred after-hours vendor",
|
|||
|
|
TotalJobs: 72,
|
|||
|
|
IsActive: true,
|
|||
|
|
PreferredContact: "Email",
|
|||
|
|
},
|
|||
|
|
{
|
|||
|
|
Id: 2,
|
|||
|
|
CompanyId: 102,
|
|||
|
|
CompanyName: "Metro HVAC",
|
|||
|
|
ContactName: "Maya Chen",
|
|||
|
|
Email: "maya@metro.test",
|
|||
|
|
Phone: "314-555-0112",
|
|||
|
|
CompanyPhone: "314-555-0110",
|
|||
|
|
Address: "2 Pine St",
|
|||
|
|
City: "Clayton",
|
|||
|
|
State: "MO",
|
|||
|
|
Zip: "63105",
|
|||
|
|
TradeSpecialties: "HVAC",
|
|||
|
|
GoogleMapsUrl: "",
|
|||
|
|
Notes: "",
|
|||
|
|
TotalJobs: 18,
|
|||
|
|
IsActive: true,
|
|||
|
|
},
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
const inactiveVendors = [
|
|||
|
|
{
|
|||
|
|
...activeVendors[0],
|
|||
|
|
Id: 3,
|
|||
|
|
CompanyId: 103,
|
|||
|
|
CompanyName: "Drain Cleaning Bros",
|
|||
|
|
ContactName: "Drew Banks",
|
|||
|
|
TotalJobs: 151,
|
|||
|
|
IsActive: false,
|
|||
|
|
},
|
|||
|
|
];
|
|||
|
|
|
|||
|
|
async function fulfillJson(route: Route, body: unknown, status = 200) {
|
|||
|
|
await route.fulfill({ status, contentType: "application/json", body: JSON.stringify(body) });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function mockVendorApi(page: Page, mode: "default" | "empty" | "error" = "default") {
|
|||
|
|
await page.clock.setFixedTime(new Date("2026-08-10T12:00:00.000Z"));
|
|||
|
|
await page.addInitScript((user) => localStorage.setItem("auth", JSON.stringify(user)), TEST_USER);
|
|||
|
|
|
|||
|
|
await page.route("**/api/**", async (route) => {
|
|||
|
|
const request = route.request();
|
|||
|
|
const url = new URL(request.url());
|
|||
|
|
|
|||
|
|
if (!url.pathname.startsWith("/api/")) {
|
|||
|
|
await route.continue();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (url.pathname.includes("/DropdownOptions/ByCategory/Trade")) {
|
|||
|
|
await fulfillJson(route, {
|
|||
|
|
data: [
|
|||
|
|
{ id: 1, value: "Plumbing" },
|
|||
|
|
{ id: 2, value: "HVAC" },
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (url.pathname.endsWith("/api/Vendor/facets")) {
|
|||
|
|
await fulfillJson(route, {
|
|||
|
|
data: {
|
|||
|
|
companies: activeVendors.map((vendor) => ({
|
|||
|
|
companyId: vendor.CompanyId,
|
|||
|
|
name: vendor.CompanyName,
|
|||
|
|
})),
|
|||
|
|
trades: ["Plumbing", "Backflow Preventers", "HVAC"],
|
|||
|
|
locations: [
|
|||
|
|
{ city: "St. Louis", state: "MO", label: "St. Louis, MO" },
|
|||
|
|
{ city: "Clayton", state: "MO", label: "Clayton, MO" },
|
|||
|
|
],
|
|||
|
|
jobBuckets: [
|
|||
|
|
{ id: "under-50", label: "Under 50" },
|
|||
|
|
{ id: "50-99", label: "50–99" },
|
|||
|
|
{ id: "100-149", label: "100–149" },
|
|||
|
|
{ id: "150-plus", label: "150+" },
|
|||
|
|
],
|
|||
|
|
},
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (url.pathname.endsWith("/api/Vendor/GetVendorList")) {
|
|||
|
|
const isCount = url.searchParams.get("pageSize") === "1";
|
|||
|
|
if (mode === "error" && !isCount) {
|
|||
|
|
await fulfillJson(route, { message: "Vendor directory unavailable" }, 500);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
const source =
|
|||
|
|
mode === "empty"
|
|||
|
|
? []
|
|||
|
|
: url.searchParams.get("isActive") === "false"
|
|||
|
|
? inactiveVendors
|
|||
|
|
: activeVendors;
|
|||
|
|
await fulfillJson(route, {
|
|||
|
|
Data: isCount ? source.slice(0, 1) : source,
|
|||
|
|
TotalCount: source.length,
|
|||
|
|
PageNumber: 1,
|
|||
|
|
PageSize: Number(url.searchParams.get("pageSize") ?? 12),
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (url.pathname.startsWith("/api/vendor-company-roster")) {
|
|||
|
|
await fulfillJson(route, {
|
|||
|
|
companyId: 101,
|
|||
|
|
rowVersion: "rv-visual",
|
|||
|
|
name: "Gateway Plumbing",
|
|||
|
|
companyPhone: "314-555-0100",
|
|||
|
|
email: "dispatch@gateway.test",
|
|||
|
|
address: "1 Market St",
|
|||
|
|
city: "St. Louis",
|
|||
|
|
state: "MO",
|
|||
|
|
zip: "63101",
|
|||
|
|
googleMapsUrl: "https://maps.google.com/gateway",
|
|||
|
|
notes: "Preferred after-hours vendor",
|
|||
|
|
technicians: [
|
|||
|
|
{
|
|||
|
|
id: 1,
|
|||
|
|
contactName: "Adam Whyte",
|
|||
|
|
phone: "314-555-0198",
|
|||
|
|
email: "dispatch@gateway.test",
|
|||
|
|
preferredContact: "Email",
|
|||
|
|
tradeSpecialties: "Plumbing, Backflow Preventers",
|
|||
|
|
isActive: true,
|
|||
|
|
totalJobs: 72,
|
|||
|
|
},
|
|||
|
|
],
|
|||
|
|
});
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
await fulfillJson(route, { data: {} });
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function openVendorPage(page: Page, mode: "default" | "empty" | "error" = "default") {
|
|||
|
|
await mockVendorApi(page, mode);
|
|||
|
|
await page.goto("/vendors");
|
|||
|
|
await page.evaluate(() => document.fonts.ready);
|
|||
|
|
await page.addStyleTag({
|
|||
|
|
content: `
|
|||
|
|
*, *::before, *::after { transition: none !important; animation: none !important; }
|
|||
|
|
.MuiDrawer-paper { transform: none !important; }
|
|||
|
|
.Toastify__toast-container { display: none !important; }
|
|||
|
|
.tsqd-parent-container { display: none !important; }
|
|||
|
|
`,
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function expectStableScreenshot(page: Page, name: string) {
|
|||
|
|
await page.waitForTimeout(250);
|
|||
|
|
await page.evaluate(
|
|||
|
|
() =>
|
|||
|
|
new Promise<void>((resolve) =>
|
|||
|
|
requestAnimationFrame(() => requestAnimationFrame(() => resolve())),
|
|||
|
|
),
|
|||
|
|
);
|
|||
|
|
await page.screenshot({ animations: "disabled", caret: "hide" });
|
|||
|
|
await expect(page).toHaveScreenshot(name);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
test.describe("Vendor deterministic pixel regression", () => {
|
|||
|
|
test("list", async ({ page }) => {
|
|||
|
|
await openVendorPage(page);
|
|||
|
|
await expect(page.getByText("Gateway Plumbing")).toBeVisible();
|
|||
|
|
await expectStableScreenshot(page, "vendor-list.png");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test("filter", async ({ page }) => {
|
|||
|
|
await openVendorPage(page);
|
|||
|
|
await page.getByRole("button", { name: "Open vendor filters" }).click();
|
|||
|
|
await expect(page.getByRole("heading", { name: "Filters" })).toBeVisible();
|
|||
|
|
await expectStableScreenshot(page, "vendor-filter.png");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test("add", async ({ page }) => {
|
|||
|
|
await openVendorPage(page);
|
|||
|
|
await page.getByRole("button", { name: "Add Vendor", exact: true }).click();
|
|||
|
|
await expect(page.getByRole("dialog", { name: /Add Vendor/ })).toBeVisible();
|
|||
|
|
await expectStableScreenshot(page, "vendor-add.png");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test("detail", async ({ page }) => {
|
|||
|
|
await openVendorPage(page);
|
|||
|
|
await page.getByRole("button", { name: "View vendor Gateway Plumbing" }).click();
|
|||
|
|
await expect(page.getByRole("button", { name: "Close drawer" })).toBeVisible();
|
|||
|
|
await expectStableScreenshot(page, "vendor-detail.png");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test("edit", async ({ page }) => {
|
|||
|
|
await openVendorPage(page);
|
|||
|
|
await page.getByRole("button", { name: "Edit vendor Gateway Plumbing" }).click();
|
|||
|
|
await expect(page.getByRole("button", { name: "Save changes" })).toBeVisible();
|
|||
|
|
await expectStableScreenshot(page, "vendor-edit.png");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test("inactive", async ({ page }) => {
|
|||
|
|
await openVendorPage(page);
|
|||
|
|
await page.getByRole("tab", { name: "Inactive (1)" }).click();
|
|||
|
|
await expect(page.getByText("Drain Cleaning Bros")).toBeVisible();
|
|||
|
|
await expectStableScreenshot(page, "vendor-inactive.png");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test("empty", async ({ page }) => {
|
|||
|
|
await openVendorPage(page, "empty");
|
|||
|
|
await expect(page.getByText("No active technicians found")).toBeVisible();
|
|||
|
|
await expectStableScreenshot(page, "vendor-empty.png");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test("error", async ({ page }) => {
|
|||
|
|
await openVendorPage(page, "error");
|
|||
|
|
await expect(page.getByRole("main").getByRole("alert")).toContainText(
|
|||
|
|
/server error|vendor directory unavailable/i,
|
|||
|
|
);
|
|||
|
|
await expectStableScreenshot(page, "vendor-error.png");
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
test("mobile", async ({ page }) => {
|
|||
|
|
await page.setViewportSize({ width: 390, height: 844 });
|
|||
|
|
await openVendorPage(page);
|
|||
|
|
await expect(page.getByText("Gateway Plumbing")).toBeVisible();
|
|||
|
|
await expectStableScreenshot(page, "vendor-mobile.png");
|
|||
|
|
|
|||
|
|
await page.getByRole("button", { name: "Toggle navigation" }).click();
|
|||
|
|
await expect(page.getByRole("navigation", { name: "Primary navigation" })).toBeVisible();
|
|||
|
|
await expectStableScreenshot(page, "vendor-mobile-navigation.png");
|
|||
|
|
});
|
|||
|
|
});
|