package server import ( "encoding/json" "net/http" "testing" "music-server/internal/backend" "music-server/internal/db" "music-server/internal/db/repository" "github.com/labstack/echo/v5" "github.com/stretchr/testify/assert" ) // ensureSyncRan ensures that sync has been run before testing music endpoints func ensureSyncRan(t *testing.T, e *echo.Echo) { repo := repository.New(backend.BackendPool()) games, err := repo.FindAllGames(backend.BackendCtx()) assert.NoError(t, err) if len(games) == 0 { // Run sync t.Log("No games found, running sync first...") resp := MakeTestRequest(t, e, "GET", "/sync/full") assert.Equal(t, http.StatusOK, resp.Code) // Wait for sync to complete using shared helper if !waitForSyncCompletion(t, e, 60) { t.Error("Sync did not complete within timeout") } } } // TestGetAllGames verifies the /music/all/order endpoint func TestZGetAllGames(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Ensure sync has run ensureSyncRan(t, e) resp := MakeTestRequest(t, e, "GET", "/music/all/order") assert.Equal(t, http.StatusOK, resp.Code) var games []string err := json.Unmarshal(resp.Body.Bytes(), &games) assert.NoError(t, err) assert.NotEmpty(t, games, "Should have games after sync") t.Logf("Found %d games", len(games)) } // TestGetAllGamesRandom verifies the /music/all/random endpoint func TestZGetAllGamesRandom(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Ensure sync has run ensureSyncRan(t, e) resp := MakeTestRequest(t, e, "GET", "/music/all/random") assert.Equal(t, http.StatusOK, resp.Code) var games []string err := json.Unmarshal(resp.Body.Bytes(), &games) assert.NoError(t, err) assert.NotEmpty(t, games, "Should have games after sync") // Verify it's shuffled (not in original order) // We can't easily verify randomness, but we can check it's the same length resp2 := MakeTestRequest(t, e, "GET", "/music/all/order") var gamesOrdered []string json.Unmarshal(resp2.Body.Bytes(), &gamesOrdered) assert.Equal(t, len(games), len(gamesOrdered), "Random and ordered should have same count") } // TestGetRandomSong verifies the /music/rand endpoint func TestZGetRandomSong(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Ensure sync has run ensureSyncRan(t, e) resp := MakeTestRequest(t, e, "GET", "/music/rand") assert.Equal(t, http.StatusOK, resp.Code) // The endpoint returns a file stream, not JSON // Just verify we got a response with content assert.NotEmpty(t, resp.Body.Bytes(), "Should return song file content") t.Logf("Random song returned %d bytes", len(resp.Body.Bytes())) } // TestGetRandomSongLowChance verifies the /music/rand/low endpoint func TestZGetRandomSongLowChance(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Ensure sync has run ensureSyncRan(t, e) resp := MakeTestRequest(t, e, "GET", "/music/rand/low") assert.Equal(t, http.StatusOK, resp.Code) // The endpoint returns a file stream, not JSON assert.NotEmpty(t, resp.Body.Bytes(), "Should return song file content") } // TestGetRandomSongClassic verifies the /music/rand/classic endpoint func TestZGetRandomSongClassic(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Ensure sync has run ensureSyncRan(t, e) resp := MakeTestRequest(t, e, "GET", "/music/rand/classic") assert.Equal(t, http.StatusOK, resp.Code) // The endpoint returns a file stream, not JSON assert.NotEmpty(t, resp.Body.Bytes(), "Should return song file content") } // TestGetSongInfo verifies the /music/info endpoint func TestZGetSongInfo(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Ensure sync has run and get a song first ensureSyncRan(t, e) MakeTestRequest(t, e, "GET", "/music/rand") // Add to queue and mark as played MakeTestRequest(t, e, "GET", "/music/addQue") MakeTestRequest(t, e, "GET", "/music/addPlayed") resp := MakeTestRequest(t, e, "GET", "/music/info") assert.Equal(t, http.StatusOK, resp.Code) var info backend.SongInfo err := json.Unmarshal(resp.Body.Bytes(), &info) assert.NoError(t, err) // Note: CurrentlyPlaying might be false if no song is currently set // Just verify we got a valid response t.Logf("Song info: Game=%s, Song=%s", info.Game, info.Song) } // TestGetPlayedSongs verifies the /music/list endpoint func TestZGetPlayedSongs(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Ensure sync has run and add some songs to queue ensureSyncRan(t, e) MakeTestRequest(t, e, "GET", "/music/rand") MakeTestRequest(t, e, "GET", "/music/addQue") MakeTestRequest(t, e, "GET", "/music/rand") MakeTestRequest(t, e, "GET", "/music/addQue") resp := MakeTestRequest(t, e, "GET", "/music/list") assert.Equal(t, http.StatusOK, resp.Code) var songs []backend.SongInfo err := json.Unmarshal(resp.Body.Bytes(), &songs) assert.NoError(t, err) assert.NotEmpty(t, songs, "Should have played songs in queue") t.Logf("Found %d songs in queue", len(songs)) } // TestGetNextSong verifies the /music/next endpoint func TestZGetNextSong(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Ensure sync has run and add songs to queue ensureSyncRan(t, e) MakeTestRequest(t, e, "GET", "/music/rand") MakeTestRequest(t, e, "GET", "/music/addQue") MakeTestRequest(t, e, "GET", "/music/rand") MakeTestRequest(t, e, "GET", "/music/addQue") resp := MakeTestRequest(t, e, "GET", "/music/next") assert.Equal(t, http.StatusOK, resp.Code) // The endpoint returns a file stream, not JSON assert.NotEmpty(t, resp.Body.Bytes(), "Should return song file content") } // TestGetPreviousSong verifies the /music/previous endpoint func TestZGetPreviousSong(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Ensure sync has run and add songs to queue ensureSyncRan(t, e) MakeTestRequest(t, e, "GET", "/music/rand") MakeTestRequest(t, e, "GET", "/music/addQue") MakeTestRequest(t, e, "GET", "/music/rand") MakeTestRequest(t, e, "GET", "/music/addQue") // Move forward MakeTestRequest(t, e, "GET", "/music/next") resp := MakeTestRequest(t, e, "GET", "/music/previous") assert.Equal(t, http.StatusOK, resp.Code) // The endpoint returns a file stream, not JSON assert.NotEmpty(t, resp.Body.Bytes(), "Should return song file content") } // TestResetMusic verifies the /music/reset endpoint func TestZResetMusic(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Ensure sync has run and add songs to queue ensureSyncRan(t, e) MakeTestRequest(t, e, "GET", "/music/rand") MakeTestRequest(t, e, "GET", "/music/addQue") // Verify queue has items respBefore := MakeTestRequest(t, e, "GET", "/music/list") var songsBefore []backend.SongInfo json.Unmarshal(respBefore.Body.Bytes(), &songsBefore) assert.True(t, len(songsBefore) > 0, "Should have songs before reset") // Reset queue resp := MakeTestRequest(t, e, "GET", "/music/reset") assert.Equal(t, http.StatusOK, resp.Code) // Verify queue is empty respAfter := MakeTestRequest(t, e, "GET", "/music/list") var songsAfter []backend.SongInfo json.Unmarshal(respAfter.Body.Bytes(), &songsAfter) assert.Equal(t, 0, len(songsAfter), "Queue should be empty after reset") } // TestAddLatestToQue verifies the /music/addQue endpoint func TestZAddLatestToQue(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Ensure sync has run ensureSyncRan(t, e) // Get a random song (this sets lastFetchedNew) MakeTestRequest(t, e, "GET", "/music/rand") // Add to queue resp := MakeTestRequest(t, e, "GET", "/music/addQue") assert.Equal(t, http.StatusOK, resp.Code) // Verify it was added to queue respList := MakeTestRequest(t, e, "GET", "/music/list") var songs []backend.SongInfo json.Unmarshal(respList.Body.Bytes(), &songs) assert.True(t, len(songs) > 0, "Song should be in queue") } // TestAddLatestPlayed verifies the /music/addPlayed endpoint func TestZAddLatestPlayed(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Ensure sync has run and add song to queue ensureSyncRan(t, e) MakeTestRequest(t, e, "GET", "/music/rand") MakeTestRequest(t, e, "GET", "/music/addQue") // Mark as played resp := MakeTestRequest(t, e, "GET", "/music/addPlayed") assert.Equal(t, http.StatusOK, resp.Code) } // TestPutPlayed verifies the PUT /music/played endpoint func TestZPutPlayed(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Ensure sync has run and add songs to queue ensureSyncRan(t, e) MakeTestRequest(t, e, "GET", "/music/rand") MakeTestRequest(t, e, "GET", "/music/addQue") // Mark song 0 as played resp := MakeTestRequestWithBody(t, e, "PUT", "/music/played?song=0", nil) assert.Equal(t, http.StatusOK, resp.Code) }