package scanner import ( "testing" "naviwatcher/internal/database" "naviwatcher/internal/musicbrainz" ) func TestTypeFilterSuppressedMatchesMusicbrainzFilter(t *testing.T) { // Test cases covering various combinations of types and secondary types testCases := []struct { name string releaseType string secondaryTypes []string ignoreSingles bool ignoreCompilations bool expectedSuppressed bool }{ // Single type tests {"Single primary type", "Single", []string{}, true, false, true}, {"Single primary type with EP ignore", "Single", []string{}, false, true, false}, // EP as primary type (should be treated as Single when IgnoreSingles=true) {"EP primary type", "EP", []string{}, true, false, true}, {"EP primary type with EP ignore", "EP", []string{}, false, true, false}, // Album type tests {"Album primary type", "Album", []string{}, true, false, false}, {"Album primary type with Compilation ignore", "Album", []string{}, false, true, false}, // Compilation type tests {"Compilation primary type", "Compilation", []string{}, true, false, false}, {"Compilation primary type with Compilation ignore", "Compilation", []string{}, false, true, true}, // Secondary types - Single {"Album with Single secondary", "Album", []string{"Single"}, true, false, true}, {"Album with Single secondary (no ignore)", "Album", []string{"Single"}, false, false, false}, {"EP with Single secondary", "EP", []string{"Single"}, true, false, true}, // Secondary types - EP (should trigger Single ignore) {"Album with EP secondary", "Album", []string{"EP"}, true, false, true}, {"Album with EP secondary (no ignore)", "Album", []string{"EP"}, false, false, false}, // Secondary types - Compilation {"Album with Compilation secondary", "Album", []string{"Compilation"}, true, false, false}, {"Album with Compilation secondary (with ignore)", "Album", []string{"Compilation"}, false, true, true}, // Multiple secondary types {"Album with Single and EP secondary", "Album", []string{"Single", "EP"}, true, false, true}, {"Album with Compilation secondary", "Album", []string{"Compilation"}, false, true, true}, {"Album with multiple secondary types", "Album", []string{"Single", "Compilation"}, true, true, true}, // Edge cases {"Empty types", "", []string{}, false, false, false}, {"Unknown type", "Live", []string{}, false, false, false}, } for _, tc := range testCases { tc := tc // capture range variable t.Run(tc.name, func(t *testing.T) { // Create test release release := database.ExternalRelease{ Type: tc.releaseType, SecondaryTypes: tc.secondaryTypes, } // Test scanner filter scannerFilter := TypeFilter{ IgnoreSingles: tc.ignoreSingles, IgnoreCompilations: tc.ignoreCompilations, } scannerSuppressed := scannerFilter.suppressed(release) // Test musicbrainz filter mbFilter := musicbrainz.FilterOptions{ IgnoreSingles: tc.ignoreSingles, IgnoreCompilations: tc.ignoreCompilations, } mbFiltered := musicbrainz.ApplyTypeToggles([]database.ExternalRelease{release}, mbFilter) mbSuppressed := len(mbFiltered) == 0 // Both should agree if scannerSuppressed != mbSuppressed { t.Errorf("Scanner and MusicBrainz filter disagree for %v: scanner=%v, musicbrainz=%v", tc, scannerSuppressed, mbSuppressed) } // Check against expected value if scannerSuppressed != tc.expectedSuppressed { t.Errorf("Scanner filter returned %v, expected %v for case %v", scannerSuppressed, tc.expectedSuppressed, tc.name) } }) } } // Test that verifies the specific case mentioned in the issue: EP in SecondaryTypes counts as Single func TestTypeFilterTreatsEPAsSingleWhenIgnoreSingles(t *testing.T) { testCases := []struct { name string releaseType string secondaryTypes []string ignoreSingles bool ignoreCompilations bool expectedSuppressed bool }{ {"Album with EP secondary - should be suppressed when IgnoreSingles=true", "Album", []string{"EP"}, true, false, true}, {"Album with EP secondary - should NOT be suppressed when IgnoreSingles=false", "Album", []string{"EP"}, false, false, false}, {"Single with EP secondary - should be suppressed when IgnoreSingles=true", "Single", []string{"EP"}, true, false, true}, {"Compilation with EP secondary - should be suppressed when IgnoreSingles=true (because EP in secondary counts as Single)", "Compilation", []string{"EP"}, true, false, true}, } for _, tc := range testCases { tc := tc // capture range variable t.Run(tc.name, func(t *testing.T) { // Create test release release := database.ExternalRelease{ Type: tc.releaseType, SecondaryTypes: tc.secondaryTypes, } // Test scanner filter scannerFilter := TypeFilter{ IgnoreSingles: tc.ignoreSingles, IgnoreCompilations: tc.ignoreCompilations, } scannerSuppressed := scannerFilter.suppressed(release) // Test musicbrainz filter mbFilter := musicbrainz.FilterOptions{ IgnoreSingles: tc.ignoreSingles, IgnoreCompilations: tc.ignoreCompilations, } mbFiltered := musicbrainz.ApplyTypeToggles([]database.ExternalRelease{release}, mbFilter) mbSuppressed := len(mbFiltered) == 0 // Both should agree and match expected if scannerSuppressed != mbSuppressed { t.Errorf("Scanner and MusicBrainz filter disagree for %v: scanner=%v, musicbrainz=%v", tc, scannerSuppressed, mbSuppressed) } if scannerSuppressed != tc.expectedSuppressed { t.Errorf("Filter returned %v, expected %v for case %v", scannerSuppressed, tc.expectedSuppressed, tc.name) } }) } }