Skip to content

[Internal QA]: Fix broken connection visibility for Cards#76620

Closed
narefyev91 wants to merge 7 commits intoExpensify:mainfrom
callstack-internal:fix-broken-connection
Closed

[Internal QA]: Fix broken connection visibility for Cards#76620
narefyev91 wants to merge 7 commits intoExpensify:mainfrom
callstack-internal:fix-broken-connection

Conversation

@narefyev91
Copy link
Contributor

Explanation of Change

Visual fix for Company card broken connection and in wallet cards

Fixed Issues

$ #76438
PROPOSAL:

Tests

  1. Add a direct or Plaid card feed
  2. Break the feed's connection
  3. Go to the company cards page - verify that broken connection text with link is shown
  4. Go to Wallet page - verify that card in wallet broken connection is shown
  5. Go to #admins room - verify that message about broken connection is presented
  • Verify that no errors appear in the JS console

Offline tests

No changes

QA Steps

  1. Add a direct or Plaid card feed
  2. Break the feed's connection
  3. Go to the company cards page - verify that broken connection text with link is shown
  4. Go to Wallet page - verify that card in wallet broken connection is shown
  5. Go to #admins room - verify that message about broken connection is presented
  • 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 there are no new alerts related to the canBeMissing param for useOnyx
  • I followed proper code patterns (see Reviewing the code)
    • I verified that any callback methods that were added or modified are named for what the method does and never what callback they handle (i.e. toggleReport and not onIconClick)
    • I verified that comments were added to code that is not self explanatory
    • I verified that any new or modified comments were clear, correct English, and explained "why" the code was doing something instead of only explaining "what" the code was doing.
    • I verified any copy / text shown in the product is localized by adding it to src/languages/* files and using the translation method
      • If any non-english text was added/modified, I used JaimeGPT to get English > Spanish translation. I then posted it in #expensify-open-source and it was approved by an internal Expensify engineer. Link to Slack message:
    • I verified all numbers, amounts, dates and phone numbers shown in the product are using the localization methods
    • I verified any copy / text that was added to the app is grammatically correct in English. It adheres to proper capitalization guidelines (note: only the first word of header/labels should be capitalized), and 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)
    • I verified proper file naming conventions were followed for any new files or renamed files. All non-platform specific files are named after what they export and are not named "index.js". All platform-specific files are named for the platform the code supports as outlined in the README.
    • I verified the JSDocs style guidelines (in STYLE.md) were followed
  • If a new code pattern is added I verified it was agreed to be used by multiple Expensify engineers
  • I followed the guidelines as stated in the Review Guidelines
  • 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)
  • I verified all code is DRY (the PR doesn't include any logic written more than once, with the exception of tests)
  • I verified any variables that can be defined as constants (ie. in CONST.ts or at the top of the file that uses the constant) are defined as such
  • I verified that if a function's arguments changed that all usages have also been updated correctly
  • If any new file was added I verified that:
    • The file has a description of what it does and/or why is needed at the top of the file if the code is not self explanatory
  • If a new CSS style is added I verified that:
    • A similar style doesn't already exist
    • The style can't be created with an existing StyleUtils function (i.e. StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))
  • 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 a new page is added, I verified it's using the ScrollView component to make it scrollable when more elements are added to the page.
  • 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 android1 android2
Android: mWeb Chrome android-web2 android-web
iOS: Native ios ios2
iOS: mWeb Safari ios-web ios-web2
MacOS: Chrome / Safari web1 web2

@narefyev91 narefyev91 requested review from a team as code owners December 3, 2025 15:26
@melvin-bot melvin-bot bot requested review from Krishna2323 and removed request for a team December 3, 2025 15:26
@melvin-bot
Copy link

melvin-bot bot commented Dec 3, 2025

@Krishna2323 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 heyjennahay and removed request for a team December 3, 2025 15:26
@narefyev91 narefyev91 changed the title Fix broken connection visibility for Cards [Internal QA]: Fix broken connection visibility for Cards Dec 3, 2025
@codecov
Copy link

codecov bot commented Dec 3, 2025

Codecov Report

❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.

Files with missing lines Coverage Δ
src/components/FeedSelector.tsx 0.00% <0.00%> (ø)
src/pages/settings/Wallet/PaymentMethodList.tsx 0.00% <0.00%> (ø)
src/libs/CardUtils.ts 70.20% <0.00%> (-0.37%) ⬇️
...rc/pages/settings/Wallet/PaymentMethodListItem.tsx 0.00% <0.00%> (ø)
... and 7 files with indirect coverage changes

@narefyev91
Copy link
Contributor Author

@joekaufmanexpensify could you please run ad-hocs and test this one? all UI issues should be fixed

@joekaufmanexpensify
Copy link
Contributor

Yep, will test today 👍

@github-actions
Copy link
Contributor

github-actions bot commented Dec 5, 2025

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

@github-actions

This comment has been minimized.

@Krishna2323
Copy link
Contributor

Reviewing...

@Krishna2323
Copy link
Contributor

Hi @narefyev91 — as an external contributor, I don’t have access to a company card. I simulated a broken connection by setting lastScrapeResult to 401 in Onyx and tested the UI. Is that enough for reviewing the frontend?

Monosnap.screencast.2025-12-06.00-45-31.mp4
Code used to Seed Mock Broken CompanyCard
/**
 * DEV-ONLY: Seed a mock company card feed and a broken connection card into Onyx to enable local UI testing
 * without needing a real bank connection.
 *
 * This will:
 * - Create a feed entry in SHARED_NVP_PRIVATE_DOMAIN_MEMBER for the workspace
 * - Set the LAST_SELECTED_FEED for the given policy
 * - Create one card under WORKSPACE_CARDS_LIST with lastScrapeResult set to a non-ignored error (401)
 * - Mirror the card into CARD_LIST for global consumers
 */
function seedMockBrokenCompanyCard(policyID: string) {
    // Only allow seeding in dev
    // eslint-disable-next-line no-undef
    if (typeof __DEV__ !== 'undefined' && !__DEV__) {
        return;
    }

    const workspaceAccountID = PolicyUtils.getWorkspaceAccountID(policyID);
    if (!workspaceAccountID) {
        return;
    }

    const bankName = CONST.COMPANY_CARD.FEED_BANK_NAME.CAPITAL_ONE;
    const domainOrWorkspaceAccountID = workspaceAccountID;
    const cardID = '99990001';
    const lastScrapeResult = 401; // not in BROKEN_CONNECTION_IGNORED_STATUSES, so treated as broken
    const mockDomainName = 'Mock Workspace';
    const mockCardName = 'Business Gold Card - 3333';
    const mockCardState = CONST.EXPENSIFY_CARD.STATE.OPEN;
    const mockErrors = {
        connection: "There's an issue with this card's connection, which may result in you not seeing transactions. Please contact your administrator to resolve.",
    };

    const feedWithDomainID = CardUtils.getCompanyCardFeedWithDomainID(bankName, domainOrWorkspaceAccountID);

    const updates: OnyxUpdate[] = [
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: `${ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_DOMAIN_MEMBER}${domainOrWorkspaceAccountID}`,
            value: {
                settings: {
                    companyCards: {
                        [bankName]: {
                            preferredPolicy: policyID,
                        },
                    },
                },
            },
        },
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: `${ONYXKEYS.COLLECTION.LAST_SELECTED_FEED}${policyID}`,
            value: feedWithDomainID,
        },
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: `${ONYXKEYS.COLLECTION.WORKSPACE_CARDS_LIST}${domainOrWorkspaceAccountID}_${bankName}`,
            value: {
                [cardID]: {
                    cardID: Number(cardID),
                    bank: bankName,
                    domainName: mockDomainName,
                    cardName: mockCardName,
                    lastScrapeResult,
                    state: mockCardState,
                    errors: mockErrors,
                },
            },
        },
        {
            onyxMethod: Onyx.METHOD.MERGE,
            key: ONYXKEYS.CARD_LIST,
            value: {
                [cardID]: {
                    cardID: Number(cardID),
                    bank: bankName,
                    domainName: mockDomainName,
                    cardName: mockCardName,
                    lastScrapeResult,
                    state: mockCardState,
                    errors: mockErrors,
                },
            },
        },
    ];

    Onyx.update(updates);
}

@joekaufmanexpensify
Copy link
Contributor

@narefyev91 Minor issue. We are showing the red dot twice on the card row on wallet. If you look at OP in the issue, we previously only showed it alongside the error. Can we do that we did before?

image

@joekaufmanexpensify
Copy link
Contributor

I also am not seeing the new message in #admins, is that expected?

image

@joekaufmanexpensify
Copy link
Contributor

Also, when I fixed the broken connection, we removed the error on the card feed, but the one on wallet remained. Both should be removed when the connection is fixed.

image image

@narefyev91
Copy link
Contributor Author

I also am not seeing the new message in #admins, is that expected?

image

@joekaufmanexpensify could you please send Onyx data for "reportActions_ID_OF_YOUR_ADMIN_CHAT" - let's see if we get from Onyx that message.

@narefyev91
Copy link
Contributor Author

Also, when I fixed the broken connection, we removed the error on the card feed, but the one on wallet remained. Both should be removed when the connection is fixed.

image image

I could be wrong - but could you also check cardList - in onyx - and see if card which you fixed does not have any text inside errors field. Based on the logic and your screenshot - card last scrape result was fixed and updated in onyx - but error prop is not changed.

@joekaufmanexpensify joekaufmanexpensify requested review from joekaufmanexpensify and removed request for heyjennahay December 8, 2025 13:43
@joekaufmanexpensify
Copy link
Contributor

Sure. I will retest this morning to get the error state back to send both of those onyx details to you 👍

@joekaufmanexpensify
Copy link
Contributor

@joekaufmanexpensify could you please send Onyx data for "reportActions_ID_OF_YOUR_ADMIN_CHAT" - let's see if we get from Onyx that message.

I DM'ed this to you 👍

I could be wrong - but could you also check cardList - in onyx - and see if card which you fixed does not have any text inside errors field. Based on the logic and your screenshot - card last scrape result was fixed and updated in onyx - but error prop is not changed.

The card in onyx has this error, even after I fix the broken connection and the error is removed from the Company cards page:

"There's an issue with this card's connection, which may result in you not seeing transactions. Please contact your administrator to resolve."

@github-actions
Copy link
Contributor

github-actions bot commented Dec 8, 2025

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

@github-actions
Copy link
Contributor

github-actions bot commented Dec 8, 2025

🧪🧪 Use the links below to test this adhoc build on Android, iOS, Desktop, and Web. Happy testing! 🧪🧪
Built from App PR #76620.

Android 🤖 iOS 🍎
⏩ SKIPPED ⏩ ⏩ SKIPPED ⏩
The build for Android was skipped The build for iOS was skipped
Desktop 💻 Web 🕸️
⏩ SKIPPED ⏩ https://76620.pr-testing.expensify.com
The build for Desktop was skipped Web

👀 View the workflow run that generated this build 👀

@joekaufmanexpensify
Copy link
Contributor

@narefyev91 One other thought. Would it be easy to change the error message on the card row of Wallet for admins, but leave it for employees? I had thought that it's odd we tell admins to contact their administrator to resolve there, since that is them. If we could leave the employee error message as-is, but change the admin one to the below, that would make the UX much clearer:

There's an issue with this card's connection, whucg may result in you not seeing transactions. [Log into your bank](link to error on company cards page) to restore card imports.

@narefyev91
Copy link
Contributor Author

@narefyev91 One other thought. Would it be easy to change the error message on the card row of Wallet for admins, but leave it for employees? I had thought that it's odd we tell admins to contact their administrator to resolve there, since that is them. If we could leave the employee error message as-is, but change the admin one to the below, that would make the UX much clearer:

There's an issue with this card's connection, whucg may result in you not seeing transactions. [Log into your bank](link to error on company cards page) to restore card imports.

Well error message is taken from API response - i think based on the logged user - API could return correct error message in Onyx or just return 2 error messages - one for regular user - one for admin. And on FE side i could pick correct one to show

@joekaufmanexpensify
Copy link
Contributor

Ah. I see. So doing that change correctly would require a backend change?

@narefyev91
Copy link
Contributor Author

Ah. I see. So doing that change correctly would require a backend change?

yeah you are 100% right

@NikkiWines
Copy link
Contributor

@github-actions
Copy link
Contributor

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

@github-actions
Copy link
Contributor

🧪🧪 Use the links below to test this adhoc build on Android, iOS, Desktop, and Web. Happy testing! 🧪🧪
Built from App PR #76620.

Android 🤖 iOS 🍎
⏩ SKIPPED ⏩ https://ad-hoc-expensify-cash.s3.amazonaws.com/ios/76620/index.html
The build for Android was skipped iOS
Desktop 💻 Web 🕸️
⏩ SKIPPED ⏩ https://76620.pr-testing.expensify.com
The build for Desktop was skipped Web

👀 View the workflow run that generated this build 👀

@joekaufmanexpensify
Copy link
Contributor

Nice, thanks @NikkiWines! I see that PR is merged, so I ran an adhoc and will test the fix. Are you able to help with the other backend changes we were looking to make:

@joekaufmanexpensify
Copy link
Contributor

Chatted with @NikkiWines and confirmed she doesn't have bandwidth to help with the other backend changes right now, so looking for another volunteer.

@joekaufmanexpensify
Copy link
Contributor

PR to fix #76620 (comment) is up: https://github.com/Expensify/Auth/pull/18719

Retested this and still one minor issue. Discussing in the BE PR.

@joekaufmanexpensify
Copy link
Contributor

BUG: We're incorrectly showing broken connection across multiple feeds

Steps

  1. Connect a direct feed and commercial feed on a workspace.
  2. Assign a card under both.
  3. Break the direct feed connection.

Expected behavior

We only show the broken connection error for the direct feed, not the commercial feed. Commercial feed connections can't break.

Actual behavior

We show the broken connection error for both feeds.

image image image image

@joekaufmanexpensify
Copy link
Contributor

New backend PR is up to fix #76620 (comment). It's merged and awaiting deploy

@narefyev91
Copy link
Contributor Author

@joekaufmanexpensify updated FE part as well - now should show correctly error for the selected feed

@github-actions
Copy link
Contributor

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

@github-actions
Copy link
Contributor

🧪🧪 Use the links below to test this adhoc build on Android, iOS, Desktop, and Web. Happy testing! 🧪🧪
Built from App PR #76620.

Android 🤖 iOS 🍎
⏩ SKIPPED ⏩ ⏩ SKIPPED ⏩
The build for Android was skipped The build for iOS was skipped
Desktop 💻 Web 🕸️
⏩ SKIPPED ⏩ https://76620.pr-testing.expensify.com
The build for Desktop was skipped Web

👀 View the workflow run that generated this build 👀

@joekaufmanexpensify
Copy link
Contributor

Retested #76620 (comment) and mostly working now. Only minor feedback @narefyev91 is we should still show a red dot next to the Visa feed name when the Visa feed is open, which is meant to guide the user to open the feed selector where they can select the feed with the error. LMK if you have any questions on what I mean by that.

image image

@github-actions
Copy link
Contributor

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

@github-actions
Copy link
Contributor

🧪🧪 Use the links below to test this adhoc build on Android, iOS, Desktop, and Web. Happy testing! 🧪🧪
Built from App PR #76620.

Android 🤖 iOS 🍎
⏩ SKIPPED ⏩ ⏩ SKIPPED ⏩
The build for Android was skipped The build for iOS was skipped
Desktop 💻 Web 🕸️
⏩ SKIPPED ⏩ https://76620.pr-testing.expensify.com
The build for Desktop was skipped Web

👀 View the workflow run that generated this build 👀

@joekaufmanexpensify
Copy link
Contributor

Retested #76620 (comment) and the red dot fix looks good. TY!

@joekaufmanexpensify
Copy link
Contributor

@nkuoch volunteered to handle these remaining backend changes. We'll tackle them in this internal issue.

@joekaufmanexpensify
Copy link
Contributor

This other backend PR is still pending deploy. Will retest that bug as soon as it's out.

# Conflicts:
#	src/components/FeedSelector.tsx
#	src/libs/CardUtils.ts
#	src/pages/settings/Wallet/PaymentMethodListItem.tsx
#	src/pages/workspace/companyCards/WorkspaceCompanyCardsListHeaderButtons.tsx
@narefyev91
Copy link
Contributor Author

@joekaufmanexpensify my PR and correct changes were fully broke down by this PR https://github.com/Expensify/App/pull/78178/files
I do not know exactly what it's doing - probably a new feature

@joekaufmanexpensify
Copy link
Contributor

It is a new feature and I agree there are some considerations related to it. Let's discuss here.

chrispader added a commit to margelo/Expensify that referenced this pull request Jan 8, 2026
@narefyev91 narefyev91 closed this Jan 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants