Skip to content

Commit d28924e

Browse files
committed
Update backend test
1 parent b51978d commit d28924e

File tree

2 files changed

+228
-7
lines changed

2 files changed

+228
-7
lines changed
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
import request from "supertest";
2+
import app from "../src/index";
3+
import timetablesController from "../src/controllers/timetablesController";
4+
import { Request, Response, NextFunction } from "express";
5+
import { jest, describe, test, expect, beforeEach } from "@jest/globals";
6+
import { supabase } from "../src/db/setupDb";
7+
import { authHandler } from "../src/middleware/authHandler";
8+
import {
9+
Json,
10+
mapValues,
11+
} from "@pinecone-database/pinecone/dist/pinecone-generated-ts-fetch/db_control";
12+
import { stringify } from "qs";
13+
14+
const mockAuthHandler = (user_id: string) => {
15+
return (req: Request, res: Response, next: NextFunction) => {
16+
(req as any).user = { id: user_id }; // Inject user_id dynamically
17+
next();
18+
19+
console.log((req as any).user.id);
20+
};
21+
};
22+
23+
// Mock authHandler globally
24+
jest.mock("../src/middleware/authHandler", () => ({
25+
authHandler: jest.fn() as jest.MockedFunction<typeof authHandler>,
26+
}));
27+
28+
// Mock timetables data
29+
const mockTimetables1 = [
30+
{
31+
id: 1,
32+
name: "Timetable 1",
33+
user_id: "ab9e6877-f603-4c6a-9832-864e520e4d01",
34+
},
35+
{
36+
id: 2,
37+
name: "Timetable 2",
38+
user_id: "ab9e6877-f603-4c6a-9832-864e520e4d01",
39+
},
40+
];
41+
42+
jest.mock("../src/db/setupDb", () => ({
43+
supabase: {
44+
from: jest.fn(() => ({
45+
select: jest.fn().mockImplementation(() => {
46+
let mockQuery = {
47+
filters: {} as Record<string, any>, // Store multiple filters
48+
49+
eq: jest.fn(function (this: any, column: string, value: any) {
50+
this.filters[column] = value;
51+
return this; // Ensure method chaining works
52+
}) as (column: string, value: any) => any,
53+
54+
then: jest.fn(function (
55+
this: any,
56+
callback: (result: { data: any[]; error: null }) => void
57+
) {
58+
// Simulate Supabase filtering logic
59+
const { user_id, timetable_title } = this.filters;
60+
61+
if (
62+
user_id === "valid-user-id" &&
63+
timetable_title === "Test Timetable"
64+
) {
65+
return callback({
66+
data: [{ id: 1, title: "Test Timetable", semester: "Fall" }],
67+
error: null,
68+
});
69+
}
70+
return callback({ data: [], error: null });
71+
}) as (
72+
callback: (result: { data: any[]; error: null }) => void
73+
) => any,
74+
};
75+
76+
return mockQuery;
77+
}),
78+
})),
79+
insert: jest.fn().mockImplementation((data: Json) => {
80+
return {
81+
data: [{ ...data[0], id: 1 }],
82+
error: null,
83+
};
84+
}),
85+
},
86+
}));
87+
88+
/**
89+
// Mock the Supabase database calls for different user_ids
90+
jest.mock("../src/db/setupDb", () => ({
91+
supabase: {
92+
schema: jest.fn().mockReturnThis(),
93+
from: jest.fn().mockReturnThis(),
94+
select: jest.fn().mockReturnThis(),
95+
eq: jest.fn().mockImplementation((key: unknown, value: unknown) => {
96+
const typedKey = key as string;
97+
const typedValue = value as string;
98+
99+
// Create an object to hold the key-value pairs for eq() checks
100+
const eqCalls: { [key: string]: string | undefined } = {};
101+
eqCalls[typedKey] = typedValue;
102+
103+
// Skip the duplicate title check for testing
104+
if (eqCalls.user_id === "ab9e6877-f603-4c6a-9832-864e520e4d01") {
105+
if (eqCalls.timetable_title === "Test Timetable") {
106+
// Simulate that the title doesn't block the creation of a new timetable
107+
return { data: [], error: null }; // No duplicate found, return an empty array
108+
}
109+
return { data: mockTimetables1, error: null }; // Existing timetable found
110+
}
111+
112+
if (eqCalls.user_id === "1d3f02df-f926-4c1f-9f41-58ca50816a33") {
113+
return { data: null, error: null };
114+
}
115+
116+
return { data: null, error: null }; // Default return if no conditions match
117+
}),
118+
insert: jest.fn().mockImplementation((data: Json) => {
119+
return {
120+
data: [{ ...data[0], id: 1 }],
121+
error: null,
122+
};
123+
}),
124+
},
125+
}));
126+
*/
127+
128+
// Spy on the getTimetables method
129+
jest
130+
.spyOn(timetablesController, "getTimetables")
131+
.mockImplementation(timetablesController.getTimetables);
132+
133+
// Spy on the createTimetable method
134+
jest
135+
.spyOn(timetablesController, "createTimetable")
136+
.mockImplementation(timetablesController.createTimetable);
137+
138+
// Spy on the updateTimetable method
139+
jest
140+
.spyOn(timetablesController, "updateTimetable")
141+
.mockImplementation(timetablesController.updateTimetable);
142+
143+
// Spy on the deleteTimetable method
144+
jest
145+
.spyOn(timetablesController, "deleteTimetable")
146+
.mockImplementation(timetablesController.deleteTimetable);
147+
148+
describe("GET /api/timetables", () => {
149+
beforeEach(() => {
150+
jest.clearAllMocks();
151+
});
152+
153+
test("should return timetables for user 1", async () => {
154+
// Initialize the session with user 1's ID
155+
(
156+
authHandler as jest.MockedFunction<typeof authHandler>
157+
).mockImplementationOnce(
158+
mockAuthHandler("ab9e6877-f603-4c6a-9832-864e520e4d01")
159+
);
160+
161+
const response = await request(app).get("/api/timetables");
162+
163+
// Check database interaction and response
164+
expect(response.statusCode).toBe(200);
165+
expect(response.body).toEqual(mockTimetables1);
166+
});
167+
168+
test("should return 404 if no timetables found", async () => {
169+
// Initialize the session with a non-existent user ID
170+
(
171+
authHandler as jest.MockedFunction<typeof authHandler>
172+
).mockImplementationOnce(
173+
mockAuthHandler("1d3f02df-f926-4c1f-9f41-58ca50816a33")
174+
);
175+
176+
const response = await request(app).get("/api/timetables");
177+
178+
console.log(response.body);
179+
// Verify the response status and error message
180+
expect(response.statusCode).toBe(404);
181+
expect(response.body).toEqual({
182+
error: "Calendar id not found",
183+
});
184+
});
185+
});
186+
187+
describe("POST /api/timetables", () => {
188+
beforeEach(() => {
189+
jest.clearAllMocks;
190+
});
191+
192+
test("should create a new timetable given timetable title, timetable semester, timetable favorite", async () => {
193+
const user_id = "1d3f02df-f926-4c1f-9f41-58ca50816a33";
194+
const newTimetable = {
195+
timetable_title: "Minh timetable",
196+
semester: "Fall 2025",
197+
favorite: false,
198+
};
199+
200+
(
201+
authHandler as jest.MockedFunction<typeof authHandler>
202+
).mockImplementationOnce(mockAuthHandler(user_id));
203+
204+
const response = await request(app)
205+
.post("/api/timetables")
206+
.send(newTimetable);
207+
// Check database interaction and response
208+
expect(response.statusCode).toBe(201); // Created
209+
expect(response.body).toEqual([
210+
{
211+
id: 1,
212+
user_id,
213+
timetable_title: "Minh timetable",
214+
semester: "Fall 2025",
215+
favorite: false,
216+
},
217+
]);
218+
});
219+
});

course-matrix/backend/src/controllers/timetablesController.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,29 @@ export default {
2626
.json({ error: "timetable title and semester are required" });
2727
}
2828

29+
console.log("Comming into the check duplicate timetable_title");
2930
// Check if a timetable with the same title already exist for this user
3031
const { data: existingTimetable, error: existingTimetableError } =
3132
await supabase
3233
.schema("timetable")
3334
.from("timetables")
34-
.select("id")
35+
.select("*")
3536
.eq("user_id", user_id)
36-
.eq("timetable_title", timetable_title)
37-
.maybeSingle();
37+
.eq("timetable_title", timetable_title);
38+
console.log("pass the querying");
39+
console.log(existingTimetable);
40+
console.log(existingTimetableError);
3841

3942
if (existingTimetableError) {
4043
return res.status(400).json({ error: existingTimetableError.message });
4144
}
4245

43-
if (existingTimetable) {
46+
if (existingTimetable && existingTimetable.length > 0) {
4447
return res
4548
.status(400)
4649
.json({ error: "A timetable with this title already exists" });
4750
}
51+
console.log("Comming out the check duplicate timetable_title");
4852

4953
console.log("Calling Supabase insert...");
5054
//Create query to insert the user_id and timetable_title into the db
@@ -58,9 +62,7 @@ export default {
5862
semester,
5963
favorite,
6064
},
61-
])
62-
.select()
63-
.single();
65+
]);
6466

6567
const { data: timetableData, error: timetableError } =
6668
await insertTimetable;

0 commit comments

Comments
 (0)