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

Refactor Session.resendValidationLink and the ResendValidationForm to use the new API #10556

Merged
merged 35 commits into from
Sep 1, 2022

Conversation

jasperhuangg
Copy link
Contributor

@jasperhuangg jasperhuangg commented Aug 25, 2022

Details

Fixed Issues

$ https://github.com/Expensify/Expensify/issues/211841

Tests

  1. Use EmailOnDeck to register for a temporary email address.
  2. Add the following line to ~/Web-Expensify/_config.local.php to whitelist this email address for dev.
define('DEV_EMAILS', ['<email address>']);
  1. Navigate to the sign in page and enter this email address.
  2. Click "Resend link". Verify that the following message appears when you do:

Screen Shot 2022-08-25 at 9 43 24 AM

6. Now run `vssh php /vagrant/Web-Expensify/script/notifyall.php` to send out the validation link emails. 7. Verify that [EmailOnDeck](https://www.emailondeck.com/) has received 2 emails with subject "Your magic sign in link for Expensify".

Screen Shot 2022-08-23 at 12 01 49 PM

8. Now back on NewDot, click "Resend link" a bunch of times. Eventually, you'll get an error that should display like so:

Screen Shot 2022-08-25 at 10 31 13 AM

PR Review Checklist

Contributor (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 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 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 tagging the marketing team 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
  • 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 */
    • Any functional components have the displayName property
    • 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.

PR Reviewer Checklist

The Contributor+ will copy/paste it into a new comment and complete it after the author checklist is completed

  • 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 verified tests pass on all platforms & I tested again 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 verified proper code patterns were followed (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 tagging the marketing team 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 verified that this PR follows the guidelines as stated in the Review Guidelines
  • 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)
  • 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
  • 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 */
    • Any functional components have the displayName property
    • 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 reviewer checklist, including those that don't apply to this PR.

QA Steps

Same as the testing steps, except you can skip steps 2 and 6.

  • Verify that no errors appear in the JS console

Screenshots

Web

Screen Shot 2022-08-25 at 10 13 05 AM

Mobile Web

Screen Shot 2022-08-25 at 10 22 57 AM

Desktop

Screen Shot 2022-08-25 at 10 22 14 AM

iOS

Screen Shot 2022-08-25 at 10 23 12 AM

Android

Screen Shot 2022-08-25 at 10 23 06 AM

@jasperhuangg jasperhuangg self-assigned this Aug 25, 2022
@jasperhuangg jasperhuangg marked this pull request as ready for review August 25, 2022 00:31
@jasperhuangg jasperhuangg requested a review from a team as a code owner August 25, 2022 00:31
@melvin-bot melvin-bot bot requested review from puneetlath and removed request for a team August 25, 2022 00:32
@jasperhuangg
Copy link
Contributor Author

@shawnborton picking up from this:

I feel like this should be extrapolated out into a reusable component, and should build off of what we already have in place for the red brick road message.

Where is this red brick road message located?

@jasperhuangg jasperhuangg removed the request for review from puneetlath August 25, 2022 00:33
@shawnborton
Copy link
Contributor

Here is some good reading: #9931

@jasperhuangg
Copy link
Contributor Author

Here is some good reading: #9931

@shawnborton I see! That component is intended to be used with Pattern B, but the resend validation link flow is actually Pattern C, so this component isn't entirely reusable.

What I'll do is refactor the red brick/text styles from the OfflineWithFeedback component that was added in that PR into another component (name suggestions welcome), and reuse that component in both the OfflineWithFeedback component and the ResendValidationForm. Thoughts?

@jasperhuangg
Copy link
Contributor Author

jasperhuangg commented Aug 25, 2022

@shawnborton Ended up creating a DotIndicatorMessage component, since it can be used for both errors and success messages. Please let me know what you think!
Screen Shot 2022-08-25 at 10 31 13 AM

Screen Shot 2022-08-25 at 9 43 24 AM

Also made sure that I didn't break the OfflineWithFeedback component that was added in #9931 by recreating the screenshots included in the OP for that PR that use this new component:
Screen Shot 2022-08-25 at 10 05 44 AM

@jasperhuangg
Copy link
Contributor Author

jasperhuangg commented Aug 25, 2022

@shawnborton @bondydaa @aldo-expensify Updated the screenshots in the OP to include the new dot indicator message styles, ready for another review, thanks in advance :)

@jasperhuangg jasperhuangg requested a review from iwiznia August 25, 2022 02:29
@jasperhuangg
Copy link
Contributor Author

@iwiznia Requesting you for review as well since I touched the OfflineWithFeedback component you implemented recently.

Copy link
Contributor

@aldo-expensify aldo-expensify left a comment

Choose a reason for hiding this comment

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

Left a suggestion, looking good

src/libs/actions/Session/index.js Outdated Show resolved Hide resolved
@aldo-expensify
Copy link
Contributor

I tested in Android device and the styles are looking good for the error/success message

@bondydaa
Copy link
Contributor

updated again, here are more screenshots of desktop
Screen Shot 2022-08-31 at 6 06 46 PM
Screen Shot 2022-08-31 at 6 07 55 PM
Screen Shot 2022-08-31 at 6 08 04 PM
Screen Shot 2022-08-31 at 6 08 12 PM

</Text>
</View>
{!_.isEmpty(props.account.message) && (
<DotIndicatorMessage style={[styles.mb5]} type="success" messages={{[DateUtils.getMicroseconds()]: props.account.message}} />
Copy link
Contributor

@aldo-expensify aldo-expensify Aug 31, 2022

Choose a reason for hiding this comment

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

NAB: I don't like that key changing on every render, but considering the code in DotIndicatorMessage, this won't cause any issue at the moment. If the code changes in DotIndicatorMessage and the errors keys where used as the key prop in the map creating the <Text> this could create performance issues:

image

The code in DotIndicatorMessage could change like that at some point in the future because using array indexes as keys is not recommended and using the error key as the key prop would have been better.

--- but all this has low importance => NAB

(There is not benefit on using DateUtils.getMicroseconds() vs just 0 as a key because you only have one error, so sorting doesn't matter)

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree we should use a constant and also NAB

Copy link
Contributor

Choose a reason for hiding this comment

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

👍 yeah I hear ya on the potential performance issue, I can add a comment as a "beware" here if you think it might help.

(There is not benefit on using DateUtils.getMicroseconds() vs just 0 as a key because you only have one error, so sorting doesn't matter)

and yeah I agree, we could use anything as the key in this object 0, abc, etc. I'll update that to make it simpler.

@aldo-expensify aldo-expensify self-requested a review August 31, 2022 17:31
iwiznia
iwiznia previously approved these changes Aug 31, 2022
.map(key => this.props.account.errors[key])
.first()
.value();
const error = formErrorTranslated || ErrorUtils.getLatestErrorMessage(this.props.account);
Copy link
Contributor

Choose a reason for hiding this comment

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

I still don't get why we only care about one error... NAB though since this existed before

</Text>
</View>
{!_.isEmpty(props.account.message) && (
<DotIndicatorMessage style={[styles.mb5]} type="success" messages={{[DateUtils.getMicroseconds()]: props.account.message}} />
Copy link
Contributor

Choose a reason for hiding this comment

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

I agree we should use a constant and also NAB

@jasperhuangg
Copy link
Contributor Author

jasperhuangg commented Sep 1, 2022

@bondydaa cool if I assign you this PR? that way you also get contributions (I think) when it gets merged.

@bondydaa
Copy link
Contributor

bondydaa commented Sep 1, 2022

that way you also get contributions (I think) when it gets merged

contributions are about commits not who's assigned so we'll both get them for the commits that we author'd (or co-author'd) that get merged. 😉

@bondydaa
Copy link
Contributor

bondydaa commented Sep 1, 2022

ready for another review 🙏

@bondydaa bondydaa merged commit 8b510f8 into main Sep 1, 2022
@bondydaa bondydaa deleted the jasper-resendValidateCodeRefactor2 branch September 1, 2022 08:43
@OSBotify
Copy link
Contributor

OSBotify commented Sep 1, 2022

✋ 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

OSBotify commented Sep 1, 2022

🚀 Deployed to staging by @bondydaa in version: 1.1.96-0 🚀

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

@sobitneupane
Copy link
Contributor

sobitneupane commented Jan 24, 2023

This PR specifically this commit might have caused this regression.

@bondydaa
Copy link
Contributor

I think you linked the wrong thing on this regression but I see #13824 popping up underneath your comment so figured it out.

Yeah I agree this was probably the cause, we should always be sure to test with 0, 1, many workspace members (and errors) to ensure the border is displayed properly.

@sobitneupane
Copy link
Contributor

I think you linked the wrong thing on this regression

Oops my mistake. Updated the comment.

key: ONYXKEYS.ACCOUNT,
value: {
isLoading: false,
message: Localize.translateLocal('resendValidationForm.linkHasBeenResent'),
Copy link
Contributor

Choose a reason for hiding this comment

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

Hi ✋ coming from #17216, where this message is not translated when a user changes the language.

Localized text saved in Onyx is not translated when the locale is changed. So instead, we should save the key and translate it at the component level.

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.

8 participants