Http::response( $this->fixture('vk/video_ext_success.html'), 200, ['Content-Type' => 'text/html; charset=windows-1251'], ), ]); $strategy = new VideoExtStrategy($this->app->make(HttpClient::class)); $info = $strategy->extract($this->ref()); self::assertSame('-18403220_456239696', $info->id); self::assertSame('Trump cancels grants // DeepSeek revolution', $info->title); self::assertSame(1983, $info->duration); self::assertSame(1738252883, $info->timestamp); self::assertSame(699108, $info->viewCount); self::assertSame(4320, $info->likeCount); self::assertSame(213, $info->commentCount); self::assertSame('Ruslan Usachev', $info->uploader); // Thumbnails: multiple resolutions; best should be 1920x1080. self::assertNotEmpty($info->thumbnails); self::assertSame(1920, $info->bestThumbnail()?->width); self::assertStringContainsString('video_thumb', (string) $info->thumbnailUrl()); } public function test_video_ext_strategy_extracts_only_thumbnail(): void { Http::fake([ 'vk.com/video_ext.php*' => Http::response( $this->fixture('vk/video_ext_success.html'), 200, ['Content-Type' => 'text/html; charset=windows-1251'], ), ]); $strategy = new VideoExtStrategy($this->app->make(HttpClient::class)); $url = $strategy->extractThumbnail($this->ref()); self::assertNotNull($url); self::assertStringContainsString('video_thumb', $url); } public function test_video_ext_strategy_extracts_formats_with_expiry(): void { Http::fake([ 'vk.com/video_ext.php*' => Http::response( $this->fixture('vk/video_ext_success.html'), 200, ['Content-Type' => 'text/html; charset=windows-1251'], ), ]); $strategy = new VideoExtStrategy($this->app->make(HttpClient::class)); $info = $strategy->extract($this->ref()); // 6 mp4 heights + hls + dash_sep = 8 formats. self::assertCount(8, $info->formats); $mp41080 = null; foreach ($info->formats as $format) { if ($format->formatId === 'mp4_1080') { $mp41080 = $format; } } self::assertNotNull($mp41080); self::assertSame(1080, $mp41080->height); // expires=1784467826444 is milliseconds -> 1784467826 seconds. self::assertSame(1784467826, $mp41080->expiresAt); } public function test_video_ext_strategy_throws_when_video_not_found(): void { Http::fake([ 'vk.com/video_ext.php*' => Http::response( $this->fixture('vk/video_ext_not_found.html'), 200, ['Content-Type' => 'text/html; charset=windows-1251'], ), ]); $strategy = new VideoExtStrategy($this->app->make(HttpClient::class)); $this->expectException(VideoNotFoundException::class); $strategy->extract($this->ref()); } public function test_al_video_strategy_extracts_info(): void { Http::fake([ 'vk.com/al_video.php' => Http::response( $this->fixture('vk/al_video_success.json'), 200, ['Content-Type' => 'application/json; charset=windows-1251'], ), ]); $strategy = new AlVideoStrategy($this->app->make(HttpClient::class)); $info = $strategy->extract($this->ref()); self::assertSame('Trump cancels grants // DeepSeek revolution', $info->title); self::assertSame(1983, $info->duration); self::assertSame('Ruslan Usachev', $info->uploader); self::assertSame(4320, $info->likeCount); self::assertSame(213, $info->commentCount); // AlVideo returns a single jpg thumbnail. self::assertCount(1, $info->thumbnails); self::assertStringContainsString('800x450', (string) $info->thumbnailUrl()); } public function test_al_video_strategy_throws_for_deleted_video(): void { Http::fake([ 'vk.com/al_video.php' => Http::response( $this->fixture('vk/al_video_deleted.json'), 200, ['Content-Type' => 'application/json; charset=windows-1251'], ), ]); $strategy = new AlVideoStrategy($this->app->make(HttpClient::class)); $this->expectException(VideoNotFoundException::class); $this->expectExceptionMessage('Video has been deleted'); $strategy->extract($this->ref()); } }