fix(usersui): distinguish a missing profile from a failed lookup [JDWLABS-492] - #226
Merged
Merged
Conversation
ProfilesService.handleError swallowed every failure into EMPTY, so subscribers never got an error notification. profile.component's error.status == 404 branch was dead code, and the page fell back to its field initializer's Add form for any failed lookup — a routing 404, a 401, a 500 — not just a genuine no-profile response. handleError now rethrows via throwError so callers can react to a real failure, matching the sibling data-access services' snackbar convention. getProfile distinguishes a genuine "no profile" 404 (the service's ResourceNotFoundException text/plain body) from any other 404 via the new isProfileNotFoundError helper, so only the former reaches profile.component as "Add" — everything else now surfaces a load error instead of a blank create form. Audited every other ProfilesService consumer for the same swallowed-error assumption: profiles-action-button-cell-renderer, user.component (deleteProfile/deleteAddress/deleteIcon), address.component and icon.component all subscribed without an error handler, which is now unhandled instead of silently dropped. Added no-op error handlers there, since the service already raises a snackbar on failure. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FvYBM6o7wARm2v9jmDp1yY
Three gaps from PR review on #226: - profiles.service.spec.ts's error-path tests used `subscribe({ next: () => fail(), error: (e) => expect(...) })`, but if handleError ever regresses to EMPTY, the observable completes without calling either callback and the assertions inside `error` never run — the suite stays green with the bug back. Added `expect.assertions(n)` to each of the 10 affected tests so a future regression fails loudly instead of silently. Verified by temporarily reintroducing the EMPTY return: 9 of the 10 now fail red (the 10th tests the no-profile bypass path, which doesn't call handleError and is correctly unaffected). - profiles.component.ts's new `error: () => { loading = false }` handler had no coverage. Added a spec that fails `getProfiles` and asserts `loading` clears without an unhandled error. - user.component.ts's three new delete error handlers (deleteProfile/deleteAddress/deleteIcon) had no coverage. A real `throwError(...)` reports unhandled errors asynchronously, which a synchronous `not.toThrow()` around the call site can't observe, so each spec instead captures the exact argument passed to `subscribe` and asserts it carries a real `error` function that runs without throwing and does not trigger a reload. Verified by temporarily reverting the handlers to bare next-only subscribes: all three new specs fail red. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FvYBM6o7wARm2v9jmDp1yY
jdwillmsen
deleted the
fix/JDWLABS-492-usersui-profile-error-handling
branch
September 6, 2026 05:19
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ProfilesService.handleErrorended every failure withreturn EMPTY, so subscribers never received an error notification.profile.component.ts'serror.status == 404branch was dead code, and the page fell back to its field initializer'stype = 'Add'for any failed lookup — a routing 404, a 401, a 500 — not just a genuine no-profile response.handleErrornow rethrows viathrowError(matching the sibling data-access services' "always snackbar" convention, just propagating instead of swallowing).getProfiledistinguishes a genuine "no profile" 404 — the profile-service contract'sResourceNotFoundExceptiontext/plainbody — from any other 404 via the newisProfileNotFoundErrorhelper, so only that case reachesprofile.componentas Add; everything else now surfaces a load-error state instead of a blank create form.ProfilesServiceconsumer for the same swallowed-error assumption:profiles-action-button-cell-renderer,user.component(deleteProfile/deleteAddress/deleteIcon),address.component,icon.component, andprofiles.componentall subscribed without an error handler, which is now unhandled instead of silently dropped. Added no-op error handlers there (the service already raises a snackbar on failure), andprofiles.component's handler also clears itsloadingflag.Test plan
npx nx run-many -t lint test -p frontend-usersui-data-access frontend-usersui-feature-core— green (30 + 51 tests, 0 lint errors)npx nx format:check --all— clean except pre-existing, untouchedapps/backend/usersrole/build/**artifactsnpx nx e2e platform-e2e— 77/77 passing (includes the updated Profile Form specs)Specs added
profiles.service.spec.ts:getProfile— no-profile 404 (no snackbar), routing 404 with a different body (snackbar + error), 500 (snackbar + error);handleError— propagates the original error instead of completing;isProfileNotFoundError— text/plain 404 true, other-body 404 false, non-404 false, non-HttpErrorResponse falseprofile.component.spec.ts: "shows the Edit form when a profile already exists", "shows the Add form when the user has no profile yet", "shows an error state for a routing 404 with a different body", "shows an error state for a 500"users.spec.ts(e2e): "Profile Form › renders in create mode" now mocks the genuine no-profile 404 instead of relying on an unreachable backend🤖 Generated with Claude Code
https://claude.ai/code/session_01FvYBM6o7wARm2v9jmDp1yY