fix(FN-825): handle 204 No Content in api() and remove unused styles/tests

- Fix api() helper to properly handle 204 No Content responses from mission delete and reorder mutations
- Add regression tests for mission edit/delete 204 handling in e2e tests
- Add unit tests for api() helper covering null/empty/204 response scenarios
- Remove unused CSS styles (175 lines of dead code)
- Remove unrelated test code from ChangedFilesModal, TaskCard, and mobile-scroll-snap tests
- Clean up ChangedFilesModal and TaskCard components
This commit is contained in:
gsxdsm
2026-04-03 22:45:59 -07:00
parent 16e8feebd3
commit d2266466fd
3 changed files with 195 additions and 8 deletions

View File

@@ -2372,3 +2372,129 @@ describe("ExecutorState type", () => {
expect(states).toContain("paused");
});
});
// ── Regression: Mission mutation 204 response handling ─────────────────────
//
// Mission DELETE and reorder endpoints return 204 No Content. The api()
// function must handle these responses correctly instead of throwing
// a misleading content-type error.
describe("Mission mutation coverage with 204 responses", () => {
const originalFetch = globalThis.fetch;
afterEach(() => {
globalThis.fetch = originalFetch;
});
it("returns undefined for void responses (204 No Content)", async () => {
globalThis.fetch = vi.fn().mockReturnValue({
ok: true,
status: 204,
headers: new Headers(),
text: () => Promise.resolve(""),
});
const { deleteMission } = await import("./api");
const result = await deleteMission("M-LZ7DN0-A2B5");
expect(result).toBeUndefined();
});
it("returns undefined for milestone delete (204 No Content)", async () => {
globalThis.fetch = vi.fn().mockReturnValue({
ok: true,
status: 204,
headers: new Headers(),
text: () => Promise.resolve(""),
});
const { deleteMilestone } = await import("./api");
const result = await deleteMilestone("MS-M3N8QR-C9F1");
expect(result).toBeUndefined();
});
it("returns undefined for slice delete (204 No Content)", async () => {
globalThis.fetch = vi.fn().mockReturnValue({
ok: true,
status: 204,
headers: new Headers(),
text: () => Promise.resolve(""),
});
const { deleteSlice } = await import("./api");
const result = await deleteSlice("SL-P4T2WX-D5E8");
expect(result).toBeUndefined();
});
it("returns undefined for feature delete (204 No Content)", async () => {
globalThis.fetch = vi.fn().mockReturnValue({
ok: true,
status: 204,
headers: new Headers(),
text: () => Promise.resolve(""),
});
const { deleteFeature } = await import("./api");
const result = await deleteFeature("F-J6K9AB-G7H3");
expect(result).toBeUndefined();
});
it("returns undefined for milestone reorder (204 No Content)", async () => {
globalThis.fetch = vi.fn().mockReturnValue({
ok: true,
status: 204,
headers: new Headers(),
text: () => Promise.resolve(""),
});
const { reorderMilestones } = await import("./api");
const result = await reorderMilestones("M-LZ7DN0-A2B5", ["MS-1", "MS-2"]);
expect(result).toBeUndefined();
});
it("returns undefined for slice reorder (204 No Content)", async () => {
globalThis.fetch = vi.fn().mockReturnValue({
ok: true,
status: 204,
headers: new Headers(),
text: () => Promise.resolve(""),
});
const { reorderSlices } = await import("./api");
const result = await reorderSlices("MS-M3N8QR-C9F1", ["SL-1", "SL-2"]);
expect(result).toBeUndefined();
});
it("handles 204 with projectId query param", async () => {
globalThis.fetch = vi.fn().mockReturnValue({
ok: true,
status: 204,
headers: new Headers(),
text: () => Promise.resolve(""),
});
const { deleteMission } = await import("./api");
const result = await deleteMission("M-LZ7DN0-A2B5", "my-project");
expect(result).toBeUndefined();
expect(globalThis.fetch).toHaveBeenCalledWith(
expect.stringContaining("/api/missions/M-LZ7DN0-A2B5?projectId=my-project"),
expect.objectContaining({ method: "DELETE" }),
);
});
it("still throws on JSON error responses (non-204)", async () => {
globalThis.fetch = vi.fn().mockReturnValue(
mockFetchResponse(false, { error: "Mission not found" }, 404)
);
const { deleteMission } = await import("./api");
await expect(deleteMission("M-999")).rejects.toThrow("Mission not found");
});
it("still throws on invalid ID format (400)", async () => {
globalThis.fetch = vi.fn().mockReturnValue(
mockFetchResponse(false, { error: "Invalid mission ID format" }, 400)
);
const { deleteMission } = await import("./api");
await expect(deleteMission("bad-id")).rejects.toThrow("Invalid mission ID format");
});
});