diff --git a/src/Mixins/Expectation.php b/src/Mixins/Expectation.php index 4522155e..d5f843b9 100644 --- a/src/Mixins/Expectation.php +++ b/src/Mixins/Expectation.php @@ -1171,6 +1171,22 @@ final class Expectation return $this; } + /** + * Asserts that the value is an email address. + * + * @return self + */ + public function toBeEmail(string $message = ''): self + { + if ($message === '') { + $message = "Failed asserting that {$this->value} is an email address."; + } + + Assert::assertTrue(Str::isEmail((string) $this->value), $message); + + return $this; + } + /** * Asserts that the value is a url * diff --git a/src/Support/Str.php b/src/Support/Str.php index 85ba4115..51cb6cc2 100644 --- a/src/Support/Str.php +++ b/src/Support/Str.php @@ -118,6 +118,14 @@ final class Str return sprintf(str_repeat('`%s` → ', count($describeDescriptions)).'%s', ...$descriptionComponents); } + /** + * Determine if a given value is a valid email address. + */ + public static function isEmail(string $value): bool + { + return (bool) filter_var($value, FILTER_VALIDATE_EMAIL); + } + /** * Determine if a given value is a valid URL. */ diff --git a/tests/Features/Expect/toBeEmail.php b/tests/Features/Expect/toBeEmail.php new file mode 100644 index 00000000..fc9edff7 --- /dev/null +++ b/tests/Features/Expect/toBeEmail.php @@ -0,0 +1,24 @@ +toBeEmail() + ->and('notanemail')->not->toBeEmail(); +}); + +test('failures', function () { + expect('notanemail')->toBeEmail(); +})->throws(ExpectationFailedException::class); + +test('failures with custom message', function () { + expect('notanemail')->toBeEmail('oh no!'); +})->throws(ExpectationFailedException::class, 'oh no!'); + +test('failures with default message', function () { + expect('notanemail')->toBeEmail(); +})->throws(ExpectationFailedException::class, 'Failed asserting that notanemail is an email address.'); + +test('not failures', function () { + expect('user@example.com')->not->toBeEmail(); +})->throws(ExpectationFailedException::class);