feat(images): 課程圖片伺服器端壓縮——scaleDown 2048 + JPEG 85,上限放寬至 10MB
Run Tests / test (pull_request) Successful in 2m0s
Run Tests / test (pull_request) Successful in 2m0s
實作 openspec change course-image-compression(O3.1 體感優化): - 新增 App\Traits\CompressesImages:與聊天圖片管線參數一致的共用壓縮邏輯 - CourseImageController 封面/相簿套用壓縮,上傳上限 2MB→10MB(容納手機原圖) - 前端課程卡片與相簿縮圖加 loading=lazy(詳情頁首屏封面刻意不加) - CourseImageTest +4 案例(10MB 邊界、轉存 .jpg、>2048 縮小、小圖不放大) - course-image-upload 主規格同步(新增伺服器端壓縮 requirement) 容器內全套件 155 passed / 400 assertions。 聊天端改用 trait 留待後續(該處無測試覆蓋,不在本 change 重構)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -73,10 +73,75 @@ class CourseImageTest extends TestCase
|
||||
|
||||
$this->actingAs($provider)
|
||||
->postJson("/api/provider/offers/{$offer->id}/cover", [
|
||||
'image' => UploadedFile::fake()->image('big.png')->size(3000),
|
||||
'image' => UploadedFile::fake()->image('big.png')->size(11000),
|
||||
])->assertStatus(422);
|
||||
}
|
||||
|
||||
public function test_upload_cover_accepts_phone_sized_original(): void
|
||||
{
|
||||
// 原上限 2MB 會擋掉手機原圖;放寬至 10MB 後 5MB 應通過(伺服器端會壓縮)
|
||||
Storage::fake('public');
|
||||
$provider = $this->makeProvider();
|
||||
$offer = $this->makeOffer($provider);
|
||||
|
||||
$this->actingAs($provider)
|
||||
->postJson("/api/provider/offers/{$offer->id}/cover", [
|
||||
'image' => UploadedFile::fake()->image('phone.jpg', 800, 600)->size(5000),
|
||||
])->assertOk();
|
||||
}
|
||||
|
||||
public function test_uploaded_cover_is_stored_as_jpeg(): void
|
||||
{
|
||||
Storage::fake('public');
|
||||
$provider = $this->makeProvider();
|
||||
$offer = $this->makeOffer($provider);
|
||||
|
||||
$this->actingAs($provider)
|
||||
->postJson("/api/provider/offers/{$offer->id}/cover", [
|
||||
'image' => UploadedFile::fake()->image('photo.png', 400, 300),
|
||||
])->assertOk();
|
||||
|
||||
$path = $offer->fresh()->cover_image;
|
||||
$this->assertStringEndsWith('.jpg', $path);
|
||||
Storage::disk('public')->assertExists($path);
|
||||
}
|
||||
|
||||
public function test_oversized_cover_is_scaled_down_to_2048(): void
|
||||
{
|
||||
// 2048px 上限保護的是課程列表頁的載入重量:原圖直存會讓手機照片
|
||||
// (數 MB)直接進列表,壓縮管線是 O3.1 體感優化的核心
|
||||
Storage::fake('public');
|
||||
$provider = $this->makeProvider();
|
||||
$offer = $this->makeOffer($provider);
|
||||
|
||||
$this->actingAs($provider)
|
||||
->postJson("/api/provider/offers/{$offer->id}/cover", [
|
||||
'image' => UploadedFile::fake()->image('huge.jpg', 3000, 2500),
|
||||
])->assertOk();
|
||||
|
||||
$stored = Storage::disk('public')->get($offer->fresh()->cover_image);
|
||||
[$width, $height] = getimagesizefromstring($stored);
|
||||
$this->assertLessThanOrEqual(2048, $width);
|
||||
$this->assertLessThanOrEqual(2048, $height);
|
||||
}
|
||||
|
||||
public function test_small_image_is_not_upscaled(): void
|
||||
{
|
||||
Storage::fake('public');
|
||||
$provider = $this->makeProvider();
|
||||
$offer = $this->makeOffer($provider);
|
||||
|
||||
$this->actingAs($provider)
|
||||
->postJson("/api/provider/offers/{$offer->id}/cover", [
|
||||
'image' => UploadedFile::fake()->image('small.jpg', 640, 480),
|
||||
])->assertOk();
|
||||
|
||||
$stored = Storage::disk('public')->get($offer->fresh()->cover_image);
|
||||
[$width, $height] = getimagesizefromstring($stored);
|
||||
$this->assertSame(640, $width);
|
||||
$this->assertSame(480, $height);
|
||||
}
|
||||
|
||||
public function test_upload_cover_forbidden_for_other_provider(): void
|
||||
{
|
||||
Storage::fake('public');
|
||||
|
||||
Reference in New Issue
Block a user