'https://dev.local', 'services.freepik.api_key' => 'test-freepik-key', 'services.freepik.base_url' => 'https://api.freepik.com/v1/ai/text-to-image', 'filesystems.disks.public.root' => $diskRoot, 'filesystems.disks.public.url' => '/storage', ]); Storage::disk('public')->put('social_assets/images/source.jpg', 'source-image-binary'); Http::fake([ 'https://api.freepik.com/v1/ai/text-to-image/seedream-v4-5-edit' => Http::response([ 'data' => [ 'task_id' => 'img-task-1', 'status' => 'CREATED', ], ], 200), 'https://api.freepik.com/v1/ai/text-to-image/seedream-v4-5-edit/img-task-1' => Http::response([ 'data' => [ 'status' => 'COMPLETED', 'generated' => ['https://cdn.example.com/remix-image.jpg'], ], ], 200), ]); $service = app(FreepikAssetRemixService::class); $result = $service->remixImage([ 'type' => 'image', 'url' => '/storage/social_assets/images/source.jpg', ], 'Ubah jadi visual promosi premium', 'restyle'); $this->assertSame('freepik-seedream-v45-edit', $result['provider']); $this->assertSame(['https://cdn.example.com/remix-image.jpg'], $result['urls']); } public function test_remix_video_persists_generated_mp4_inside_public_storage(): void { $diskRoot = sys_get_temp_dir().'/dev-local-public-remix-video-'.uniqid(); if (! is_dir($diskRoot)) { mkdir($diskRoot, 0777, true); } config([ 'app.url' => 'https://dev.local', 'services.freepik.api_key' => 'test-freepik-key', 'services.freepik.base_url' => 'https://api.freepik.com/v1/ai/text-to-image', 'filesystems.disks.public.root' => $diskRoot, 'filesystems.disks.public.url' => '/storage', ]); Storage::disk('public')->put('social_assets/images/ref.jpg', 'reference-image-binary'); Http::fake([ 'https://api.freepik.com/v1/ai/image-to-video/runway-4-5' => Http::response([ 'data' => [ 'task_id' => 'vid-task-1', 'status' => 'CREATED', ], ], 200), 'https://api.freepik.com/v1/ai/image-to-video/runway-4-5/vid-task-1' => Http::response([ 'data' => [ 'status' => 'COMPLETED', 'generated' => ['https://cdn.example.com/remix-video.mp4'], ], ], 200), 'https://cdn.example.com/remix-video.mp4' => Http::response('fake-video-binary', 200, [ 'Content-Type' => 'video/mp4', ]), ]); $service = app(FreepikAssetRemixService::class); $result = $service->remixVideo([ 'type' => 'image', 'url' => '/storage/social_assets/images/ref.jpg', ], 'Animasikan jadi story vertikal', 'mockup'); Http::assertSent(function ($request) { if ($request->url() !== 'https://api.freepik.com/v1/ai/image-to-video/runway-4-5') { return false; } $image = $request['image'] ?? null; return is_string($image) && str_starts_with($image, 'data:image/'); }); $relativePath = ltrim(str_replace('/storage/', '', $result['url']), '/'); $this->assertSame('freepik-runway-i2v', $result['provider']); $this->assertTrue(Storage::disk('public')->exists($relativePath)); $this->assertSame(5, $result['duration_seconds']); } }