From db35a97910523458f9cfe4eb644be0224a1d9d8b Mon Sep 17 00:00:00 2001 From: Yisroel Baum Date: Sun, 24 May 2026 22:28:44 +0300 Subject: [PATCH] test set elements --- backend/tests/Fakes/FakeElementRepository.php | 68 +++++++ backend/tests/Fakes/FakeSetRepository.php | 57 ++++++ backend/tests/Unit/Element/ElementTest.php | 33 ++++ .../Element/UseCases/CreateElementTest.php | 171 ++++++++++++++++++ backend/tests/Unit/Set/SetTest.php | 17 ++ .../tests/Unit/Set/UseCases/CreateSetTest.php | 63 +++++++ 6 files changed, 409 insertions(+) create mode 100644 backend/tests/Fakes/FakeElementRepository.php create mode 100644 backend/tests/Fakes/FakeSetRepository.php create mode 100644 backend/tests/Unit/Element/ElementTest.php create mode 100644 backend/tests/Unit/Element/UseCases/CreateElementTest.php create mode 100644 backend/tests/Unit/Set/SetTest.php create mode 100644 backend/tests/Unit/Set/UseCases/CreateSetTest.php diff --git a/backend/tests/Fakes/FakeElementRepository.php b/backend/tests/Fakes/FakeElementRepository.php new file mode 100644 index 0000000..d624a9a --- /dev/null +++ b/backend/tests/Fakes/FakeElementRepository.php @@ -0,0 +1,68 @@ +elementsById) + 1; + $element = new Element( + id: $id, + title: $dto->title, + set: $dto->set, + parentElement: $dto->parentElement, + ); + $this->elementsById[$id] = $element; + + return $element; + } + + public function find(int $id): ?Element + { + if (! isset($this->elementsById[$id])) { + return null; + } + + return $this->cloneElement($this->elementsById[$id]); + } + + /** + * @return Element[] + */ + public function findBySetId(int $id): array + { + $elements = []; + foreach ($this->elementsById as $element) { + if ($element->getSet()->getId() === $id) { + $elements[] = $this->cloneElement($element); + } + } + + return $elements; + } + + private function cloneElement(Element $element): Element + { + $parentElement = $element->getParentElement(); + if ($parentElement !== null) { + $parentElement = $this->cloneElement($parentElement); + } + + return new Element( + id: $element->getId(), + title: $element->getTitle(), + set: $element->getSet(), + parentElement: $parentElement, + ); + } +} diff --git a/backend/tests/Fakes/FakeSetRepository.php b/backend/tests/Fakes/FakeSetRepository.php new file mode 100644 index 0000000..295e619 --- /dev/null +++ b/backend/tests/Fakes/FakeSetRepository.php @@ -0,0 +1,57 @@ +setsById) + 1; + $set = new DomainSet( + id: $id, + name: $dto->name, + ); + $this->setsById[$id] = $set; + + return $set; + } + + public function find(int $id): ?DomainSet + { + if (! isset($this->setsById[$id])) { + return null; + } + + return $this->cloneSet($this->setsById[$id]); + } + + /** + * @return DomainSet[] + */ + public function getAll(): array + { + $sets = []; + foreach ($this->setsById as $set) { + $sets[] = $this->cloneSet($set); + } + + return $sets; + } + + private function cloneSet(DomainSet $set): DomainSet + { + return new DomainSet( + id: $set->getId(), + name: $set->getName(), + ); + } +} diff --git a/backend/tests/Unit/Element/ElementTest.php b/backend/tests/Unit/Element/ElementTest.php new file mode 100644 index 0000000..3e914d9 --- /dev/null +++ b/backend/tests/Unit/Element/ElementTest.php @@ -0,0 +1,33 @@ +assertSame(2, $childElement->getId()); + $this->assertSame('Child', $childElement->getTitle()); + $this->assertSame($set, $childElement->getSet()); + $this->assertSame($rootElement, $childElement->getParentElement()); + $this->assertNull($rootElement->getParentElement()); + } +} diff --git a/backend/tests/Unit/Element/UseCases/CreateElementTest.php b/backend/tests/Unit/Element/UseCases/CreateElementTest.php new file mode 100644 index 0000000..da6f024 --- /dev/null +++ b/backend/tests/Unit/Element/UseCases/CreateElementTest.php @@ -0,0 +1,171 @@ +setRepo = new FakeSetRepository(); + $this->elementRepo = new FakeElementRepository(); + $this->createElement = new CreateElement( + $this->elementRepo, + $this->setRepo, + ); + } + + public function testCreatesRootElement(): void + { + $set = $this->setRepo->create(new CreateSetDto('Daily learning')); + + $element = $this->createElement->execute(new CreateElementRequest( + setId: $set->getId(), + title: 'Root', + parentElementId: null, + )); + + $this->assertInstanceOf(Element::class, $element); + $this->assertSame('Root', $element->getTitle()); + $this->assertSame($set->getId(), $element->getSet()->getId()); + $this->assertNull($element->getParentElement()); + } + + public function testCreatesChildElement(): void + { + $set = $this->setRepo->create(new CreateSetDto('Daily learning')); + $rootElement = $this->createElement->execute( + new CreateElementRequest( + setId: $set->getId(), + title: 'Root', + parentElementId: null, + ) + ); + + $childElement = $this->createElement->execute( + new CreateElementRequest( + setId: $set->getId(), + title: 'Child', + parentElementId: $rootElement->getId(), + ) + ); + + $this->assertSame('Child', $childElement->getTitle()); + $this->assertSame( + $rootElement->getId(), + $childElement->getParentElement()->getId(), + ); + } + + public function testThrowsWhenSetIdMissing(): void + { + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('setId is required'); + + $this->createElement->execute(new CreateElementRequest( + setId: null, + title: 'Root', + parentElementId: null, + )); + } + + public function testThrowsWhenTitleMissing(): void + { + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('title is required'); + + $this->createElement->execute(new CreateElementRequest( + setId: 1, + title: null, + parentElementId: null, + )); + } + + public function testThrowsWhenSetDoesNotExist(): void + { + $this->expectException(DomainException::class); + $this->expectExceptionMessage('Set with id: 99 doesnt exist'); + + $this->createElement->execute(new CreateElementRequest( + setId: 99, + title: 'Root', + parentElementId: null, + )); + } + + public function testThrowsWhenParentElementDoesNotExist(): void + { + $set = $this->setRepo->create(new CreateSetDto('Daily learning')); + + $this->expectException(DomainException::class); + $this->expectExceptionMessage( + 'Element with id: 99 doesnt exist' + ); + + $this->createElement->execute(new CreateElementRequest( + setId: $set->getId(), + title: 'Child', + parentElementId: 99, + )); + } + + public function testThrowsWhenRootElementAlreadyExists(): void + { + $set = $this->setRepo->create(new CreateSetDto('Daily learning')); + $this->createElement->execute(new CreateElementRequest( + setId: $set->getId(), + title: 'Root', + parentElementId: null, + )); + + $this->expectException(DomainException::class); + $this->expectExceptionMessage( + 'A root element already exists for this set' + ); + + $this->createElement->execute(new CreateElementRequest( + setId: $set->getId(), + title: 'Another root', + parentElementId: null, + )); + } + + public function testThrowsWhenParentBelongsToAnotherSet(): void + { + $parentSet = $this->setRepo->create(new CreateSetDto('Parent set')); + $childSet = $this->setRepo->create(new CreateSetDto('Child set')); + $parentElement = $this->createElement->execute( + new CreateElementRequest( + setId: $parentSet->getId(), + title: 'Parent root', + parentElementId: null, + ) + ); + + $this->expectException(DomainException::class); + $this->expectExceptionMessage( + 'Parent element must belong to the same set' + ); + + $this->createElement->execute(new CreateElementRequest( + setId: $childSet->getId(), + title: 'Invalid child', + parentElementId: $parentElement->getId(), + )); + } +} diff --git a/backend/tests/Unit/Set/SetTest.php b/backend/tests/Unit/Set/SetTest.php new file mode 100644 index 0000000..a98ac5f --- /dev/null +++ b/backend/tests/Unit/Set/SetTest.php @@ -0,0 +1,17 @@ +assertSame(1, $set->getId()); + $this->assertSame('Daily learning', $set->getName()); + } +} diff --git a/backend/tests/Unit/Set/UseCases/CreateSetTest.php b/backend/tests/Unit/Set/UseCases/CreateSetTest.php new file mode 100644 index 0000000..bd3c9f4 --- /dev/null +++ b/backend/tests/Unit/Set/UseCases/CreateSetTest.php @@ -0,0 +1,63 @@ +setRepo = new FakeSetRepository(); + $this->elementRepo = new FakeElementRepository(); + $this->createSet = new CreateSet( + $this->setRepo, + $this->elementRepo, + ); + } + + public function testCreatesSet(): void + { + $set = $this->createSet->execute( + new CreateSetRequest('Daily learning') + ); + + $this->assertInstanceOf(DomainSet::class, $set); + $this->assertSame(1, $set->getId()); + $this->assertSame('Daily learning', $set->getName()); + } + + public function testCreatesRootElementForSet(): void + { + $set = $this->createSet->execute( + new CreateSetRequest('Daily learning') + ); + + $elements = $this->elementRepo->findBySetId($set->getId()); + + $this->assertCount(1, $elements); + $this->assertSame('Daily learning', $elements[0]->getTitle()); + $this->assertSame($set->getId(), $elements[0]->getSet()->getId()); + $this->assertNull($elements[0]->getParentElement()); + } + + public function testThrowsWhenNameMissing(): void + { + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('name is required'); + + $this->createSet->execute(new CreateSetRequest(null)); + } +}