createSet('Bible'); $repository = app(ElementRepository::class); $genesisBook = $repository->create(new CreateElementDto( set: $set, name: 'Genesis', kind: 'book', parentElement: null, )); $exodusBook = $repository->create(new CreateElementDto( set: $set, name: 'Exodus', kind: 'book', parentElement: null, )); $genesisPortion = $repository->create(new CreateElementDto( set: $set, name: 'Genesis', kind: 'portion', parentElement: $genesisBook, )); $noahPortion = $repository->create(new CreateElementDto( set: $set, name: 'Noah', kind: 'portion', parentElement: $genesisBook, )); $this->assertSame(1, $genesisBook->getPosition()); $this->assertSame(2, $exodusBook->getPosition()); $this->assertSame(1, $genesisPortion->getPosition()); $this->assertSame(2, $noahPortion->getPosition()); $this->assertDatabaseHas('elements', [ 'id' => $genesisPortion->getId(), 'set_id' => $set->getId(), 'name' => 'Genesis', 'kind' => 'portion', 'parent_element_id' => $genesisBook->getId(), 'position' => 1, ]); $foundElement = $repository->find($noahPortion->getId()); $this->assertNotNull($foundElement); $this->assertSame('Noah', $foundElement->getName()); $this->assertSame('portion', $foundElement->getKind()); $this->assertSame($set->getId(), $foundElement->getSet()->getId()); $this->assertSame( $genesisBook->getId(), $foundElement->getParentElement()?->getId(), ); } public function testItRejectsAParentFromAnotherSet(): void { $bible = $this->createSet('Bible'); $course = $this->createSet('Course'); $repository = app(ElementRepository::class); $book = $repository->create(new CreateElementDto( set: $bible, name: 'Genesis', kind: 'book', parentElement: null, )); $this->expectException(DomainException::class); $this->expectExceptionMessage( 'parent element must belong to the same set', ); $repository->create(new CreateElementDto( set: $course, name: 'Invalid lesson', kind: 'lesson', parentElement: $book, )); } public function testItListsOrderedElementsWithinTheirTreeScope(): void { $bible = $this->createSet('Bible'); $course = $this->createSet('Course'); $repository = app(ElementRepository::class); $genesisBook = $repository->create(new CreateElementDto( set: $bible, name: 'Genesis', kind: 'book', parentElement: null, )); $exodusBook = $repository->create(new CreateElementDto( set: $bible, name: 'Exodus', kind: 'book', parentElement: null, )); $repository->create(new CreateElementDto( set: $course, name: 'Module 1', kind: 'module', parentElement: null, )); $repository->create(new CreateElementDto( set: $bible, name: 'Genesis', kind: 'portion', parentElement: $genesisBook, )); $repository->create(new CreateElementDto( set: $bible, name: 'Noah', kind: 'portion', parentElement: $genesisBook, )); $repository->create(new CreateElementDto( set: $bible, name: 'Shemot', kind: 'portion', parentElement: $exodusBook, )); $topLevelElements = $repository->findTopLevelBySet($bible); $childElements = $repository->findByParentElement($genesisBook); $this->assertSame( ['Genesis', 'Exodus'], array_map(function ($element): string { return $element->getName(); }, $topLevelElements), ); $this->assertSame( ['Genesis', 'Noah'], array_map(function ($element): string { return $element->getName(); }, $childElements), ); } public function testItListsEveryElementForASet(): void { $bible = $this->createSet('Bible'); $course = $this->createSet('Course'); $repository = app(ElementRepository::class); $genesis = $repository->create(new CreateElementDto( set: $bible, name: 'Genesis', kind: 'book', parentElement: null, )); $repository->create(new CreateElementDto( set: $bible, name: 'Creation', kind: 'portion', parentElement: $genesis, )); $repository->create(new CreateElementDto( set: $course, name: 'Foundations', kind: 'module', parentElement: null, )); $elements = $repository->findBySet($bible); $this->assertSame( ['Genesis', 'Creation'], array_map(function ($element): string { return $element->getName(); }, $elements), ); $this->assertNull($elements[0]->getParentElement()); $this->assertSame( $genesis->getId(), $elements[1]->getParentElement()?->getId(), ); } private function createSet(string $name): Set { $creator = app(UserRepository::class)->create(new CreateUserDto( email: new EmailAddress(strtolower($name) . '@example.com'), passwordHash: 'hashed-password', )); return app(SetRepository::class)->create(new CreateSetDto( name: $name, creator: $creator, )); } }