The validation rules provided by Laravel may be sufficient to cover most of the use cases. Laravel also makes it possible to extend the validation rules with custom rules. There are two ways to create custom validation rules: rule objects or closures. I prefer the rule object because it can easily be tested in isolation.
What we're going to test
We will create a custom password validation rule that uses zxcvbn, a realistic password strength estimation developed by Dropbox. The strength of passwords calculated by zxcvbn ranges from 0 to 4 i.e.
0 - too guessable and therefore risky password
1 - very guessable password
2 - somewhat guessable password
3 - safely unguessable password
4 - very unguessable password
To learn more about zxcvbn, see the links at the end of this article.
We are going to create a custom password rule and use Pest PHP to test it.
Prerequisites
Before we proceed, ensure that:
Your at least know how to install Laravel or have one application already.
You have Pest PHP installed in your Laravel application. Refer to Pest PHP installation instructions.
Install zxcvbn
Start by installing a zxcvbn wrapper for PHP.
Creating Custom Password Validation Rule
Next create a custom validation rule.
The command will create a new file at app/Rules/StrongPasswordRule.php. We are now ready to define it behaviour as follows:
We also create a custom validation message translation `lang/en/validation.php.
Here are a couple of things going on:
When the StrongPasswordRule class is called, we create a new instance of Zxcvbn. Of course, we could register a binding in-service provider but let us keep things simple.
We implement the DataAwareRule interface. We use the setData to access other data undergoing validation data. We then pass this data to zxcvbn by calling getUserInputs. Accessing additional data prevents the user from creating a password containing the user's email, name, phone, etc.
We then get the user password value and pass it to the zxcvbn passwordStrength method, which calculates password strength via non-overlapping minimum entropy patterns. You can set the minimum password strength score of your choice. I prefer at least three, but you can also put 4, the maximum.
When validation fails, we call a custom translation message located at lang/en/validation.php.
Implementing a Custom Validation Rule
Once you have defined the custom password rule, you may attach it to a validator by passing an instance of the rule object with your other validation rules.
Coupled with min and uncompromised rules, you can allow your users to create strong and secure passwords.
Testing a Custom Validation Rule
We create a custom expectation to test the invokable rule in Laravel, as Freek Van der Herten described in his article - How to test Laravel invokable rules. Modify your Pest.php file.
Next, we create a test file, Feature/Rules/StrongPasswordRuleTest.php, and add the tests. You can add tests to the scope you are comfortable with.
Conclusion
I hope you now have an idea of how you can test a custom Laravel validation rule. You can take a step further and extract the validation rule into a composer package for others. In addition, the article demonstrates techniques such as using data sets, the beforeAll method, and adding a custom expectation.