test element update dispatcher

This commit is contained in:
Yisroel Baum 2026-05-28 20:30:03 +03:00
parent 240ab4e771
commit 581852ecbc
Signed by: yisroelbaum
GPG key ID: 0FA60884F75520A9
4 changed files with 314 additions and 1 deletions

View file

@ -0,0 +1,24 @@
<?php
namespace Tests\Unit\Element;
use App\Element\Element;
use App\Element\ElementRepository;
use ReflectionMethod;
use Tests\TestCase;
class ElementRepositoryContractTest extends TestCase
{
public function testUpdateAcceptsOnlyElement(): void
{
$method = new ReflectionMethod(ElementRepository::class, 'update');
$parameters = $method->getParameters();
$this->assertCount(1, $parameters);
$this->assertSame('element', $parameters[0]->getName());
$this->assertSame(
Element::class,
$parameters[0]->getType()->getName(),
);
}
}

View file

@ -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: '<p>Original</p>',
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('<p>Updated</p>');
$element->setPdfPath(null);
$element->setYoutubeUrl(null);
$this->assertSame('Updated', $element->getTitle());
$this->assertSame('Updated description', $element->getDescription());
$this->assertNull($element->getIconImageUrl());
$this->assertSame('<p>Updated</p>', $element->getRichText());
$this->assertNull($element->getPdfPath());
$this->assertNull($element->getYoutubeUrl());
}
}

View file

@ -0,0 +1,175 @@
<?php
namespace Tests\Unit\Element\UseCases;
use App\Element\CreateElementDto;
use App\Element\Element;
use App\Element\UseCases\UpdateElement\UpdateDescription;
use App\Element\UseCases\UpdateElement\UpdateDescriptionRequest;
use App\Element\UseCases\UpdateElement\UpdateIconImageUrl;
use App\Element\UseCases\UpdateElement\UpdateIconImageUrlRequest;
use App\Element\UseCases\UpdateElement\UpdatePdfPath;
use App\Element\UseCases\UpdateElement\UpdatePdfPathRequest;
use App\Element\UseCases\UpdateElement\UpdateRichText;
use App\Element\UseCases\UpdateElement\UpdateRichTextRequest;
use App\Element\UseCases\UpdateElement\UpdateTitle;
use App\Element\UseCases\UpdateElement\UpdateTitleRequest;
use App\Element\UseCases\UpdateElement\UpdateYoutubeUrl;
use App\Element\UseCases\UpdateElement\UpdateYoutubeUrlRequest;
use App\Exceptions\BadRequestException;
use App\Set\Set as DomainSet;
use Tests\Fakes\FakeElementRepository;
use Tests\TestCase;
class UpdateElementFieldsTest extends TestCase
{
private FakeElementRepository $elementRepo;
protected function setUp(): void
{
$this->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: '<p>Updated rich text</p>',
)
);
$this->assertSame(
'<p>Updated rich text</p>',
$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: '<p>Original rich text</p>',
pdfPath: '/assets/pdfs/original.pdf',
youtubeUrl: 'https://www.youtube.com/watch?v=yHx-r4p6hHU',
parentElement: null,
));
}
}

View file

@ -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',
'<p>Original rich text</p>',
'/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(
'<p>Original rich text</p>',
$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);