matcher = new RouteMatcher(); } private function route(string $method, string $path): RouteDef { return new RouteDef($method, $path, 'C', 'm'); } public function testMatchesExactPath(): void { $route = $this->route('GET', '/entries'); $this->assertTrue($this->matcher->matches($route, 'get', '/entries')); $this->assertFalse($this->matcher->matches($route, 'POST', '/entries')); $this->assertFalse($this->matcher->matches($route, 'GET', '/entries/1')); } public function testMatchesParameterizedPath(): void { $route = $this->route('GET', '/entries/{slug}'); $this->assertTrue($this->matcher->matches($route, 'GET', '/entries/hello-world')); $this->assertFalse($this->matcher->matches($route, 'GET', '/entries/hello/world')); } public function testExtractsNamedParameters(): void { $route = $this->route('GET', '/entries/{slug}'); $this->assertSame( ['slug' => 'hello-world'], $this->matcher->extractParams($route, '/entries/hello-world'), ); } public function testLiteralBeatsParameter(): void { $literal = $this->route('GET', '/entries/archive'); $param = $this->route('GET', '/entries/{slug}'); $this->assertLessThan(0, $this->matcher->compare($literal, $param)); $this->assertGreaterThan(0, $this->matcher->compare($param, $literal)); } public function testExactBeatsParameterAtSamePosition(): void { $exact = $this->route('POST', '/admin/entries/preview'); $param = $this->route('POST', '/admin/entries/{id}'); $this->assertLessThan(0, $this->matcher->compare($exact, $param)); } }