Skip to content

[CP Staging] Show "removed" instead of "set to """ when a text report field is cleared - #104551

Merged
grgia merged 3 commits into
mainfrom
claude-fixClearedTextReportFieldMessage
Oct 21, 2026
Merged

grgia merged 3 commits into
mainfrom
claude-fixClearedTextReportFieldMessage

Conversation

@MelvinBot

@MelvinBot MelvinBot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Explanation of Change

Clearing a text report field that only showed its workspace initial value produced the system message set text to "". The report had no saved value for the field, so the CHANGEFIELD action had an empty oldValue. The message builder used the "removed" wording only when oldValue was non-empty. With both values empty, it fell through to changeFieldEmpty (set {field} to "{value}").

This PR:

  • Changes getMessageOfOldDotReportAction to check for an empty newValue first. It shows removed {field} (previously "{oldValue}") when there is an old value, and a new changeFieldCleared message, removed {field}, when there isn't. A cleared field can no longer render as set {field} to "".
  • Adds changeFieldCleared to every locale, plus unit tests.
  • Leaves buildOptimisticChangeFieldAction as it is on main: oldValue is the report's saved value. Falling back to the field's defaultValue made the optimistic message read removed text (previously "<initial value>"), then flicker to removed text when the server's action, which reuses the same reportActionID, replaced it. Clearing a never-saved field now shows removed text from the start.

Fixed Issues

$ #104507
PROPOSAL: #104507 (comment)

Tests

// TODO: The human co-author must fill out the tests you ran before marking this PR as "ready for review"
// Please describe what tests you performed that validates your changed worked.

  • Verify that no errors appear in the JS console

Offline tests

QA Steps

// TODO: The human co-author must fill out the QA tests you ran before marking this PR as "ready for review".
// Please describe what QA needs to do to validate your changes and what areas do they need to test for regressions.

  • Verify that no errors appear in the JS console

PR Author Checklist

  • I linked the correct issue in the ### Fixed Issues section above
  • I wrote clear testing steps that cover the changes made in this PR
    • I added steps for local testing in the Tests section
    • I added steps for the expected offline behavior in the Offline steps section
    • I added steps for Staging and/or Production testing in the QA steps section
    • I added steps to cover failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
    • I tested this PR with a High Traffic account against the staging or production API to ensure there are no regressions (e.g. long loading states that impact usability).
  • I included screenshots or videos for tests on all platforms
  • I ran the tests on all platforms & verified they passed on:
    • Android: Native
    • Android: mWeb Chrome
    • iOS: Native
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • I verified there are no console errors (if there's a console error not related to the PR, report it or open an issue for it to be fixed)
  • I verified any copy / text that was added to the app is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I tested other components that can be impacted by my changes (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar are working as expected)
  • If new assets were added or existing ones were modified, I verified that:
    • The assets are optimized and compressed (for SVG files, run npm run compress-svg)
    • The assets load correctly across all supported platforms.
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If the PR adds or modifies the UI:
    • I asked an AI agent to review the changes for accessibility issues and addressed its findings.
    • I tested with a screen reader (VoiceOver on macOS) and verified all new/changed elements are reachable with a logical focus order.
    • I verified all new/changed elements have meaningful accessible names and roles.
    • I verified state changes are announced (e.g. checked/unchecked, expanded/collapsed, selected).
  • I added unit tests for any new feature or bug fix in this PR to help automatically prevent regressions in this user flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.

Screenshots/Videos

Android: Native

MelvinBot test run on standalone Android NewDot. Clearing a text report field that showed its initial value "hello" posts removed text instead of set text to "".

Expense report showing the text report field with value hello System message reads removed text
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari

AI Tests

  • npm run typecheck: passed
  • npm run lint-changed: passed
  • npm run fmt (oxfmt): no formatting changes
  • npm test -- tests/unit/ReportActionsUtilsTest.ts tests/unit/ReportUtilsTest.ts: 2009/2009 passed (includes 3 new tests)
  • Not run: the full Jest suite, Storybook smoke test, and generateTranslations.ts --dry-run (ts-node is not installed in this environment)
  • After removing the defaultValue fallback: npm run typecheck passed and the two test files above passed 2009/2009. Lint and oxfmt could not run in that environment; the change restores the lines from main.

@MelvinBot
MelvinBot requested a review from a team October 21, 2026 10:50
@melvin-bot melvin-bot Bot added Melvin-Test-Android Melvin-Test-Web Triggers Melvin to run the testing steps of the PR on web labels Oct 21, 2026
@MelvinBot MelvinBot changed the title Show "removed" instead of "set to \"\"" when a text report field is cleared Show "removed" instead of "set to """ when a text report field is cleared Oct 21, 2026
@MelvinBot

Copy link
Copy Markdown
Contributor Author

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:

git remote add upstream https://github.com/Expensify/App.git
git fetch upstream claude-fixClearedTextReportFieldMessage
git checkout -b claude-fixClearedTextReportFieldMessage upstream/claude-fixClearedTextReportFieldMessage
git push -u origin claude-fixClearedTextReportFieldMessage

Then you can close this PR and open a new one from your fork.

@OSBotify

Copy link
Copy Markdown
Contributor

🦜 Polyglot Parrot! 🦜

Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues:

View the translation diff
diff --git a/src/languages/el.ts b/src/languages/el.ts
index e5ce5b44..e982bb98 100644
--- a/src/languages/el.ts
+++ b/src/languages/el.ts
@@ -10752,7 +10752,7 @@ ${reportName}`,
                 changeField: (oldValue, newValue, fieldName) => `άλλαξε το ${fieldName} σε «${newValue}» (προηγουμένως «${oldValue}»)`,
                 changeFieldEmpty: (newValue, fieldName) => `ορίστε το ${fieldName} σε «${newValue}»`,
                 changeFieldRemoved: (oldValue, fieldName) => `αφαίρεσε το ${fieldName} (προηγουμένως «${oldValue}»)`,
-                changeFieldCleared: (fieldName) => `αφαίρεσε το ${fieldName}`,
+                changeFieldCleared: (fieldName: string) => `καταργήθηκε το ${fieldName}`,
                 changeReportPolicy: (toPolicyName: string, fromPolicyName?: string) => {
                     if (!toPolicyName) {
                         return `άλλαξε τον χώρο εργασίας${fromPolicyName ? `(προηγουμένως ${fromPolicyName})` : ''}`;
diff --git a/src/languages/es.ts b/src/languages/es.ts
index 4a7148d4..766459f9 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -10354,7 +10354,7 @@ ${reportName}`,
                 changeField: (oldValue, newValue, fieldName) => `cambió ${fieldName} a "${newValue}" (previamente "${oldValue}")`,
                 changeFieldEmpty: (newValue, fieldName) => `estableció ${fieldName} a ${newValue}`,
                 changeFieldRemoved: (oldValue, fieldName) => `eliminó ${fieldName} (previamente "${oldValue}")`,
-                changeFieldCleared: (fieldName) => `eliminó ${fieldName}`,
+                changeFieldCleared: (fieldName: string) => `eliminó ${fieldName}`,
                 changeReportPolicy: (toPolicyName, fromPolicyName) => {
                     if (!toPolicyName) {
                         return `cambió el espacio de trabajo${fromPolicyName ? ` (previamente ${fromPolicyName})` : ''}`;
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 4dae6d7d..caebbae9 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -10500,7 +10500,7 @@ Aggiungi altre regole di spesa per proteggere il flusso di cassa aziendale.`,
                 changeField: (oldValue: string | undefined, newValue: string, fieldName: string) => `ha modificato ${fieldName} in "${newValue}" (in precedenza "${oldValue}")`,
                 changeFieldEmpty: (newValue: string, fieldName: string) => `imposta ${fieldName} su "${newValue}"`,
                 changeFieldRemoved: (oldValue: string, fieldName: string) => `ha rimosso ${fieldName} (in precedenza "${oldValue}")`,
-                changeFieldCleared: (fieldName: string) => `ha rimosso ${fieldName}`,
+                changeFieldCleared: (fieldName: string) => `rimosso ${fieldName}`,
                 changeReportPolicy: (toPolicyName: string, fromPolicyName?: string) => {
                     if (!toPolicyName) {
                         return `ha modificato il workspace${fromPolicyName ? `(precedentemente ${fromPolicyName})` : ''}`;
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index eb588fad..b147222d 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -10346,7 +10346,7 @@ ${reportName}`,
                 changeField: (oldValue: string | undefined, newValue: string, fieldName: string) => `${fieldName} を「${newValue}」(以前は「${oldValue}」)に変更しました`,
                 changeFieldEmpty: (newValue: string, fieldName: string) => `${fieldName} を「${newValue}」に設定`,
                 changeFieldRemoved: (oldValue: string, fieldName: string) => `${fieldName} を削除しました(以前は「${oldValue}」)`,
-                changeFieldCleared: (fieldName: string) => `${fieldName} を削除しました`,
+                changeFieldCleared: (fieldName: string) => `${fieldName}を削除しました`,
                 changeReportPolicy: (toPolicyName: string, fromPolicyName?: string) => {
                     if (!toPolicyName) {
                         return `ワークスペース${fromPolicyName ? `(以前は${fromPolicyName})` : ''}を変更しました`;
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index f8f7cd52..c2e70842 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -10470,7 +10470,7 @@ er bestedingsregels toe om de kasstroom van het bedrijf te beschermen.`,
                 changeField: (oldValue: string | undefined, newValue: string, fieldName: string) => `heeft ${fieldName} gewijzigd in „${newValue}” (voorheen „${oldValue}”)`,
                 changeFieldEmpty: (newValue: string, fieldName: string) => `stel ${fieldName} in op "${newValue}"`,
                 changeFieldRemoved: (oldValue: string, fieldName: string) => `heeft ${fieldName} verwijderd (voorheen „${oldValue}”)`,
-                changeFieldCleared: (fieldName: string) => `heeft ${fieldName} verwijderd`,
+                changeFieldCleared: (fieldName: string) => `${fieldName} verwijderd`,
                 changeReportPolicy: (toPolicyName: string, fromPolicyName?: string) => {
                     if (!toPolicyName) {
                         return `heeft de werkruimte${fromPolicyName ? `(voorheen ${fromPolicyName})` : ''} gewijzigd`;
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 6bf3c6ab..ed7e49a0 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -10065,7 +10065,7 @@ ${reportName}`,
                 changeField: (oldValue: string | undefined, newValue: string, fieldName: string) => `将${fieldName}更改为“${newValue}”(先前为“${oldValue}”)`,
                 changeFieldEmpty: (newValue: string, fieldName: string) => `将 ${fieldName} 设置为“${newValue}”`,
                 changeFieldRemoved: (oldValue: string, fieldName: string) => `已移除${fieldName}(先前为“${oldValue}”)`,
-                changeFieldCleared: (fieldName: string) => `已移除${fieldName}`,
+                changeFieldCleared: (fieldName: string) => `已移除 ${fieldName}`,
                 changeReportPolicy: (toPolicyName: string, fromPolicyName?: string) => {
                     if (!toPolicyName) {
                         return `更改了工作区${fromPolicyName ? `(原为 ${fromPolicyName})` : ''}`;

Note

You can apply these changes to your branch by copying the patch to your clipboard, then running pbpaste | git apply 😉

View workflow run

@MelvinBot

Copy link
Copy Markdown
Contributor Author

The failing check is unrelated to this PR, so I didn't push a fix. Please rerun the failed test (job 8) job.

Analysis: In test (job 8), the runner killed a Jest worker (signal=SIGKILL, exitCode=null) while it ran tests/unit/ReportSelectorTest.ts. That's an infrastructure kill, usually from running out of memory, not a failed assertion. All 3,503 tests that ran passed.

Evidence: This PR changes the language files, ReportUtils.ts, ReportActionsUtils.ts, and their unit tests. It doesn't touch ReportSelectorTest.ts. The other failing check, Check independent approval, waits on a reviewer approval and needs no code change.


view run

@MelvinBot

MelvinBot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 Android test steps verification results: ⚠️ partial

The broken set text to "" message is gone. But clearing a text report field that only showed its workspace initial value now posts just removed text, not the expected removed text (previously "hello"). The PR's Tests section is still a TODO, so these steps come from the linked issue's reproduction steps.

System message reads removed text without the previously clause

Step Status
Report fields are enabled on the workspace, and a text report field with an initial value existsWorkspace Settings > Reports shows the Report fields toggle on and a field named "text" (Type: Text, Initial value: hello).
Workspace Reports settings with Report fields enabled and text field listed
✅
Create an expense in the workspace chat and open its report; the text field shows the initial valueAfter a $25 expense was created in the workspace chat, the expense report shows the Text field pre-filled with "hello".
Expense report showing the text report field with value hello
✅
Clear the text report field and saveThe cleared value persisted. Reopening the report shows the field empty, with the inline error "text is required".
Report field cleared, showing empty value and validation error
✅
The system message is not set text to "" and reads removed text (previously "hello")The system message reads exactly removed text. The old set text to "" wording is gone, but the (previously "hello") clause is missing, even though the field showed the initial value "hello" before it was cleared.
System message reads removed text without the previously clause
❌

view run · view recording

@daledah

daledah commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

@MelvinBot please open this PR and fill your checklists

@MelvinBot

MelvinBot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor Author

🤖 Web test steps verification results: ⚠️ partial

I confirmed the report field setup and that a new expense's report shows the field's workspace initial value. I could not finish the clear-and-press-Enter step, so I could not capture the system message: the web test tool cannot send an Enter keypress. This is a test tooling limit, not a product result. The PR's Tests section is still a TODO, so these steps come from the linked issue's reproduction steps.

Text report field still showing hello after the clear attempt reverted

Step Status
Report fields are enabled on the workspace, and a text report field with an initial value existsWorkspace > Reports shows the Report fields switch on and a field named "text" (Type: Text, Initial value: hello).
Workspace Reports settings with Report fields enabled and the text field created
✅
Create an expense in the workspace chat and open its report; the text field shows the initial valueAfter a $10 expense was created, its expense report shows the Text field with the value "hello".
Expense report showing the Text report field pre-filled with hello
✅
Click the text report field, clear it, and press EnterBlocked by test tooling. The field was cleared, but the web driver could not send Enter (keyboard enter is not supported on web). Clicking away from the empty field restored the saved value and posted no system message, so the clear needs an Enter submit to save.
❌
The system message is not set text to "" and reads removed text (previously "hello")Not observed. The clear could not be saved without Enter, so no system message was posted for the removal.
❌

view run · view recording

@MelvinBot
MelvinBot marked this pull request as ready for review October 21, 2026 11:29
@MelvinBot
MelvinBot requested a review from a team as a code owner October 21, 2026 11:29
@melvin-bot
melvin-bot Bot requested review from daledah and removed request for a team October 21, 2026 11:29
@melvin-bot

melvin-bot Bot commented Oct 21, 2026

Copy link
Copy Markdown

@daledah 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]

@melvin-bot
melvin-bot Bot requested review from trjExpensify and removed request for a team October 21, 2026 11:29
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-21T11:32:43.821606Z 19a6503 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

I marked this PR ready for review and updated the PR Author Checklist. I checked only items that are true or don't apply. The Tests, Offline tests, and QA Steps sections are still yours to fill in.

What I checked: the items that don't apply to this change. It changes only system message text in ReportActionsUtils.ts, ReportUtils.ts, and the locale files. It adds no assets, components, UI layout, pages, or new code patterns, and main hasn't been merged after a review. I also added my Android screenshots under Android: Native.

What you still need to do:

  • Write the Tests, Offline, and QA steps.
  • Test on the remaining platforms and add screenshots.
  • Check for console errors.
  • Get copy approval for the new removed {field} string.
  • Check the accessibility items.

Possible gap: On Android, clearing a field that showed only its initial value posts removed text, not removed text (previously "hello"). That meets the issue's expected result. But the optimistic (previously …) text described in this PR didn't show up in the final message, so please confirm it's acceptable during review.

Comment thread src/libs/ReportUtils.ts Outdated
*/
function buildOptimisticChangeFieldAction(reportField: PolicyReportField, previousReportField: PolicyReportField, currentUserAccountID: number): OptimisticChangeFieldAction {
// A field that was never saved on the report shows its workspace default, so that is the value the user changed
const previousValue = previousReportField.value ?? previousReportField.defaultValue;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MelvinBot the ?? previousReportField.defaultValue fallback in buildOptimisticChangeFieldAction is what causes the flicker. I logged it on web:

  • Client sends its own id via reportFieldsActionIDs, so the server reuses the same reportActionID and overwrites originalMessage.
  • Optimistic: oldValue: 'init text' → removed Text (previously "init text").
  • ~760ms later the server's copy lands with oldValue gone → removed Text.

@MelvinBot

Copy link
Copy Markdown
Contributor Author

I didn't push a fix because no code change is needed. Since my last comment, the PR head is unchanged (19a6503) and nobody has rerun test (job 8). Please rerun that job; I'm not allowed to rerun it myself.

Why it's unrelated: The runner killed a Jest worker (signal=SIGKILL, exitCode=null) while it ran tests/unit/ReportSelectorTest.ts. That's an infrastructure kill, usually from running out of memory, not a failed assertion. The other 3,503 tests passed.

Details
  • ReportSelectorTest.ts imports ReportUtils and ReportActionsUtils through src/selectors/Report.ts, and this PR edits both files. The edits only change two report action message strings (getMessageOfOldDotReportAction and buildOptimisticChangeFieldAction). They add no loops, recursion, or work at import time, so they can't plausibly exhaust a worker's memory.
  • Check independent approval and checklist are approval and checklist checks that reviewers complete. They don't need code changes.

view run

@daledah

daledah commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Reviewer Checklist

  • I have verified the author checklist is complete (all boxes are checked off).
  • I verified the correct issue is linked in the ### Fixed Issues section above
  • I verified testing steps are clear and they cover the changes made in this PR
    • I verified the steps for local testing are in the Tests section
    • I verified the steps for Staging and/or Production testing are in the QA steps section
    • I verified the steps cover any possible failure scenarios (i.e. verify an input displays the correct error message if the entered data is not correct)
    • I turned off my network connection and tested it while offline to ensure it matches the expected behavior (i.e. verify the default avatar icon is displayed if app is offline)
  • I checked that screenshots or videos are included for tests on all platforms
  • I included screenshots or videos for tests on all platforms
  • I verified that the composer does not automatically focus or open the keyboard on mobile unless explicitly intended. This includes checking that returning the app from the background does not unexpectedly open the keyboard.
  • I verified tests pass on all platforms & I tested again on:
    • Android: HybridApp
    • Android: mWeb Chrome
    • iOS: HybridApp
    • iOS: mWeb Safari
    • MacOS: Chrome / Safari
  • If there are any errors in the console that are unrelated to this PR, I either fixed them (preferred) or linked to where I reported them in Slack
  • I verified any copy / text that was added to the app is either coming verbatim from figma or has been approved by marketing (in order to get marketing approval, ask the Bug Zero team member to add the Waiting for copy label to the issue)
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I verified other components that can be impacted by these changes have been tested, and I retested again (i.e. if the PR modifies a shared library or component like Avatar, I verified the components using Avatar have been tested & I retested again)
  • If a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately
    • The component has a clear name that is non-ambiguous and the purpose of the component can be inferred from the name alone
    • The only data being stored in the state is data necessary for rendering and nothing else
    • The component has the minimum amount of code necessary for its purpose, and it is broken down into smaller components in order to separate concerns and functions
  • If the PR modifies code that runs when editing or sending messages, I tested and verified there is no unexpected behavior for all supported markdown - URLs, single line code, code blocks, quotes, headings, bold, strikethrough, and italic.
  • If the PR modifies a generic component, I tested and verified that those changes do not break usages of that component in the rest of the App (i.e. if a shared library or component like Avatar is modified, I verified that Avatar is working as expected in all cases)
  • If the PR modifies a component related to any of the existing Storybook stories, I tested and verified all stories for that component are still working as expected.
  • If the PR modifies a component or page that can be accessed by a direct deeplink, I verified that the code functions as expected when the deeplink is used - from a logged in and logged out account.
  • If the PR modifies the UI (e.g. new buttons, new UI components, changing the padding/spacing/sizing, moving components, etc) or modifies the form input styles:
    • I verified that all the inputs inside a form are aligned with each other.
    • I added Design label and/or tagged @Expensify/design so the design team can review the changes.
  • If the PR adds or modifies the UI:
    • I asked an AI agent to review the changes for accessibility issues and addressed its findings.
    • I tested with a screen reader (VoiceOver on macOS) and verified all new/changed elements are reachable with a logical focus order.
    • I verified all new/changed elements have meaningful accessible names and roles.
    • I verified state changes are announced (e.g. checked/unchecked, expanded/collapsed, selected).
  • For any bug fix or new feature in this PR, I verified that sufficient unit tests are included to prevent regressions in this flow.
  • If the main branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to the Test steps.
  • I have checked off every checkbox in the PR reviewer checklist, including those that don't apply to this PR.

Screenshots/Videos

MacOS: Chrome / Safari
Screen.Recording.2026-10-21.at.18.36.28.mov

@MelvinBot

Copy link
Copy Markdown
Contributor Author

No code change is needed, so I didn't push anything. The failure won't clear until someone with Actions access reruns the failed test (job 8) job. I'm not allowed to rerun it.

  • test (job 8): still the same run as before, on the same PR head (19a6503). The CI runner killed a Jest worker (SIGKILL) during tests/unit/ReportSelectorTest.ts, which this PR doesn't touch. None of the tests that ran failed (3,503 passed).
  • Check independent approval and checklist: these are checklist and approval checks. They need a reviewer, not a code change.

To fix it, open the failed job and select Re-run failed jobs.


view run

The server reuses the client's reportActionID and overwrites originalMessage
without the default as oldValue, so the fallback made the message flicker from
'removed text (previously ...)' to 'removed text'.

Co-authored-by: daledah <[email protected]>
@MelvinBot
MelvinBot requested a review from a team as a code owner October 21, 2026 11:40
@melvin-bot
melvin-bot Bot requested a review from AndrewGable October 21, 2026 11:40
@melvin-bot
melvin-bot Bot requested review from daledah and removed request for a team October 21, 2026 11:40
@melvin-bot

melvin-bot Bot commented Oct 21, 2026

Copy link
Copy Markdown

@daledah @AndrewGable 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]

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Agreed. I removed the ?? previousReportField.defaultValue fallback in a172bc9. buildOptimisticChangeFieldAction now matches main again: oldValue is the report's saved value. Clearing a field that was never saved now shows removed text from the start, so nothing changes when the server's action arrives.

Typecheck passed, and ReportUtilsTest plus ReportActionsUtilsTest passed (2009/2009). Lint and oxfmt could not run in my environment. The change only restores the lines from main.


view run

@MelvinBot

Copy link
Copy Markdown
Contributor Author

Fixed the failing ESLint check in 52c3292.

Cause: The new buildOptimisticChangeFieldAction test read action.originalMessage?.oldValue and action.originalMessage?.newValue directly. That property is deprecated, so @typescript-eslint/no-deprecated failed at tests/unit/ReportUtilsTest.ts:24729-24730.

Fix: Replaced the two reads with one expect(action).toMatchObject({originalMessage: {oldValue: undefined, newValue: ''}}), the same pattern the next test uses. getOriginalMessage isn't an option here because the CHANGE_FIELD message type is never.

Verification: ESLint no longer reports these errors on the file. I couldn't run Jest in this environment, so CI will confirm the test still passes.

test (job 8) passed on this run. Check independent approval needs a reviewer approval, not a code change.


view run

@daledah daledah left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@grgia grgia changed the title Show "removed" instead of "set to """ when a text report field is cleared [CP Staging] Show "removed" instead of "set to """ when a text report field is cleared Oct 21, 2026

@grgia grgia left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@grgia
grgia merged commit 0a1f77f into main Oct 21, 2026
37 of 39 checks passed
@grgia
grgia deleted the claude-fixClearedTextReportFieldMessage branch October 21, 2026 13:01
OSBotify pushed a commit that referenced this pull request Oct 21, 2026
…FieldMessage

[CP Staging] Show "removed" instead of "set to """ when a text report field is cleared

(cherry picked from commit 0a1f77f)

(cherry-picked to staging by grgia)
@OSBotify OSBotify added the CP Staging marks PRs that have been CP'd to staging label Oct 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🚧 grgia has triggered a test Expensify/App build. You can view the workflow run here.

@OSBotify

Copy link
Copy Markdown
Contributor

✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release.

@os-botify

os-botify Bot commented Oct 21, 2026

Copy link
Copy Markdown

🔁 Filed a Staging retest request for deploy blockers #104507 after this PR was cherry-picked to staging.

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Cherry-picked to staging by https://github.com/grgia in version: 9.5.15-2 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@MelvinBot

Copy link
Copy Markdown
Contributor Author

No help site update is needed. This bug fix only changes the in-app system message shown after you clear a text report field, and no help article describes that message.


view run

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/grgia in version: 9.5.15-3 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

Bundle Size Analysis (Sentry):

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Cherry-picked to staging by https://github.com/grgia in version: 9.5.16-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

@MelvinBot

Copy link
Copy Markdown
Contributor Author

No help site update is needed. This bug fix only changes the in-app system message shown after someone clears a text report field, and no article under App/docs/articles describes that message.


view run

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Cherry-picked to staging by https://github.com/grgia in version: 9.5.18-0 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 cancelled 🔪

@MelvinBot

Copy link
Copy Markdown
Contributor Author

No help site update needed. This PR fixes the wording of a report-history system message when someone clears a report field, and no article in docs/articles describes that message.


view run

@OSBotify

Copy link
Copy Markdown
Contributor

🚀 Deployed to production by https://github.com/grgia in version: 9.5.18-1 🚀

platform result
🕸 web 🕸 success ✅
🤖 android 🤖 success ✅
🍎 iOS 🍎 success ✅

Bundle Size Analysis (Sentry):

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

Labels

CP Staging marks PRs that have been CP'd to staging Melvin-Test-Android Melvin-Test-Web Triggers Melvin to run the testing steps of the PR on web

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants