Fix false-positive dynamic route matching when multiple suffixes match the same path#91621
Conversation
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
| const pathWithoutLeadingSlash = path.replaceAll(/^\/+/g, ''); | ||
| const match = findMatchingDynamicSuffix(pathWithoutLeadingSlash); | ||
| if (match && match.pattern === dynamicRouteSuffix) { | ||
| const match = findAllMatchingDynamicSuffixes(pathWithoutLeadingSlash).find((m) => m.pattern === dynamicRouteSuffix); |
There was a problem hiding this comment.
Are we sure it should be find here and not findLast?
There was a problem hiding this comment.
In useDynamicForwardPath and useDynamicBackPath, we already pass the dynamic suffix we want to find. Therefore, there are only two possibilities: either it is in the array, or it isn't. Ambiguous matches are impossible here (we can't have duplicate patterns), so it doesn't matter whether we use find or findLast 🙂
|
LGTM! |
|
@carlosmiceli Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid: mWeb ChromeiOS: HybridAppiOS: mWeb SafariMacOS: Chrome / SafariScreen.Recording.2026-05-27.at.10.23.47.mp4 |
|
@mjasikowski looks like this was merged without a test passing. Please add a note explaining why this was done and remove the |
|
🚧 @mjasikowski has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
Not an emergency, the checklists were not missing. Not sure what's going on here. |
|
🚀 Deployed to staging by https://github.com/mjasikowski in version: 9.3.84-0 🚀
Bundle Size Analysis (Sentry): |
|
I reviewed the changes in this PR. This is a purely internal navigation/routing refactor that changes how the app resolves dynamic URL suffixes ( No help site changes are required for this PR. @collectioneur, please review the linked help site PR and confirm it reflects the current behavior. Then mark the linked help site PR |
|
🚀 Deployed to staging by https://github.com/mjasikowski in version: 9.3.86-0 🚀
Bundle Size Analysis (Sentry): |
|
I reviewed the changes in this PR. This is an internal navigation/routing bug fix that refactors No help site documentation changes are required — the PR does not alter any user-facing features, UI labels, settings, or workflows. All changes are to internal navigation utilities, developer-facing docs ( @collectioneur, no help site PR was created since no documentation changes are needed for this internal routing fix. |
|
🚀 Deployed to staging by https://github.com/mjasikowski in version: 9.3.88-0 🚀
Bundle Size Analysis (Sentry): |
|
I've reviewed the changes in this PR. This is a purely internal navigation/routing code fix that refactors
There are no user-facing feature changes, no new settings, no changed workflows, and no UI modifications. The help site docs under No help site changes are required for this PR. @collectioneur, please review the linked help site PR and confirm it reflects the current behavior. Then mark the linked help site PR |
|
🚀 Deployed to production by https://github.com/mountiny in version: 9.3.88-2 🚀
|
Explanation of Change
Refactored
findMatchingDynamicSuffixintofindAllMatchingDynamicSuffixes, which returns all syntactically matching suffixes in priority order instead of just the first one. Callers (getStateFromPath,getAdaptedStateFromPath,getDynamicRouteAdaptedState, hooks) now iterate candidates and validate each againstentryScreens, preventing false-positive greedy matches where a user-defined name (e.g. a tag named "gl-code") coincides with a registered static suffix.Fixed Issues
$ #91703
$ #91480
Tests
Test 1: Workspace invite role
/workspaces/<policyID>/overview/invite/invite-message)Test 2: Settings profile address country
/settings/profile/address)/settings/profile/address/country?country=<country>)Test 3: gl-code
settings/<policyID>/tags(wherepolicyIDis the ID of the workspace)Offline tests
N/A
QA Steps
Same as tests
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
Test 1:
test_2.mov
Test 2:
test_1.mov
Test 3:
Screen.Recording.2026-05-25.at.17.42.33.mov