Repository navigation
[Refactor] Move remaining PolicyUtils member, domain, and travel helpers into members.ts, domains.ts, and travel.ts - #104331
Conversation
…mbers.ts, domains.ts, and travel.ts Co-authored-by: nkdengineer <[email protected]>
…mport cycle Co-authored-by: nkdengineer <[email protected]>
|
I created this PR from an upstream branch since I don't have push access to your fork. To take ownership of this branch and be able to push updates, run: Then you can close this PR and open a new one from your fork. |
Codecov Report✅ Changes either increased or maintained existing code coverage, great job!
|
|
🤖 Android test steps verification results: ✅ pass On standalone Android NewDot, the Members, Invite, Workflows, and Travel pages all opened and rendered correctly, with no red-box errors or crashes. The PR's Tests section only lists "Verify that no errors appear in the JS console", so I also smoke-tested the pages the PR description names as affected.
|
|
🤖 Web test steps verification results: ✅ pass On the dev web build, the Members, Invite, Workflows, and Travel pages all opened and rendered correctly, with no error pages or crashes. The PR's Tests section only lists "Verify that no errors appear in the JS console", so I also smoke-tested the pages the PR description names as affected.
|
|
@MelvinBot Let's add unit tests for |
…space, getTravelStep and group moved helpers by submodule Co-authored-by: nkdengineer <[email protected]>
|
I added the unit tests and grouped the moved helpers by submodule in New tests
Regrouping (moved tests are unchanged apart from indentation)
|
|
@MelvinBot, fill out the Test section
Prerequisite: a Control workspace where User A is the admin. User B and User C are members, and Add approvals is on with User C as User B's approver.
Prerequisite: a workspace that has an assigned guide, or an
Prerequisite: Account is public domain email
Then update |
|
Updated the PR description:
|
|
@MelvinBot Let's move |
…getHighestPolicyRole.ts Co-authored-by: nkdengineer <[email protected]>
|
I moved
Checks
|
|
@MelvinBot, fill the Screenshots/VideosAndroid: NativeScreen.Recording.2026-10-19.at.22.22.14.movAndroid: mWeb ChromeScreen.Recording.2026-10-19.at.22.21.10.moviOS: NativeScreen.Recording.2026-10-19.at.22.21.20.moviOS: mWeb SafariScreen.Recording.2026-10-19.at.22.21.48.movMacOS: Chrome / SafariScreen.Recording.2026-10-19.at.22.16.12.movScreen.Recording.2026-10-19.at.22.17.09.movScreen.Recording.2026-10-19.at.22.17.32.mov |
|
Filled out the
The rest of the description is unchanged. |
|
@MelvinBot, Update the Author Checklist section. Also, I verified there's no console error; then let's check for PR Author Checklist
|
|
Done. I updated the PR description and marked the PR as ready for review.
|
|
@nkdengineer 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] |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppScreen.Recording.2026-10-19.at.22.22.14.movAndroid: mWeb ChromeScreen.Recording.2026-10-19.at.22.21.10.moviOS: HybridAppScreen.Recording.2026-10-19.at.22.21.20.moviOS: mWeb SafariScreen.Recording.2026-10-19.at.22.21.48.movMacOS: Chrome / SafariScreen.Recording.2026-10-19.at.22.16.12.movScreen.Recording.2026-10-19.at.22.17.09.movScreen.Recording.2026-10-19.at.22.17.32.mov |
nkdengineer
left a comment
There was a problem hiding this comment.
LGTM! @blimpich All yours.
|
The failing ESLint check is unrelated to this PR. Analysis: The only lint error is in a file this PR doesn't touch: Move Categories & Tags settings into the header More menu merged into Fix in progress: [No QA] Split SettingsNavigatorParamList out of Navigation/types.ts to fix max-lines lint already fixes this on Evidence
|
|
Nothing has changed since my earlier comment, so I still haven't pushed a fix.
After that PR merges, rerun ESLint or merge |
|
I still haven't pushed a fix, because nothing has changed since my earlier comment.
After that fix PR merges, merge |
|
@MelvinBot The fix was merged, please merge main. |
…se9MembersDomainsTravel Co-authored-by: nkdengineer <[email protected]>
|
Merged
|
|
@nkdengineer @blimpich One of you needs to 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] |
|
@blimpich Fixed lint. |
|
🚧 blimpich has triggered a test Expensify/App build. You can view the workflow run here. |
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/blimpich in version: 9.5.15-1 🚀
|
|
No help site update needed. This PR only moves |
|
🚀 Deployed to production by https://github.com/grgia in version: 9.5.15-3 🚀
Bundle Size Analysis (Sentry): |











Explanation of Change
Phase 9, the last phase of the
PolicyUtilssplit. It moves everything left inPolicyUtils/index.tsinto submodules, soindex.tsis now only the barrel.index.tsdrops from 591 to 23 lines, which keeps the folder well under the 4000-line ESLint limit.This is a pure move. Nothing is renamed, no signature changes, and behavior is the same. Callers stay on
@libs/PolicyUtils.members.ts: membership checks, Expensify-team filtering, invite exclusions, guides and account managers, member account IDs, and bank-account share recipients (19 helpers). TheMemberEmailsToAccountIDstype moved here too, andexport *re-exports it. It imports from./permissionsand./policy.domains.ts: the policy domain name, admin private domains, the most frequent domain, and domain-card lookups (6 helpers). It importsisExpensifyTeamfrom./members.travel.ts: travel provisioning, accepted terms, non-USD workspaces, and the travel step (4 helpers). The localTravelSteptype moved withgetTravelStep, its only user. It imports from./policy,./domains, and./policyType.approvals.ts:isNonMemberApprovermoved next togetDefaultApprover.approvals.tsnow importsisPolicyMemberfrom./members.approvals.tsorindex.ts, so there is no cycle and noimport/no-cycledisable.index.tskeeps theexport *comment and list, and adds./members,./domains, and./travel.@libs/PolicyUtilswith a factory that runs while the barrel is still loading inside an import cycle. Before this PR, the moved helpers were named exports onindex.ts, so they were already on the module. Now they come throughexport *, which is not populated yet at that point. Those mocks now spreadjest.requireActual('@libs/PolicyUtils/members'), the same fix earlier phases used for other submodules:ReportPrimaryActionUtilsTest,ReportSecondaryActionUtilsTest,ReportUtilsTest,SidebarUtilsTest, andCreateDraftTransactionTest.AI tests run locally
npm run typecheck: passednpm run lint-changed: passednpm run fmt(oxfmt): no changesnpm run spell-changed: passed--color-moved) shows every removed function line fromindex.tslanding unchanged in the new files. Only header, import, and export lines differ.@libs/PolicyUtilspassed after the mock fix (3557 tests), plus 31 suites that cover the moved helpers (3376 tests), includingPolicyUtilsTest,CardUtilsTest,createFilteredMemberCountSelectorTest,OptionsListUtilsTest,TravelUtilsTest, andWorkflowUtilsTest. The fullnpm testrun doesn't finish within the local time limit, so CI is the full-suite signal.Fixed Issues
$ #102675
PROPOSAL: #102675 (comment)
Tests
Members list, invites and removing a member
Prerequisite: a Control workspace where User A is the admin. User B and User C are members, and Add approvals is on with User C as User B's approver.
Expensify team and guide filtering
Prerequisite: a workspace that has an assigned guide, or an
@expensify.com/@team.expensify.commemberTravel
Prerequisite: Account is public domain email
Offline tests
Same as test
QA Steps
Same as test
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectionAvatar, 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.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
Screen.Recording.2026-10-19.at.22.22.14.mov
Android: mWeb Chrome
Screen.Recording.2026-10-19.at.22.21.10.mov
iOS: Native
Screen.Recording.2026-10-19.at.22.21.20.mov
iOS: mWeb Safari
Screen.Recording.2026-10-19.at.22.21.48.mov
MacOS: Chrome / Safari
Screen.Recording.2026-10-19.at.22.16.12.mov
Screen.Recording.2026-10-19.at.22.17.09.mov
Screen.Recording.2026-10-19.at.22.17.32.mov