mirror of
https://github.com/Sea-Haven-Industries/shoc-frontend-new.git
synced 2026-10-02 10:53:13 +00:00
Two sections, Work order and Uplift request, divided by a single rule. Work order shows Service, Vendor / Technician, Assigned Dispatcher and Scheduled from the queue item, so it no longer fetches the work order and no longer degrades to Unavailable for account-scoped staff. Uplift request shows Requested By, Requested At, the justification in a bordered block, the approved-on-WO breakdown and a horizontal attachment row whose chips open the evidence in a new tab. Every field renders data or an explicit placeholder. The footer shows Reject and Approve for pending uplifts, Revoke for approved ones and nothing for read-only records; closing is the header X.
94 lines
3 KiB
TypeScript
94 lines
3 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
const apiGet = vi.fn();
|
|
const apiPost = vi.fn();
|
|
const apiRequestRaw = vi.fn();
|
|
|
|
vi.mock("@/api/api", () => ({
|
|
apiGet: (...args: unknown[]) => apiGet(...args),
|
|
apiPost: (...args: unknown[]) => apiPost(...args),
|
|
apiRequestRaw: (...args: unknown[]) => apiRequestRaw(...args),
|
|
}));
|
|
|
|
import { upliftsApi } from "@/domain/uplifts/api/uplifts-api";
|
|
|
|
describe("upliftsApi", () => {
|
|
beforeEach(() => {
|
|
apiGet.mockReset();
|
|
apiPost.mockReset();
|
|
apiRequestRaw.mockReset();
|
|
});
|
|
|
|
it("posts admin revoke decisions to the uplift decision endpoint", async () => {
|
|
apiPost.mockResolvedValueOnce(undefined);
|
|
|
|
await upliftsApi.revoke(42, "Scope was already covered");
|
|
|
|
expect(apiPost).toHaveBeenCalledWith("uplifts/42/revoke", {
|
|
note: "Scope was already covered",
|
|
});
|
|
});
|
|
|
|
it("reads the backend tier decision permission", async () => {
|
|
apiGet.mockResolvedValueOnce({ status: "Success", data: { canApprove: true } });
|
|
|
|
await expect(upliftsApi.canApprove(1)).resolves.toBe(true);
|
|
|
|
expect(apiGet).toHaveBeenCalledWith("uplifts/can-approve", { searchParams: { tier: 1 } });
|
|
});
|
|
|
|
it("treats a missing tier permission as false", async () => {
|
|
apiGet.mockResolvedValueOnce({ status: "Success", data: {} });
|
|
|
|
await expect(upliftsApi.canApprove(2)).resolves.toBe(false);
|
|
});
|
|
|
|
describe("openEvidence", () => {
|
|
function evidenceResponse(body: string, contentType: string): Response {
|
|
return new Response(body, {
|
|
headers: {
|
|
"Content-Type": contentType,
|
|
"Content-Disposition": 'attachment; filename="quote.pdf"',
|
|
},
|
|
});
|
|
}
|
|
|
|
function fakeTab() {
|
|
return { location: { href: "about:blank" }, close: vi.fn() };
|
|
}
|
|
|
|
beforeEach(() => {
|
|
URL.createObjectURL = vi.fn(() => "blob:evidence");
|
|
URL.revokeObjectURL = vi.fn();
|
|
});
|
|
|
|
it("renders an inert evidence type in the tab opened by the click", async () => {
|
|
apiRequestRaw.mockResolvedValueOnce(evidenceResponse("%PDF", "application/pdf"));
|
|
const tab = fakeTab();
|
|
|
|
await upliftsApi.openEvidence(7, tab as unknown as Window);
|
|
|
|
expect(apiRequestRaw).toHaveBeenCalledWith(
|
|
"get",
|
|
"uplifts/7/evidence",
|
|
undefined,
|
|
"upliftsApi.openEvidence",
|
|
);
|
|
expect(tab.location.href).toBe("blob:evidence");
|
|
expect(tab.close).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("downloads a type the browser could execute instead of rendering it on the app origin", async () => {
|
|
apiRequestRaw.mockResolvedValueOnce(evidenceResponse("<svg/>", "image/svg+xml"));
|
|
const tab = fakeTab();
|
|
const click = vi.spyOn(HTMLAnchorElement.prototype, "click").mockImplementation(() => {});
|
|
|
|
await upliftsApi.openEvidence(8, tab as unknown as Window);
|
|
|
|
expect(tab.location.href).toBe("about:blank");
|
|
expect(tab.close).toHaveBeenCalled();
|
|
expect(click).toHaveBeenCalled();
|
|
click.mockRestore();
|
|
});
|
|
});
|
|
});
|