pelagia-portal/App/tests/unit/project-code-field.test.tsx
Hardik 02c0806d35
All checks were successful
PR checks / checks (pull_request) Successful in 51s
PR checks / integration (pull_request) Successful in 32s
refactor(po): admin-managed Project Codes instead of a static list
Replaces the hardcoded PROJECT_CODES array with an admin-managed
`ProjectCode` model, mirroring the Delivery Locations pattern (PR #100):

- ProjectCode model (unique `code` + isActive) + migration seeding the
  five previously-hardcoded codes; PO.projectCode stays a free-text
  snapshot (no FK) so history/exports/imports are unchanged.
- manage_project_codes permission (Manager + SuperUser + Admin).
- /admin/project-codes CRUD screen (table + Add/Edit + activate/delete)
  and an Administration sidebar link.
- ProjectCodeField now takes `options` from the active codes; the three
  PO forms + pages fetch them from the DB. Static list removed.
- Unit test reworked to the options API; CRUD integration test added;
  documented in App/CLAUDE.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 02:52:03 +05:30

55 lines
2.4 KiB
TypeScript

import { describe, it, expect } from "vitest";
import { render, screen } from "@testing-library/react";
import { ProjectCodeField } from "@/components/po/project-code-field";
const OPTIONS = ["Petronet LNG Cochin", "Haldia Reach", "COMACOE Mandvi"];
function options(container: HTMLElement) {
return Array.from(container.querySelectorAll("option")).map((o) => ({
value: o.getAttribute("value"),
text: o.textContent,
}));
}
describe("ProjectCodeField", () => {
it("renders a select named projectCode with an empty option + every supplied code", () => {
const { container } = render(<ProjectCodeField options={OPTIONS} />);
const select = container.querySelector("select");
expect(select?.getAttribute("name")).toBe("projectCode");
const opts = options(container);
// empty "none" option first, then exactly the supplied codes
expect(opts[0].value).toBe("");
expect(opts.slice(1).map((o) => o.value)).toEqual(OPTIONS);
});
it("selects a current value that is one of the options (no duplicate option)", () => {
const { container } = render(<ProjectCodeField options={OPTIONS} current="Haldia Reach" />);
const select = container.querySelector("select") as HTMLSelectElement;
expect(select.value).toBe("Haldia Reach");
// only the options + empty option — no extra "(current)" entry
expect(container.querySelectorAll("option")).toHaveLength(OPTIONS.length + 1);
});
it("preserves a legacy current value not in the list as a leading (current) option", () => {
const { container } = render(<ProjectCodeField options={OPTIONS} current="Legacy Project X" />);
const select = container.querySelector("select") as HTMLSelectElement;
expect(select.value).toBe("Legacy Project X");
expect(screen.getByText("Legacy Project X (current)")).toBeInTheDocument();
// empty + (current) + options
expect(container.querySelectorAll("option")).toHaveLength(OPTIONS.length + 2);
});
it("defaults to the empty option when no current value is given", () => {
const { container } = render(<ProjectCodeField options={OPTIONS} current={null} />);
const select = container.querySelector("select") as HTMLSelectElement;
expect(select.value).toBe("");
});
it("renders just the empty option when no codes are configured", () => {
const { container } = render(<ProjectCodeField options={[]} />);
const opts = options(container);
expect(opts).toHaveLength(1);
expect(opts[0].value).toBe("");
});
});