mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-07 16:19:01 +00:00
Comment and mention items open the work order on the Comments tab with the comments they were raised for highlighted; a grouped assignment opens the dispatcher's own open queue; uplift decisions open the work order's uplifts. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
183 lines
6 KiB
TypeScript
183 lines
6 KiB
TypeScript
import { screen, waitFor, within } from "@testing-library/react";
|
|
import userEvent from "@testing-library/user-event";
|
|
import { useLocation } from "react-router";
|
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import { NotificationBell } from "@/components/notifications/notification-bell";
|
|
import { NotificationSessionProvider } from "@/domain/notifications/session/notification-session-provider";
|
|
import { renderWithProviders } from "@/test/test-utils";
|
|
|
|
const apiGet = vi.hoisted(() => vi.fn());
|
|
|
|
vi.mock("@/api/api", () => ({ apiGet }));
|
|
|
|
vi.mock("@/providers/auth-context", async (importOriginal) => ({
|
|
...(await importOriginal<typeof import("@/providers/auth-context")>()),
|
|
useAuthContext: () => ({ user: { id: "dispatcher-me" } }),
|
|
}));
|
|
|
|
type Target = { kind: "workOrder" | "queue"; workOrderId?: number; tab?: string; queue?: string };
|
|
|
|
function item(
|
|
id: string,
|
|
reason: string,
|
|
severity: string,
|
|
title: string,
|
|
target: Target,
|
|
extra = {},
|
|
) {
|
|
return {
|
|
id,
|
|
reason,
|
|
severity,
|
|
rowType: "dismissable",
|
|
title,
|
|
count: 1,
|
|
triggeredAt: "2026-09-18T12:00:00Z",
|
|
target,
|
|
workOrders: [],
|
|
...extra,
|
|
};
|
|
}
|
|
|
|
const mention = item("mention-501", "mentions", "High", "Omar Diaz mentioned you on WO #1011", {
|
|
kind: "workOrder",
|
|
workOrderId: 11,
|
|
tab: "comments",
|
|
});
|
|
|
|
const comments = item(
|
|
"comments-12-505",
|
|
"activity",
|
|
"Medium",
|
|
"2 new comments on WO #1012",
|
|
{ kind: "workOrder", workOrderId: 12, tab: "comments" },
|
|
{ triggeredAt: "2026-09-18T09:30:00Z" },
|
|
);
|
|
|
|
const assignedGroup = item(
|
|
"new-assigned-group-30",
|
|
"activity",
|
|
"Low",
|
|
"3 new work orders assigned to you",
|
|
{ kind: "queue", queue: "assigned-to-me" },
|
|
{ count: 3 },
|
|
);
|
|
|
|
const assignedOne = item("new-assigned-40", "activity", "Low", "WO #1040 was assigned to you", {
|
|
kind: "workOrder",
|
|
workOrderId: 40,
|
|
tab: "info",
|
|
});
|
|
|
|
const upliftRejected = item(
|
|
"uplift-rejected-9",
|
|
"activity",
|
|
"High",
|
|
"Your $400.00 uplift on WO #1020 was rejected: “Quote does not match”",
|
|
{ kind: "workOrder", workOrderId: 20, tab: "uplifts" },
|
|
);
|
|
|
|
const feed = {
|
|
generatedAt: "2026-09-18T16:00:00Z",
|
|
sections: [
|
|
{ reason: "mentions", label: "Mentions", severity: "High", count: 1, items: [mention] },
|
|
{
|
|
reason: "activity",
|
|
label: "Recent activity",
|
|
severity: "High",
|
|
count: 6,
|
|
items: [upliftRejected, comments, assignedOne, assignedGroup],
|
|
},
|
|
],
|
|
};
|
|
|
|
function LocationProbe() {
|
|
const location = useLocation();
|
|
return <output aria-label="Current location">{`${location.pathname}${location.search}`}</output>;
|
|
}
|
|
|
|
async function openItem(title: RegExp) {
|
|
const user = userEvent.setup();
|
|
renderWithProviders(
|
|
<NotificationSessionProvider>
|
|
<NotificationBell />
|
|
<LocationProbe />
|
|
</NotificationSessionProvider>,
|
|
{ withAuth: false },
|
|
);
|
|
await user.click(await screen.findByRole("button", { name: /^Notifications, \d+ unread$/ }));
|
|
const panel = await screen.findByRole("dialog");
|
|
await user.click(within(panel).getByRole("button", { name: title }));
|
|
await waitFor(() => expect(screen.queryByRole("dialog")).not.toBeInTheDocument());
|
|
const location = screen.getByRole("status", { name: "Current location" }).textContent ?? "";
|
|
return new URL(location, "http://localhost");
|
|
}
|
|
|
|
describe("event notifications in the Notification Center", () => {
|
|
beforeEach(() => {
|
|
apiGet.mockReset();
|
|
apiGet.mockResolvedValue(feed);
|
|
});
|
|
|
|
it("lists mentions, comments, assignments and uplift decisions in their sections", async () => {
|
|
const user = userEvent.setup();
|
|
renderWithProviders(
|
|
<NotificationSessionProvider>
|
|
<NotificationBell />
|
|
</NotificationSessionProvider>,
|
|
{ withAuth: false },
|
|
);
|
|
|
|
await user.click(await screen.findByRole("button", { name: "Notifications, 5 unread" }));
|
|
const panel = await screen.findByRole("dialog");
|
|
const mentions = within(panel).getByRole("region", { name: "Mentions, 1" });
|
|
expect(within(mentions).getByText(mention.title)).toBeInTheDocument();
|
|
const activity = within(panel).getByRole("region", { name: "Recent activity, 6" });
|
|
for (const row of [upliftRejected, comments, assignedOne, assignedGroup]) {
|
|
expect(within(activity).getByText(row.title)).toBeInTheDocument();
|
|
}
|
|
});
|
|
|
|
it("opens a comment item on the Comments tab with the comments to highlight", async () => {
|
|
const url = await openItem(/2 new comments on WO #1012/);
|
|
|
|
expect(url.pathname).toBe("/workorders");
|
|
expect(url.searchParams.get("wo")).toBe("12");
|
|
expect(url.searchParams.get("tab")).toBe("comments");
|
|
expect(url.searchParams.get("since")).toBe("2026-09-18T09:30:00Z");
|
|
expect(url.searchParams.get("focus")).toBe("comments");
|
|
});
|
|
|
|
it("opens a mention on the Comments tab focused on the mentioning comment", async () => {
|
|
const url = await openItem(/Omar Diaz mentioned you on WO #1011/);
|
|
|
|
expect(url.searchParams.get("wo")).toBe("11");
|
|
expect(url.searchParams.get("tab")).toBe("comments");
|
|
expect(url.searchParams.get("since")).toBe("2026-09-18T12:00:00Z");
|
|
expect(url.searchParams.get("focus")).toBe("mentions");
|
|
});
|
|
|
|
it("opens a grouped assignment as the signed-in dispatcher's open queue", async () => {
|
|
const url = await openItem(/3 new work orders assigned to you/);
|
|
|
|
expect(url.pathname).toBe("/workorders");
|
|
expect(url.searchParams.get("dispatchers")).toBe("dispatcher-me");
|
|
expect(url.searchParams.get("dateFrom")).toBe("1970-01-01");
|
|
expect(url.searchParams.get("dateTo")).toBe("2099-12-31");
|
|
expect(url.searchParams.get("statuses")).toBeTruthy();
|
|
expect(url.searchParams.get("wo")).toBeNull();
|
|
});
|
|
|
|
it("opens a single assignment straight on the work order, with no highlight", async () => {
|
|
const url = await openItem(/WO #1040 was assigned to you/);
|
|
|
|
expect(`${url.pathname}${url.search}`).toBe("/workorders?wo=40&tab=info");
|
|
});
|
|
|
|
it("opens an uplift decision on the work order's uplifts", async () => {
|
|
const url = await openItem(/uplift on WO #1020 was rejected/);
|
|
|
|
expect(`${url.pathname}${url.search}`).toBe("/workorders?wo=20&tab=uplifts");
|
|
});
|
|
});
|