From 855ac0a25c2d1eb75ea189bd99d3a999d1d7d3da Mon Sep 17 00:00:00 2001 From: Mercy017 Date: Mon, 31 Aug 2026 17:23:37 +0100 Subject: [PATCH] fix: restore GET /api/v1/users/me/learning-path route registration (#359) The route registration for /me/learning-path was already wired up to userController.getLearningPath (itself fully implemented, along with userService.getLearningPath), but was missing its closing ');' -- the route handler callback ran straight into the next app.get<...>( call with no statement terminator, a syntax error that broke parsing of the entire file. Fixes the syntax error and adds e2e coverage (auth rejection + shape of the returned recommendation array), matching the tolerance pattern already used by the other /me/* tests in this file for environments without a seeded user. Closes #351 Closes #359 Closes #365 Closes #364 --- src/modules/users/user.routes.ts | 2 ++ tests/e2e/users.test.ts | 38 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/modules/users/user.routes.ts b/src/modules/users/user.routes.ts index 4a72ea5..0974537 100644 --- a/src/modules/users/user.routes.ts +++ b/src/modules/users/user.routes.ts @@ -104,6 +104,8 @@ export async function userRoutes(app: FastifyInstance): Promise { } as FastifySchema, }, (request, reply) => userController.getLearningPath(request, reply) + ); + app.get<{ Querystring: import("../notifications/notification.types.js").ListNotificationsQuery }>( "/me/notifications", { diff --git a/tests/e2e/users.test.ts b/tests/e2e/users.test.ts index 71538c8..5cbc754 100644 --- a/tests/e2e/users.test.ts +++ b/tests/e2e/users.test.ts @@ -171,6 +171,44 @@ describe("Users API", () => { }); }); + describe("GET /api/v1/users/me/learning-path", () => { + it("should reject unauthenticated requests", async () => { + const response = await app.inject({ + method: "GET", + url: "/api/v1/users/me/learning-path", + }); + + expect(response.statusCode).toBe(401); + }); + + it("should return an array of course recommendations for an authenticated user", async () => { + const token = createToken(); + + const response = await app.inject({ + method: "GET", + url: "/api/v1/users/me/learning-path", + headers: { authorization: `Bearer ${token}` }, + }); + + // May return 200 (success), 401 (auth rejected), or 404 (user not + // seeded in this environment's DB) -- mirrors the tolerance the other + // /me/* tests in this file use, since these e2e tests run against + // whatever DB state happens to be present. + expect([200, 401, 404]).toContain(response.statusCode); + if (response.statusCode === 200) { + const body = JSON.parse(response.payload); + expect(body.success).toBe(true); + expect(Array.isArray(body.data)).toBe(true); + for (const recommendation of body.data) { + expect(typeof recommendation.courseId).toBe("string"); + expect(typeof recommendation.courseTitle).toBe("string"); + expect(typeof recommendation.difficulty).toBe("string"); + expect(typeof recommendation.rationale).toBe("string"); + } + } + }); + }); + describe("GET /api/v1/users/me/activity", () => { it("should reject unauthenticated requests", async () => { const response = await app.inject({