Repository navigation
test(frontend): cover ToastContainer a11y, public tracking, notification prefs + consolidate duplicate profile pages - #1430
Merged
Conversation
…ion prefs + consolidate duplicate profile pages
|
@Diggardson270 is attempting to deploy a commit to the Mftee's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@Diggardson270 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
mftee
approved these changes
Aug 28, 2026
3 tasks
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
Four frontend issues from the test-coverage / dead-route campaign. Three add
missing coverage — and FE-129 fixes a real frontend↔backend contract mismatch
uncovered while writing its tests. FE-130 consolidates a duplicate route.
No production dependency changes, no backend/schema changes.
FE-127 — ToastContainer aria-live announcement coverage (#1362)
Real-time shipment events (
useShipmentSocket) surface throughcomponents/ui/ToastContainer.tsx, so toast content must be announced toassistive technology. There was no test locking that in.
Added
components/ui/ToastContainer.test.tsx:aria-live="polite"region(asserted with
within(liveRegion), so a future refactor that moves the textout of the region fails the test).
role="alert"for immediate announcement.announcement is picked up.
components/ui/ToastContainer.tsxadded tocollectCoverageFrom(now 100%).No production code changed.
FE-128 — Public tracking page: invalid / unknown tracking number (#1363)
app/track/[trackingNumber]/page.tsxis public. There was no coverage for theinvalid-tracking-number path, nor a test pinning what an anonymous viewer is
allowed to see.
Added
app/track/[trackingNumber]/page.test.tsx:404from the API renders a clear "Shipment not found" state (not a rawerror, not a blank page).
unknown-but-well-formed one — no "invalid format" / "bad pattern" wording that
would let a caller enumerate valid tracking-number shapes.
page).
data with no auth token / no login redirect, and exposes only the intended
public fields (route, status, cargo summary, weight, price, party names, ETA)
while not rendering contact emails, internal notes, or raw ids. This test
now acts as a change-detector for that boundary.
Added to
middleware.test.ts:/track/*passes through for unauthenticatedusers and is not caught by any protected-route prefix.
No production code changed — behaviour was already correct; it's now locked in.
FE-129 — Notification preferences did not round-trip with the backend (#1364)
While writing the requested test I found the frontend and
backend/src/notification-preferencesdid not agree:notification-preferences)NotificationPreference[]NotificationPreferencesentity objectshipment_in_transit)shipmentInTransit)shipment_created,document_uploadedUpdateNotificationPreferencesDtoshipmentCompletedSo
getPreferences()would have set state to a non-array and thrown on render,and every
updatePreferences()PATCH would have been ignored by the DTOwhitelist. The toggles could not have persisted.
Fixed
lib/api/notifications.api.ts:NotificationPreferenceKey(the 7 canonical camelCase keys matching theentity + DTO exactly),
NotificationPreferencesResponse, andNotificationPreferencesPatch.getPreferences()now fetches the backend entity and adapts it to thedisplay-ready
NotificationPreference[]viatoPreferenceList(), in a stableorder (
NOTIFICATION_PREFERENCE_KEYS).updatePreferences()is typed to send only DTO-valid keys and returns theupdated entity.
defaultPreferenceList()for the load-failure fallback.Updated
app/(dashboard)/settings/notifications/page.tsx:FALLBACK_PREFERENCES(which used the wrong keys) fordefaultPreferenceList().handleToggleis now typedNotificationPreferenceKey; the optimisticupdate / revert / toast flow is unchanged.
Added tests:
lib/api/notifications.api.test.ts— the adapter maps every entity flag ontoa display row preserving on/off state; the key set is exactly the DTO's key
set;
getPreferences()calls the right endpoint and adapts;updatePreferences()PATCHes a camelCase key the backend understands.
app/(dashboard)/settings/notifications/page.test.tsx— drivesapiClientagainst an in-memory copy of the backend row so GET reflects state and PATCH
persists it:
aria-checked),round-trip),
lib/api/notifications.api.tsadded tocollectCoverageFrom(100%).FE-130 — Two profile pages consolidated to one (#1365)
app/(dashboard)/profile/page.tsxandapp/(dashboard)/settings/profile/page.tsxboth edited name + Stellar wallet;
settings/profileadditionally repeated thepassword form that
/settingsalready provides. Only/profileis linkedanywhere in the app (sidebar + mobile nav);
grepfinds zero references to/settings/profile. It was an orphaned, confusing duplicate.Consolidated onto the linked, canonical
/profile:app/(dashboard)/profile/page.tsx— ported the stricter Stellar addressvalidation from the old settings page:
walletAddressstays optional but isnow validated against
/^G[A-Z2-7]{55}$/when present, with the error messagerendered under the field.
app/(dashboard)/settings/profile/page.tsx— replaced with a server-componentpermanent
redirect('/profile')plus a comment explaining the intentionalconsolidation and pointing at FE-130.
/settings(password) is unaffected andstill the place for password changes.
Added tests:
app/(dashboard)/settings/profile/page.test.tsx— the route redirects to/profileand renders no editable UI of its own.app/(dashboard)/profile/page.test.tsx—/profileis the single editor(name + wallet inputs + Save, alongside read-only account details); a
malformed Stellar address is rejected and not submitted; a well-formed one is
accepted and submitted; an empty wallet field is treated as "no wallet"
(optional), not an error.
Closes #1362
Closes #1363
Closes #1364
Closes #1365