diff --git a/backend/tests/Unit/Element/ElementRepositoryContractTest.php b/backend/tests/Unit/Element/ElementRepositoryContractTest.php new file mode 100644 index 0000000..84e5bb9 --- /dev/null +++ b/backend/tests/Unit/Element/ElementRepositoryContractTest.php @@ -0,0 +1,24 @@ +getParameters(); + + $this->assertCount(1, $parameters); + $this->assertSame('element', $parameters[0]->getName()); + $this->assertSame( + Element::class, + $parameters[0]->getType()->getName(), + ); + } +} diff --git a/backend/tests/Unit/Element/ElementTest.php b/backend/tests/Unit/Element/ElementTest.php index 16c08a7..89e9c84 100644 --- a/backend/tests/Unit/Element/ElementTest.php +++ b/backend/tests/Unit/Element/ElementTest.php @@ -68,4 +68,39 @@ class ElementTest extends TestCase $this->assertNull($rootElement->getYoutubeUrl()); $this->assertNull($rootElement->getParentElement()); } + + public function testUpdatesEditableFields(): void + { + $set = new DomainSet( + id: 1, + name: 'Daily learning', + description: 'Daily learning description', + iconImageUrl: '/assets/daily-learning-icon.svg', + ); + $element = new Element( + id: 1, + title: 'Original', + description: 'Original description', + iconImageUrl: '/assets/original.svg', + richText: '
Original
', + pdfPath: '/assets/pdfs/original.pdf', + youtubeUrl: 'https://www.youtube.com/watch?v=yHx-r4p6hHU', + set: $set, + parentElement: null, + ); + + $element->setTitle('Updated'); + $element->setDescription('Updated description'); + $element->setIconImageUrl(null); + $element->setRichText('Updated
'); + $element->setPdfPath(null); + $element->setYoutubeUrl(null); + + $this->assertSame('Updated', $element->getTitle()); + $this->assertSame('Updated description', $element->getDescription()); + $this->assertNull($element->getIconImageUrl()); + $this->assertSame('Updated
', $element->getRichText()); + $this->assertNull($element->getPdfPath()); + $this->assertNull($element->getYoutubeUrl()); + } } diff --git a/backend/tests/Unit/Element/UseCases/UpdateElementFieldsTest.php b/backend/tests/Unit/Element/UseCases/UpdateElementFieldsTest.php new file mode 100644 index 0000000..7c27c9c --- /dev/null +++ b/backend/tests/Unit/Element/UseCases/UpdateElementFieldsTest.php @@ -0,0 +1,175 @@ +elementRepo = new FakeElementRepository(); + } + + public function testUpdateTitleUpdatesOnlyTitle(): void + { + $element = $this->createFilledElement(); + $updateTitle = new UpdateTitle($this->elementRepo); + + $updatedElement = $updateTitle->execute(new UpdateTitleRequest( + id: $element->getId(), + title: 'Updated title', + )); + + $this->assertSame('Updated title', $updatedElement->getTitle()); + $this->assertSame( + $element->getDescription(), + $updatedElement->getDescription(), + ); + $this->assertSame( + $element->getRichText(), + $updatedElement->getRichText(), + ); + } + + public function testUpdateTitleRejectsBlankTitle(): void + { + $this->createFilledElement(); + $updateTitle = new UpdateTitle($this->elementRepo); + + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('title is required'); + + $updateTitle->execute(new UpdateTitleRequest(id: 1, title: '')); + } + + public function testUpdateDescriptionUpdatesOnlyDescription(): void + { + $element = $this->createFilledElement(); + $updateDescription = new UpdateDescription($this->elementRepo); + + $updatedElement = $updateDescription->execute( + new UpdateDescriptionRequest( + id: $element->getId(), + description: 'Updated description', + ) + ); + + $this->assertSame( + 'Updated description', + $updatedElement->getDescription(), + ); + $this->assertSame($element->getTitle(), $updatedElement->getTitle()); + $this->assertSame( + $element->getYoutubeUrl(), + $updatedElement->getYoutubeUrl(), + ); + } + + public function testUpdateIconImageUrlClearsEmptyString(): void + { + $element = $this->createFilledElement(); + $updateIconImageUrl = new UpdateIconImageUrl($this->elementRepo); + + $updatedElement = $updateIconImageUrl->execute( + new UpdateIconImageUrlRequest( + id: $element->getId(), + iconImageUrl: '', + ) + ); + + $this->assertNull($updatedElement->getIconImageUrl()); + $this->assertSame($element->getTitle(), $updatedElement->getTitle()); + } + + public function testUpdateRichTextUpdatesOnlyRichText(): void + { + $element = $this->createFilledElement(); + $updateRichText = new UpdateRichText($this->elementRepo); + + $updatedElement = $updateRichText->execute( + new UpdateRichTextRequest( + id: $element->getId(), + richText: 'Updated rich text
', + ) + ); + + $this->assertSame( + 'Updated rich text
', + $updatedElement->getRichText(), + ); + $this->assertSame( + $element->getDescription(), + $updatedElement->getDescription(), + ); + } + + public function testUpdatePdfPathClearsEmptyString(): void + { + $element = $this->createFilledElement(); + $updatePdfPath = new UpdatePdfPath($this->elementRepo); + + $updatedElement = $updatePdfPath->execute( + new UpdatePdfPathRequest(id: $element->getId(), pdfPath: '') + ); + + $this->assertNull($updatedElement->getPdfPath()); + $this->assertSame($element->getTitle(), $updatedElement->getTitle()); + } + + public function testUpdateYoutubeUrlClearsEmptyString(): void + { + $element = $this->createFilledElement(); + $updateYoutubeUrl = new UpdateYoutubeUrl($this->elementRepo); + + $updatedElement = $updateYoutubeUrl->execute( + new UpdateYoutubeUrlRequest( + id: $element->getId(), + youtubeUrl: '', + ) + ); + + $this->assertNull($updatedElement->getYoutubeUrl()); + $this->assertSame($element->getTitle(), $updatedElement->getTitle()); + } + + private function createFilledElement(): Element + { + $set = new DomainSet( + id: 1, + name: 'Baderech', + description: 'Baderech description', + iconImageUrl: '/assets/baderech-icon.png', + ); + + return $this->elementRepo->create(new CreateElementDto( + set: $set, + title: 'Original title', + description: 'Original description', + iconImageUrl: '/assets/original-icon.png', + richText: 'Original rich text
', + pdfPath: '/assets/pdfs/original.pdf', + youtubeUrl: 'https://www.youtube.com/watch?v=yHx-r4p6hHU', + parentElement: null, + )); + } +} diff --git a/backend/tests/Unit/Element/UseCases/UpdateElementTest.php b/backend/tests/Unit/Element/UseCases/UpdateElementTest.php index 0bb1195..0ce0d88 100644 --- a/backend/tests/Unit/Element/UseCases/UpdateElementTest.php +++ b/backend/tests/Unit/Element/UseCases/UpdateElementTest.php @@ -4,8 +4,14 @@ namespace Tests\Unit\Element\UseCases; use App\Element\CreateElementDto; use App\Element\Element; +use App\Element\UseCases\UpdateElement\UpdateDescription; +use App\Element\UseCases\UpdateElement\UpdateIconImageUrl; use App\Element\UseCases\UpdateElement\UpdateElement; use App\Element\UseCases\UpdateElement\UpdateElementRequest; +use App\Element\UseCases\UpdateElement\UpdatePdfPath; +use App\Element\UseCases\UpdateElement\UpdateRichText; +use App\Element\UseCases\UpdateElement\UpdateTitle; +use App\Element\UseCases\UpdateElement\UpdateYoutubeUrl; use App\Exceptions\BadRequestException; use App\Exceptions\NotFoundException; use App\Set\Set as DomainSet; @@ -21,7 +27,15 @@ class UpdateElementTest extends TestCase protected function setUp(): void { $this->elementRepo = new FakeElementRepository(); - $this->updateElement = new UpdateElement($this->elementRepo); + $this->updateElement = new UpdateElement( + new UpdateTitle($this->elementRepo), + new UpdateDescription($this->elementRepo), + new UpdateIconImageUrl($this->elementRepo), + new UpdateRichText($this->elementRepo), + new UpdatePdfPath($this->elementRepo), + new UpdateYoutubeUrl($this->elementRepo), + $this->elementRepo, + ); } public function testUpdatesContentFields(): void @@ -109,6 +123,55 @@ class UpdateElementTest extends TestCase $this->assertNull($updatedElement->getYoutubeUrl()); } + public function testUpdatesOnlySuppliedFields(): void + { + $set = $this->createSet(1, 'Baderech'); + $element = $this->createElement( + $set, + 'Original title', + 'Original description', + '/assets/original-icon.png', + 'Original rich text
', + '/assets/pdfs/original.pdf', + 'https://www.youtube.com/watch?v=yHx-r4p6hHU&t=1s', + null, + ); + + $updatedElement = $this->updateElement->execute( + new UpdateElementRequest( + id: $element->getId(), + title: 'Updated title', + description: null, + iconImageUrl: null, + richText: null, + pdfPath: null, + youtubeUrl: null, + ) + ); + + $this->assertSame('Updated title', $updatedElement->getTitle()); + $this->assertSame( + 'Original description', + $updatedElement->getDescription(), + ); + $this->assertSame( + '/assets/original-icon.png', + $updatedElement->getIconImageUrl(), + ); + $this->assertSame( + 'Original rich text
', + $updatedElement->getRichText(), + ); + $this->assertSame( + '/assets/pdfs/original.pdf', + $updatedElement->getPdfPath(), + ); + $this->assertSame( + 'https://www.youtube.com/watch?v=yHx-r4p6hHU&t=1s', + $updatedElement->getYoutubeUrl(), + ); + } + public function testThrowsWhenIdMissing(): void { $this->expectException(BadRequestException::class); @@ -125,6 +188,22 @@ class UpdateElementTest extends TestCase )); } + public function testThrowsWhenNothingProvided(): void + { + $this->expectException(BadRequestException::class); + $this->expectExceptionMessage('nothing to update'); + + $this->updateElement->execute(new UpdateElementRequest( + id: 1, + title: null, + description: null, + iconImageUrl: null, + richText: null, + pdfPath: null, + youtubeUrl: null, + )); + } + public function testThrowsWhenTitleIsBlank(): void { $this->expectException(BadRequestException::class);