Add extensive controller and model tests
All checks were successful
CI/CD Pipeline / test (push) Successful in 10s
CI/CD Pipeline / deploy (push) Successful in 25s

This commit is contained in:
2026-02-07 22:14:42 +01:00
parent 9c60a8944e
commit 160430e128
39 changed files with 3941 additions and 1 deletions

View File

@@ -0,0 +1,446 @@
<?php
use App\Models\Setting;
use App\Services\AttachmentThumbnailService;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
it('returns null for non-images', function (): void {
Storage::fake('local');
$service = new AttachmentThumbnailService();
$file = UploadedFile::fake()->create('document.txt', 10, 'text/plain');
$result = $service->createForUpload($file, 'misc', 'local');
expect($result)->toBeNull();
});
it('creates thumbnail for large images', function (): void {
if (!function_exists('imagecreatetruecolor')) {
$this->markTestSkipped('GD extension not available.');
}
Storage::fake('local');
Setting::updateOrCreate(['key' => 'attachments.create_thumbnails'], ['value' => 'true']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_width'], ['value' => '100']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_height'], ['value' => '100']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_quality'], ['value' => '80']);
$service = new AttachmentThumbnailService();
$file = UploadedFile::fake()->image('photo.jpg', 800, 600);
$result = $service->createForUpload($file, 'threads/10', 'local');
expect($result)->not->toBeNull();
expect($result)->toHaveKeys(['path', 'mime', 'size']);
Storage::disk('local')->assertExists($result['path']);
});
it('skips thumbnail when disabled or too small', function (): void {
if (!function_exists('imagecreatetruecolor')) {
$this->markTestSkipped('GD extension not available.');
}
Storage::fake('local');
Setting::updateOrCreate(['key' => 'attachments.create_thumbnails'], ['value' => 'false']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_width'], ['value' => '300']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_height'], ['value' => '300']);
$service = new AttachmentThumbnailService();
$file = UploadedFile::fake()->image('small.jpg', 100, 100);
$result = $service->createForUpload($file, 'threads/1', 'local');
expect($result)->toBeNull();
});
it('skips thumbnail when image is within size limits', function (): void {
if (!function_exists('imagecreatetruecolor')) {
$this->markTestSkipped('GD extension not available.');
}
Storage::fake('local');
Setting::updateOrCreate(['key' => 'attachments.create_thumbnails'], ['value' => 'true']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_width'], ['value' => '300']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_height'], ['value' => '300']);
$service = new AttachmentThumbnailService();
$file = UploadedFile::fake()->image('small.jpg', 100, 100);
$result = $service->createForUpload($file, 'threads/1', 'local');
expect($result)->toBeNull();
});
it('returns null when max dimensions are invalid', function (): void {
if (!function_exists('imagecreatetruecolor')) {
$this->markTestSkipped('GD extension not available.');
}
Storage::fake('local');
Setting::updateOrCreate(['key' => 'attachments.create_thumbnails'], ['value' => 'true']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_width'], ['value' => '0']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_height'], ['value' => '0']);
$service = new AttachmentThumbnailService();
$file = UploadedFile::fake()->image('photo.jpg', 800, 600);
$result = $service->createForUpload($file, 'threads/1', 'local');
expect($result)->toBeNull();
});
it('returns null for invalid image payloads', function (): void {
Storage::fake('local');
Setting::updateOrCreate(['key' => 'attachments.create_thumbnails'], ['value' => 'true']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_width'], ['value' => '100']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_height'], ['value' => '100']);
$service = new AttachmentThumbnailService();
$file = UploadedFile::fake()->create('bad.jpg', 10, 'image/jpeg');
$result = $service->createForUpload($file, 'threads/1', 'local');
expect($result)->toBeNull();
});
it('creates thumbnail for existing attachments', function (): void {
if (!function_exists('imagecreatetruecolor')) {
$this->markTestSkipped('GD extension not available.');
}
Storage::fake('local');
Setting::updateOrCreate(['key' => 'attachments.create_thumbnails'], ['value' => 'true']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_width'], ['value' => '100']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_height'], ['value' => '100']);
$category = \App\Models\Forum::create([
'name' => 'Category',
'description' => null,
'type' => 'category',
'parent_id' => null,
'position' => 1,
]);
$forum = \App\Models\Forum::create([
'name' => 'Forum',
'description' => null,
'type' => 'forum',
'parent_id' => $category->id,
'position' => 1,
]);
$thread = \App\Models\Thread::create([
'forum_id' => $forum->id,
'user_id' => null,
'title' => 'Thread',
'body' => 'Body',
]);
$image = UploadedFile::fake()->image('photo.jpg', 800, 600);
$path = "attachments/threads/{$thread->id}/photo.jpg";
Storage::disk('local')->put($path, file_get_contents($image->getPathname()));
$attachment = \App\Models\Attachment::create([
'thread_id' => $thread->id,
'post_id' => null,
'attachment_extension_id' => null,
'attachment_group_id' => null,
'user_id' => null,
'disk' => 'local',
'path' => $path,
'original_name' => 'photo.jpg',
'extension' => 'jpg',
'mime_type' => 'image/jpeg',
'size_bytes' => 1234,
]);
$service = new AttachmentThumbnailService();
$result = $service->createForAttachment($attachment, true);
expect($result)->not->toBeNull();
Storage::disk('local')->assertExists($result['path']);
});
it('returns null for attachments without stored files', function (): void {
Storage::fake('local');
$category = \App\Models\Forum::create([
'name' => 'Category',
'description' => null,
'type' => 'category',
'parent_id' => null,
'position' => 1,
]);
$forum = \App\Models\Forum::create([
'name' => 'Forum',
'description' => null,
'type' => 'forum',
'parent_id' => $category->id,
'position' => 1,
]);
$thread = \App\Models\Thread::create([
'forum_id' => $forum->id,
'user_id' => null,
'title' => 'Thread',
'body' => 'Body',
]);
$attachment = \App\Models\Attachment::create([
'thread_id' => $thread->id,
'post_id' => null,
'attachment_extension_id' => null,
'attachment_group_id' => null,
'user_id' => null,
'disk' => 'local',
'path' => "attachments/threads/{$thread->id}/missing.jpg",
'original_name' => 'missing.jpg',
'extension' => 'jpg',
'mime_type' => 'image/jpeg',
'size_bytes' => 10,
]);
$service = new AttachmentThumbnailService();
$result = $service->createForAttachment($attachment, true);
expect($result)->toBeNull();
});
it('returns null when thumbnail already exists and not forcing', function (): void {
Storage::fake('local');
$category = \App\Models\Forum::create([
'name' => 'Category',
'description' => null,
'type' => 'category',
'parent_id' => null,
'position' => 1,
]);
$forum = \App\Models\Forum::create([
'name' => 'Forum',
'description' => null,
'type' => 'forum',
'parent_id' => $category->id,
'position' => 1,
]);
$thread = \App\Models\Thread::create([
'forum_id' => $forum->id,
'user_id' => null,
'title' => 'Thread',
'body' => 'Body',
]);
$attachment = \App\Models\Attachment::create([
'thread_id' => $thread->id,
'post_id' => null,
'attachment_extension_id' => null,
'attachment_group_id' => null,
'user_id' => null,
'disk' => 'local',
'path' => "attachments/threads/{$thread->id}/photo.jpg",
'thumbnail_path' => "attachments/threads/{$thread->id}/thumbs/existing.jpg",
'original_name' => 'photo.jpg',
'extension' => 'jpg',
'mime_type' => 'image/jpeg',
'size_bytes' => 10,
]);
Storage::disk('local')->put($attachment->thumbnail_path, 'thumb');
$service = new AttachmentThumbnailService();
$result = $service->createForAttachment($attachment, false);
expect($result)->toBeNull();
});
it('returns null for non-image attachments', function (): void {
Storage::fake('local');
$category = \App\Models\Forum::create([
'name' => 'Category',
'description' => null,
'type' => 'category',
'parent_id' => null,
'position' => 1,
]);
$forum = \App\Models\Forum::create([
'name' => 'Forum',
'description' => null,
'type' => 'forum',
'parent_id' => $category->id,
'position' => 1,
]);
$thread = \App\Models\Thread::create([
'forum_id' => $forum->id,
'user_id' => null,
'title' => 'Thread',
'body' => 'Body',
]);
$attachment = \App\Models\Attachment::create([
'thread_id' => $thread->id,
'post_id' => null,
'attachment_extension_id' => null,
'attachment_group_id' => null,
'user_id' => null,
'disk' => 'local',
'path' => "attachments/threads/{$thread->id}/doc.pdf",
'original_name' => 'doc.pdf',
'extension' => 'pdf',
'mime_type' => 'application/pdf',
'size_bytes' => 10,
]);
$service = new AttachmentThumbnailService();
$result = $service->createForAttachment($attachment, true);
expect($result)->toBeNull();
});
it('uses post scope when creating thumbnails', function (): void {
if (!function_exists('imagecreatetruecolor')) {
$this->markTestSkipped('GD extension not available.');
}
Storage::fake('local');
Setting::updateOrCreate(['key' => 'attachments.create_thumbnails'], ['value' => 'true']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_width'], ['value' => '100']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_height'], ['value' => '100']);
$category = \App\Models\Forum::create([
'name' => 'Category',
'description' => null,
'type' => 'category',
'parent_id' => null,
'position' => 1,
]);
$forum = \App\Models\Forum::create([
'name' => 'Forum',
'description' => null,
'type' => 'forum',
'parent_id' => $category->id,
'position' => 1,
]);
$thread = \App\Models\Thread::create([
'forum_id' => $forum->id,
'user_id' => null,
'title' => 'Thread',
'body' => 'Body',
]);
$post = \App\Models\Post::create([
'thread_id' => $thread->id,
'user_id' => null,
'body' => 'Post',
]);
$image = UploadedFile::fake()->image('photo.png', 800, 600);
$path = "attachments/posts/{$post->id}/photo.png";
Storage::disk('local')->put($path, file_get_contents($image->getPathname()));
$attachment = \App\Models\Attachment::create([
'thread_id' => null,
'post_id' => $post->id,
'attachment_extension_id' => null,
'attachment_group_id' => null,
'user_id' => null,
'disk' => 'local',
'path' => $path,
'original_name' => 'photo.png',
'extension' => 'png',
'mime_type' => 'image/png',
'size_bytes' => 1234,
]);
$service = new AttachmentThumbnailService();
$result = $service->createForAttachment($attachment, true);
expect($result)->not->toBeNull();
expect($result['path'])->toContain("attachments/posts/{$post->id}/thumbs/");
});
it('returns null when mime is unsupported even if image data is valid', function (): void {
if (!function_exists('imagecreatetruecolor')) {
$this->markTestSkipped('GD extension not available.');
}
Storage::fake('local');
Setting::updateOrCreate(['key' => 'attachments.create_thumbnails'], ['value' => 'true']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_width'], ['value' => '100']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_height'], ['value' => '100']);
$category = \App\Models\Forum::create([
'name' => 'Category',
'description' => null,
'type' => 'category',
'parent_id' => null,
'position' => 1,
]);
$forum = \App\Models\Forum::create([
'name' => 'Forum',
'description' => null,
'type' => 'forum',
'parent_id' => $category->id,
'position' => 1,
]);
$thread = \App\Models\Thread::create([
'forum_id' => $forum->id,
'user_id' => null,
'title' => 'Thread',
'body' => 'Body',
]);
$image = UploadedFile::fake()->image('photo.png', 800, 600);
$path = "attachments/threads/{$thread->id}/photo.png";
Storage::disk('local')->put($path, file_get_contents($image->getPathname()));
$attachment = \App\Models\Attachment::create([
'thread_id' => $thread->id,
'post_id' => null,
'attachment_extension_id' => null,
'attachment_group_id' => null,
'user_id' => null,
'disk' => 'local',
'path' => $path,
'original_name' => 'photo.png',
'extension' => 'png',
'mime_type' => 'image/avif',
'size_bytes' => 1234,
]);
$service = new AttachmentThumbnailService();
$result = $service->createForAttachment($attachment, true);
expect($result)->toBeNull();
});
it('creates thumbnails for gif images', function (): void {
if (!function_exists('imagecreatetruecolor')) {
$this->markTestSkipped('GD extension not available.');
}
if (!function_exists('imagegif')) {
$this->markTestSkipped('GIF support not available.');
}
Storage::fake('local');
Setting::updateOrCreate(['key' => 'attachments.create_thumbnails'], ['value' => 'true']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_width'], ['value' => '100']);
Setting::updateOrCreate(['key' => 'attachments.thumbnail_max_height'], ['value' => '100']);
$service = new AttachmentThumbnailService();
$file = UploadedFile::fake()->image('photo.gif', 800, 600);
$result = $service->createForUpload($file, 'threads/1', 'local');
expect($result)->not->toBeNull();
Storage::disk('local')->assertExists($result['path']);
});