From 437b7c55acac57bbb315a4e48d60ca4c9b416adc Mon Sep 17 00:00:00 2001 From: Aleksey Filippov Date: Thu, 19 Feb 2026 19:38:42 +0300 Subject: [PATCH] =?utf8?q?auto-claude:=20subtask-1-1=20-=20=D0=A1=D0=BE?= =?utf8?q?=D0=B7=D0=B4=D0=B0=D1=82=D1=8C=20FileServiceVideoTest.php=20?= =?utf8?q?=D1=81=20=D1=82=D0=B5=D1=81=D1=82=D0=B0=D0=BC=D0=B8=20=D0=B4?= =?utf8?q?=D0=BB=D1=8F=20convertToMp4()?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit TDD RED phase: тесты написаны ДО реализации метода convertToMp4(). Добавлены тесты: - testConvertToMp4MethodExists: проверка наличия метода - testConvertToMp4MethodSignature: проверка сигнатуры метода - testConvertToMp4ChecksFfmpegAvailability: проверка FFmpeg через which - testConvertToMp4UsesEscapeshellarg: проверка безопасности shell-команд - testConvertToMp4UsesFfmpegOverwriteFlag: проверка флага -y - testConvertToMp4UsesFaststartFlag: проверка movflags +faststart - testConvertToMp4LogsWhenFfmpegNotInstalled: проверка логирования - testAviFileTypeIsVideo: проверка типа AVI файлов - testSaveUploadedFileAutoConvertsMovAvi: проверка авто-конвертации - testOriginalFileDeletedOnlyAfterSuccessfulConversion: проверка удаления - testConvertToMp4UsesH264Codec: проверка h264 кодека - testConvertToMp4UsesAacCodec: проверка aac кодека Co-Authored-By: Claude Opus 4.5 --- .../unit/services/FileServiceVideoTest.php | 311 ++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 erp24/tests/unit/services/FileServiceVideoTest.php diff --git a/erp24/tests/unit/services/FileServiceVideoTest.php b/erp24/tests/unit/services/FileServiceVideoTest.php new file mode 100644 index 00000000..67e78794 --- /dev/null +++ b/erp24/tests/unit/services/FileServiceVideoTest.php @@ -0,0 +1,311 @@ +fileServicePath = dirname(__DIR__, 3) . '/services/FileService.php'; + } + + /** + * Проверяет наличие метода convertToMp4 в FileService + * + * TDD RED: Этот тест должен ПРОВАЛИТЬСЯ пока метод не реализован. + */ + public function testConvertToMp4MethodExists(): void + { + if (!file_exists($this->fileServicePath)) { + $this->markTestSkipped('FileService.php not found'); + } + + $content = file_get_contents($this->fileServicePath); + + // Проверяем наличие метода convertToMp4 + $hasMethod = preg_match( + '/public\s+static\s+function\s+convertToMp4\s*\(/s', + $content + ); + + $this->assertEquals( + 1, + $hasMethod, + 'FileService should have public static method convertToMp4()' + ); + } + + /** + * Проверяет сигнатуру метода convertToMp4 + * + * Ожидаемая сигнатура: + * public static function convertToMp4(string $sourcePath, string $targetPath): ?string + */ + public function testConvertToMp4MethodSignature(): void + { + if (!file_exists($this->fileServicePath)) { + $this->markTestSkipped('FileService.php not found'); + } + + $content = file_get_contents($this->fileServicePath); + + // Проверяем сигнатуру метода с типами параметров и возвращаемым типом + $hasCorrectSignature = preg_match( + '/public\s+static\s+function\s+convertToMp4\s*\(\s*string\s+\$\w+\s*,\s*string\s+\$\w+\s*\)\s*:\s*\?string/s', + $content + ); + + $this->assertEquals( + 1, + $hasCorrectSignature, + 'convertToMp4 should have signature: (string $sourcePath, string $targetPath): ?string' + ); + } + + /** + * Проверяет что convertToMp4 проверяет наличие FFmpeg + * + * Метод должен использовать `which ffmpeg` для проверки. + */ + public function testConvertToMp4ChecksFfmpegAvailability(): void + { + if (!file_exists($this->fileServicePath)) { + $this->markTestSkipped('FileService.php not found'); + } + + $content = file_get_contents($this->fileServicePath); + + // Проверяем что метод проверяет наличие FFmpeg + $this->assertStringContainsString( + 'which ffmpeg', + $content, + 'convertToMp4 should check FFmpeg availability using "which ffmpeg"' + ); + } + + /** + * Проверяет что convertToMp4 использует escapeshellarg для безопасности + */ + public function testConvertToMp4UsesEscapeshellarg(): void + { + if (!file_exists($this->fileServicePath)) { + $this->markTestSkipped('FileService.php not found'); + } + + $content = file_get_contents($this->fileServicePath); + + // Проверяем использование escapeshellarg для безопасности shell-команд + $this->assertStringContainsString( + 'escapeshellarg', + $content, + 'convertToMp4 should use escapeshellarg() for security' + ); + } + + /** + * Проверяет что convertToMp4 использует флаг -y для перезаписи + */ + public function testConvertToMp4UsesFfmpegOverwriteFlag(): void + { + if (!file_exists($this->fileServicePath)) { + $this->markTestSkipped('FileService.php not found'); + } + + $content = file_get_contents($this->fileServicePath); + + // Проверяем использование флага -y для перезаписи без подтверждения + $hasFfmpegCommand = preg_match( + '/ffmpeg\s+-y\s+-i/s', + $content + ); + + $this->assertEquals( + 1, + $hasFfmpegCommand, + 'convertToMp4 should use ffmpeg -y flag for overwrite without confirmation' + ); + } + + /** + * Проверяет что convertToMp4 использует movflags для быстрого старта + */ + public function testConvertToMp4UsesFaststartFlag(): void + { + if (!file_exists($this->fileServicePath)) { + $this->markTestSkipped('FileService.php not found'); + } + + $content = file_get_contents($this->fileServicePath); + + // Проверяем использование -movflags +faststart для быстрого старта воспроизведения + $this->assertStringContainsString( + 'faststart', + $content, + 'convertToMp4 should use -movflags +faststart for quick playback start' + ); + } + + /** + * Проверяет что convertToMp4 логирует при отсутствии FFmpeg + */ + public function testConvertToMp4LogsWhenFfmpegNotInstalled(): void + { + if (!file_exists($this->fileServicePath)) { + $this->markTestSkipped('FileService.php not found'); + } + + $content = file_get_contents($this->fileServicePath); + + // Проверяем что есть логирование при отсутствии FFmpeg + $hasWarningLog = preg_match( + '/Yii::warning\s*\([^)]*FFmpeg[^)]*\)/si', + $content + ); + + $this->assertEquals( + 1, + $hasWarningLog, + 'convertToMp4 should log warning when FFmpeg is not installed' + ); + } + + /** + * Проверяет что AVI файлы определяются как video тип + * + * TDD RED: AVI должен быть добавлен в switch-case. + */ + public function testAviFileTypeIsVideo(): void + { + if (!file_exists($this->fileServicePath)) { + $this->markTestSkipped('FileService.php not found'); + } + + $content = file_get_contents($this->fileServicePath); + + // Проверяем наличие avi в типах + $this->assertStringContainsString( + "'avi'", + $content, + 'FileService should support .avi file type' + ); + + // Проверяем, что avi определяется как video + // Паттерн: case 'avi': ... $type = 'video' + $hasAviAsVideo = preg_match( + "/case\s+'avi'.*?'video'/s", + $content + ); + + $this->assertEquals( + 1, + $hasAviAsVideo, + '.avi files should be classified as video type' + ); + } + + /** + * Проверяет авто-конвертацию MOV/AVI после saveAs + */ + public function testSaveUploadedFileAutoConvertsMovAvi(): void + { + if (!file_exists($this->fileServicePath)) { + $this->markTestSkipped('FileService.php not found'); + } + + $content = file_get_contents($this->fileServicePath); + + // Проверяем что saveUploadedFile вызывает convertToMp4 для mov/avi + $hasAutoConvert = preg_match( + "/in_array\s*\([^)]*\['mov',\s*'avi'\]|in_array\s*\([^)]*\['avi',\s*'mov'\]/s", + $content + ); + + $this->assertEquals( + 1, + $hasAutoConvert, + 'saveUploadedFile should auto-convert mov/avi files using convertToMp4' + ); + } + + /** + * Проверяет что оригинальный файл удаляется только после успешной конвертации + */ + public function testOriginalFileDeletedOnlyAfterSuccessfulConversion(): void + { + if (!file_exists($this->fileServicePath)) { + $this->markTestSkipped('FileService.php not found'); + } + + $content = file_get_contents($this->fileServicePath); + + // Проверяем паттерн: if ($converted !== null) { @unlink(...) } + // Это означает что удаление происходит только при успешной конвертации + $hasCorrectDeleteLogic = preg_match( + '/if\s*\(\s*\$\w+\s*!==\s*null\s*\)\s*\{[^}]*@?unlink/s', + $content + ); + + $this->assertEquals( + 1, + $hasCorrectDeleteLogic, + 'Original file should only be deleted after successful conversion (when result !== null)' + ); + } + + /** + * Проверяет что convertToMp4 использует h264 видеокодек + */ + public function testConvertToMp4UsesH264Codec(): void + { + if (!file_exists($this->fileServicePath)) { + $this->markTestSkipped('FileService.php not found'); + } + + $content = file_get_contents($this->fileServicePath); + + // Проверяем использование h264 кодека + $this->assertStringContainsString( + 'h264', + $content, + 'convertToMp4 should use h264 video codec for browser compatibility' + ); + } + + /** + * Проверяет что convertToMp4 использует aac аудиокодек + */ + public function testConvertToMp4UsesAacCodec(): void + { + if (!file_exists($this->fileServicePath)) { + $this->markTestSkipped('FileService.php not found'); + } + + $content = file_get_contents($this->fileServicePath); + + // Проверяем использование aac кодека + $this->assertStringContainsString( + 'aac', + $content, + 'convertToMp4 should use aac audio codec for browser compatibility' + ); + } +} -- 2.39.5