createUser(); $set = $this->createSet($user, 'Bible'); $repository = app(ElementRepository::class); $bookLevel = $this->createLevel($set, 'book'); $portionLevel = $this->createLevel($set, 'portion'); $chapterLevel = $this->createLevel($set, 'chapter'); $genesis = $repository->create(new CreateElementDto( name: 'Genesis', level: $bookLevel, parentElement: null, )); $repository->create(new CreateElementDto( name: 'Exodus', level: $bookLevel, parentElement: null, )); $creation = $repository->create(new CreateElementDto( name: 'Creation', level: $portionLevel, parentElement: $genesis, )); $chapter = $repository->create(new CreateElementDto( name: 'Chapter 1', level: $chapterLevel, parentElement: $creation, )); $this->createSession($user); $response = $this->credentialedGet("/api/sets/{$set->getId()}"); $response->assertOk()->assertExactJson([ 'set' => [ 'id' => $set->getId(), 'name' => 'Bible', ], 'levels' => [ [ 'id' => $bookLevel->getId(), 'kind' => 'book', 'depth' => 0, 'elementCount' => 2, ], [ 'id' => $portionLevel->getId(), 'kind' => 'portion', 'depth' => 1, 'elementCount' => 1, ], [ 'id' => $chapterLevel->getId(), 'kind' => 'chapter', 'depth' => 2, 'elementCount' => 1, ], ], 'elements' => [ [ 'id' => $genesis->getId(), 'name' => 'Genesis', 'kind' => 'book', 'levelId' => $bookLevel->getId(), 'children' => [ [ 'id' => $creation->getId(), 'name' => 'Creation', 'kind' => 'portion', 'levelId' => $portionLevel->getId(), 'children' => [ [ 'id' => $chapter->getId(), 'name' => 'Chapter 1', 'kind' => 'chapter', 'levelId' => $chapterLevel->getId(), 'children' => [], ], ], ], ], ], [ 'id' => $genesis->getId() + 1, 'name' => 'Exodus', 'kind' => 'book', 'levelId' => $bookLevel->getId(), 'children' => [], ], ], ]); } public function test_it_returns_an_empty_element_layout(): void { $user = $this->createUser(); $set = $this->createSet($user, 'Empty set'); $taskLevel = $this->createLevel($set, 'task'); $this->createSession($user); $response = $this->credentialedGet("/api/sets/{$set->getId()}"); $response->assertOk()->assertExactJson([ 'set' => [ 'id' => $set->getId(), 'name' => 'Empty set', ], 'levels' => [[ 'id' => $taskLevel->getId(), 'kind' => 'task', 'depth' => 0, 'elementCount' => 0, ]], 'elements' => [], ]); } public function test_it_returns_not_found_for_an_unknown_set(): void { $user = $this->createUser(); $this->createSession($user); $response = $this->credentialedGet('/api/sets/999'); $response->assertNotFound()->assertExactJson([ 'error' => 'set not found', ]); } public function test_it_rejects_an_unauthenticated_request(): void { $response = $this->getJson('/api/sets/1'); $response->assertStatus(401)->assertExactJson([ 'error' => 'unauthenticated', ]); } private function createUser(): User { return app(UserRepository::class)->create(new CreateUserDto( email: new EmailAddress('reader@example.com'), passwordHash: 'hashed-password', )); } private function createSet(User $user, string $name): Set { return app(SetRepository::class)->create(new CreateSetDto( name: $name, creator: $user, )); } private function createLevel(Set $set, string $kind): SetLevel { return app(SetLevelRepository::class)->create(new CreateSetLevelDto( set: $set, kind: $kind, )); } private function createSession(User $user): void { $createdAt = new DateTimeImmutable( '2026-08-03T12:00:00', new DateTimeZone('UTC'), ); app(SessionRepository::class)->create(new CreateSessionDto( token: 'valid-token', user: $user, createdAt: $createdAt, expiresAt: $createdAt->modify('+10 years'), )); } private function credentialedGet(string $uri): TestResponse { return $this->withCredentials() ->withUnencryptedCookie( AuthMiddleware::COOKIE_NAME, 'valid-token', )->getJson($uri); } }