analyzer = new FilenameAnalyzer(); } public function test_it_analyzes_one_piece_filename_correctly(): void { // Given $filename = 'one-piece_vol108_ch1094.cbz'; // When $result = $this->analyzer->analyze($filename); // Then $this->assertEquals('one-piece', $result->getTitle()->getValue()); $this->assertEquals(1094.0, $result->getChapterNumber()->getValue()); $this->assertEquals(108.0, $result->getVolumeNumber()->getValue()); $this->assertTrue($result->hasChapterNumber()); $this->assertTrue($result->hasVolumeNumber()); } public function test_it_handles_different_filename_formats(): void { $testCases = [ // Format underscore [ 'filename' => 'attack-on-titan_vol32_ch130.cbz', 'expectedTitle' => 'attack-on-titan', 'expectedChapter' => 130.0, 'expectedVolume' => 32.0, ], // Format avec espaces [ 'filename' => 'Dragon Ball vol 1 ch 5.cbz', 'expectedTitle' => 'Dragon Ball', 'expectedChapter' => 5.0, 'expectedVolume' => 1.0, ], // Format avec tirets [ 'filename' => 'my-hero-academia-vol15-ch150.cbr', 'expectedTitle' => 'my-hero-academia', 'expectedChapter' => 150.0, 'expectedVolume' => 15.0, ], // Format chapitre décimal [ 'filename' => 'naruto_vol50_ch456.5.cbz', 'expectedTitle' => 'naruto', 'expectedChapter' => 456.5, 'expectedVolume' => 50.0, ], ]; foreach ($testCases as $case) { $result = $this->analyzer->analyze($case['filename']); $this->assertEquals($case['expectedTitle'], $result->getTitle()->getValue(), "Failed for filename: {$case['filename']}"); $this->assertEquals($case['expectedChapter'], $result->getChapterNumber()->getValue(), "Failed chapter extraction for: {$case['filename']}"); $this->assertEquals($case['expectedVolume'], $result->getVolumeNumber()->getValue(), "Failed volume extraction for: {$case['filename']}"); } } public function test_it_extracts_and_cleans_title(): void { // Given $filename = 'one-piece_vol108_ch1094.cbz'; // When $result = $this->analyzer->analyze($filename); // Then - should extract and clean the title $this->assertEquals('one-piece', $result->getTitle()->getValue()); $this->assertNotEmpty($result->getTitle()->getValue(), 'Title should not be empty'); } public function test_it_handles_files_without_volume_or_chapter(): void { $testCases = [ [ 'filename' => 'one-piece.cbz', 'expectedTitle' => 'one-piece', ], [ 'filename' => 'manga_title_only.cbr', 'expectedTitle' => 'manga_title_only', ], ]; foreach ($testCases as $case) { $result = $this->analyzer->analyze($case['filename']); $this->assertEquals($case['expectedTitle'], $result->getTitle()->getValue()); $this->assertFalse($result->hasChapterNumber()); $this->assertFalse($result->hasVolumeNumber()); $this->assertNull($result->getChapterNumber()); $this->assertNull($result->getVolumeNumber()); } } public function test_it_handles_cbz_and_cbr_extensions(): void { // Given $testCases = [ ['filename' => 'one-piece.cbz', 'expectedTitle' => 'one-piece'], ['filename' => 'manga.cbr', 'expectedTitle' => 'manga'], ['filename' => 'test.CBZ', 'expectedTitle' => 'test'], ['filename' => 'test.CBR', 'expectedTitle' => 'test'], ]; foreach ($testCases as $case) { // When $result = $this->analyzer->analyze($case['filename']); // Then - L'extension est enlevée et le titre est extrait $this->assertEquals($case['expectedTitle'], $result->getTitle()->getValue()); } } public function test_it_cleans_common_patterns(): void { $testCases = [ [ 'filename' => 'one-piece-scan-fr_vol108_ch1094.cbz', 'cleanedTitle' => 'one-piece', ], [ 'filename' => 'manga-raw-jp_vol1_ch1.cbz', 'cleanedTitle' => 'manga', ], ]; foreach ($testCases as $case) { $result = $this->analyzer->analyze($case['filename']); $title = $result->getTitle()->getValue(); // Vérifie que le titre est nettoyé $this->assertEquals($case['cleanedTitle'], $title, "Title should be cleaned for {$case['filename']}"); // Vérifie que le titre nettoyé ne contient pas les mots indésirables $this->assertDoesNotMatchRegularExpression('/\b(?:scan|raw|fr|en|jp|hq|lq)\b/i', $title, "Cleaned title should not contain unwanted patterns for {$case['filename']}"); } } public function test_it_handles_filename_with_only_volume(): void { $testCases = [ [ 'filename' => 'one-piece_vol108.cbz', 'expectedTitle' => 'one-piece', 'expectedVolume' => 108.0, ], [ 'filename' => 'attack-on-titan vol 32.cbz', 'expectedTitle' => 'attack-on-titan', 'expectedVolume' => 32.0, ], [ 'filename' => 'naruto-tome-50.cbz', 'expectedTitle' => 'naruto', 'expectedVolume' => 50.0, ], [ 'filename' => 'bleach_t15.cbz', 'expectedTitle' => 'bleach', 'expectedVolume' => 15.0, ], ]; foreach ($testCases as $case) { $result = $this->analyzer->analyze($case['filename']); $this->assertEquals($case['expectedTitle'], $result->getTitle()->getValue(), "Failed title extraction for: {$case['filename']}"); $this->assertEquals($case['expectedVolume'], $result->getVolumeNumber()->getValue(), "Failed volume extraction for: {$case['filename']}"); $this->assertFalse($result->hasChapterNumber(), "Should not have chapter for: {$case['filename']}"); } } public function test_it_handles_filename_with_only_chapter(): void { $testCases = [ [ 'filename' => 'naruto_ch456.cbz', 'expectedTitle' => 'naruto', 'expectedChapter' => 456.0, ], [ 'filename' => 'my-hero-academia ch 150.cbz', 'expectedTitle' => 'my-hero-academia', 'expectedChapter' => 150.0, ], [ 'filename' => 'bleach-chap-200.cbz', 'expectedTitle' => 'bleach', 'expectedChapter' => 200.0, ], [ 'filename' => 'one-piece_chapter_1094.cbz', 'expectedTitle' => 'one-piece', 'expectedChapter' => 1094.0, ], ]; foreach ($testCases as $case) { $result = $this->analyzer->analyze($case['filename']); $this->assertEquals($case['expectedTitle'], $result->getTitle()->getValue(), "Failed title extraction for: {$case['filename']}"); $this->assertEquals($case['expectedChapter'], $result->getChapterNumber()->getValue(), "Failed chapter extraction for: {$case['filename']}"); $this->assertFalse($result->hasVolumeNumber(), "Should not have volume for: {$case['filename']}"); } } public function test_it_handles_full_dash_patterns(): void { $testCases = [ [ 'filename' => 'berserk-volume-42.cbz', 'expectedTitle' => 'berserk', 'expectedVolume' => 42.0, ], [ 'filename' => 'berserk-chapter-100.cbz', 'expectedTitle' => 'berserk', 'expectedChapter' => 100.0, ], [ 'filename' => 'berserk-chapitre-100.cbz', 'expectedTitle' => 'berserk', 'expectedChapter' => 100.0, ], [ 'filename' => 'berserk-volume-42-chapter-100.cbz', 'expectedTitle' => 'berserk', 'expectedVolume' => 42.0, 'expectedChapter' => 100.0, ], [ 'filename' => 'berserk-chapitre-100-volume-42.cbz', 'expectedTitle' => 'berserk', 'expectedVolume' => 42.0, 'expectedChapter' => 100.0, ], ]; foreach ($testCases as $case) { $result = $this->analyzer->analyze($case['filename']); $this->assertEquals($case['expectedTitle'], $result->getTitle()->getValue(), "Failed title extraction for: {$case['filename']}"); if (isset($case['expectedVolume'])) { $this->assertTrue($result->hasVolumeNumber(), "Should have volume for: {$case['filename']}"); $this->assertEquals($case['expectedVolume'], $result->getVolumeNumber()->getValue(), "Failed volume extraction for: {$case['filename']}"); } else { $this->assertFalse($result->hasVolumeNumber(), "Should not have volume for: {$case['filename']}"); } if (isset($case['expectedChapter'])) { $this->assertTrue($result->hasChapterNumber(), "Should have chapter for: {$case['filename']}"); $this->assertEquals($case['expectedChapter'], $result->getChapterNumber()->getValue(), "Failed chapter extraction for: {$case['filename']}"); } else { $this->assertFalse($result->hasChapterNumber(), "Should not have chapter for: {$case['filename']}"); } } } }