restore invited login when OpenReport settles the participant without one#95594
Conversation
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
|
|
…ertions Narrow request.data.emailList with a typeof check instead of a bare template-string coercion, and replace (global.fetch as jest.Mock) casts with jest.spyOn(HttpUtils, 'xhr') so the new middleware tests type-check without unsafe assertions. Also restructure the participants for-in loop back into a single guard if to satisfy guard-for-in.
|
@codex review |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
|
The main OpenReport reconciliation looks good to me and matches the accepted RCA. One thing I think we should adjust before approval: the generic @mukhrr @inimaga What do you think about remove that block, or scope it very explicitly with a unit test if it is still needed? Thank you. |
The sanitizer previously ran for the response of any API command that included a PERSONAL_DETAILS_LIST merge with an empty login, not just the OpenReport/profile flow it exists for. Narrow it to the one command it's meant to guard against, and add tests covering both that it still fixes OpenPublicProfilePage and that it now leaves other commands alone.
|
@brunovjk you’re right that it was running for every response, not just this flow. I’ve narrowed it to OpenPublicProfilePage specifically: App/src/libs/Middleware/HandleUnusedOptimisticID.ts Lines 174 to 188 in 93a3d4f |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid: mWeb ChromeiOS: HybridAppScreen.Recording.2026-07-14.at.16.04.38.moviOS: mWeb SafariMacOS: Chrome / SafariScreen.Recording.2026-07-14.at.15.56.05.mov |
Resolved prepareOnyxDataForCleanUpOptimisticParticipants both ways: kept upstream's (personalDetails, currentUserAccountID) params and current-user skip (Expensify#95427 avatar flicker fix), kept our missingLoginParticipants collection and the middleware's invitedEmails capture; extended upstream's new ReportTest expectations with the missingLoginParticipants field. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
| if (!isRecord(detail) || detail.login !== '' || !getLoginByAccountID(Number(accountID))) { | ||
| continue; | ||
| } | ||
| delete detail.login; |
There was a problem hiding this comment.
login: '' is not the same as a missing login. We should only restore the typed email only when the backend leaves login out. If the backend sends an explicit empty login (which is possible), we should respect it, otherwise we may show an old email for an account that should stay hidden. Could you please check for the login key being absent instead of using a falsy check. Also retrospectively fix this for other parts of the code.
| redundantParticipants[accountID] = null; | ||
| } else if (personalDetails?.[accountID] && !personalDetails[accountID].login) { | ||
| // '' counts as missing: SearchForReports seeds login: '' for unvalidated accounts, and in Onyx the two are indistinguishable | ||
| missingLoginParticipants.push(Number(accountID)); |
There was a problem hiding this comment.
in Onyx the two are indistinguishable
This doesn't seem correct to me. They are distinguishable by checking whether the login key exists. You should use !Object.hasOwn(personalDetail, 'login') instead of !personalDetails[accountID].login.
The point is login: '' can be intentional, so we should not treat it as missing or delete it from responses. Please apply the same “missing key only” rule to the OpenPublicProfilePage handling.
There was a problem hiding this comment.
hmm yes that makes sense to me. thanks
inimaga
left a comment
There was a problem hiding this comment.
Nice! Thanks for handling. 🚀
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚧 inimaga 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! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/inimaga in version: 9.4.36-0 🚀
|
|
🤖 Help site review: no docs changes required. This PR is an internal bug fix in the optimistic-data middleware ( It restores expected existing behavior and introduces no new feature, setting, tab, label, or workflow. Nothing in @mukhrr, please confirm you agree no help site changes are needed here. If you believe an article should be updated, let me know and I'll create the draft PR. |
Explanation of Change
Fixed Issues
$ #92581
PROPOSAL: #92581 (comment)
Tests
Verify login detail displays "Email" and the email
Verify that no errors appear in the JS console
Offline tests
QA Steps
Same as tests
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectioncanBeMissingparam foruseOnyxtoggleReportand 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
Uploading 92581-android-app.mp4…
Android: mWeb Chrome
92581-android-web.mp4
iOS: Native
92581-ios-app.mp4
iOS: mWeb Safari
92581-ios-web.mp4
MacOS: Chrome / Safari
92581-web.mp4