Skip to content

Commit 260838e

Browse files
Handle malformed application status JSON
1 parent 1aa19cb commit 260838e

2 files changed

Lines changed: 37 additions & 1 deletion

File tree

src/app/api/applications/[id]/status/route.test.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,15 @@ function makeRequest(body: Record<string, unknown>) {
4040
});
4141
}
4242

43+
function makeRawRequest(body: string) {
44+
const url = "http://localhost/api/applications/test-app-id/status";
45+
return new NextRequest(url, {
46+
method: "PUT",
47+
headers: { "Content-Type": "application/json" },
48+
body,
49+
});
50+
}
51+
4352
const routeParams = { params: Promise.resolve({ id: "test-app-id" }) };
4453

4554
/** Build a chain-able Supabase query mock that resolves to `result`. */
@@ -99,6 +108,20 @@ describe("PUT /api/applications/[id]/status", () => {
99108
expect(res.status).toBe(400);
100109
});
101110

111+
it("returns 400 for malformed JSON without querying Supabase", async () => {
112+
mockGetAuthContext.mockResolvedValue({
113+
user: { id: "poster-user-id", authMethod: "session" },
114+
supabase: supabaseClient,
115+
} as MockAuthContext);
116+
117+
const res = await PUT(makeRawRequest("{"), routeParams);
118+
const json = await res.json();
119+
120+
expect(res.status).toBe(400);
121+
expect(json.error).toBe("Invalid JSON body");
122+
expect(mockFrom).not.toHaveBeenCalled();
123+
});
124+
102125
it("returns 404 when application not found", async () => {
103126
mockGetAuthContext.mockResolvedValue({
104127
user: { id: "poster-user-id", authMethod: "session" },

src/app/api/applications/[id]/status/route.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@ import { getAuthContext } from "@/lib/auth/get-user";
33
import { applicationStatusSchema } from "@/lib/validations";
44
import { getUserDid, onHired } from "@/lib/reputation-hooks";
55

6+
async function parseJsonBody(request: NextRequest) {
7+
try {
8+
return { body: await request.json() };
9+
} catch {
10+
return {
11+
response: NextResponse.json({ error: "Invalid JSON body" }, { status: 400 }),
12+
};
13+
}
14+
}
15+
616
// PUT /api/applications/[id]/status - Update application status
717
export async function PUT(
818
request: NextRequest,
@@ -16,7 +26,10 @@ export async function PUT(
1626
}
1727
const { user, supabase } = auth;
1828

19-
const body = await request.json();
29+
const parsed = await parseJsonBody(request);
30+
if (parsed.response) return parsed.response;
31+
32+
const body = parsed.body;
2033
const validationResult = applicationStatusSchema.safeParse(body);
2134

2235
if (!validationResult.success) {

0 commit comments

Comments
 (0)