diff --git a/src/Routing/Route/RegexRoute.php b/src/Routing/Route/RegexRoute.php new file mode 100644 index 0000000..cff17a6 --- /dev/null +++ b/src/Routing/Route/RegexRoute.php @@ -0,0 +1,31 @@ +pattern = $pattern; + } + + /** + * @param string $requestTarget + * @param array $captures + * @return bool + * @throws \RuntimeException + */ + public function matchesRequestTarget($requestTarget, &$captures = null) + { + $matched = @preg_match($this->pattern, $requestTarget, $captures); + if ($matched) { + return true; + } elseif ($matched === false) { + throw new \RuntimeException("Invalid regular expression: " . $this->pattern); + } + return false; + } +} diff --git a/test/tests/unit/Routing/Route/RegexRouteTest.php b/test/tests/unit/Routing/Route/RegexRouteTest.php new file mode 100644 index 0000000..2c7f9c0 --- /dev/null +++ b/test/tests/unit/Routing/Route/RegexRouteTest.php @@ -0,0 +1,96 @@ +request = $this->prophesize("\\Psr\\Http\\Message\\ServerRequestInterface"); + $this->response = $this->prophesize("\\Psr\\Http\\Message\\ResponseInterface"); + $this->middleware = $this->prophesize("\\WellRESTed\\Routing\\MiddlewareInterface"); + } + + /** + * @dataProvider matchingRouteProvider + */ + public function testMatchesPattern($pattern, $path) + { + $route = new RegexRoute($pattern, $this->middleware->reveal()); + $this->assertTrue($route->matchesRequestTarget($path)); + } + + /** + * @dataProvider matchingRouteProvider + */ + public function testExtractsCaptures($pattern, $path, $expectedCaptures) + { + $route = new RegexRoute($pattern, $this->middleware->reveal()); + $route->matchesRequestTarget($path, $captures); + $this->assertEquals($expectedCaptures, $captures); + } + + public function matchingRouteProvider() + { + return [ + ["~/cat/[0-9]+~", "/cat/2", [0 => "/cat/2"]], + ["#/dog/.*#", "/dog/his-name-is-bear", [0 => "/dog/his-name-is-bear"]], + ["~/cat/([0-9]+)~", "/cat/2", [ + 0 => "/cat/2", + 1 => "2" + ]], + ["~/dog/(?[0-9+])~", "/dog/2", [ + 0 => "/dog/2", + 1 => "2", + "id" => "2" + ]] + ]; + } + + /** + * @dataProvider mismatchingRouteProvider + */ + public function testFailsToMatchMismatchingPattern($pattern, $path) + { + $route = new RegexRoute($pattern, $this->middleware->reveal()); + $this->assertFalse($route->matchesRequestTarget($path)); + } + + public function mismatchingRouteProvider() + { + return [ + ["~/cat/[0-9]+~", "/cat/molly"], + ["~/cat/[0-9]+~", "/dog/bear"], + ["#/dog/.*#", "/dog"] + ]; + } + + /** + * @dataProvider invalidRouteProvider + * @expectedException \RuntimeException + */ + public function testThrowsExceptionOnInvalidPattern($pattern) + { + $route = new RegexRoute($pattern, $this->middleware->reveal()); + $route->matchesRequestTarget("/"); + } + + public function invalidRouteProvider() + { + return [ + ["~/unterminated"], + ["/nope"] + ]; + } +}