feat: replace raw image path input with interactive visual gallery and multi-image manager in admin and shop

This commit is contained in:
2026-11-01 16:24:12 +01:00
parent c06701673a
commit 4994d4a8ef
9 changed files with 724 additions and 29 deletions
+83
View File
@@ -8,6 +8,8 @@ use App\Models\Product;
use App\Models\Setting;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class AdminContentTest extends TestCase
@@ -174,4 +176,85 @@ class AdminContentTest extends TestCase
$showResponse->assertStatus(200);
$showResponse->assertSee('ORD-TEST-999');
}
public function test_admin_can_update_product_images_and_gallery(): void
{
$category = Category::create([
'name' => 'Fidget Gadgets',
'slug' => 'fidget-gadgets-gallery-test',
]);
$product = Product::create([
'category_id' => $category->id,
'name' => 'Multi Foto Draak',
'slug' => 'multi-foto-draak',
'short_description' => 'Test met meerdere fotos',
'description' => 'Test beschrijving met galerij',
'base_price' => 19.95,
'image_url' => 'https://cdn.example.com/cover.jpg',
'gallery_images' => ['https://cdn.example.com/photo1.jpg', 'https://cdn.example.com/photo2.jpg'],
'is_active' => true,
]);
// Edit page loads with visual image gallery
$editResponse = $this->actingAs($this->admin)->get(route('admin.products.edit', $product));
$editResponse->assertStatus(200);
$editResponse->assertSee('Productafbeeldingen & Fotogalerij', false);
$editResponse->assertSee('Hoofdafbeelding (Cover)');
// Update product with new cover and extra gallery images
$updateResponse = $this->actingAs($this->admin)->put(route('admin.products.update', $product), [
'name' => 'Multi Foto Draak Bijgewerkt',
'category_id' => $category->id,
'base_price' => 21.50,
'short_description' => 'Geüpdatet',
'description' => 'Nieuwe omschrijving',
'image_url' => 'https://cdn.example.com/new-cover.jpg',
'gallery_images' => [
'https://cdn.example.com/photo1.jpg',
'https://cdn.example.com/photo2.jpg',
'https://cdn.example.com/photo3.jpg',
'https://cdn.example.com/new-cover.jpg', // Should be excluded because it matches cover
],
'is_active' => 1,
]);
$updateResponse->assertRedirect(route('admin.products.index'));
$product->refresh();
$this->assertEquals('https://cdn.example.com/new-cover.jpg', $product->image_url);
$this->assertCount(3, $product->gallery_images);
$this->assertContains('https://cdn.example.com/photo3.jpg', $product->gallery_images);
$this->assertNotContains('https://cdn.example.com/new-cover.jpg', $product->gallery_images);
// Storefront product details page shows the multi-image gallery
$shopResponse = $this->get(route('product.show', $product->slug));
$shopResponse->assertStatus(200);
$shopResponse->assertSee('https://cdn.example.com/new-cover.jpg');
$shopResponse->assertSee('https://cdn.example.com/photo1.jpg');
$shopResponse->assertSee('https://cdn.example.com/photo3.jpg');
}
public function test_admin_can_upload_product_image(): void
{
Storage::fake('public');
$onePixelJpeg = base64_decode('/9j/4AAQSkZJRgABAQEASABIAAD/2wBDAP//////////////////////////////////////////////////////////////////////////////////////wgALCAABAAEBAREA/8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQABPxA=');
$file = UploadedFile::fake()->createWithContent('test-print-photo.jpg', $onePixelJpeg);
$response = $this->actingAs($this->admin)->postJson(route('admin.products.upload-image'), [
'image' => $file,
]);
$response->assertStatus(200);
$response->assertJson([
'success' => true,
]);
$url = $response->json('url');
$this->assertStringStartsWith('/storage/products/', $url);
$storagePath = str_replace('/storage/', '', $url);
Storage::disk('public')->assertExists($storagePath);
}
}