expect(fn () => new PathSegment('test')) ->toBeInstanceOf(PathSegment::class); it('can get the content') ->expect(fn () => (new PathSegment('test'))->getContent()) ->toBe('test'); 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, ''], ($t = PathSegmentType::Parameter)->name => [$t, ''], ]); it('gets raw keys lowercase', function() { $seg = new PathSegment('TesTiNg'); expect($seg->getType())->toBe(PathSegmentType::Raw); expect($seg->getKey())->toBe('testing'); }); 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'); it('has null parent by default') ->expect(fn () => (new PathSegment('test'))->getParent()) ->toBeNull(); it('can get all ancestors') ->expect(fn () => $testChain()->getAncestors()) ->toBeArray() ->toContainOnlyInstancesOf(PathSegment::class) ->toHaveCount(3); it('order all ancestors root first') ->expect(fn () => $testChain()->getAncestors()) ->{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(4); it('order all ancestors and self root first') ->expect(fn () => $testChain()->getAncestorsAndSelf()) ->{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('when adding child sets its parent') ->expect(fn () => $makeWithChildren()->getChildren()) ->{'test2'}->getParent()->toBeInstanceOf(PathSegment::class); it('gets the children count') ->expect(fn () => $makeWithChildren()->getChildrenCount()) ->toBe(2); it('creates new child and returns') ->expect(fn () => (new PathSegment('test1'))->child('test2')) ->toBeInstanceOf(PathSegment::class) ->getContent()->toBe('test2'); 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('can build full path') ->expect(fn () => $testChain()->getPath()) ->toBe('/test1/test2/test3'); it('can build path with parameters', function() { $seg = new PathSegment(type: PathSegmentType::Root); $child = $seg->child('test1') ->child('test2', PathSegmentType::Parameter) ->child('test3', PathSegmentType::Parameter) ->child('test4'); expect($child->getPath([ 'test2' => 'a', 'test3' => 'b', ]))->toBe('/test1/a/b/test4'); }); it('throws when building path with missing parameters', function() { $seg = new PathSegment(type: PathSegmentType::Root); $child = $seg->child('test1') ->child('test2', PathSegmentType::Parameter) ->child('test3', PathSegmentType::Parameter) ->child('test4'); expect($child->getPath([ 'test2' => 'a', ]))->toBe('/test1/a/b/test4'); })->throws(MissingParameterException::class); 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();