diff --git a/API.md b/API.md index d3d90823..af5befc8 100644 --- a/API.md +++ b/API.md @@ -248,20 +248,35 @@ Users can always see and manipulate their own profile. The profile object is a p - **Description**: Retrieve a list of projects the authenticated user is a member of. - **Responses**: - - **200**: Projects found + - **200**: Projects found (or empty list if user has no projects) ```json - [ - { - "_id": "hexstring", - "label": "string", - "roles": ["string"] - }, ... - ] + { + "metrics": { + "newest": "project:hexstring/page:hexstring", + "lastModified": "project:hexstring/page:hexstring", + "myRecent": "hexstring" + }, + "projects": [ + { + "_id": "hexstring", + "label": "string", + "roles": ["string"] + }, ... + ] + } + ``` + + When the user has no projects, returns: + ```json + { + "metrics": null, + "projects": [] + } ``` - **401**: Unauthorized - **500**: Server error -The response is a list of projects the user is a member of regardless of the permissions afforded to them in each project. +The response includes a list of projects the user is a member of regardless of the permissions afforded to them in each project, along with metrics about the newest and most recently modified projects. #### `GET /user/:id` diff --git a/classes/User/__tests__/unit.test.js b/classes/User/__tests__/unit.test.js index d9893ffb..9ca2396b 100644 --- a/classes/User/__tests__/unit.test.js +++ b/classes/User/__tests__/unit.test.js @@ -154,3 +154,28 @@ describe("GET /my/projects #user_class", () => { expect(response.status).toBe(401) }) }) + +describe("GET /my/projects with no projects #user_class", () => { + beforeAll(() => { + jest.spyOn(User.prototype, "getProjects").mockResolvedValue([]) + jest.spyOn(User.prototype, "getSelf").mockResolvedValue({ + _id: "123456", + _lastModified: null + }) + }) + + afterAll(() => { + jest.restoreAllMocks() + }) + + it.skip("should return 200 with empty projects array when user has no projects", async () => { + const response = await request(app) + .get("/my/projects") + .set("Authorization", `Bearer ${token}`) + expect(response.status).toBe(200) + expect(response.body).toHaveProperty("projects") + expect(Array.isArray(response.body.projects)).toBe(true) + expect(response.body.projects.length).toBe(0) + expect(response.body.metrics).toBeNull() + }) +}) diff --git a/userProfile/privateProfile.js b/userProfile/privateProfile.js index 9b3d508c..555a8279 100644 --- a/userProfile/privateProfile.js +++ b/userProfile/privateProfile.js @@ -44,8 +44,15 @@ router.route("/projects").get(auth0Middleware(), async (req, res) => { const userObj = await new User(user._id) const userProjects = await userObj.getProjects() const validMetrics = userProjects.filter((proj) => proj._createdAt && proj._modifiedAt && proj._lastModified) + + res.set("Content-Type", "application/json; charset=utf-8") + if (validMetrics.length === 0) { - return respondWithError(res, 404, "No valid projects found") + // Return empty response when user has no projects + return res.status(200).json({ + metrics: null, + projects: [] + }) } // TODO: When the projects are all formatted correctly, we will not need this @@ -59,8 +66,6 @@ router.route("/projects").get(auth0Middleware(), async (req, res) => { const userData = await userObj.getSelf() const myRecent = userData._lastModified - res.set("Content-Type", "application/json; charset=utf-8") - res.status(200).json({ metrics: { newest,