package playlist import "testing" func TestToggleShuffle(t *testing.T) { p := makePlaylist(5, false) p.SetIndex(2) // C if p.Shuffled() { t.Fatal("Shuffled() initially should be false") } p.ToggleShuffle() if !p.Shuffled() { t.Fatal("Shuffled() after toggle should be true") } cur, _ := p.Current() if cur.Title != "C" { t.Fatalf("Current after shuffle = %q, want C", cur.Title) } } func TestToggleShuffleOff(t *testing.T) { p := makePlaylist(5, true) // start shuffled curTrack, _ := p.Current() p.ToggleShuffle() // turn off if p.Shuffled() { t.Fatal("Shuffled() after toggle off should be false") } // Current track should be preserved cur2, _ := p.Current() if cur2.Title != curTrack.Title { t.Fatalf("Current after unshuffle = %q, want %q", cur2.Title, curTrack.Title) } // Playback should follow sequential order from current track onward for i := range 4 { next, ok := p.Next() if !ok { t.Fatalf("Next() returned false at step %d", i) } _ = next // just verify it advances without error } } func TestToggleShuffleEmpty(t *testing.T) { p := New() p.ToggleShuffle() // should not panic if !p.Shuffled() { t.Fatal("Shuffled() should be true even when empty") } } func TestCycleRepeat(t *testing.T) { p := New() if p.Repeat() != RepeatOff { t.Fatalf("initial repeat = %v, want Off", p.Repeat()) } p.CycleRepeat() if p.Repeat() != RepeatAll { t.Fatalf("after 1 cycle = %v, want All", p.Repeat()) } p.CycleRepeat() if p.Repeat() != RepeatOne { t.Fatalf("after 2 cycles = %v, want One", p.Repeat()) } p.CycleRepeat() if p.Repeat() != RepeatOff { t.Fatalf("after 3 cycles = %v, want Off", p.Repeat()) } } func TestSetRepeat(t *testing.T) { p := New() p.SetRepeat(RepeatOne) if p.Repeat() != RepeatOne { t.Fatalf("Repeat() = %v, want One", p.Repeat()) } p.SetRepeat(RepeatAll) if p.Repeat() != RepeatAll { t.Fatalf("Repeat() = %v, want All", p.Repeat()) } } func TestShufflePreservesAllTracks(t *testing.T) { p := makePlaylist(10, false) p.SetRepeat(RepeatAll) p.ToggleShuffle() // Walk through all tracks via Next() and verify each title appears exactly once seen := make(map[string]bool) cur, _ := p.Current() seen[cur.Title] = true for i := range 9 { next, ok := p.Next() if !ok { t.Fatalf("Next() returned false at step %d", i) } if seen[next.Title] { t.Fatalf("duplicate track %q at step %d", next.Title, i) } seen[next.Title] = true } if len(seen) != 10 { t.Fatalf("saw %d unique tracks, want 10", len(seen)) } } func TestSetTrack(t *testing.T) { p := makePlaylist(3, false) p.SetTrack(1, Track{Title: "NEW"}) tracks := p.Tracks() if tracks[1].Title != "NEW" { t.Fatalf("tracks[1].Title = %q, want NEW", tracks[1].Title) } } func TestSetTrackOutOfBounds(t *testing.T) { p := makePlaylist(3, false) // Should be no-op, not panic p.SetTrack(-1, Track{Title: "X"}) p.SetTrack(5, Track{Title: "X"}) if p.Tracks()[0].Title != "A" { t.Fatal("tracks were modified by out-of-bounds SetTrack") } } func TestToggleBookmark(t *testing.T) { p := makePlaylist(3, false) p.ToggleBookmark(0) if !p.Tracks()[0].Bookmark { t.Fatal("track 0 should be bookmarked") } if p.BookmarkCount() != 1 { t.Fatalf("BookmarkCount() = %d, want 1", p.BookmarkCount()) } p.ToggleBookmark(0) // toggle off if p.Tracks()[0].Bookmark { t.Fatal("track 0 should be unbookmarked") } if p.BookmarkCount() != 0 { t.Fatalf("BookmarkCount() = %d, want 0", p.BookmarkCount()) } } func TestToggleBookmarkOutOfBounds(t *testing.T) { p := makePlaylist(3, false) // Should be no-op, not panic p.ToggleBookmark(-1) p.ToggleBookmark(5) if p.BookmarkCount() != 0 { t.Fatal("bookmarks were modified by out-of-bounds ToggleBookmark") } } func TestBookmarkCount(t *testing.T) { p := makePlaylist(5, false) p.ToggleBookmark(0) p.ToggleBookmark(2) p.ToggleBookmark(4) if got := p.BookmarkCount(); got != 3 { t.Fatalf("BookmarkCount() = %d, want 3", got) } }