Skip to content

Commit b27ee73

Browse files
committed
next/api/projects/delete: signed-in check inside try/catch + add test with mocking
1 parent 4749f39 commit b27ee73

File tree

2 files changed

+74
-4
lines changed

2 files changed

+74
-4
lines changed
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/** @jest-environment node */
2+
3+
import { createMocks } from "lib/api/test-framework";
4+
import handler from "./delete";
5+
6+
// Mock the dependencies
7+
jest.mock("@cocalc/server/projects/delete", () => jest.fn());
8+
jest.mock("lib/account/get-account", () => jest.fn());
9+
10+
describe("/api/v2/projects/delete", () => {
11+
beforeEach(() => {
12+
jest.clearAllMocks();
13+
});
14+
15+
test("unauthenticated request should return JSON error, not throw", async () => {
16+
// Mock getAccountId to return undefined (not authenticated)
17+
const getAccountId = require("lib/account/get-account");
18+
getAccountId.mockResolvedValue(undefined);
19+
20+
const { req, res } = createMocks({
21+
method: "POST",
22+
url: "/api/v2/projects/delete",
23+
body: {
24+
project_id: "00000000-0000-0000-0000-000000000000",
25+
},
26+
});
27+
28+
// This should NOT throw - it should handle the error gracefully
29+
await expect(handler(req, res)).resolves.not.toThrow();
30+
31+
// Should return JSON error response
32+
const data = res._getJSONData();
33+
expect(data).toHaveProperty("error");
34+
expect(data.error).toContain("must be signed in");
35+
});
36+
37+
test("authenticated request calls deleteProject", async () => {
38+
const mockAccountId = "11111111-1111-1111-1111-111111111111";
39+
const mockProjectId = "00000000-0000-0000-0000-000000000000";
40+
41+
// Mock getAccountId to return a valid account_id
42+
const getAccountId = require("lib/account/get-account");
43+
getAccountId.mockResolvedValue(mockAccountId);
44+
45+
// Mock deleteProject
46+
const deleteProject = require("@cocalc/server/projects/delete");
47+
deleteProject.mockResolvedValue(undefined);
48+
49+
const { req, res } = createMocks({
50+
method: "POST",
51+
url: "/api/v2/projects/delete",
52+
body: {
53+
project_id: mockProjectId,
54+
},
55+
});
56+
57+
await handler(req, res);
58+
59+
// Should call deleteProject with correct params
60+
expect(deleteProject).toHaveBeenCalledWith({
61+
account_id: mockAccountId,
62+
project_id: mockProjectId,
63+
});
64+
65+
// Should return OK status
66+
const data = res._getJSONData();
67+
expect(data).toHaveProperty("status");
68+
expect(data.status).toBe("ok");
69+
});
70+
});

src/packages/next/pages/api/v2/projects/delete.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ async function handle(req, res) {
1515
const { project_id } = getParams(req);
1616
const account_id = await getAccountId(req);
1717

18-
if (!account_id) {
19-
throw Error("must be signed in");
20-
}
21-
2218
try {
19+
if (!account_id) {
20+
throw Error("must be signed in");
21+
}
22+
2323
await deleteProject({ account_id, project_id });
2424
res.json(OkStatus);
2525
} catch (err) {

0 commit comments

Comments
 (0)