package playlist import "testing" func TestNextRepeatOff(t *testing.T) { p := makePlaylist(3, false) // A B C // Advance through all tracks track, ok := p.Next() if !ok || track.Title != "B" { t.Fatalf("Next() = (%q, %v), want (B, true)", track.Title, ok) } track, ok = p.Next() if !ok || track.Title != "C" { t.Fatalf("Next() = (%q, %v), want (C, true)", track.Title, ok) } // Past the end with RepeatOff _, ok = p.Next() if ok { t.Fatal("Next() past end should return false with RepeatOff") } } func TestNextRepeatAll(t *testing.T) { p := makePlaylist(3, false) // A B C p.SetRepeat(RepeatAll) // Advance to end p.Next() // B p.Next() // C // Should wrap around track, ok := p.Next() if !ok || track.Title != "A" { t.Fatalf("Next() wrap = (%q, %v), want (A, true)", track.Title, ok) } } func TestNextRepeatOne(t *testing.T) { p := makePlaylist(3, false) // A B C p.SetRepeat(RepeatOne) // Should repeat the same track track, ok := p.Next() if !ok || track.Title != "A" { t.Fatalf("Next() RepeatOne = (%q, %v), want (A, true)", track.Title, ok) } track, ok = p.Next() if !ok || track.Title != "A" { t.Fatalf("Next() RepeatOne again = (%q, %v), want (A, true)", track.Title, ok) } } func TestNextWithQueue(t *testing.T) { p := makePlaylist(4, false) // A B C D p.Queue(2) // Queue C p.Queue(3) // Queue D // Queue should be played first track, ok := p.Next() if !ok || track.Title != "C" { t.Fatalf("Next() from queue = (%q, %v), want (C, true)", track.Title, ok) } track, ok = p.Next() if !ok || track.Title != "D" { t.Fatalf("Next() from queue = (%q, %v), want (D, true)", track.Title, ok) } // Queue exhausted, resume normal order track, ok = p.Next() if !ok || track.Title != "B" { t.Fatalf("Next() after queue = (%q, %v), want (B, true)", track.Title, ok) } } func TestNextRepeatOneResumesOrderAfterQueuedTrack(t *testing.T) { p := makePlaylist(2, false) // A B p.SetRepeat(RepeatOne) p.Queue(1) track, ok := p.Next() if !ok || track.Title != "B" { t.Fatalf("Next() from queue = (%q, %v), want (B, true)", track.Title, ok) } track, ok = p.Next() if !ok || track.Title != "A" { t.Fatalf("Next() after queued repeat-one = (%q, %v), want (A, true)", track.Title, ok) } if current, idx := p.Current(); current.Title != "A" || idx != 0 { t.Fatalf("Current() = (%q, %d), want (A, 0)", current.Title, idx) } } func TestPrevBasic(t *testing.T) { p := makePlaylist(3, false) p.SetIndex(2) // C track, ok := p.Prev() if !ok || track.Title != "B" { t.Fatalf("Prev() = (%q, %v), want (B, true)", track.Title, ok) } track, ok = p.Prev() if !ok || track.Title != "A" { t.Fatalf("Prev() = (%q, %v), want (A, true)", track.Title, ok) } // At the beginning with RepeatOff _, ok = p.Prev() if ok { t.Fatal("Prev() at beginning should return false with RepeatOff") } } func TestPrevRepeatAll(t *testing.T) { p := makePlaylist(3, false) p.SetRepeat(RepeatAll) // At position 0, should wrap to end track, ok := p.Prev() if !ok || track.Title != "C" { t.Fatalf("Prev() wrap = (%q, %v), want (C, true)", track.Title, ok) } } func TestPeekNextBasic(t *testing.T) { p := makePlaylist(3, false) track, ok := p.PeekNext() if !ok || track.Title != "B" { t.Fatalf("PeekNext() = (%q, %v), want (B, true)", track.Title, ok) } // PeekNext should NOT advance the position cur, _ := p.Current() if cur.Title != "A" { t.Fatalf("Current after PeekNext = %q, want A", cur.Title) } } func TestPeekNextAtEnd(t *testing.T) { p := makePlaylist(3, false) p.SetIndex(2) // C // RepeatOff at end _, ok := p.PeekNext() if ok { t.Fatal("PeekNext() at end with RepeatOff should return false") } } func TestPeekNextRepeatAll(t *testing.T) { p := makePlaylist(3, false) p.SetRepeat(RepeatAll) p.SetIndex(2) // C track, ok := p.PeekNext() if !ok || track.Title != "A" { t.Fatalf("PeekNext() RepeatAll at end = (%q, %v), want (A, true)", track.Title, ok) } } func TestPeekNextRepeatOne(t *testing.T) { p := makePlaylist(3, false) p.SetRepeat(RepeatOne) p.SetIndex(1) // B track, ok := p.PeekNext() if !ok || track.Title != "B" { t.Fatalf("PeekNext() RepeatOne = (%q, %v), want (B, true)", track.Title, ok) } } func TestPeekNextWithQueue(t *testing.T) { p := makePlaylist(3, false) p.Queue(2) // Queue C track, ok := p.PeekNext() if !ok || track.Title != "C" { t.Fatalf("PeekNext() with queue = (%q, %v), want (C, true)", track.Title, ok) } } func TestPeekNextRepeatOneUsesOrderAfterQueuedTrack(t *testing.T) { p := makePlaylist(2, false) // A B p.SetRepeat(RepeatOne) p.Queue(1) if track, ok := p.Next(); !ok || track.Title != "B" { t.Fatalf("Next() from queue = (%q, %v), want (B, true)", track.Title, ok) } track, ok := p.PeekNext() if !ok || track.Title != "A" { t.Fatalf("PeekNext() after queued repeat-one = (%q, %v), want (A, true)", track.Title, ok) } } func TestCurrentEmpty(t *testing.T) { p := New() _, idx := p.Current() if idx != -1 { t.Fatalf("Current() on empty = %d, want -1", idx) } } func TestIndexEmpty(t *testing.T) { p := New() if idx := p.Index(); idx != -1 { t.Fatalf("Index() on empty = %d, want -1", idx) } } func TestNextEmpty(t *testing.T) { p := New() _, ok := p.Next() if ok { t.Fatal("Next() on empty should return false") } } func TestPrevEmpty(t *testing.T) { p := New() _, ok := p.Prev() if ok { t.Fatal("Prev() on empty should return false") } } func TestSetIndex(t *testing.T) { p := makePlaylist(5, false) p.SetIndex(3) // D cur, idx := p.Current() if idx != 3 || cur.Title != "D" { t.Fatalf("Current() = (%q, %d), want (D, 3)", cur.Title, idx) } } func TestReplace(t *testing.T) { p := makePlaylist(3, false) p.SetIndex(2) // Replace with new tracks newTracks := []Track{ {Title: "X"}, {Title: "Y"}, } p.Replace(newTracks) if p.Len() != 2 { t.Fatalf("Len() = %d, want 2", p.Len()) } cur, idx := p.Current() if idx != 0 || cur.Title != "X" { t.Fatalf("Current() = (%q, %d), want (X, 0)", cur.Title, idx) } }