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

Update phone validation regex to accept only numbers and correct amount - Fix "must consist of only numbers" validation error message to be specific #112

Open
wants to merge 40 commits into
base: develop
Choose a base branch
from

Conversation

MaxwellGarceau
Copy link
Collaborator

@MaxwellGarceau MaxwellGarceau commented Jan 3, 2025

Description of the Change

Update phone validation to fix several bugs and give detailed error messages.

Issue #101 - Update phone validation regex to accept only numbers and correct amount

  • Fix a bug that would allow a user to enter phone numbers that contained letters.

Issue #104 - Update phone validation regex to accept only numbers and correct amount

  • Fix a bug that would allow a user to enter whitespace in the middle of the last group of numbers
  • If too few digits are entered, the form displays an appropriate error message letting the user know that too few digits were entered

Closes #101
Closes #104
Both these issues required work in the same function that would have created ugly merge conflicts.

How to test the Change

Setup

  1. Change the phone format in the test user Mailchimp account to US format
  2. Click the "Update List" button in the Mailchimp admin
  3. Set the Phone number merge field to be included
  4. Navigate to a FE form for submission testing

General

  • Form submission with empty phone number and only email should succeed

Phone number should not accept letters

Phone number should not accept letters - Bug is fixed

  • Submit a form with a phone number that contains a letter. The submission should fail. The error message should notify the user that the phone number must only contain numbers.

Test a valid phone number

  • Submit a valid US phone number and the submission should succeed

Test that other invalid characters are not accepted

The phone number field should only accept numbers. The error message should notify the user that the phone number must only contain numbers.

  • The phone field should not accept any of these characters
    • Letters (A–Z, a–z).
    • Special characters like @, #, $, %, *, &, !, etc.
    • Whitespace, both at the ends and also in the middle.
    • Multiple or misplaced delimiters, such as --, (123)), or leading/trailing symbols.
    • Any character outside the ASCII range (e.g., emojis, non-standard symbols). - too broad to really test comprehensively

Phone number does not contain enough digits

Whitespace testing

All whitespace should be stripped and should return an error notifying the user that the phone number does not have enough digits.

  • 1 3 - 12 - 234 should fail validation with an error messaging stating that there are not enough digits

Changelog Entry

Added - New feature
Changed - Existing functionality
Deprecated - Soon-to-be removed feature
Removed - Feature
Fixed - Bug fix
Security - Vulnerability

Credits

Props @username, @username2, ...

Checklist:

  • I agree to follow this project's Code of Conduct.
  • I have updated the documentation accordingly.
  • I have added tests to cover my change.
  • All new and existing tests pass.

@github-actions github-actions bot added this to the 1.7.0 milestone Jan 3, 2025
@MaxwellGarceau
Copy link
Collaborator Author

MaxwellGarceau commented Jan 4, 2025

@dkotter I think this ticket would be a good candidate for some PHP unit tests around the address validation. The changes are small, the only WP dependency is WP_Error, and some easy to run tests would help me feel better that we're covering the right validation conditions. What do you think?

Assuming that you think it's worth adding the tests, I wanted to ask if 10up had a preferred testing library or "10up way" of unit testing? There's currently no PHP tests in this project.

My preference would be to use Pest with WP_Mock or Brain Monkey, but I'm open to anything.

@MaxwellGarceau MaxwellGarceau marked this pull request as ready for review January 4, 2025 00:40
@MaxwellGarceau MaxwellGarceau requested a review from dkotter January 4, 2025 00:40
@github-actions github-actions bot added the needs:feedback This requires reporter feedback to better understand the request. label Jan 4, 2025
Copy link

github-actions bot commented Jan 4, 2025

@MaxwellGarceau thanks for the PR! Could you please fill out the PR template with description, changelog, and credits information so that we can properly review and merge this?

@github-actions github-actions bot added needs:code-review This requires code review. and removed needs:feedback This requires reporter feedback to better understand the request. labels Jan 4, 2025
mailchimp.php Outdated Show resolved Hide resolved
@dkotter
Copy link
Collaborator

dkotter commented Jan 6, 2025

Assuming that you think it's worth adding the tests, I wanted to ask if 10up had a preferred testing library or "10up way" of unit testing? There's currently no PHP tests in this project.

I'm fine with spending the time to add unit tests here. As far as a preferred way, we don't have a well documented approach, though we typically use PHPUnit (as this is what WordPress core itself uses) and either use WP_Mock or use the testing framework that WordPress provides, for more complicated setups.

I think PHPUnit + WP_Mock would probably work fine here. Can see how we do things on Safe SVG for one example.

@MaxwellGarceau
Copy link
Collaborator Author

MaxwellGarceau commented Jan 7, 2025

Arrow functions not caught by PHPCS

TLDR:

  • PHPCS/PHPCompatibilityWP linter isn't catching arrow functions locally or in the CI/CD pipeline.
  • Tried various fixes and nothing worked.
  • One workaround is using rector in --dry-run mode.
  • Should I submit a bug report in the PHPCompatibility repo or do you think it's more likely some kind of user/config error on my end?

Verifying the problem

@dkotter while updating the arrow function I noticed that the current PHPCS compatibility check doesn't catch arrow functions. The specific CLI command I was running was phpcs --standard=./phpcs-compat.xml -p -s .. I tried this command both outside the docker container on my local machine running PHP 8.4 and inside the wp-env docker container.

I also tried PHP 5.0 as the test version to ensure the XML file was working and the linter picked up on several incompatibilities.

Solution attempts

I tried to explicitly add the arrow function rule, tried other rulesets (PHPCompatibility), and tried adding a custom sniff to register the T_FN keyword for the token value PHPCS looks for. I couldn't get the arrow functions to register as errors on PHP 7.0.

PRs in PHPCompatibility adding arrow function support

I looked through some of the merged PRs in the PHPCompatibility codebase and it seems like arrow functions should trigger on the fn keyword.

Workaround: Rector

I did a quick test with rector and rector catches arrow functions. An alternative would be using rector in --dry-run mode and failing the Github action if any diffs came back.

Not the best solution and kind of a hack, but may be nice to have for easy PHP upgrades in the future as well.

Screenshot 2025-01-07 at 3 24 03 PM

Bug report for PHPCompatibility

Do you think this is worth making a bug report in the PHPCompatibility codebase? It's definitely possible I'm just missing something obvious.

@dkotter
Copy link
Collaborator

dkotter commented Jan 7, 2025

Do you think this is worth making a bug report in the PHPCompatibility codebase? It's definitely possible I'm just missing something obvious.

I'm pretty sure the issue here is the PHPCompat repo hasn't pushed out a new release since December 2019, so all new sniffs added since then don't actually run if you're not using a development version of the tool (which is unfortunate). The easiest way to address this (which I should have done when I was setting up PHPCS on this repo) is to install the dev version of that tool.

Can see instructions on how to do that here: 10up/phpcs-composer#52. Basically just need to run:
composer require --dev phpcompatibility/php-compatibility:"dev-develop as 9.99.99"

This enables us to just import the merge_validate_phone instead of loading the entire Mailchimp plugin
Following 10up namespace standards with functions
Give us the flexibility to set variables during testing and allows us to test that we are setting locations correctly
Copy link
Collaborator Author

@MaxwellGarceau MaxwellGarceau left a comment

Choose a reason for hiding this comment

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

@dkotter I've added PHPUnit, WP_Mock, and created the tests for the validation logic. I moved a few functions out of mailchimp.php into their own namespaced files and turned them into classes for easier testing.

I highlighted the most import parts. It's kind of a large PR and I'm happy to make any changes you think would be beneficial.

*/
public function __construct( $wp_error_factory = null ) {
// Default to return WP_Error objects
$this->wp_error_factory = $wp_error_factory ?? function ( string $code, string $message, $data = null ) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I added a wp_error_factory in order to pass mocked WP_Error messages in the tests.

It's kind of ugly, but this is the best way I had to make assertions that the WP_Error objects returned from the validation functions had exactly the error code and message that was expected.

If you have any suggestions I'd love to take the opportunity to learn how to better handle mocking assertions on WP instantiated objects directly in the code.

@@ -0,0 +1,41 @@
<?php
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Kept the original functions here for backwards compatibility. The idea is work towards more class based modularization for easier unit testing.

After the composer autoload changes go into develop it would be great to get a DI container involved to avoid direct class instantiation in the function.

Comment on lines +113 to +124
$wp_error_factory = function ( $code, $message, $data = null ) use ( $wp_error ) {
// Step 3: Make assertions against the properties we want the WP_Error object to contain
// and dynamically fill them to return what our validate functions will pass in.
$wp_error
->shouldReceive('get_error_code')
->andReturn($code);
$wp_error
->shouldReceive('get_error_message')
->with($code)
->andReturn($message);
return $wp_error;
};
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We're dynamically filling the WP_Error assertions here with what we actually get back from the validate functions.

Comment on lines +135 to +142
// Error code
$this->assertEquals(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE, $result->get_error_code());

// Error message
$this->assertMatchesRegularExpression(
'/must consist of only numbers/',
$result->get_error_message(Validate_Merge_Fields::PHONE_VALIDATION_ERROR_CODE)
);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Here we're testing the dynamically filled WP_Error mock with what we really should be getting back from the validation functions.

Comment on lines +31 to +48
* Strategy:
* - Unit testing only (no integration or end-to-end).
* - Mock WP core functions with WP_Mock (WP core is not loaded).
* - Promote long-term maintainability through modularization.
*
* Reasoning:
* This plugin is not modular and initializing the plugin
* will require mocking all of the WP core functions
* used in order to avoid fatal errors on loading.
*
* Instead, we'll require functionality as it's needed
* by first:
*
* 1) Modularizing the functionality into a namespaced file and then
* 2) Importing it directly into the test.
*
* End to end tests are handled in Cypress. Integration
* and E2E tests should be handled in Cypress.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I wrote a little strategy here for long-term app health that could be moved to over time. What do you think?

@MaxwellGarceau
Copy link
Collaborator Author

Can see instructions on how to do that here: 10up/phpcs-composer#52. Basically just need to run:
composer require --dev phpcompatibility/php-compatibility:"dev-develop as 9.99.99"

Ahh! Thank you that fixed it!! I saw the dev require in the 10up/phpcs-composer composer.json file and just assumed we were already using dev-develop.

This saved me so much time and an embarrassing bug report 😂

The form must return null when a field is not filled out. Other values will cause a validation failure
@jeffpaul jeffpaul requested a review from dkotter January 9, 2025 15:35
mailchimp.php Show resolved Hide resolved
@MaxwellGarceau MaxwellGarceau requested a review from dkotter January 9, 2025 21:40
@qasumitbagthariya
Copy link
Collaborator

qasumitbagthariya commented Jan 16, 2025

QA Update: ✅

I have verified this PR in the bug/issue-101-and-104/fix-phone-number-validation-and-error-messages branch which has been fixed and is functioning as intended.

  • Form Submission Without Phone Number:
image
  • Phone Number Accepts Only Valid Inputs: ✅

  • Letters: e.g., "ABC123".

  • Special Characters: e.g., "@123$".

  • Whitespace: e.g., " 123 456 ".

  • Invalid Delimiters: e.g., "12--34", "(123))", or "123-456-".

image

Accepts only numeric characters (0–9). ✅

Successfully accepts valid US-format phone numbers. ✅

Screen.Recording.2025-01-18.at.8.14.43.PM.mov

Testing Environment

  • WordPress: 6.7.1
  • Theme: Twenty Twenty-Four 1.3
  • PHP: 8.0.30
  • Web Server: Nginx 1.20.2
  • Browser: Chrome
  • OS: macOS 15.2
  • Branch: bug/issue-101-and-104/fix-phone-number-validation-and-error-messages

@github-actions github-actions bot added the needs:refresh This requires a refreshed PR to resolve. label Jan 29, 2025
Copy link

@MaxwellGarceau thanks for the PR! Could you please rebase your PR on top of the latest changes in the base branch?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs:code-review This requires code review. needs:refresh This requires a refreshed PR to resolve.
Projects
None yet
3 participants