App: [HOLD for payment 2022-12-20] [HOLD] [$1000] Mobile keyboard doesn't include `/` char when expiration field is in focus

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


CC @Gonals

Action Performed:

  • Navigate to Profile > Payments > Add A debit Card
  • Fill in the data until you get to the expiration date field
  • Select the expiration date input
  • Enter 2 characters

Expected Result:

  • Either the / char should appear in the soft keyboard, or we should automatically add it for users

Actual Result:

  • Neither the / char appears in the soft keyboard, or do we automatically add it for users

Screenshot_20221129_152213 Simulator Screen Shot - iPhone 14 Pro - 2022-11-29 at 15 34 19

Note: Users still seem to pass validation without it, but this is still confusing

Platform:

Where is this issue occurring?

  • iOS
  • Android
  • Mobile Web

Version Number: all Reproducible in staging?: yes Reproducible in production?: yes Email or phone of affected tester (no customers): all

View all open jobs on GitHub

Upwork Automation - Do Not Edit

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 49 (36 by maintainers)

Most upvoted comments

Paid @thesahindia and @Puneet-here the price + bonus for this issue.

Proposal

  1. Reproducible This issue is easy to reproduce and I don’t think I have to attach video or screenshot again. 😄
  2. Why reproduced? As @Puneet-here mentioned, appending slash module was removed while implementing with new Form logic. And need to update the our Form as @thesahindia mentioned.
  3. How to resolve? We can use the changes from here if it was working correctly.
  • Add new props shouldAppendSlash props to the TextInput in AddDebitCartPage.js
        <TextInput
                                inputID="expirationDate"
                                label={this.props.translate('addDebitCardPage.expiration')}
                                placeholder={this.props.translate('addDebitCardPage.expirationDate')}
                                keyboardType={CONST.KEYBOARD_TYPE.NUMBER_PAD}
+                                shouldAppendSlash
                            />
  • Update the Form component like below:
        this.inputRefs = {};
        this.touchedInputs = {};

        this.setTouchedInput = this.setTouchedInput.bind(this);
....
+  /**
+     * Append slash if needed e.g. ExpirationDate input
+     * @param {string} inputValue - input value on text change event
+     * @param {string} inputKey - key of state for specific input field
+     * @returns {string}
+     */
+    appendSlashIfNeeded(inputValue, inputKey) {
+        let slashAppended = inputValue;
+        const inputStateValue = this.state.inputValues[inputKey]
+        if (inputStateValue && inputValue.length < inputStateValue.length
+            && (((inputValue.length === 3 && inputValue.charAt(2) === '/')
+              || (inputValue.length === 2 && inputStateValue.charAt(1) === '/')))) {
+                slashAppended = inputValue.substring(0, inputValue.length - 1);
+        } else if (inputValue.length === 2 && _.indexOf(inputValue, '/') === -1) {
+            // An Expiry Date was added, so we should append a slash '/'
+            slashAppended = `${inputValue}/`;
+        } else if (inputValue.length > 2 && _.indexOf(inputValue, '/') === -1) {
+            // Expiry Date with MM and YY without slash, hence adding slash(/)
+            slashAppended = `${inputValue.slice(0, 2)}/${inputValue.slice(2)}`;
+        }
+        return slashAppended;
+    }
...
                 onInputChange: (value, key) => {
                     const inputKey = key || inputID;
-                    this.setState(prevState => ({
-                        inputValues: {
-                            ...prevState.inputValues,
-                            [inputKey]: value,
-                        },
-                    }), () => this.validate(this.state.inputValues));
+                    if (child.props.shouldAppendSlash) {
+                        const slashAppended = this.appendSlashIfNeeded(value, inputKey);
+                        this.setState(prevState => ({
+                            inputValues: {
+                                ...prevState.inputValues,
+                                [inputKey]: slashAppended,
+                            },
+                        }), () => this.validate(this.state.inputValues));                        
+                    } else {
+                        this.setState(prevState => ({
+                            inputValues: {
+                                ...prevState.inputValues,
+                                [inputKey]: value,
+                            },
+                        }), () => this.validate(this.state.inputValues));
+                    }
...

https://user-images.githubusercontent.com/29966461/204745809-efc937bd-4147-47c1-b0da-d4a9586c2b51.mov

I’m going to close this due to the above reasoning, but let me know if you disagree @mallenexpensify and we can discuss further

Hey, sorry but I ran out of time for this today. Will return to this tomorrow.

^ This was not a regression

BugZero Checklist: The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed:

  • [@thesahindia / @Julesssss] The PR that introduced the bug has been identified. Link to the PR:
  • [@thesahindia / @Julesssss] The offending PR has been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake. Link to comment:
  • [@thesahindia / @Julesssss] A discussion in #expensify-bugs has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner. Link to discussion:
  • [@kadiealexander] A regression test has been added or updated so that the same bug will not reach production again. Link to the GH issue for creating the test here:

Oh sorry, I can’t read. That makes sense, thanks!