feat: add image upload service
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace BattleForge\Tests\Unit\Application;
|
||||
|
||||
use BattleForge\Application\ImageUploadService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class ImageUploadServiceTest extends TestCase
|
||||
{
|
||||
private string $tmpDir;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->tmpDir = sys_get_temp_dir() . '/bf-uploads-' . bin2hex(random_bytes(4));
|
||||
mkdir($this->tmpDir, 0700, true);
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
if (is_dir($this->tmpDir)) {
|
||||
foreach (glob($this->tmpDir . '/*/*') as $file) {
|
||||
unlink($file);
|
||||
}
|
||||
foreach (glob($this->tmpDir . '/*') as $dir) {
|
||||
rmdir($dir);
|
||||
}
|
||||
rmdir($this->tmpDir);
|
||||
}
|
||||
}
|
||||
|
||||
public function testItStoresAValidImageAndReturnsAStableUrl(): void
|
||||
{
|
||||
$service = new ImageUploadService('user-token-1', $this->tmpDir);
|
||||
$tmp = tempnam(sys_get_temp_dir(), 'bf-up');
|
||||
file_put_contents($tmp, self::validPng(8, 8));
|
||||
|
||||
$url = $service->store($tmp, 'image/png');
|
||||
|
||||
self::assertStringStartsWith('/assets/user-token-1/', $url);
|
||||
self::assertStringEndsWith('.png', $url);
|
||||
|
||||
$stored = $this->tmpDir . '/user-token-1/' . basename($url);
|
||||
self::assertFileExists($stored);
|
||||
}
|
||||
|
||||
public function testItCreatesTheUserNamespaceDirectory(): void
|
||||
{
|
||||
$service = new ImageUploadService('fresh-user', $this->tmpDir);
|
||||
$tmp = tempnam(sys_get_temp_dir(), 'bf-up');
|
||||
file_put_contents($tmp, self::validPng(8, 8));
|
||||
|
||||
$service->store($tmp, 'image/png');
|
||||
|
||||
self::assertDirectoryExists($this->tmpDir . '/fresh-user');
|
||||
}
|
||||
|
||||
public function testItProducesUniqueFilenamesForRepeatedUploads(): void
|
||||
{
|
||||
$service = new ImageUploadService('user-token-2', $this->tmpDir);
|
||||
$tmp1 = tempnam(sys_get_temp_dir(), 'bf-up');
|
||||
$tmp2 = tempnam(sys_get_temp_dir(), 'bf-up');
|
||||
file_put_contents($tmp1, self::validPng(8, 8));
|
||||
file_put_contents($tmp2, self::validPng(8, 8));
|
||||
|
||||
$url1 = $service->store($tmp1, 'image/png');
|
||||
$url2 = $service->store($tmp2, 'image/png');
|
||||
|
||||
self::assertNotSame($url1, $url2);
|
||||
}
|
||||
|
||||
public function testItRejectsAnInvalidImage(): void
|
||||
{
|
||||
$service = new ImageUploadService('user-token-3', $this->tmpDir);
|
||||
$tmp = tempnam(sys_get_temp_dir(), 'bf-up');
|
||||
file_put_contents($tmp, 'not an image');
|
||||
|
||||
$this->expectException(\BattleForge\Application\InvalidImageException::class);
|
||||
$service->store($tmp, 'image/png');
|
||||
}
|
||||
|
||||
private static function validPng(int $width, int $height): string
|
||||
{
|
||||
if ($width === 8 && $height === 8) {
|
||||
return base64_decode(
|
||||
'iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAYAAADED76LAAAAFElEQVR4nGNgYGD4z0AswK' .
|
||||
'EWBgYGRgYGBkYGRgAAB4nCH2AAAAAElFTkSuQmCC',
|
||||
true,
|
||||
);
|
||||
}
|
||||
throw new \InvalidArgumentException('Only 8x8 base PNG supported in tests.');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user