Skip to content

Spend - Save button does not disappear after resetting currency on total spend footer #104014

Closed

Description

@applause-bot

If you haven’t already, check out our contributing guidelines for onboarding. To join our Slack channel, fill out this form.


Version Number: 9.5.9-0
Reproducible in staging?: Yes
Reproducible in production?: N/A - new feature, doesn't exist in prod
If this was caught during regression testing, add the test name, ID and link from BrowserStack: #100674
Email or phone of affected tester (no customers): [email protected]
Issue reported by: Applause Internal Team
Bug source: Exploratory - Significant User Experience Deterioration
Device used: Mac 26.5 / Chrome
App Component: Search

Action Performed:

Precondition:

  • Enable spendFooterSelectors beta.
  1. Go to staging.new.expensify.com
  2. Go to workspace chat.
  3. Create an expense.
  4. Go to Spend > Expenses..
  5. Click total spend on the footer.
  6. Click Currency.
  7. Select any currency > Apply.
  8. Click total spend on the footer.
  9. Click Currency.
  10. Click Reset.

Expected Result:

Save button next to search field should be removed after resetting currency on total spend footer.

Actual Result:

Save button next to search field does not disappear after resetting currency on total spend footer.

Workaround:

Unknown

Platforms:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome Safari

Screenshots/Videos

Bug7286396_1791992311254.7.1.mp4

View all open jobs on GitHub

Applause Internal Information
Exported by: Julia Ponikarchuk
Bug ID: 7286396

Activity

  1. added
    DeployBlockerCashThis issue or pull request should block deployment
    BugSomething is broken. Auto assigns a BugZero manager.
    on Oct 14, 2026
  2. applause-bot commented on Oct 14, 2026

    @applause-bot
    Author

    While Applause doesn't embed attachments for this bug, here are the links for quick view:
    https://platform.applause.com/services/links/v1/external/a29a06e91bd7d5753a8dada1a4a593cdc56548b0968c0265f0e9eb1e094d1048

  3. melvin-bot commented on Oct 14, 2026

    @melvin-bot

    You have been assigned to this deploy blocker because you recently merged this PR: #100674

  4. github-actions commented on Oct 14, 2026

    @github-actions
    Contributor

    👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:

    1. Identify the pull request that introduced this issue and revert it.
    2. Find someone who can quickly fix the issue.
    3. Fix the issue yourself.
  5. melvin-bot commented on Oct 14, 2026

    @melvin-bot

    @JS00001 @mkhutornyi you have been assigned to this deploy blocker because you reviewed the offending PR: #100674

  6. melvin-bot commented on Oct 14, 2026

    @melvin-bot

    @truph01 you have been assigned to this deploy blocker because you authored the offending PR: #100674

  7. melvin-bot commented on Oct 14, 2026

    @melvin-bot

    💬 A slack conversation has been started in #expensify-open-source

  8. MelvinBot commented on Oct 14, 2026

    @MelvinBot
    Contributor

    Deploy Blocker Analysis

    Causing PR: feat: Add count and spend total selectors to the Spend footer (high confidence). It merged 2026-10-13 and is on the current deploy checklist.

    Root Cause: Reset doesn't remove the currency from the query. It writes the default currency into it, for example footerCurrency:USD. Any footer filter left in the query makes the search savable, so the Save button stays.

    Recommendation: roll forward with a one-line fix. Reverting would remove a 45-file feature that is behind the spendFooterSelectors beta. In SearchSelectionFooter.tsx, drop the currency from the query when it matches the search's default:

    applyFooterSelection({footerCurrency: currency === searchTargetCurrency ? undefined : currency});

    Add a unit test: pick EUR, then Reset. Expect no footerCurrency in the query and isSearchQuerySavable to return false.

    Investigation details
    1. Reset picks the default explicitly. handleCurrencyChange turns Reset into item?.value ?? defaultCurrency (SearchPageFooter.tsx:118-129). The default is searchTargetCurrency, which is the active policy's output currency or USD (SearchSelectionFooter.tsx:163). This was harmless before the PR, because the currency only lived in component state.
    2. The PR writes the currency into the URL. handleFooterCurrencyChange calls applyFooterSelection({footerCurrency: currency}), which navigates to a rebuilt query (SearchSelectionFooter.tsx:653-672).
    3. Only the default count and total are dropped. In getQueryWithFooterSelection, isDefaultSelection covers footerTotal and footerCount but not footerCurrency (SearchQueryUtils.ts:806-812).
    4. The leftover filter makes the search savable. canSave comes from isSearchQuerySavable (useSearchFiltersBar.tsx:247). That function ignores groupCurrency but not footer filters (SearchQueryUtils.ts:1241-1253).

    Why the fix works: getQueryWithFooterSelection merges the new selection over the query's current one ({...getFooterSelectionFromQuery(queryJSON), ...selection}). An explicit footerCurrency: undefined therefore overrides the old value, and the !value check skips it. Totals don't change, because the server already uses the policy currency when the query names none.

    Alternative fix: pass the default currency into getQueryWithFooterSelection and add it to isDefaultSelection. This keeps all default-dropping logic in one place, but it changes the function's signature.

    Other PRs ruled out: Fix group-by:from total going down when an expense is created offline touches only SearchUpdate.ts.

    Code review rule: I'm not proposing one. Catching this requires knowing each filter's default value, and a pattern check can't detect that.


    Next Steps: Reply with @MelvinBot implement this to create a draft PR, or @MelvinBot <your feedback> to refine this analysis.


    view run

  9. mkhutornyi commented on Oct 14, 2026

    @mkhutornyi
    Contributor

    Behind not blocker.
    Also, not reproducible in non-beta account

  10. JS00001 commented on Oct 14, 2026

    @JS00001
    Contributor

    this is behind a beta, lets fix this though @mkhutornyi @truph01, going to link it to the original issue

  11. truph01 commented on Oct 15, 2026

    @truph01
    Contributor

    @MelvinBot Post proposal

  12. MelvinBot commented on Oct 15, 2026

    @MelvinBot
    Contributor

    Proposal

    Please re-state the problem that we are trying to solve in this issue.

    With the spendFooterSelectors beta on, the Save button next to the search field stays visible after you reset the footer currency.

    What is the root cause of that problem?

    Reset doesn't remove the currency from the search query. It writes the default currency in explicitly, for example footerCurrency:USD.

    1. Reset turns "no selection" into the default currency, item?.value ?? defaultCurrency (SearchPageFooter.tsx:118-129). That default is searchTargetCurrency: the active policy's output currency, or USD (SearchSelectionFooter.tsx:163).
    2. handleFooterCurrencyChange passes that currency to applyFooterSelection, which writes it into the URL query (SearchSelectionFooter.tsx:664-672).
    3. getQueryWithFooterSelection leaves out the default count and the default total, but not the default currency (SearchQueryUtils.ts:806-812).
    4. Because of the leftover footerCurrency filter, isSearchQuerySavable reports the query as different from the default search, so the Save button shows (useSearchFiltersBar.tsx:247).

    Applying the default currency directly, without Reset, has the same effect.

    What changes do you think we should make in order to solve the problem?

    In handleFooterCurrencyChange in SearchSelectionFooter.tsx, pass footerCurrency: undefined to applyFooterSelection when the chosen currency equals searchTargetCurrency. Otherwise pass the chosen currency as it does today.

    This works without other changes:

    • getQueryWithFooterSelection merges the new selection over the query's current one, so an explicit undefined replaces the old currency. The existing !value check then skips it.
    • The local footer state still records the pick, so the footer shows the right currency until the URL updates.
    • The totals don't change, because the server already uses the policy currency when the query names none.

    Add a unit test: pick EUR, then Reset. The query should have no footerCurrency, and isSearchQuerySavable should return false.

    What alternative solutions did you explore? (Optional)

    Pass the default currency into getQueryWithFooterSelection and add a footerCurrency case to isDefaultSelection. This keeps all the "leave defaults out" logic in one place, but it changes the function's signature and every caller.


    Next Steps for Contributor+ team:
    To accept: @MelvinBot implement [this](https://github.com/Expensify/App/issues/104014#issuecomment-6183730622) to create a draft PR.
    To refine: @MelvinBot <your feedback>
    To reject: Explain why you are rejecting Melvin's proposal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugSomething is broken. Auto assigns a BugZero manager.EngineeringHourlyKSv2ReviewingHas a PR in review

Type

No type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions