pelagia-portal/App/tests/integration/delivery-locations.test.ts
Hardik 5aae45299b
All checks were successful
PR checks / checks (pull_request) Successful in 42s
PR checks / integration (pull_request) Successful in 30s
feat(po): admin-managed delivery locations + Place of Delivery dropdown (#19)
Replaces the free-text "Place of Delivery" with a dropdown sourced from a new
admin-managed Delivery Locations list (each = a Company FK + free-text address).

- schema + migration: new DeliveryLocation model (companyId, address, isActive).
- permission: manage_delivery_locations granted to Manager + SuperUser + Admin
  (Manager-accessible, not admin-only, per the issue).
- admin screen /admin/delivery-locations: table + Add/Edit dialogs +
  activate/deactivate + delete (mirrors /admin/sites); sidebar link under
  Administration for Manager/SuperUser/Admin.
- PO forms (new / edit / manager-edit): shared <DeliveryLocationField> native
  select populated from active locations, formatted "Company — address".
- PurchaseOrder.placeOfDelivery stays a free-text SNAPSHOT (no FK) — the dropdown
  only changes how the value is picked, so export/import/historical POs are
  unchanged, and an edit preserves a current value not in the list as a
  "(current)" option. Deleting a location is therefore always safe.
- tests: delivery-location CRUD + permission guard (6).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 02:08:59 +05:30

89 lines
3.8 KiB
TypeScript

/**
* Integration tests for the Delivery Locations admin CRUD (issue #19).
* Covers create/update/toggle/delete + the manage_delivery_locations guard.
*/
import { vi, describe, it, expect, beforeAll, afterAll } from "vitest";
vi.mock("@/auth", () => ({ auth: vi.fn() }));
vi.mock("next/cache", () => ({ revalidatePath: vi.fn() }));
import { auth } from "@/auth";
import { db } from "@/lib/db";
import {
createDeliveryLocation,
updateDeliveryLocation,
toggleDeliveryLocationActive,
deleteDeliveryLocation,
} from "@/app/(portal)/admin/delivery-locations/actions";
import { makeSession, fd } from "./helpers";
const mockedAuth = vi.mocked(auth);
const PREFIX = "INTTEST_DELLOC_";
let companyId: string;
const asManager = () => mockedAuth.mockResolvedValue(makeSession("u-mgr", "MANAGER") as never);
beforeAll(async () => {
const company = await db.company.create({ data: { name: `${PREFIX}Co`, code: "ZZDELLOC" } });
companyId = company.id;
});
afterAll(async () => {
await db.deliveryLocation.deleteMany({ where: { companyId } });
await db.company.deleteMany({ where: { name: { startsWith: PREFIX } } });
});
describe("createDeliveryLocation", () => {
it("persists a location tied to its company", async () => {
asManager();
const result = await createDeliveryLocation(fd({ companyId, address: "Dock 4, Mumbai" }));
expect(result).toEqual({ ok: true });
const loc = await db.deliveryLocation.findFirstOrThrow({ where: { companyId, address: "Dock 4, Mumbai" } });
expect(loc.isActive).toBe(true);
expect(loc.companyId).toBe(companyId);
});
it("requires both a company and an address", async () => {
asManager();
expect("error" in (await createDeliveryLocation(fd({ companyId, address: " " })))).toBe(true);
expect("error" in (await createDeliveryLocation(fd({ companyId: "", address: "x" })))).toBe(true);
});
it("rejects a company that no longer exists", async () => {
asManager();
const result = await createDeliveryLocation(fd({ companyId: "nonexistent", address: "x" }));
expect("error" in result).toBe(true);
});
it("refuses callers without manage_delivery_locations", async () => {
mockedAuth.mockResolvedValue(makeSession("u-tech", "TECHNICAL") as never);
expect(await createDeliveryLocation(fd({ companyId, address: "x" }))).toEqual({ error: "Forbidden" });
mockedAuth.mockResolvedValue(makeSession("u-acc", "ACCOUNTS") as never);
expect(await createDeliveryLocation(fd({ companyId, address: "x" }))).toEqual({ error: "Forbidden" });
});
});
describe("updateDeliveryLocation / toggle / delete", () => {
it("edits, toggles active, then deletes a location", async () => {
asManager();
await createDeliveryLocation(fd({ companyId, address: "Old Address" }));
const loc = await db.deliveryLocation.findFirstOrThrow({ where: { companyId, address: "Old Address" } });
expect(await updateDeliveryLocation(loc.id, fd({ companyId, address: "New Address" }))).toEqual({ ok: true });
expect((await db.deliveryLocation.findUniqueOrThrow({ where: { id: loc.id } })).address).toBe("New Address");
expect(await toggleDeliveryLocationActive(loc.id)).toEqual({ ok: true });
expect((await db.deliveryLocation.findUniqueOrThrow({ where: { id: loc.id } })).isActive).toBe(false);
expect(await deleteDeliveryLocation(loc.id)).toEqual({ ok: true });
expect(await db.deliveryLocation.findUnique({ where: { id: loc.id } })).toBeNull();
});
it("guards update/toggle/delete behind the permission", async () => {
mockedAuth.mockResolvedValue(makeSession("u-tech", "TECHNICAL") as never);
expect(await updateDeliveryLocation("x", fd({ companyId, address: "y" }))).toEqual({ error: "Forbidden" });
expect(await toggleDeliveryLocationActive("x")).toEqual({ error: "Forbidden" });
expect(await deleteDeliveryLocation("x")).toEqual({ error: "Forbidden" });
});
});