Files
go-mxl-player/internal/playback/playlist_selection_test.go
2026-09-01 19:53:01 +03:00

190 lines
5.7 KiB
Go

package playback
import (
"errors"
"testing"
"time"
)
func TestApplyPlaylistSelectionFirstNext(t *testing.T) {
retry := validPlaylistRetryPolicy()
next, command, apply, err := ApplyPlaylistSelection(
navigationPlaylist(false),
PlaylistState{},
PlaylistCommand{Kind: PlaylistNext},
retry,
)
if err != nil {
t.Fatalf("ApplyPlaylistSelection() error = %v", err)
}
if !apply {
t.Fatal("ApplyPlaylistSelection() apply = false, want true")
}
wantState := PlaylistState{CurrentIndex: 0, HasSelection: true}
if next != wantState {
t.Fatalf("ApplyPlaylistSelection() state = %#v, want %#v", next, wantState)
}
wantCommand := SessionCommand{
Kind: CommandSetSession,
Session: SessionConfig{
Video: FeedConfig{Domain: "domain", UUID: "video-1", Active: true},
Retry: retry,
},
}
if command != wantCommand {
t.Fatalf("ApplyPlaylistSelection() command = %#v, want %#v", command, wantCommand)
}
}
func TestApplyPlaylistSelectionUsesCompleteEntrySession(t *testing.T) {
retry := validPlaylistRetryPolicy()
playlist := Playlist{Entries: []PlaylistEntry{
{
Video: PlaylistFeed{Domain: "video-domain", UUID: "video"},
Audio: PlaylistFeed{Domain: "audio-domain", UUID: "audio"},
SyncRequested: true,
},
{Video: PlaylistFeed{Domain: "next-domain", UUID: "next-video"}},
}}
_, command, apply, err := ApplyPlaylistSelection(
playlist,
PlaylistState{CurrentIndex: 1, HasSelection: true},
PlaylistCommand{Kind: PlaylistSelect, Index: 0},
retry,
)
if err != nil {
t.Fatalf("ApplyPlaylistSelection() error = %v", err)
}
if !apply {
t.Fatal("ApplyPlaylistSelection() apply = false, want true")
}
want := SessionConfig{
Video: FeedConfig{Domain: "video-domain", UUID: "video", Active: true},
Audio: FeedConfig{Domain: "audio-domain", UUID: "audio", Active: true},
SyncRequested: true,
Retry: retry,
}
if command.Kind != CommandSetSession || command.Session != want {
t.Fatalf("ApplyPlaylistSelection() command = %#v, want session %#v", command, want)
}
}
func TestApplyPlaylistSelectionVideoOnlyClearsAudio(t *testing.T) {
_, command, apply, err := ApplyPlaylistSelection(
navigationPlaylist(false),
PlaylistState{CurrentIndex: 1, HasSelection: true},
PlaylistCommand{Kind: PlaylistSelect, Index: 0},
validPlaylistRetryPolicy(),
)
if err != nil {
t.Fatalf("ApplyPlaylistSelection() error = %v", err)
}
if !apply {
t.Fatal("ApplyPlaylistSelection() apply = false, want true")
}
if command.Session.Audio != (FeedConfig{}) {
t.Fatalf("ApplyPlaylistSelection() audio = %#v, want zero value", command.Session.Audio)
}
}
func TestApplyPlaylistSelectionApplicationDecision(t *testing.T) {
tests := []struct {
name string
loop bool
current int
command PlaylistCommand
want int
apply bool
}{
{name: "reselect current", current: 1, command: PlaylistCommand{Kind: PlaylistSelect, Index: 1}, want: 1, apply: true},
{name: "move next", current: 1, command: PlaylistCommand{Kind: PlaylistNext}, want: 2, apply: true},
{name: "next stops at end", current: 2, command: PlaylistCommand{Kind: PlaylistNext}, want: 2},
{name: "previous stops at beginning", current: 0, command: PlaylistCommand{Kind: PlaylistPrevious}, want: 0},
{name: "next wraps", loop: true, current: 2, command: PlaylistCommand{Kind: PlaylistNext}, want: 0, apply: true},
{name: "previous wraps", loop: true, current: 0, command: PlaylistCommand{Kind: PlaylistPrevious}, want: 2, apply: true},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
next, command, apply, err := ApplyPlaylistSelection(
navigationPlaylist(test.loop),
PlaylistState{CurrentIndex: test.current, HasSelection: true},
test.command,
validPlaylistRetryPolicy(),
)
if err != nil {
t.Fatalf("ApplyPlaylistSelection() error = %v", err)
}
wantState := PlaylistState{CurrentIndex: test.want, HasSelection: true}
if next != wantState {
t.Fatalf("ApplyPlaylistSelection() state = %#v, want %#v", next, wantState)
}
if apply != test.apply {
t.Fatalf("ApplyPlaylistSelection() apply = %v, want %v", apply, test.apply)
}
if apply && command.Kind != CommandSetSession {
t.Fatalf("ApplyPlaylistSelection() command kind = %v, want %v", command.Kind, CommandSetSession)
}
if !apply && command != (SessionCommand{}) {
t.Fatalf("ApplyPlaylistSelection() command = %#v, want zero value", command)
}
})
}
}
func TestApplyPlaylistSelectionErrorsDoNotApply(t *testing.T) {
current := PlaylistState{CurrentIndex: 1, HasSelection: true}
tests := []struct {
name string
command PlaylistCommand
retry RetryPolicy
wantErr error
}{
{
name: "invalid command",
command: PlaylistCommand{},
retry: validPlaylistRetryPolicy(),
wantErr: ErrUnknownPlaylistCommand,
},
{
name: "invalid retry",
command: PlaylistCommand{Kind: PlaylistNext},
retry: RetryPolicy{},
wantErr: ErrInvalidRetryDelay,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
next, command, apply, err := ApplyPlaylistSelection(
navigationPlaylist(false),
current,
test.command,
test.retry,
)
if !errors.Is(err, test.wantErr) {
t.Fatalf("ApplyPlaylistSelection() error = %v, want %v", err, test.wantErr)
}
if next != current {
t.Fatalf("ApplyPlaylistSelection() state = %#v, want unchanged %#v", next, current)
}
if apply {
t.Fatal("ApplyPlaylistSelection() apply = true, want false")
}
if command != (SessionCommand{}) {
t.Fatalf("ApplyPlaylistSelection() command = %#v, want zero value", command)
}
})
}
}
func validPlaylistRetryPolicy() RetryPolicy {
return RetryPolicy{
MaxAttempts: 3,
InitialDelay: time.Millisecond,
MaxDelay: time.Second,
}
}