elementRepository = new FakeElementRepository(); $this->fileUploader = new FakeFileUploader(); $this->useCase = new UpdateElementIconImage( $this->elementRepository, $this->fileUploader, ); } /** * @return array{ * iconImageContents: string, * iconImageOriginalName: string, * iconImageMimeType: string, * iconImageSizeBytes: int * } */ private function imageArgs(): array { return [ 'iconImageContents' => 'binary-image-bytes', 'iconImageOriginalName' => 'icon.png', 'iconImageMimeType' => 'image/png', 'iconImageSizeBytes' => 1024, ]; } public function testUploadsIconImageAndStoresPath(): void { $element = $this->createElement(); $updatedElement = $this->useCase->execute( new UpdateElementIconImageRequest( ...$this->imageArgs(), id: $element->getId(), ) ); $this->assertSame( 'element-icons/fake-icon.png', $updatedElement->getIconImageUrl(), ); $this->assertSame( 'element-icons/fake-icon.png', $this->elementRepository ->find($element->getId()) ->getIconImageUrl(), ); $this->assertSame( 'element-icons', $this->fileUploader->uploads[0]['folder'], ); } public function testNullIdThrowsBadRequest(): void { $this->expectException(BadRequestException::class); $this->expectExceptionMessage('id is required'); $this->useCase->execute( new UpdateElementIconImageRequest( ...$this->imageArgs(), id: null, ) ); } public function testNullIconImageThrowsBadRequest(): void { $this->expectException(BadRequestException::class); $this->expectExceptionMessage('icon image is required'); $this->useCase->execute( new UpdateElementIconImageRequest( id: 1, iconImageContents: null, iconImageOriginalName: null, iconImageMimeType: null, iconImageSizeBytes: null, ) ); } public function testDisallowedMimeThrowsBadRequest(): void { $this->expectException(BadRequestException::class); $this->expectExceptionMessage( 'icon image must be a jpeg, png or webp image', ); $this->useCase->execute( new UpdateElementIconImageRequest( id: 1, iconImageContents: 'not-an-image', iconImageOriginalName: 'icon.pdf', iconImageMimeType: 'application/pdf', iconImageSizeBytes: 1024, ) ); } public function testOversizedIconImageThrowsBadRequest(): void { $this->expectException(BadRequestException::class); $this->expectExceptionMessage('icon image must be 5MB or smaller'); $this->useCase->execute( new UpdateElementIconImageRequest( id: 1, iconImageContents: 'big', iconImageOriginalName: 'icon.png', iconImageMimeType: 'image/png', iconImageSizeBytes: 6 * 1024 * 1024, ) ); } public function testMissingElementThrowsNotFound(): void { $this->expectException(NotFoundException::class); $this->expectExceptionMessage('Element not found'); $this->useCase->execute( new UpdateElementIconImageRequest( ...$this->imageArgs(), id: 999, ) ); } private function createElement(): Element { $set = new DomainSet( id: 1, name: 'Baderech', description: 'Baderech description', iconImageUrl: '/assets/baderech-icon.png', ); return $this->elementRepository->create(new CreateElementDto( set: $set, title: 'Original title', description: 'Original description', iconImageUrl: null, richText: '', pdfPath: null, youtubeUrl: null, parentElement: null, )); } }