From 8c0efd0d9317ad92bd55cd6afcd41bdbab827bf8 Mon Sep 17 00:00:00 2001 From: Sam Light Date: Wed, 10 Jun 2026 19:00:32 +0100 Subject: Make basic routing work --- tests/Unit/BasicStrategyTest.php | 44 +++++++++++++++++++++++ tests/Unit/PathSegmentMatchTest.php | 17 +++++++++ tests/Unit/RouteCallTest.php | 22 ++++++++++++ tests/Unit/RouteTest.php | 14 ++++---- tests/Unit/RouterTest.php | 56 ++++++++++++++++++++++++++++++ tests/Utils/TestCall.php | 16 +++++++++ tests/Utils/TestCallable.php | 69 +++++++++++++++++++++++++++++++++++++ 7 files changed, 230 insertions(+), 8 deletions(-) create mode 100644 tests/Unit/BasicStrategyTest.php create mode 100644 tests/Unit/PathSegmentMatchTest.php create mode 100644 tests/Unit/RouteCallTest.php create mode 100644 tests/Utils/TestCall.php create mode 100644 tests/Utils/TestCallable.php (limited to 'tests') diff --git a/tests/Unit/BasicStrategyTest.php b/tests/Unit/BasicStrategyTest.php new file mode 100644 index 0000000..2a0b550 --- /dev/null +++ b/tests/Unit/BasicStrategyTest.php @@ -0,0 +1,44 @@ +expect(fn() => new BasicStrategy) + ->toBeInstanceOf(BasicStrategy::class); + +it('throws on not found', function() { + (new BasicStrategy)->notFound( + (new Psr17Factory)->createServerRequest( + HttpMethod::Get->value, + '/testing/testing' + ) + ); +})->throws(NotFoundException::class); + +it('calls route', function () { + $factory = new Psr17Factory; + $response = $factory->createResponse(200, 'OK'); + $cb = TestCallable::make(fn () => $response); + $res = (new BasicStrategy)->runRoute($rc = new RouteCall( + $factory->createServerRequest( + HttpMethod::Get->value, + '/testing/testing' + ), + new Route( + HttpMethod::Get, + $cb + ), + [] + )); + + $cb->assertIsCalled(); + $call = $cb->getLastCall(); + expect($call->args[0] ?? null)->toBe($rc); + expect($res)->toBe($response); +}); diff --git a/tests/Unit/PathSegmentMatchTest.php b/tests/Unit/PathSegmentMatchTest.php new file mode 100644 index 0000000..9a522a4 --- /dev/null +++ b/tests/Unit/PathSegmentMatchTest.php @@ -0,0 +1,17 @@ + 'test2'], + ); + + expect($match) + ->segment->toBe($seg) + ->parameters->toBe($params); +}); diff --git a/tests/Unit/RouteCallTest.php b/tests/Unit/RouteCallTest.php new file mode 100644 index 0000000..70cc50e --- /dev/null +++ b/tests/Unit/RouteCallTest.php @@ -0,0 +1,22 @@ +createServerRequest(HttpMethod::Get->value, '/test/test'), + route: $route = new Route(HttpMethod::Get, fn () => null), + parameters: $params = ['test1' => 'test2'], + ); + + expect($call) + ->request->toBe($req) + ->route->toBe($route) + ->parameters->toBe($params); +}); diff --git a/tests/Unit/RouteTest.php b/tests/Unit/RouteTest.php index 104401b..50513a1 100644 --- a/tests/Unit/RouteTest.php +++ b/tests/Unit/RouteTest.php @@ -47,12 +47,10 @@ it('gets method') ))->getMethod()) ->toBe(HttpMethod::Get); -it('can call handler') - ->expect(fn () => (new Route( +it('can get handler', function() { + $r = new Route( HttpMethod::Get, - fn (RequestInterface $req) => $req->getUri()->getPath() - ))( - (new Psr17Factory())->createRequest(HttpMethod::Get->value, '/testing') - ) - ) - ->toBe('/testing'); + $h = fn (RequestInterface $req) => $req->getUri()->getPath() + ); + expect($r->getHandler())->toBe($h); +}); diff --git a/tests/Unit/RouterTest.php b/tests/Unit/RouterTest.php index 5d08441..12e27a4 100644 --- a/tests/Unit/RouterTest.php +++ b/tests/Unit/RouterTest.php @@ -2,14 +2,32 @@ declare(strict_types=1); +use Lightscale\Router\BasicStrategy; +use Lightscale\Router\Contracts\Strategy; +use Lightscale\Router\Enums\HttpMethod; use Lightscale\Router\Enums\PathSegmentType; use Lightscale\Router\PathSegment; +use Lightscale\Router\Route; +use Lightscale\Router\RouteCall; use Lightscale\Router\Router; +use Nyholm\Psr7\Factory\Psr17Factory; it('initializes') ->expect(fn () => new Router()) ->toBeInstanceOf(Router::class); +it('initializes with basic strategy') + ->expect((new Router)->getStrategy()) + ->toBeInstanceOf(BasicStrategy::class); + +it('can set strategy', function() { + $router = new Router; + $s = new BasicStrategy; + expect($router->getStrategy())->not->toBe($s); + $router->setStrategy($s); + expect($router->getStrategy())->toBe($s); +}); + it('has root') ->expect(fn () => (new Router())->root()) ->toBeInstanceOf(PathSegment::class) @@ -88,3 +106,41 @@ it('return null when segment not found', function () { expect($router->findSegment('/testing/testing'))->toBeNull(); }); + +it('calls strategy notFound with dispatch', function () { + $router = new Router(); + $factory = new Psr17Factory; + $request = $factory->createServerRequest(HttpMethod::Get->value, '/testing/testing'); + $response = $factory->createResponse(); + + $strat = Mockery::mock(Strategy::class); + $strat->shouldReceive('notFound') + ->with($request) + ->andReturn($response); + + $router->setStrategy($strat); + $result = $router->dispatch($request); + expect($result)->toBe($response); +}); + +it('calls strategy runRoute with dispatch on match', function() { + $router = new Router(); + + $router->root()->child('testing')->addRoute(new Route( + HttpMethod::Get, + fn () => null, + )); + + $factory = new Psr17Factory; + $request = $factory->createServerRequest(HttpMethod::Get->value, '/testing'); + $response = $factory->createResponse(); + + $strat = Mockery::mock(Strategy::class); + $strat->shouldReceive('runRoute') + ->with(Mockery::type(RouteCall::class)) + ->andReturn($response); + + $router->setStrategy($strat); + $result = $router->dispatch($request); + expect($result)->toBe($response); +}); diff --git a/tests/Utils/TestCall.php b/tests/Utils/TestCall.php new file mode 100644 index 0000000..971e6a7 --- /dev/null +++ b/tests/Utils/TestCall.php @@ -0,0 +1,16 @@ +cb = Closure::fromCallable($cb); + } + + public static function make(callable $cb): static + { + return new static($cb); + } + + public function __invoke(mixed ...$args): mixed + { + $call = new TestCall( + args: $args, + return: ($this->cb)(...$args), + ); + $this->calls[] = $call; + + return $call->return; + } + + public function getCallCount(): int + { + return count($this->calls); + } + + /** @return TestCall[] */ + public function getCalls(): array + { + return $this->calls; + } + + public function getLastCall(): ?TestCall + { + return $this->calls[$this->getCallCount() - 1] ?? null; + } + + public function assertIsCalled(): void + { + Assert::assertGreaterThan(0, $this->getCallCount(), 'Not been called'); + } + + public function assertNotCalled(): void + { + Assert::assertSame(0, $this->getCallCount()); + } + + public function assertCalledTimes(int $amount): void + { + Assert::assertSame($amount, $this->getCallCount()); + } + +} -- cgit v1.2.3