Conversation
📝 WalkthroughWalkthroughIntroduces a DeletedUserNotice component and changes useUserDetails to return a discriminated union (ok / not-found). Consumers (pages/components) now use extractUserDetail and isUserDetailsNotFound to render user data or the DeletedUserNotice when a user is not found. Changes
Sequence Diagram(s)sequenceDiagram
participant Component as Page/Component
participant Hook as useUserDetails
participant API as Backend
rect rgba(200,200,255,0.5)
Component->>Hook: call useUserDetails(userId)
Hook->>API: GET /users/:userId
alt 200 OK
API-->>Hook: 200 + user data
Hook-->>Component: { kind: "ok", user }
Component->>Component: extractUserDetail() -> user
Component->>Component: render user info
else 404 / RecordNotFound
API-->>Hook: 404 / error indicating not found
Hook-->>Component: { kind: "not-found", userId }
Component->>Component: isUserDetailsNotFound() -> true
Component->>Component: render DeletedUserNotice(userId)
end
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
services/main-frontend/src/hooks/useUserDetails.ts (1)
57-68: Consider more robust error detection for RecordNotFound.The
message.includes("RecordNotFound")check is fragile as it depends on the exact error message format from the backend. If the backend error message format changes, this detection could break silently.Consider also checking for a structured error code if the backend provides one, or documenting this coupling with the backend error format.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@services/main-frontend/src/hooks/useUserDetails.ts` around lines 57 - 68, The current catch in useUserDetails (handling axiosError: AxiosError<ErrorResponse>) relies on message.includes("RecordNotFound"), which is brittle; update the detection in the catch block to first check for a structured error code (e.g., axiosError.response?.data?.code === "RecordNotFound" or other backend-provided code) and only fall back to inspecting the message if the code is absent, preserving the existing 404 check and returning the same { kind: "not-found", userId: safeUserId } shape; ensure you reference axiosError, ErrorResponse, and safeUserId in the changes and handle undefined response/data safely.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@services/main-frontend/src/hooks/useUserDetails.ts`:
- Around line 57-68: The current catch in useUserDetails (handling axiosError:
AxiosError<ErrorResponse>) relies on message.includes("RecordNotFound"), which
is brittle; update the detection in the catch block to first check for a
structured error code (e.g., axiosError.response?.data?.code ===
"RecordNotFound" or other backend-provided code) and only fall back to
inspecting the message if the code is absent, preserving the existing 404 check
and returning the same { kind: "not-found", userId: safeUserId } shape; ensure
you reference axiosError, ErrorResponse, and safeUserId in the changes and
handle undefined response/data safely.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
services/main-frontend/src/app/manage/course-instances/[id]/points/user_id/CourseInstanceUserInfoBox.tsxservices/main-frontend/src/app/manage/users/[id]/page.tsxservices/main-frontend/src/app/submissions/[id]/page.tsxservices/main-frontend/src/components/DeletedUserNotice.tsxservices/main-frontend/src/components/UserDisplay/index.tsxservices/main-frontend/src/hooks/useUserDetails.tsshared-module/packages/common/src/locales/en/main-frontend.json
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
system-tests/src/tests/add-user-country.spec.ts (2)
71-72:⚠️ Potential issue | 🟡 MinorResearch consent save should use
waitForSuccessNotification.The "Save" button click is a backend mutation but doesn't wait for confirmation. Compare with
user-research-consent.spec.tslines 40-45 which properly useswaitForSuccessNotificationfor the same action.🐛 Proposed fix
await researchConsentDialog.getByText("I want to participate in the").click() - await researchConsentDialog.getByRole("button", { name: "Save" }).click() + await waitForSuccessNotification(page, async () => { + await researchConsentDialog.getByRole("button", { name: "Save" }).click() + })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@system-tests/src/tests/add-user-country.spec.ts` around lines 71 - 72, The test clicks the research consent Save button without awaiting the backend mutation result; replace the direct click call with a call that uses the helper to wait for the success notification (use waitForSuccessNotification) around the click on researchConsentDialog.getByRole("button", { name: "Save" }) so the test waits for the backend response (see existing pattern in user-research-consent.spec.ts where waitForSuccessNotification wraps the save click).
63-65:⚠️ Potential issue | 🟡 MinorBackend mutation should use
waitForSuccessNotification.The "Create an account" click triggers a backend mutation but doesn't use
waitForSuccessNotification. This could cause flaky tests if the operation hasn't completed before proceeding. The same action increate-account-and-login.spec.tsproperly wraps it with the helper.As per coding guidelines: "For Playwright system tests, make sure each test that triggers a backend mutation (e.g., clicking a save button) waits for a UI confirmation element that proves the request completed successfully before proceeding. Prefer using
waitForSuccessNotificationfor success toasts."🐛 Proposed fix
- await page.getByRole("button", { name: "Create an account" }).click() - - await expect(page.getByText("Success", { exact: true })).toBeVisible() + await waitForSuccessNotification( + page, + async () => { + await page.getByRole("button", { name: "Create an account" }).click() + }, + "Success", + )🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@system-tests/src/tests/add-user-country.spec.ts` around lines 63 - 65, Replace the direct assertion that checks for the "Success" text after clicking the "Create an account" button with the standardized helper: call waitForSuccessNotification(page) after the await page.getByRole("button", { name: "Create an account" }).click() so the test waits for the backend mutation to complete; locate the click call in add-user-country.spec.ts and swap the await expect(page.getByText("Success", { exact: true })).toBeVisible() with await waitForSuccessNotification(page), and ensure the waitForSuccessNotification helper is imported where other specs (e.g., create-account-and-login.spec.ts) use it.
🧹 Nitpick comments (1)
system-tests/src/tests/user-research-consent.spec.ts (1)
71-72: Inconsistent logout approach within the same file.Line 48 uses the new
logoutViaTopbar(page)helper, but line 72 still uses the directtopbar2.logout(). Consider using the helper here as well for consistency, or if the immediateclickLogin()on line 73 makes the helper's login-link verification redundant, add a brief comment explaining why.♻️ Suggested refactor for consistency
- const topbar2 = new Topbar(page) - await topbar2.logout() - await topbar2.clickLogin() + await logoutViaTopbar(page) + const topbar2 = new Topbar(page) + await topbar2.clickLogin()🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@system-tests/src/tests/user-research-consent.spec.ts` around lines 71 - 72, The logout call is inconsistent: replace the direct Topbar.logout invocation (topbar2.logout()) with the shared helper logoutViaTopbar(page) to match the earlier usage, or if you intentionally keep the direct call because the immediate clickLogin() on the next line makes the helper's login-link verification redundant, add a one-line comment above topbar2.logout() explaining that rationale; update references to Topbar/topbar2 accordingly so only one logout approach (logoutViaTopbar or documented direct logout) is used in this file.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@system-tests/src/tests/add-user-country.spec.ts`:
- Around line 71-72: The test clicks the research consent Save button without
awaiting the backend mutation result; replace the direct click call with a call
that uses the helper to wait for the success notification (use
waitForSuccessNotification) around the click on
researchConsentDialog.getByRole("button", { name: "Save" }) so the test waits
for the backend response (see existing pattern in user-research-consent.spec.ts
where waitForSuccessNotification wraps the save click).
- Around line 63-65: Replace the direct assertion that checks for the "Success"
text after clicking the "Create an account" button with the standardized helper:
call waitForSuccessNotification(page) after the await page.getByRole("button", {
name: "Create an account" }).click() so the test waits for the backend mutation
to complete; locate the click call in add-user-country.spec.ts and swap the
await expect(page.getByText("Success", { exact: true })).toBeVisible() with
await waitForSuccessNotification(page), and ensure the
waitForSuccessNotification helper is imported where other specs (e.g.,
create-account-and-login.spec.ts) use it.
---
Nitpick comments:
In `@system-tests/src/tests/user-research-consent.spec.ts`:
- Around line 71-72: The logout call is inconsistent: replace the direct
Topbar.logout invocation (topbar2.logout()) with the shared helper
logoutViaTopbar(page) to match the earlier usage, or if you intentionally keep
the direct call because the immediate clickLogin() on the next line makes the
helper's login-link verification redundant, add a one-line comment above
topbar2.logout() explaining that rationale; update references to Topbar/topbar2
accordingly so only one logout approach (logoutViaTopbar or documented direct
logout) is used in this file.
ℹ️ Review info
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
system-tests/src/tests/add-user-country.spec.tssystem-tests/src/tests/create-account-and-login.spec.tssystem-tests/src/tests/user-research-consent.spec.ts
Summary by CodeRabbit