diff --git a/src/Mixins/Expectation.php b/src/Mixins/Expectation.php index 1ba4872f..a6910b64 100644 --- a/src/Mixins/Expectation.php +++ b/src/Mixins/Expectation.php @@ -1142,4 +1142,20 @@ public function toBeBetween(int|float|DateTimeInterface $lowestValue, int|float| return $this; } + + /** + * Asserts that the value is a url + * + * @return self + */ + public function toBeUrl(string $message = ''): self + { + if ($message === '') { + $message = "Failed asserting that {$this->value} is a url."; + } + + Assert::assertTrue(Str::isUrl((string) $this->value), $message); + + return $this; + } } diff --git a/src/Support/Str.php b/src/Support/Str.php index 0f2dc63a..16fa58fc 100644 --- a/src/Support/Str.php +++ b/src/Support/Str.php @@ -108,4 +108,12 @@ public static function describe(string $describeDescription, string $testDescrip { return sprintf('`%s` → %s', $describeDescription, $testDescription); } + + /** + * Determine if a given value is a valid URL. + */ + public static function isUrl(string $value): bool + { + return (bool) filter_var($value, FILTER_VALIDATE_URL); + } } diff --git a/tests/Features/Expect/toBeUrl.php b/tests/Features/Expect/toBeUrl.php new file mode 100644 index 00000000..1191dbab --- /dev/null +++ b/tests/Features/Expect/toBeUrl.php @@ -0,0 +1,24 @@ +toBeUrl() + ->and('pestphp.com')->not->toBeUrl(); +}); + +test('failures', function () { + expect('pestphp.com')->toBeUrl(); +})->throws(ExpectationFailedException::class); + +test('failures with custom message', function () { + expect('pestphp.com')->toBeUrl('oh no!'); +})->throws(ExpectationFailedException::class, 'oh no!'); + +test('failures with default message', function () { + expect('pestphp.com')->toBeUrl(); +})->throws(ExpectationFailedException::class, 'Failed asserting that pestphp.com is a url.'); + +test('not failures', function () { + expect('https://pestphp.com')->not->toBeUrl(); +})->throws(ExpectationFailedException::class);