shoc-frontend-new/src/test/app/v/uplift-request-form.test.tsx

84 lines
2.9 KiB
TypeScript
Raw Normal View History

import { fireEvent, render, screen, waitFor } from "@testing-library/react";
import { describe, expect, it, vi } from "vitest";
import { UpliftRequestForm } from "@/app/v/[token]/dispatch/_components/uplift-request-form";
function renderForm(overrides: Partial<React.ComponentProps<typeof UpliftRequestForm>> = {}) {
return render(
<UpliftRequestForm
mode="revise"
currentNte={1000}
initialRequested="1000"
initialReason=""
hasExistingEvidence={false}
submitting={false}
uploadingPercent={undefined}
errorMessage=""
onSubmit={vi.fn()}
onCancel={vi.fn()}
{...overrides}
/>,
);
}
describe("UpliftRequestForm revise mode", () => {
it("shows reason and evidence fields regardless of amount", () => {
renderForm({ initialRequested: "900" });
expect(screen.getByLabelText(/reason/i)).toBeInTheDocument();
expect(screen.getByLabelText(/evidence/i)).toBeInTheDocument();
});
it("blocks submit and does not call onSubmit when revised NTE is at or below current NTE", () => {
const onSubmit = vi.fn();
renderForm({ initialRequested: "1000", onSubmit });
fireEvent.click(screen.getByRole("button", { name: /submit revision/i }));
expect(onSubmit).not.toHaveBeenCalled();
expect(screen.getByText(/must be greater than the current NTE/i)).toBeInTheDocument();
});
it("refuses photo evidence when the work order already has 10 photos", async () => {
renderForm({ mediaUsage: { photos: 10, videos: 0, maxPhotos: 10, maxVideos: 3 } });
fireEvent.change(screen.getByLabelText(/evidence/i), {
target: { files: [new File(["jpg"], "receipt.jpg", { type: "image/jpeg" })] },
});
expect(await screen.findByText("A work order can have at most 10 photos.")).toBeInTheDocument();
});
it("offers and accepts the same phone photo and video types as the upload allowlist", async () => {
renderForm();
const input = screen.getByLabelText("Evidence (PDF, JPG, PNG, HEIC, MP4, MOV)");
expect(input.getAttribute("accept")?.split(",")).toEqual(
expect.arrayContaining([".pdf", ".jpg", ".png", ".heic", ".mp4", ".mov"]),
);
fireEvent.change(input, {
target: { files: [new File(["gif"], "clip.gif", { type: "image/gif" })] },
});
expect(
await screen.findByText("Only PDF, JPG, PNG, HEIC, MP4, and MOV files are allowed."),
).toBeInTheDocument();
fireEvent.change(input, {
target: { files: [new File(["heic"], "site.heic", { type: "" })] },
});
await waitFor(() =>
expect(
screen.queryByText("Only PDF, JPG, PNG, HEIC, MP4, and MOV files are allowed."),
).not.toBeInTheDocument(),
);
});
it("reports the current NTE threshold in the actionable error", () => {
renderForm({ initialRequested: "900", currentNte: 1000 });
fireEvent.click(screen.getByRole("button", { name: /submit revision/i }));
expect(screen.getByText(/\$1000\.00/)).toBeInTheDocument();
});
});