package server import ( "encoding/json" "net/http" "testing" "time" "music-server/internal/backend" "music-server/internal/db" "music-server/internal/db/repository" "github.com/stretchr/testify/assert" ) // TestSyncPopulatesDatabase verifies that sync populates the database with games func TestSyncPopulatesDatabase(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Before sync - should have no games (or very few if previous test ran) repo := repository.New(db.Dbpool) gamesBefore, err := repo.FindAllGames(db.Ctx) assert.NoError(t, err) beforeCount := len(gamesBefore) t.Logf("Games before sync: %d", beforeCount) // Run sync resp := MakeTestRequest(t, e, "GET", "/sync/full") assert.Equal(t, http.StatusOK, resp.Code) // Wait for sync to complete by polling /sync/progress maxAttempts := 60 for i := 0; i < maxAttempts; i++ { progressResp := MakeTestRequest(t, e, "GET", "/sync/progress") assert.Equal(t, http.StatusOK, progressResp.Code) var progress backend.ProgressResponse err := json.Unmarshal(progressResp.Body.Bytes(), &progress) assert.NoError(t, err) t.Logf("Sync progress: %s%% (time spent: %s)", progress.Progress, progress.TimeSpent) if progress.Progress == "100" { t.Log("Sync completed!") break } if i == maxAttempts-1 { t.Error("Sync did not complete within timeout") } time.Sleep(1 * time.Second) } // After sync - should have games gamesAfter, err := repo.FindAllGames(db.Ctx) assert.NoError(t, err) afterCount := len(gamesAfter) t.Logf("Games after sync: %d", afterCount) // Should have more games than before (unless database was already populated) assert.True(t, afterCount > 0, "Database should have games after sync") } // TestSyncMakesDifference verifies that sync actually changes the database state func TestSyncMakesDifference(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Clear any existing data first db.TestClearDatabase(t) // Before sync - should have no games repo := repository.New(db.Dbpool) gamesBefore, err := repo.FindAllGames(db.Ctx) assert.NoError(t, err) assert.Equal(t, 0, len(gamesBefore), "Should have no games before sync") // Run sync resp := MakeTestRequest(t, e, "GET", "/sync/full") assert.Equal(t, http.StatusOK, resp.Code) // Wait for sync to complete maxAttempts := 60 for i := 0; i < maxAttempts; i++ { progressResp := MakeTestRequest(t, e, "GET", "/sync/progress") var progress backend.ProgressResponse json.Unmarshal(progressResp.Body.Bytes(), &progress) if progress.Progress == "100" { break } if i == maxAttempts-1 { t.Error("Sync did not complete within timeout") } time.Sleep(1 * time.Second) } // After sync - should have games gamesAfter, err := repo.FindAllGames(db.Ctx) assert.NoError(t, err) assert.True(t, len(gamesAfter) > 0, "Should have games after sync") } // TestSyncProgress verifies the sync progress endpoint func TestSyncProgress(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Start sync in background go MakeTestRequest(t, e, "GET", "/sync/full") // Poll progress endpoint maxAttempts := 30 foundNonZero := false foundComplete := false for i := 0; i < maxAttempts; i++ { resp := MakeTestRequest(t, e, "GET", "/sync/progress") assert.Equal(t, http.StatusOK, resp.Code) var progress backend.ProgressResponse err := json.Unmarshal(resp.Body.Bytes(), &progress) assert.NoError(t, err) t.Logf("Sync progress: %s%%", progress.Progress) // Verify we get valid progress values if progress.Progress != "0" { foundNonZero = true } if progress.Progress == "100" { foundComplete = true break } time.Sleep(1 * time.Second) } assert.True(t, foundNonZero, "Should have seen non-zero progress") assert.True(t, foundComplete, "Should have seen completion at 100%") } // TestSyncGamesNewOnlyChanges verifies the incremental sync endpoint func TestSyncGamesNewOnlyChanges(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Run full sync first MakeTestRequest(t, e, "GET", "/sync/full") // Wait for it to complete time.Sleep(5 * time.Second) // Get initial count repo := repository.New(db.Dbpool) gamesBefore, _ := repo.FindAllGames(db.Ctx) beforeCount := len(gamesBefore) // Run incremental sync (should not change count if nothing changed) resp := MakeTestRequest(t, e, "GET", "/sync/new") assert.Equal(t, http.StatusOK, resp.Code) // Wait a bit time.Sleep(2 * time.Second) // Count should be the same gamesAfter, _ := repo.FindAllGames(db.Ctx) afterCount := len(gamesAfter) // Note: This might not be exactly equal due to timing, but should be close t.Logf("Games before incremental sync: %d, after: %d", beforeCount, afterCount) } // TestResetGames verifies the reset endpoint clears the database // RUN THIS LAST func TestResetGames(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // First ensure we have data repo := repository.New(db.Dbpool) gamesBefore, _ := repo.FindAllGames(db.Ctx) beforeCount := len(gamesBefore) if beforeCount == 0 { // Run sync to populate MakeTestRequest(t, e, "GET", "/sync/full") time.Sleep(5 * time.Second) gamesBefore, _ = repo.FindAllGames(db.Ctx) beforeCount = len(gamesBefore) } t.Logf("Games before reset: %d", beforeCount) assert.True(t, beforeCount > 0, "Should have games to reset") // Call reset resp := MakeTestRequest(t, e, "GET", "/sync/reset") assert.Equal(t, http.StatusOK, resp.Code) // Verify database is cleared // Note: reset might take a moment to propagate time.Sleep(1 * time.Second) gamesAfter, _ := repo.FindAllGames(db.Ctx) afterCount := len(gamesAfter) t.Logf("Games after reset: %d", afterCount) assert.Equal(t, 0, afterCount, "Database should be empty after reset") } // TestSyncGamesNewFull verifies the full sync endpoint // RUN THIS LAST (before TestResetGames) func TestSyncGamesNewFull(t *testing.T) { db.TestSetupDB(t) defer db.TestTearDownDB(t) e := StartTestServer(t) // Clear database first db.TestClearDatabase(t) // Run full sync resp := MakeTestRequest(t, e, "GET", "/sync/full") assert.Equal(t, http.StatusOK, resp.Code) // Wait for sync to complete maxAttempts := 60 for i := 0; i < maxAttempts; i++ { progressResp := MakeTestRequest(t, e, "GET", "/sync/progress") var progress backend.ProgressResponse json.Unmarshal(progressResp.Body.Bytes(), &progress) if progress.Progress == "100" { t.Log("Full sync completed") break } if i == maxAttempts-1 { t.Error("Full sync did not complete within timeout") } time.Sleep(1 * time.Second) } // Verify database is populated repo := repository.New(db.Dbpool) games, err := repo.FindAllGames(db.Ctx) assert.NoError(t, err) assert.True(t, len(games) > 0, "Database should be populated after full sync") t.Logf("Full sync populated %d games", len(games)) }