summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/Unit/PathSegmentTest.php215
-rw-r--r--tests/Unit/RouteTest.php48
-rw-r--r--tests/Unit/RouterTest.php90
3 files changed, 323 insertions, 30 deletions
diff --git a/tests/Unit/PathSegmentTest.php b/tests/Unit/PathSegmentTest.php
index 1d19e0e..c537c38 100644
--- a/tests/Unit/PathSegmentTest.php
+++ b/tests/Unit/PathSegmentTest.php
@@ -2,7 +2,10 @@
declare(strict_types=1);
+use Lightscale\Router\Enums\HttpMethod;
+use Lightscale\Router\Enums\PathSegmentType;
use Lightscale\Router\PathSegment;
+use Lightscale\Router\Route;
it('initializes')
->expect(fn () => new PathSegment('test'))
@@ -12,11 +15,60 @@ it('can get the content')
->expect(fn () => (new PathSegment('test'))->getContent())
->toBe('test');
-it('can get the parent')
- ->expect(fn () => (new PathSegment(
- 'test1',
- new PathSegment('test2')
- ))->getParent())
+it('can be root')
+ ->expect((new PathSegment(type: PathSegmentType::Root))->getType())
+ ->toBe(PathSegmentType::Root);
+
+it('nulls value when type root')
+ ->expect(fn () => (new PathSegment('testing', PathSegmentType::Root))->getValue())
+ ->toBeNull();
+
+it('gets value for type :dataset', function (PathSegmentType $type, ?string $res) {
+ $seg = new PathSegment($v = 'testing', $type);
+ expect($seg->getValue())->toBe($res);
+})->with([
+ ($t = PathSegmentType::Raw)->name => [$t, 'testing'],
+ ($t = PathSegmentType::Root)->name => [$t, null],
+ ($t = PathSegmentType::Parameter)->name => [$t, 'testing'],
+]);
+
+it('gets key for type :dataset', function (PathSegmentType $type, ?string $res) {
+ $seg = new PathSegment($v = 'testing', $type);
+ expect($seg->getKey())->toBe($res);
+})->with([
+ ($t = PathSegmentType::Raw)->name => [$t, 'testing'],
+ ($t = PathSegmentType::Root)->name => [$t, '<root>'],
+ ($t = PathSegmentType::Parameter)->name => [$t, '<parameter>'],
+]);
+
+it('gets type :dataset', function (PathSegmentType $type) {
+ $seg = new PathSegment($v = 'testing', $type);
+ expect($seg->getType())->toBe($type);
+})->with(function (): Generator {
+ foreach (PathSegmentType::cases() as $t) {
+ yield $t->name => $t;
+ }
+});
+
+it('defaults type to Raw')
+ ->expect(fn () => (new PathSegment('testing'))->getType())
+ ->toBe(PathSegmentType::Raw);
+
+$testChain = function () {
+ $root = new PathSegment(type: PathSegmentType::Root);
+ $seg1 = new PathSegment('test1');
+ $seg2 = new PathSegment('test2');
+ $seg3 = new PathSegment('test3');
+
+ $seg3->setParent($seg2);
+ $seg2->setParent($seg1);
+ $seg1->setParent($root);
+
+ return $seg3;
+};
+
+it('can have a parent')
+ ->expect(fn () => $testChain()->getParent())
->toBeInstanceOf(PathSegment::class)
->getContent()->toBe('test2');
@@ -24,45 +76,154 @@ it('has null parent by default')
->expect(fn () => (new PathSegment('test'))->getParent())
->toBeNull();
-$testChain = fn () => new PathSegment(
- 'test3',
- new PathSegment(
- 'test2',
- new PathSegment(
- 'test1'
- )
- )
-);
-
it('can get all ancestors')
->expect(fn () => $testChain()->getAncestors())
->toBeArray()
->toContainOnlyInstancesOf(PathSegment::class)
- ->toHaveCount(2);
+ ->toHaveCount(3);
it('order all ancestors root first')
->expect(fn () => $testChain()->getAncestors())
- ->{0}->getContent()->toBe('test1')
- ->{1}->getContent()->toBe('test2');
+ ->{0}->getContent()->toBe('')
+ ->{0}->getType()->toBe(PathSegmentType::Root)
+ ->{1}->getContent()->toBe('test1')
+ ->{2}->getContent()->toBe('test2');
it('can get all ancestors and self')
->expect(fn () => $testChain()->getAncestorsAndSelf())
->toBeArray()
->toContainOnlyInstancesOf(PathSegment::class)
- ->toHaveCount(3);
+ ->toHaveCount(4);
it('order all ancestors and self root first')
->expect(fn () => $testChain()->getAncestorsAndSelf())
- ->{0}->getContent()->toBe('test1')
- ->{1}->getContent()->toBe('test2')
- ->{2}->getContent()->toBe('test3');
+ ->{0}->getContent()->toBe('')
+ ->{0}->getType()->toBe(PathSegmentType::Root)
+ ->{1}->getContent()->toBe('test1')
+ ->{2}->getContent()->toBe('test2')
+ ->{3}->getContent()->toBe('test3');
+
+$makeWithChildren = function () {
+ $seg = new PathSegment('test1');
+ $seg->addChild(new PathSegment('test2'));
+ $seg->addChild(new PathSegment('test3'));
+
+ return $seg;
+};
+
+it('can have children')
+ ->expect(fn () => $makeWithChildren()->getChildren())
+ ->toBeArray()
+ ->toContainOnlyInstancesOf(PathSegment::class)
+ ->{'test2'}->getContent()->toBe('test2')
+ ->{'test3'}->getContent()->toBe('test3');
-it('can have children')->todo();
+it('when adding child sets its parent')
+ ->expect(fn () => $makeWithChildren()->getChildren())
+ ->{'test2'}->getParent()->toBeInstanceOf(PathSegment::class);
-it('can build full path')->todo();
+it('gets the children count')
+ ->expect(fn () => $makeWithChildren()->getChildrenCount())
+ ->toBe(2);
-it('can have routes')->todo();
+it('can build full path')
+ ->expect(fn () => $testChain()->getPath())
+ ->toBe('/test1/test2/test3');
-it('can get routes by method')->todo();
+it('creates new child and returns')
+ ->expect(fn () => (new PathSegment('test1'))->child('test2'))
+ ->toBeInstanceOf(PathSegment::class)
+ ->getContent()->toBe('test2');
-it('can get routes for all methods')->todo();
+it('creates new child added to children')
+ ->expect(function () {
+ $seg = new PathSegment('test1');
+ $seg->child('test2');
+
+ return $seg->getChildren();
+ })
+ ->toHaveCount(1);
+
+it('does not add same child twice', function () {
+ $seg = new PathSegment('test1');
+ $seg2 = $seg->child('test2');
+ $seg3 = $seg->child('test2');
+
+ expect($seg2)->toBe($seg3);
+ expect($seg->getChildrenCount())->toBe(1);
+});
+
+it('can get a raw segment child', function () {
+ $seg = new PathSegment('test1');
+ $c1 = $seg->child('test2');
+ $c2 = $seg->child('test3');
+
+ expect($seg->findChild('test2'))->toBe($c1);
+ expect($seg->findChild('test3'))->toBe($c2);
+});
+
+it('can get a parameter segment child', function () {
+ $seg = new PathSegment('test1');
+ $c1 = $seg->child('test2');
+ $c2 = $seg->child('test3', PathSegmentType::Parameter);
+
+ expect($seg->findChild('test2'))->toBe($c1);
+ expect($seg->findChild('test4'))->toBe($c2);
+});
+
+it('sets route segment when added', function () {
+ $seg = new PathSegment('test1');
+ $seg->addRoute($r = new Route(
+ HttpMethod::Get,
+ fn () => null
+ ));
+
+ expect($r->getSegment())->toBe($seg);
+});
+
+it('can have routes', function () {
+ $seg = new PathSegment('test');
+ $seg->addRoute($r1 = new Route(
+ HttpMethod::Get,
+ fn () => null,
+ ));
+ $seg->addRoute($r2 = new Route(
+ HttpMethod::Post,
+ fn () => null,
+ ));
+
+ expect($seg->getRoutes())
+ ->toHaveCount(2)
+ ->{HttpMethod::Get->value}->toBe($r1)
+ ->{HttpMethod::Post->value}->toBe($r2);
+});
+
+it('overwrites existing routes', function () {
+ $seg = new PathSegment('test');
+ $seg->addRoute($r1 = new Route(
+ HttpMethod::Get,
+ fn () => null,
+ ));
+ $seg->addRoute($r2 = new Route(
+ HttpMethod::Get,
+ fn () => null,
+ ));
+
+ expect($seg->getRoutes())
+ ->toHaveCount(1)
+ ->{HttpMethod::Get->value}->toBe($r2);
+});
+
+it('can get route by method', function () {
+ $seg = new PathSegment('test');
+ $seg->addRoute($r = new Route(
+ HttpMethod::Get,
+ fn () => null,
+ ));
+
+ expect($seg->getRoute(HttpMethod::Get))->toBe($r);
+});
+
+it('gets null with route method that doesn\'t exist')
+ ->expect(fn () => (new PathSegment('test'))->getRoute(HttpMethod::Get))
+ ->toBeNull();
diff --git a/tests/Unit/RouteTest.php b/tests/Unit/RouteTest.php
index 0414649..104401b 100644
--- a/tests/Unit/RouteTest.php
+++ b/tests/Unit/RouteTest.php
@@ -3,14 +3,56 @@
declare(strict_types=1);
use Lightscale\Router\Enums\HttpMethod;
-use Lightscale\Router\Enums\SpecialSegment;
+use Lightscale\Router\Enums\PathSegmentType;
use Lightscale\Router\PathSegment;
use Lightscale\Router\Route;
+use Nyholm\Psr7\Factory\Psr17Factory;
+use Psr\Http\Message\RequestInterface;
it('initializes')
->expect(fn () => new Route(
- new PathSegment(SpecialSegment::Root),
HttpMethod::Get,
- fn () => null
+ fn () => null,
+ new PathSegment(type: PathSegmentType::Root),
))
->toBeInstanceOf(Route::class);
+
+it('gets segment')
+ ->expect(fn () => (new Route(
+ HttpMethod::Get,
+ fn () => null,
+ new PathSegment(type: PathSegmentType::Root),
+ ))->getSegment())
+ ->toBeInstanceOf(PathSegment::class);
+
+it('throws getting segment without being set', function () {
+ $r = new Route(HttpMethod::Get, fn () => null);
+ $r->getSegment();
+})->throws(Error::class);
+
+it('can set segment')
+ ->expect(function () {
+ $r = new Route(HttpMethod::Get, fn () => null);
+ $r->setSegment(new PathSegment('test'));
+
+ return $r->getSegment();
+ })
+ ->toBeInstanceOf(PathSegment::class)
+ ->getValue()->toBe('test');
+
+it('gets method')
+ ->expect(fn () => (new Route(
+ HttpMethod::Get,
+ fn () => null,
+ ))->getMethod())
+ ->toBe(HttpMethod::Get);
+
+it('can call handler')
+ ->expect(fn () => (new Route(
+ HttpMethod::Get,
+ fn (RequestInterface $req) => $req->getUri()->getPath()
+ ))(
+ (new Psr17Factory())->createRequest(HttpMethod::Get->value, '/testing')
+ )
+ )
+ ->toBe('/testing');
diff --git a/tests/Unit/RouterTest.php b/tests/Unit/RouterTest.php
new file mode 100644
index 0000000..5d08441
--- /dev/null
+++ b/tests/Unit/RouterTest.php
@@ -0,0 +1,90 @@
+<?php
+
+declare(strict_types=1);
+
+use Lightscale\Router\Enums\PathSegmentType;
+use Lightscale\Router\PathSegment;
+use Lightscale\Router\Router;
+
+it('initializes')
+ ->expect(fn () => new Router())
+ ->toBeInstanceOf(Router::class);
+
+it('has root')
+ ->expect(fn () => (new Router())->root())
+ ->toBeInstanceOf(PathSegment::class)
+ ->getType()->toBe(PathSegmentType::Root);
+
+it('finds root segment with :dataset path', function (string $path) {
+ $router = new Router();
+ expect($router->findSegment($path))->segment->toBe($router->root());
+})->with(['', '/']);
+
+it('finds segment one level', function () {
+ $router = new Router();
+ $c1 = $router->root()->child($p1 = 'test1');
+ $c2 = $router->root()->child($p2 = 'test2');
+
+ expect($router->findSegment("/{$p1}"))->segment->toBe($c1);
+ expect($router->findSegment("/{$p2}"))->segment->toBe($c2);
+});
+
+it('finds segment one level parameter', function () {
+ $router = new Router();
+ $c1 = $router->root()->child('test2', PathSegmentType::Parameter);
+
+ expect($router->findSegment('/anything'))
+ ->segment->toBe($c1)
+ ->parameters->{'test2'}->toBe('anything');
+});
+
+it('finds segment one falls back to parameter', function () {
+ $router = new Router();
+ $c1 = $router->root()->child($p1 = 'test1');
+ $c2 = $router->root()->child('test2', PathSegmentType::Parameter);
+
+ expect($router->findSegment("/{$p1}"))->segment->toBe($c1);
+ expect($router->findSegment('/anything'))
+ ->segment->toBe($c2)
+ ->parameters->{'test2'}->toBe('anything');
+});
+
+it('finds segments in complex routes', function () {
+ $router = new Router();
+
+ $r = $router->root();
+
+ $s1 = $r->child('level1-1')->child('level2-1');
+ $s2 = $r->child('level1-1')->child('level2-2');
+ $s3 = $r->child('level1-2')->child('level2-3');
+ $s4 = $r->child('level1-1')->child('level2-2')->child('level3-1');
+ $s5 = $r->child('level1-1');
+ $s6 = $r->child('level1-3')->child('level2-4', PathSegmentType::Parameter);
+ $s7 = $s6->child('level3-2');
+ $s8 = $s6->child('level3-3');
+
+ expect($router->findSegment('/level1-1')?->segment)->toBe($s5);
+ expect($router->findSegment('/level1-2/level2-3')?->segment)->toBe($s3);
+ expect($router->findSegment('/level1-1/level2-2/level3-1')?->segment)->toBe($s4);
+ expect($router->findSegment('/level1-1/level2-1')?->segment)->toBe($s1);
+ expect($router->findSegment('/level1-1/level2-2')?->segment)->toBe($s2);
+ expect($router->findSegment('/level1-3/param1'))
+ ->segment->toBe($s6)
+ ->parameters->{'level2-4'}->toBe('param1');
+ expect($router->findSegment('/level1-3/param2/level3-2'))
+ ->segment->toBe($s7)
+ ->parameters->{'level2-4'}->toBe('param2');
+ expect($router->findSegment('/level1-3/param3/level3-3'))
+ ->segment->toBe($s8)
+ ->parameters->{'level2-4'}->toBe('param3');
+});
+
+it('return null when segment not found', function () {
+ $router = new Router();
+ $r = $router->root();
+ $r->child('level1-1')->child('level2-1');
+ $r->child('level1-1')->child('level2-2');
+ $r->child('level1-2')->child('level2-3');
+
+ expect($router->findSegment('/testing/testing'))->toBeNull();
+});