setRepository = new FakeSetRepository(); $this->elementRepository = new FakeElementRepository(); $this->filesystem = new FakeFilesystem(); $this->updateSet = new UpdateSet( new UpdateName($this->setRepository), new UpdateDescription($this->setRepository), new UpdateIconImage( $this->setRepository, $this->filesystem, ), $this->setRepository, ); } public function testUpdatesSetWithoutChangingRootElement(): void { $set = $this->setRepository->create(new CreateSetDto( name: 'Original Set', description: 'Original set description', iconImageUrl: 'set-icons/original.png', )); $rootElement = $this->elementRepository->create(new CreateElementDto( set: $set, title: 'Original Root', description: 'Original root description', iconImageUrl: 'set-icons/original.png', richText: '', shortPdfPath: null, longPdfPath: null, youtubeUrl: null, parentElement: null, )); $updatedSet = $this->updateSet->execute(new UpdateSetRequest( id: $set->getId(), name: 'Updated Set', description: 'Updated set description', iconImageContents: null, iconImageOriginalName: null, iconImageMimeType: null, iconImageSizeBytes: null, )); $this->assertSame('Updated Set', $updatedSet->getName()); $this->assertSame( 'Updated set description', $updatedSet->getDescription(), ); $this->assertSame( 'set-icons/original.png', $updatedSet->getIconImageUrl(), ); $unchangedRootElement = $this->elementRepository->find( $rootElement->getId(), ); $this->assertNotNull($unchangedRootElement); $this->assertSame('Original Root', $unchangedRootElement->getTitle()); $this->assertSame( 'Original root description', $unchangedRootElement->getDescription(), ); $this->assertSame( 'set-icons/original.png', $unchangedRootElement->getIconImageUrl(), ); } public function testUpdatesOnlySuppliedFields(): void { $set = $this->setRepository->create(new CreateSetDto( name: 'Original Set', description: 'Original set description', iconImageUrl: 'set-icons/original.png', )); $updatedSet = $this->updateSet->execute(new UpdateSetRequest( id: $set->getId(), name: 'Updated Set', description: null, iconImageContents: null, iconImageOriginalName: null, iconImageMimeType: null, iconImageSizeBytes: null, )); $this->assertSame('Updated Set', $updatedSet->getName()); $this->assertSame( 'Original set description', $updatedSet->getDescription(), ); $this->assertSame( 'set-icons/original.png', $updatedSet->getIconImageUrl(), ); } public function testReplacesSetIconAndDeletesOldManagedIcon(): void { $set = $this->setRepository->create(new CreateSetDto( name: 'Original Set', description: 'Original set description', iconImageUrl: 'set-icons/original.png', )); $updatedSet = $this->updateSet->execute(new UpdateSetRequest( id: $set->getId(), name: 'Updated Set', description: 'Updated set description', iconImageContents: 'image contents', iconImageOriginalName: 'updated.png', iconImageMimeType: 'image/png', iconImageSizeBytes: 13, )); $this->assertSame( 'set-icons/fake-updated.png', $updatedSet->getIconImageUrl(), ); $this->assertCount(1, $this->filesystem->uploads); $this->assertSame('set-icons', $this->filesystem->uploads[0]['folder']); $this->assertSame([ 'set-icons/original.png', ], $this->filesystem->deletedPaths); } public function testRejectsNothingToUpdate(): void { $set = $this->createSet(); $this->expectException(BadRequestException::class); $this->expectExceptionMessage('nothing to update'); $this->updateSet->execute(new UpdateSetRequest( id: $set->getId(), name: null, description: null, iconImageContents: null, iconImageOriginalName: null, iconImageMimeType: null, iconImageSizeBytes: null, )); } public function testRequiresName(): void { $set = $this->createSet(); $this->expectException(BadRequestException::class); $this->expectExceptionMessage('name is required'); $this->updateSet->execute(new UpdateSetRequest( id: $set->getId(), name: '', description: null, iconImageContents: null, iconImageOriginalName: null, iconImageMimeType: null, iconImageSizeBytes: null, )); } public function testRequiresDescription(): void { $set = $this->createSet(); $this->expectException(BadRequestException::class); $this->expectExceptionMessage('description is required'); $this->updateSet->execute(new UpdateSetRequest( id: $set->getId(), name: null, description: '', iconImageContents: null, iconImageOriginalName: null, iconImageMimeType: null, iconImageSizeBytes: null, )); } public function testThrowsWhenSetIsMissing(): void { $this->expectException(NotFoundException::class); $this->expectExceptionMessage('Set not found'); $this->updateSet->execute(new UpdateSetRequest( id: 999, name: 'Updated Set', description: 'Updated set description', iconImageContents: null, iconImageOriginalName: null, iconImageMimeType: null, iconImageSizeBytes: null, )); } private function createSet(): DomainSet { return $this->setRepository->create(new CreateSetDto( name: 'Original Set', description: 'Original set description', iconImageUrl: 'set-icons/original.png', )); } }