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

Improve Phone Number Entry Validation and Error Messaging for Users #55337

Open
1 of 8 tasks
m-natarajan opened this issue Jan 16, 2025 · 3 comments
Open
1 of 8 tasks
Assignees
Labels
Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 Improvement Item broken or needs improvement.

Comments

@m-natarajan
Copy link

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Version Number: 9.0.86-1
Reproducible in staging?: Y
Reproducible in production?: Y
If this was caught on HybridApp, is this reproducible on New Expensify Standalone?:
If this was caught during regression testing, add the test name, ID and link from TestRail:
Email or phone of affected tester (no customers):
Logs: https://stackoverflow.com/c/expensify/questions/4856
Expensify/Expensify Issue URL:
Issue reported by: @quinthar
Slack conversation (hyperlinked to channel name): convert

Action Performed:

  1. Go to the phone number input field.
  2. Attempt to enter a phone number without a + or using typical formatting like parentheses or dashes.
  3. Note that the system rejects the input and displays the error message.

Expected Result:

The system should accept phone numbers with or without the + prefix and ignore non-numeric characters during validation.
The error message should be clear and provide an example of a correctly formatted phone number.
Update the error message to:
"Please enter a complete phone number (e.g., +1-(201)-867-5309)."
This provides a clearer example of the expected format.

Actual Result:

The system requires a strict format starting with + and rejects numbers with non-numeric characters.
The error message shown is vague and unhelpful: "Please enter a valid phone number."

Workaround:

Can the user still use Expensify without this being fixed? Have you informed them of the workaround?

Platforms:

Which of our officially supported platforms is this issue occurring on?

  • Android: Standalone
  • Android: HybridApp
  • Android: mWeb Chrome
  • iOS: Standalone
  • iOS: HybridApp
  • iOS: mWeb Safari
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

Add any screenshot/video evidence

Image

Image

Image

Image

Image

Image

View all open jobs on GitHub

@m-natarajan m-natarajan added Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 Improvement Item broken or needs improvement. labels Jan 16, 2025
Copy link

melvin-bot bot commented Jan 16, 2025

Triggered auto assignment to @bfitzexpensify (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

@huult
Copy link
Contributor

huult commented Jan 16, 2025

🚨 Edited by proposal-police: This proposal was edited at 2025-01-16 04:29:02 UTC.

Proposal

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

Improve Phone Number Entry Validation and Error Messaging for Users

What is the root cause of that problem?

Improvement

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

we should update validate function like this:

  1. The system should accept phone numbers with or without the + prefix and ignore non-numeric characters during validation.

const validate = useCallback(
    (
        values: FormOnyxValues<typeof ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM>
    ): FormInputErrors<typeof ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM> => {
        const errors: FormInputErrors<typeof ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM> = {};

        // Validate that the phone number field is not empty
        if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.PHONE_NUMBER])) {
            errors[INPUT_IDS.PHONE_NUMBER] = translate('common.error.fieldRequired');
            return errors; // Early return if field is empty
        }

        try {
            // Sanitize input: Remove all non-numeric characters except the leading '+'
            const sanitizedPhoneNumber = values[INPUT_IDS.PHONE_NUMBER].replace(/[^+\d]/g, '');

            // Append country code if missing
            const phoneNumberWithCountryCode = LoginUtils.appendCountryCode(sanitizedPhoneNumber);

            // Parse and validate the phone number
            const parsedPhoneNumber = PhoneNumberUtils.parsePhoneNumber(phoneNumberWithCountryCode);

            // Check if the phone number is possible and valid in E.164 format
            if (!parsedPhoneNumber.possible || !Str.isValidE164Phone(phoneNumberWithCountryCode)) {
                errors[INPUT_IDS.PHONE_NUMBER] = translate('bankAccount.error.phoneNumber');
            }
        } catch (error) {
            // Handle unexpected errors during parsing or validation
            console.error('Error validating phone number:', error);
            errors[INPUT_IDS.PHONE_NUMBER] = translate('bankAccount.error.phoneNumber');
        }

        // Clear the error if the user tries to validate the form and there are errors
        if (validateLoginError && Object.keys(errors).length > 0) {
            PersonalDetails.clearPhoneNumberError();
        }

        return errors;
    },
    [translate, validateLoginError],
);
  1. The error message should be clear and provide an example of a correctly formatted phone number.

phoneNumber: 'Please enter a valid phone number.',

to

Please enter a complete phone number (e.g., +1-(201)-867-5309).

or like

phoneNumber: `Please enter a valid phone number, with the country code (e.g. ${CONST.EXAMPLE_PHONE_NUMBER})`,
to consistent

  1. Format the phone number with the new update

PersonalDetails.updatePhoneNumber(values?.phoneNumber ?? '', currenPhoneNumber);

Update to

    const phoneNumberWithCountryCode = LoginUtils.appendCountryCode(values?.phoneNumber ?? '');
    const parsedPhoneNumber = PhoneNumberUtils.parsePhoneNumber(phoneNumberWithCountryCode);
    PersonalDetails.updatePhoneNumber(parsedPhoneNumber.number?.e164 ?? '', currenPhoneNumber);

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

Create validation UI tests for each case update

What alternative solutions did you explore? (Optional)

Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

@shubham1206agra
Copy link
Contributor

shubham1206agra commented Jan 16, 2025

Proposal

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

Improve Phone Number Entry Validation and Error Messaging for Users

What is the root cause of that problem?

In validation function here

const validate = useCallback(
(values: FormOnyxValues<typeof ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM>): FormInputErrors<typeof ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM> => {
const errors: FormInputErrors<typeof ONYXKEYS.FORMS.PERSONAL_DETAILS_FORM> = {};
if (!ValidationUtils.isRequiredFulfilled(values[INPUT_IDS.PHONE_NUMBER])) {
errors[INPUT_IDS.PHONE_NUMBER] = translate('common.error.fieldRequired');
}
const phoneNumberWithCountryCode = LoginUtils.appendCountryCode(values[INPUT_IDS.PHONE_NUMBER]);
const parsedPhoneNumber = PhoneNumberUtils.parsePhoneNumber(values[INPUT_IDS.PHONE_NUMBER]);
if (!parsedPhoneNumber.possible || !Str.isValidE164Phone(phoneNumberWithCountryCode.slice(0))) {
errors[INPUT_IDS.PHONE_NUMBER] = translate('bankAccount.error.phoneNumber');
}
// Clear the error when the user tries to validate the form and there are errors
if (validateLoginError && !!errors) {
PersonalDetails.clearPhoneNumberError();
}
return errors;
},
[translate, validateLoginError],
);

We have 2 problems -

  1. We always try to append country code here, but we used unappended phone number to check for possible number here
  2. We strictly try to check for valid E164 format only, which neglects other formats.
  3. We use bankAccount.error.phoneNumber as error.

When we show the error message the size of the view that contains the avatar increases which causes avatar to get centre with respect to the DotIndicator (error message).

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

Fixes

  1. Use appended phone number to validate phone number
  2. Use isValidPhoneFormat instead of isValidE164Phone here
  3. Maybe use placeholder text in the input to indicate a valid phone number, or, update the validation error to the following:
    Please enter a valid phone number (e.g. ${CONST.EXAMPLE_PHONE_NUMBER})

What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

NA since this is validation change

What alternative solutions did you explore? (Optional)

NA

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something is broken. Auto assigns a BugZero manager. Daily KSv2 Improvement Item broken or needs improvement.
Projects
Status: No status
Development

No branches or pull requests

4 participants