133 lines
4.8 KiB
PHP
133 lines
4.8 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Apoloz\VideoExtractor\Tests\Feature;
|
|
|
|
use Apoloz\VideoExtractor\Dto\VideoRef;
|
|
use Apoloz\VideoExtractor\Exceptions\LoginRequiredException;
|
|
use Apoloz\VideoExtractor\Exceptions\VideoNotFoundException;
|
|
use Apoloz\VideoExtractor\Http\HttpClient;
|
|
use Apoloz\VideoExtractor\Platform\Platform;
|
|
use Apoloz\VideoExtractor\Strategies\OkRu\OkRuStrategy;
|
|
use Apoloz\VideoExtractor\Tests\TestCase;
|
|
use Illuminate\Support\Facades\Http;
|
|
|
|
class OkRuExtractionTest extends TestCase
|
|
{
|
|
private function ref(): VideoRef
|
|
{
|
|
return new VideoRef(platform: Platform::OK, id: '15019292494547');
|
|
}
|
|
|
|
public function test_extracts_full_info_from_data_options(): void
|
|
{
|
|
Http::fake([
|
|
'ok.ru/video/*' => Http::response($this->fixture('ok/video_success.html'), 200),
|
|
]);
|
|
|
|
$strategy = new OkRuStrategy($this->app->make(HttpClient::class));
|
|
$info = $strategy->extract($this->ref());
|
|
|
|
self::assertSame('15019292494547', $info->id);
|
|
self::assertSame('Falcon mystery in the hood', $info->title);
|
|
self::assertSame('A radical shift of optics.', $info->description);
|
|
self::assertSame(709, $info->duration);
|
|
self::assertSame('Egor Akimov', $info->uploader);
|
|
self::assertSame(45, $info->likeCount);
|
|
self::assertSame(3419, $info->viewCount);
|
|
self::assertSame(0, $info->ageLimit);
|
|
self::assertFalse($info->isLive);
|
|
self::assertSame(strtotime('2026-07-01T19:28:15+03:00'), $info->timestamp);
|
|
|
|
// Thumbnail from movie.poster with OG dimensions.
|
|
self::assertNotEmpty($info->thumbnails);
|
|
self::assertSame(720, $info->bestThumbnail()?->width);
|
|
self::assertStringContainsString('iv.okcdn.ru', (string) $info->thumbnailUrl());
|
|
|
|
// 6 mp4 + 1 hls = 7 formats.
|
|
self::assertCount(7, $info->formats);
|
|
|
|
$full = null;
|
|
foreach ($info->formats as $format) {
|
|
if ($format->formatId === 'full') {
|
|
$full = $format;
|
|
}
|
|
}
|
|
self::assertNotNull($full);
|
|
self::assertSame(1080, $full->height);
|
|
// expires=1784298004897 ms -> 1784298004 seconds.
|
|
self::assertSame(1784298004, $full->expiresAt);
|
|
self::assertSame(1784298004, $info->formatExpiresAt);
|
|
}
|
|
|
|
public function test_thumbnail_fast_path_uses_poster(): void
|
|
{
|
|
Http::fakeSequence()->push($this->fixture('ok/video_success.html'), 200);
|
|
|
|
$strategy = new OkRuStrategy($this->app->make(HttpClient::class));
|
|
$url = $strategy->extractThumbnail($this->ref());
|
|
|
|
self::assertNotNull($url);
|
|
self::assertStringContainsString('iv.okcdn.ru', $url);
|
|
}
|
|
|
|
public function test_falls_back_to_og_meta_when_no_data_options(): void
|
|
{
|
|
// Page without the inline player payload (external/restricted video).
|
|
Http::fake([
|
|
'ok.ru/video/*' => Http::response($this->fixture('ok/video_meta_only.html'), 200),
|
|
]);
|
|
|
|
$strategy = new OkRuStrategy($this->app->make(HttpClient::class));
|
|
$info = $strategy->extract($this->ref());
|
|
|
|
self::assertSame('External embed video', $info->title);
|
|
self::assertSame('Some Channel', $info->uploader);
|
|
self::assertSame(1529, $info->duration);
|
|
self::assertSame(12345, $info->viewCount);
|
|
// No formats available from the OG fallback.
|
|
self::assertSame([], $info->formats);
|
|
// Thumbnail still recovered from og:image.
|
|
self::assertStringContainsString('EXTERNAL', (string) $info->thumbnailUrl());
|
|
}
|
|
|
|
public function test_thumbnail_falls_back_to_og_image(): void
|
|
{
|
|
Http::fakeSequence()->push($this->fixture('ok/video_meta_only.html'), 200);
|
|
|
|
$strategy = new OkRuStrategy($this->app->make(HttpClient::class));
|
|
$url = $strategy->extractThumbnail($this->ref());
|
|
|
|
self::assertSame('https://iv.okcdn.ru/i?r=EXTERNAL&fn=external_8', $url);
|
|
}
|
|
|
|
public function test_throws_not_found_for_stub_error(): void
|
|
{
|
|
Http::fake([
|
|
'ok.ru/video/*' => Http::response($this->fixture('ok/video_not_found.html'), 200),
|
|
]);
|
|
|
|
$strategy = new OkRuStrategy($this->app->make(HttpClient::class));
|
|
|
|
$this->expectException(VideoNotFoundException::class);
|
|
$this->expectExceptionMessage('author of this video has not been found');
|
|
$strategy->extract($this->ref());
|
|
}
|
|
|
|
public function test_throws_login_required_for_restricted_video(): void
|
|
{
|
|
Http::fake([
|
|
'ok.ru/video/*' => Http::response(
|
|
'<html><body><div>Access to this video is restricted</div></body></html>',
|
|
200,
|
|
),
|
|
]);
|
|
|
|
$strategy = new OkRuStrategy($this->app->make(HttpClient::class));
|
|
|
|
$this->expectException(LoginRequiredException::class);
|
|
$strategy->extract($this->ref());
|
|
}
|
|
}
|