Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix and refactor VBBA setup flow #13236

Merged
merged 38 commits into from
Jan 20, 2023
Merged

Fix and refactor VBBA setup flow #13236

merged 38 commits into from
Jan 20, 2023

Conversation

nkuoch
Copy link
Contributor

@nkuoch nkuoch commented Dec 1, 2022

Details

Refactoring and fixing different issues in the vbba setup flow:

  • Extract isPlaidDisabled from plaidData Onyx key, as it's not set in the same flow as the rest, and causing issues when we expect plaidData to be rest to empty.
  • Pass plaidData, reimbursementAccount and reimbursementAccountDraft via required props instead of withOnyx, and call them explicitly instead of via lodashGet:
    • to avoid eslint-disable-next-line react/no-unused-prop-types and other engineers thinking they can remove them because unused.
    • to avoid having declare default props for those in each view. Instead, it will be centralized in the parent view
  • Prevent infinite loader in AddPlaidBankAccount view
  • Add back button on offline blocking view. Handle backPress on parent view so the logic can be shared.
  • Remove some unused methods
  • Make sure we reset PlaidData when needed
  • Add missing reimbursementAccountDraft propTypes
  • Refactor getDefaultStateForField so engineers don't think reimbursementAccountDraft or reimbursementAccount are not used
  • Refactor WorkspaceResetBankAccountModal and fix cases were it was stuck displaying
  • Prevent editing LOCKED bank account
  • Fix bug that returns to bank login view after logging in successfully

Fixed Issues

$ #13166
$ #12708
$ https://github.com/Expensify/Expensify/issues/245747
$ #11777
$ #12123
$ #13598
$ #13911
$ https://github.com/Expensify/Expensify/issues/231253
$ https://github.com/Expensify/Expensify/issues/236672
$ https://github.com/Expensify/Expensify/issues/217507
$ #14157

Tests

To be tested with Web PR: https://github.com/Expensify/Web-Expensify/pull/35797

Same as in QA Steps

Offline steps

Included in QA Steps

QA Steps

Just complete the VBBA setup flow with random data and doing this:

  • at the beginning of the flow (when seeing the 2 options: plaid/manual), go offline. Click on Plaid. You should see the offline view. Make sure you can go back to the 2 options. Go back online. Make sure the view remains the same.
image image
  • Connect via Plaid Chase and select a plaid account without submitting. Go back (clicking on the left arrow from the right panel from the bankAccountStep), click back to a plaid bank and log in again, but picking up other bank accounts than the one you selected before plaid auth side. Make sure the selector shows the new accounts
image image
image image
  • click on the left arrow from the right panel for each step (to test the "back" behavior)

    • BankAccount
image image
  • Company
image image
  • Requestor
image image
  • Onfido
image image

Note: after resubmitting the requestor step, you shouldn't see Onfido again unless you modify your name

  • Beneficial Owners
image image
  • exit in the middle of the flow (when seeing the beneficial owners step for example), and make sure you can Continue with Setup and finish the flow
image image image

image

  • Make sure you can also add a personal bank account

  • No console error should appear

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:
    • iOS / native
    • Android / native
    • iOS / Safari
    • Android / Chrome
    • MacOS / Chrome
    • MacOS / Desktop
  • 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 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 was added in all src/languages/* files
    • I verified any copy / text that was added to the app is correct English and approved by marketing by adding the Waiting for Copy label for a copy review on the original GH to get the correct copy.
    • 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.js 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 a new component is created I verified that:
    • A similar component doesn't exist in the codebase
    • All props are defined accurately and each prop has a /** comment above it */
    • The file is named correctly
    • 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
    • For Class Components, any internal methods passed to components event handlers are bound to this properly so there are no scoping issues (i.e. for onClick={this.submit} the method this.submit should be bound to this in the constructor)
    • Any internal methods bound to this are necessary to be bound (i.e. avoid this.submit = this.submit.bind(this); if this.submit is never passed to a component event handler like onClick)
    • All JSX used for rendering exists in the render method
    • 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 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(themeColors.componentBG)
  • 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.
  • I have checked off every checkbox in the PR author checklist, including those that don't apply to this PR.

Screenshots/Videos

Web

See screenshots from QA Steps

Mobile Web
vbbaIOSSafari.mp4
Desktop

Test start back & back from each step

2023-01-17_11-43-06.mp4

Test start over

remove.mp4

Test changing Plaid bank account

2023-01-17_11-58-50.mp4

Test adding a personal bank account

2023-01-17_12-01-54.mp4
iOS

Test back from each step

TestAllTheWayBackFromOnfidoAndContinue.mp4
TestBackFromBenefStepAndOpen.mp4
Android

Offline Plaid: https://recordit.co/TR5KrMlOto

Backwards works for BankAccountStep: https://recordit.co/0Shseu59kF

Backwards from Requestor Step and Onfido: https://recordit.co/ldlH7Wugkp

Beneficial Owners: https://recordit.co/VnmIixo3QR

image

@nkuoch nkuoch self-assigned this Dec 1, 2022
@melvin-bot
Copy link

melvin-bot bot commented Dec 1, 2022

Hey, I noticed you changed some webpack configuration files. This can break production builds. Did you remember to run a production build locally to verify they still work?

@nkuoch nkuoch force-pushed the nat-back branch 9 times, most recently from 945fc23 to 6f042c2 Compare December 8, 2022 14:52
@nkuoch nkuoch force-pushed the nat-back branch 8 times, most recently from b3dca8b to d7b5176 Compare December 9, 2022 15:24
@nkuoch nkuoch changed the title Refactor VBBA setup flow and allow to go back from offline view Fix and refactor VBBA setup flow Dec 13, 2022
@nkuoch nkuoch force-pushed the nat-back branch 7 times, most recently from 95e827b to 52974c0 Compare December 16, 2022 22:15
Allow to go back from offline view
Fix and refactor startOver modal
Refactor getDefaultStateForField so people dont think reimbursementAccountDraft is not used
@nkuoch nkuoch marked this pull request as ready for review December 16, 2022 22:40
@OSBotify
Copy link
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.

@OSBotify
Copy link
Contributor

🚀 Deployed to staging by https://github.com/ctkochan22 in version: 1.2.58-0 🚀

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

@Pujan92
Copy link
Contributor

Pujan92 commented Jan 24, 2023

@nkuoch seems this PR causing the deploy blocker issue as in the BankAccounts.js we are using setBankAccountSubStep but we aren't importing that.

diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js
index b6aea981e..11fe41607 100644
--- a/src/libs/actions/BankAccounts.js
+++ b/src/libs/actions/BankAccounts.js
@@ -7,6 +7,7 @@ import DateUtils from '../DateUtils';
 import * as PlaidDataProps from '../../pages/ReimbursementAccount/plaidDataPropTypes';
 import Navigation from '../Navigation/Navigation';
 import ROUTES from '../../ROUTES';
+import * as ReimbursementAccount from './ReimbursementAccount';
 
 export {
     goToWithdrawalAccountSetupStep,
@@ -38,7 +39,7 @@ function clearPlaid() {
 }
 
 function openPlaidView() {
-    clearPlaid().then(() => this.setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID));
+    clearPlaid().then(() => ReimbursementAccount.setBankAccountSubStep(CONST.BANK_ACCOUNT.SETUP_TYPE.PLAID));
 }

@OSBotify
Copy link
Contributor

🚀 Deployed to production by https://github.com/chiragsalian in version: 1.2.58-4 🚀

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

@luacmartins
Copy link
Contributor

@nkuoch Are we supposed to be able to edit the company name and tax ID once we've saved them once and advanced to the Personal information step? They don't seem to be disabled anymore although these variables would suggest they should. I just want to confirm the expected behavior before I add a fix to this PR

@nkuoch
Copy link
Contributor Author

nkuoch commented Jan 31, 2023

I confirm we're not supposed to be able to edit them once we've reached the requestor step.
How did you reproduce the bug? I personally can't reproduce what you're saying.

@luacmartins
Copy link
Contributor

Oh weird. I can't reproduce it anymore either 🤔 Anyways, thanks for confirming!

@luacmartins
Copy link
Contributor

luacmartins commented Jan 31, 2023

Nvm, I can still reproduce on main/staging/prod on iOS/android

Comment on lines +263 to +267
if (this.props.reimbursementAccount.shouldShowResetModal && Boolean(achData.bankAccountID)) {
return (
<WorkspaceResetBankAccountModal reimbursementAccount={this.props.reimbursementAccount} />
);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Just as an FYI, this caused #14692

We missed testing for the Start over feature in this PR so we didn't notice that there was a blank screen behind the confirmation modal.

@NikkiWines
Copy link
Contributor

👋 Hi, we've identified this PR as 1/2 of the cause of #14972. The logic in getDefaultStateForField() does not work correctly in the event that lodashGet(reimbursementAccountDraft, fieldName) returns false.

 function getDefaultStateForField(reimbursementAccountDraft, reimbursementAccount, fieldName, defaultValue = '') { 
    return lodashGet(reimbursementAccountDraft, fieldName)
        || lodashGet(reimbursementAccount, ['achData', fieldName], defaultValue);
 } 

In this case, this could've been avoided by doing some more robust testing to ensure that the default state value matched what we were expecting in a variety of scenarios. We've got a proposed regression test here that should cover this scenario 🙌

@@ -93,7 +98,10 @@ class AddPersonalBankAccountPage extends React.Component {
description={this.props.translate('addPersonalBankAccountPage.successMessage')}
shouldShowButton
buttonText={this.props.translate('common.continue')}
onButtonPress={() => Navigation.navigate(ROUTES.SETTINGS_PAYMENTS)}
onButtonPress={() => {
BankAccounts.clearPersonalBankAccount();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Clearing this early cause a regression #15202

@mananjadhav
Copy link
Collaborator

I am tagging this PR to highlight an issue fixed here. All conditions in ternary expressions or left-hand operands on conditional renders, should be boolean. This PR is one of the PRs that uses conditional render with string operands, hence I am tagging it here for the contributors to check.

We've also updated the item in the checklist with this PR to avoid this issue in the future.

case CONST.BANK_ACCOUNT.STEP.VALIDATION:
if (_.contains([BankAccount.STATE.VERIFYING, BankAccount.STATE.SETUP], achData.state)) {
BankAccounts.goToWithdrawalAccountSetupStep(CONST.BANK_ACCOUNT.STEP.ACH_CONTRACT);
} else if (achData.state === BankAccount.STATE.PENDING) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We did not take into account the user being offline while adding this condition. This caused #21837 to come up later.

Comment on lines 51 to -53
onSelected: () => {
BankAccounts.clearPlaid();
Copy link
Contributor

Choose a reason for hiding this comment

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

Coming from #32906, this change caused a regression, after this change the plaid token is not cleared.

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.