180 lines
4.9 KiB
Go
180 lines
4.9 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
|
|
"music-server/internal/backend"
|
|
"music-server/internal/db"
|
|
"music-server/internal/db/repository"
|
|
|
|
"github.com/labstack/echo/v5"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestStatisticsEndpoints tests the statistics API endpoints
|
|
func TestStatisticsEndpoints(t *testing.T) {
|
|
// Skip if test database not configured
|
|
e := StartTestServer(t)
|
|
if e == nil {
|
|
t.Skip("Test database not configured")
|
|
}
|
|
|
|
// Get token first
|
|
token := getTestToken(t, e)
|
|
if token == "" {
|
|
t.Skip("Could not get test token")
|
|
}
|
|
|
|
// Test /api/v1/statistics/summary
|
|
req := httptest.NewRequest(http.MethodGet, "/api/v1/statistics/summary", nil)
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
rec := httptest.NewRecorder()
|
|
e.ServeHTTP(rec, req)
|
|
|
|
require.Equal(t, http.StatusOK, rec.Code)
|
|
|
|
var summary backend.StatisticsSummary
|
|
err := json.Unmarshal(rec.Body.Bytes(), &summary)
|
|
require.NoError(t, err)
|
|
require.NotNil(t, summary)
|
|
}
|
|
|
|
// TestPartialMigrationThenSyncThenComplete tests migration workflow
|
|
// Note: This test requires the database to be in a specific state
|
|
// It tests: partial migration → data insert → sync → complete migration
|
|
func TestPartialMigrationThenSyncThenComplete(t *testing.T) {
|
|
// This test is complex and requires careful setup
|
|
// For now, we test the final state: all migrations + sync
|
|
|
|
e := StartTestServer(t)
|
|
if e == nil {
|
|
t.Skip("Test database not configured")
|
|
}
|
|
|
|
// Get token
|
|
token := getTestToken(t, e)
|
|
if token == "" {
|
|
t.Skip("Could not get test token")
|
|
}
|
|
|
|
// Insert test data manually (5 soundtracks with songs)
|
|
insertTestData(t)
|
|
|
|
// Run sync to ensure data is properly loaded
|
|
req := httptest.NewRequest(http.MethodGet, "/sync/new", nil)
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
rec := httptest.NewRecorder()
|
|
e.ServeHTTP(rec, req)
|
|
|
|
require.Equal(t, http.StatusOK, rec.Code)
|
|
|
|
// Wait for sync to complete
|
|
if !waitForSyncCompletion(t, e, 60) {
|
|
t.Error("Sync did not complete within timeout")
|
|
}
|
|
|
|
// Verify data via statistics endpoint
|
|
req = httptest.NewRequest(http.MethodGet, "/api/v1/statistics/summary", nil)
|
|
req.Header.Set("Authorization", "Bearer "+token)
|
|
rec = httptest.NewRecorder()
|
|
e.ServeHTTP(rec, req)
|
|
|
|
require.Equal(t, http.StatusOK, rec.Code)
|
|
|
|
var summary backend.StatisticsSummary
|
|
err := json.Unmarshal(rec.Body.Bytes(), &summary)
|
|
require.NoError(t, err)
|
|
|
|
// After sync with /sync/new, only soundtracks matching filesystem remain
|
|
// testMusic has 3 games
|
|
require.Equal(t, int64(3), summary.TotalGames)
|
|
}
|
|
|
|
// insertTestData inserts 5 test soundtracks with songs into the database
|
|
func insertTestData(t *testing.T) {
|
|
if db.TestDatabase == nil || db.TestDatabase.Pool == nil {
|
|
t.Skip("Test database not initialized")
|
|
return
|
|
}
|
|
|
|
ctx := context.Background()
|
|
queries := repository.New(db.TestDatabase.Pool)
|
|
|
|
// Insert 5 soundtracks
|
|
soundtracks := []struct {
|
|
name string
|
|
path string
|
|
}{
|
|
{"Test Soundtrack 1", "/path/to/soundtrack1"},
|
|
{"Test Soundtrack 2", "/path/to/soundtrack2"},
|
|
{"Test Soundtrack 3", "/path/to/soundtrack3"},
|
|
{"Test Soundtrack 4", "/path/to/soundtrack4"},
|
|
{"Test Soundtrack 5", "/path/to/soundtrack5"},
|
|
}
|
|
|
|
for _, st := range soundtracks {
|
|
_, err := queries.InsertSoundtrack(ctx, repository.InsertSoundtrackParams{
|
|
SoundtrackName: st.name,
|
|
Path: st.path,
|
|
Hash: "test-hash-" + st.name,
|
|
})
|
|
require.NoError(t, err, "Failed to insert soundtrack: %s", st.name)
|
|
}
|
|
|
|
// Get soundtrack IDs
|
|
soundtrackIDs, err := queries.FindAllSoundtracks(ctx)
|
|
require.NoError(t, err)
|
|
require.GreaterOrEqual(t, len(soundtrackIDs), 5)
|
|
|
|
// Insert songs for each soundtrack
|
|
songData := []struct {
|
|
soundtrackID int32
|
|
songs []string
|
|
}{
|
|
{soundtrackIDs[0].ID, []string{"Song A", "Song B"}},
|
|
{soundtrackIDs[1].ID, []string{"Song C", "Song D"}},
|
|
{soundtrackIDs[2].ID, []string{"Song E"}},
|
|
{soundtrackIDs[3].ID, []string{"Song F", "Song G", "Song H"}},
|
|
{soundtrackIDs[4].ID, []string{"Song I"}},
|
|
}
|
|
|
|
for _, sd := range songData {
|
|
for _, songName := range sd.songs {
|
|
err := queries.AddSong(ctx, repository.AddSongParams{
|
|
SoundtrackID: sd.soundtrackID,
|
|
SongName: songName,
|
|
Path: "/path/to/" + songName + ".mp3",
|
|
})
|
|
require.NoError(t, err, "Failed to insert song: %s", songName)
|
|
}
|
|
}
|
|
|
|
t.Logf("Inserted %d soundtracks with %d total songs", len(soundtracks), 8)
|
|
}
|
|
|
|
// getTestToken gets a valid token for testing
|
|
func getTestToken(t *testing.T, e *echo.Echo) string {
|
|
reqBody := `{"client_type": "test"}`
|
|
req := httptest.NewRequest(http.MethodPost, "/api/v1/token", strings.NewReader(reqBody))
|
|
req.Header.Set("Content-Type", "application/json")
|
|
rec := httptest.NewRecorder()
|
|
e.ServeHTTP(rec, req)
|
|
|
|
if rec.Code != http.StatusOK {
|
|
t.Logf("Failed to get token: %s", rec.Body.String())
|
|
return ""
|
|
}
|
|
|
|
var resp struct {
|
|
Token string `json:"token"`
|
|
}
|
|
err := json.Unmarshal(rec.Body.Bytes(), &resp)
|
|
require.NoError(t, err)
|
|
return resp.Token
|
|
}
|