I get
invalid email address
when using faker to fill the email fields of my app.
'email' => ['required', 'email:rfc,dns']
is there a way to make faker spit out valid email addresses that pass these tests?
I tried safeEmail and some others but they still fail
I have the same problem and it's all related to the Egulias\EmailValidator\Validation\DNSCheckValidation
class used by Laravel to validate an email (as you can see here example
is a reserved top level domain).
There's no way of avoiding that an email created with faker
passes this validation and, IMO, it's just as it should be. But we need to do our tests don't we?
There's a simple way (that can be used also in FormRequest
or whatever you're using that implements the validator):
// In your test:
$this->post('my-url', ['email' => $this->faker->unique()->safeEmail])
// In your code
$emailRules = 'email:rfc';
if(!app()->runningUnitTests()) {
$emailRules .= ',dns';
}
$validator = Validator::make($data, ['email' => ['required', $emailRules]]);
// [...]
Another way is to create a custom email validation rule that encapsulate the runningUnitTests
logic (and I think it's much more cleaner)
<?php
namespace App\Rules;
use Egulias\EmailValidator\EmailValidator;
use Egulias\EmailValidator\Validation\DNSCheckValidation;
use Egulias\EmailValidator\Validation\MultipleValidationWithAnd;
use Egulias\EmailValidator\Validation\NoRFCWarningsValidation;
use Egulias\EmailValidator\Validation\RFCValidation;
use Egulias\EmailValidator\Validation\SpoofCheckValidation;
use Illuminate\Contracts\Validation\Rule;
use Illuminate\Validation\Concerns\FilterEmailValidation;
/** @codeCoverageIgnore */
class ValidEmail implements Rule
{
protected array $parameters;
/**
* Create a new rule instance.
*
* @return void
*/
public function __construct(array $parameters = [])
{
$this->parameters = $parameters;
}
/**
* Determine if the validation rule passes.
*
* @param string $attribute
* @param mixed $value
* @return bool
*/
public function passes($attribute, $value)
{
if (! is_string($value) && ! (is_object($value) && method_exists($value, '__toString'))) {
return false;
}
$validations = collect($this->parameters)
->unique()
->map(function ($validation) {
if ($validation === 'rfc') {
return new RFCValidation();
} elseif ($validation === 'strict') {
return new NoRFCWarningsValidation();
} elseif ($validation === 'dns' && !app()->runningUnitTests()) {
return new DNSCheckValidation();
} elseif ($validation === 'spoof') {
return new SpoofCheckValidation();
} elseif ($validation === 'filter') {
return new FilterEmailValidation();
}
return null;
})
->values()
->filter()
->all() ?: [new RFCValidation()];
return (new EmailValidator)->isValid($value, new MultipleValidationWithAnd($validations));
}
/**
* Get the validation error message.
*
* @return string
*/
public function message()
{
return __('validation.email');
}
}
Than in your code:
$validator = Validator::make($data, ['email' => ['required', new ValidEmail()]]);
// OR
$validator = Validator::make($data, ['email' => ['required', new ValidEmail(['rfc','filter','dns'])]]);
// [...]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With