diff --git a/backend/config/config_test.go b/backend/config/config_test.go index d2d37e9..329f5b2 100644 --- a/backend/config/config_test.go +++ b/backend/config/config_test.go @@ -72,7 +72,10 @@ func TestConfig_LoadSave_Roundtrip(t *testing.T) { } if loaded.Theme.BackgroundShade != theme.BackgroundLight { - t.Errorf("Theme.BackgroundShade = %q, want %q", loaded.Theme.BackgroundShade, theme.BackgroundLight) + t.Errorf( + "Theme.BackgroundShade = %q, want %q", + loaded.Theme.BackgroundShade, theme.BackgroundLight, + ) } // Verify tracklist. @@ -86,13 +89,19 @@ func TestConfig_LoadSave_Roundtrip(t *testing.T) { } for i, want := range wantColumns { if loaded.TrackList.Columns[i].ID != want { - t.Errorf("TrackList.Columns[%d].ID = %q, want %q", i, loaded.TrackList.Columns[i].ID, want) + t.Errorf( + "TrackList.Columns[%d].ID = %q, want %q", + i, loaded.TrackList.Columns[i].ID, want, + ) } } // Verify favorites. if loaded.Favorites.IconStyle != favorites.IconStar { - t.Errorf("Favorites.IconStyle = %q, want %q", loaded.Favorites.IconStyle, favorites.IconStar) + t.Errorf( + "Favorites.IconStyle = %q, want %q", + loaded.Favorites.IconStyle, favorites.IconStar, + ) } if loaded.Favorites.PinDefault != false { @@ -105,7 +114,10 @@ func TestConfig_LoadSave_Roundtrip(t *testing.T) { } if loaded.Library.ScanConcurrency != library.ScanConcurrencySSD { - t.Errorf("Library.ScanConcurrency = %q, want %q", loaded.Library.ScanConcurrency, library.ScanConcurrencySSD) + t.Errorf( + "Library.ScanConcurrency = %q, want %q", + loaded.Library.ScanConcurrency, library.ScanConcurrencySSD, + ) } // Verify window. @@ -206,9 +218,6 @@ func TestConfig_ApplyDefaults_NilSubConfigs(t *testing.T) { if c.Favorites == nil { t.Error("Favorites should not be nil after applyDefaults") } - - // Library is intentionally left nil by applyDefaults when it - // starts as nil (no library dir configured yet). } // containsSubstring is a test helper for checking error messages. diff --git a/backend/database/search_test.go b/backend/database/search_test.go index 3c64209..d14e3de 100644 --- a/backend/database/search_test.go +++ b/backend/database/search_test.go @@ -44,28 +44,50 @@ func seedSearchData(t *testing.T, db *DB) { intPtr := func(v int64) *int64 { return &v } tracks := []track{ - {1, "/music/queen/bohemian_rhapsody.mp3", "Bohemian Rhapsody", "Queen", "A Night at the Opera", intPtr(11), intPtr(1), 1975, "Rock", "Freddie Mercury", 354000, 0, 44100, 16, 2, 320000, 8500000}, - {2, "/music/beyonce/halo.flac", "Halo", "Beyoncé", "Lemonade", intPtr(1), intPtr(1), 2008, "Pop", "Ryan Tedder", 261000, 1, 96000, 24, 2, 1411000, 42000000}, - {3, "/music/acdc/back_in_black.mp3", "Back in Black", "AC/DC", "Back in Black", intPtr(1), intPtr(1), 1980, "Hard Rock", "Angus Young", 255000, 0, 44100, 16, 2, 320000, 6100000}, - {4, "/music/pinkfloyd/comfortably_numb.flac", "Comfortably Numb", "Pink Floyd", "The Dark Side of the Moon", intPtr(6), intPtr(1), 1979, "Progressive Rock", "David Gilmour", 382000, 1, 96000, 24, 2, 1411000, 54000000}, - {5, "/music/queen/another_one_bites_the_dust.mp3", "Another One Bites the Dust", "Queen", "The Game", intPtr(3), intPtr(1), 1980, "Funk Rock", "John Deacon", 215000, 0, 44100, 16, 2, 320000, 5200000}, - {6, "/music/acdc/thunderstruck.mp3", "Thunderstruck", "AC/DC", "The Razors Edge", intPtr(1), intPtr(1), 1990, "Hard Rock", "Angus Young", 292000, 0, 44100, 16, 2, 320000, 7000000}, - {7, "/music/qotsa/queen_of_the_stone_age.mp3", "Queen of the Stone Age", "Queens of the Stone Age", "Rated R", intPtr(1), intPtr(1), 2000, "Stoner Rock", "Josh Homme", 310000, 0, 44100, 16, 2, 320000, 7400000}, + { + 1, "/music/queen/bohemian_rhapsody.mp3", "Bohemian Rhapsody", "Queen", + "A Night at the Opera", intPtr(11), intPtr(1), 1975, "Rock", + "Freddie Mercury", 354000, 0, 44100, 16, 2, 320000, 8500000, + }, + { + 2, "/music/beyonce/halo.flac", "Halo", "Beyoncé", "Lemonade", + intPtr(1), intPtr(1), 2008, "Pop", "Ryan Tedder", 261000, 1, + 96000, 24, 2, 1411000, 42000000, + }, + { + 3, "/music/acdc/back_in_black.mp3", "Back in Black", "AC/DC", + "Back in Black", intPtr(1), intPtr(1), 1980, "Hard Rock", + "Angus Young", 255000, 0, 44100, 16, 2, 320000, 6100000, + }, + { + 4, "/music/pinkfloyd/comfortably_numb.flac", "Comfortably Numb", + "Pink Floyd", "The Dark Side of the Moon", intPtr(6), intPtr(1), + 1979, "Progressive Rock", "David Gilmour", 382000, 1, 96000, 24, + 2, 1411000, 54000000, + }, + { + 5, "/music/queen/another_one_bites_the_dust.mp3", + "Another One Bites the Dust", "Queen", "The Game", intPtr(3), + intPtr(1), 1980, "Funk Rock", "John Deacon", 215000, 0, 44100, + 16, 2, 320000, 5200000, + }, + { + 6, "/music/acdc/thunderstruck.mp3", "Thunderstruck", "AC/DC", + "The Razors Edge", intPtr(1), intPtr(1), 1990, "Hard Rock", + "Angus Young", 292000, 0, 44100, 16, 2, 320000, 7000000, + }, + { + 7, "/music/qotsa/queen_of_the_stone_age.mp3", + "Queen of the Stone Age", "Queens of the Stone Age", "Rated R", + intPtr(1), intPtr(1), 2000, "Stoner Rock", "Josh Homme", 310000, + 0, 44100, 16, 2, 320000, 7400000, + }, } // Build unique sets. - type artistEntry struct { - id int64 - text string - } - - type albumEntry struct { - id int64 - name string - } - artistMap := map[string]int64{} albumMap := map[string]int64{} + var artistID, albumID int64 for _, tr := range tracks { @@ -104,6 +126,7 @@ func seedSearchData(t *testing.T, db *DB) { // Insert genres + recording_genres. genreMap := map[string]int64{} + var genreID int64 for _, tr := range tracks { @@ -131,8 +154,11 @@ func seedSearchData(t *testing.T, db *DB) { // Insert recording. _, err := db.ExecContext( - "INSERT INTO recordings (id, name, artist_credit_id, track_number, disc_number, year, genre, composer) VALUES (?, ?, ?, ?, ?, ?, ?, ?)", - tr.id, tr.title, acID, tr.trackNum, tr.discNum, tr.year, tr.genre, tr.composer, + "INSERT INTO recordings (id, name, artist_credit_id, "+ + "track_number, disc_number, year, genre, composer) "+ + "VALUES (?, ?, ?, ?, ?, ?, ?, ?)", + tr.id, tr.title, acID, tr.trackNum, tr.discNum, + tr.year, tr.genre, tr.composer, ) if err != nil { t.Fatalf("insert recording %d %q: %v", tr.id, tr.title, err) @@ -140,8 +166,12 @@ func seedSearchData(t *testing.T, db *DB) { // Insert audio_files. _, err = db.ExecContext( - "INSERT INTO audio_files (id, file_path, length_milliseconds, file_type_id, recording_id, sample_rate, bit_depth, channels, bitrate, file_size) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", - tr.id, tr.filePath, tr.lenMs, tr.ftID, tr.id, tr.sr, tr.bd, tr.ch, tr.br, tr.fsize, + "INSERT INTO audio_files (id, file_path, "+ + "length_milliseconds, file_type_id, recording_id, "+ + "sample_rate, bit_depth, channels, bitrate, file_size) "+ + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + tr.id, tr.filePath, tr.lenMs, tr.ftID, tr.id, + tr.sr, tr.bd, tr.ch, tr.br, tr.fsize, ) if err != nil { t.Fatalf("insert audio_file %d: %v", tr.id, err) @@ -149,7 +179,9 @@ func seedSearchData(t *testing.T, db *DB) { // Link recording to release_group. _, err = db.ExecContext( - "INSERT INTO release_group_recordings (release_group_id, recording_id, track_number, disc_number) VALUES (?, ?, ?, ?)", + "INSERT INTO release_group_recordings "+ + "(release_group_id, recording_id, track_number, disc_number) "+ + "VALUES (?, ?, ?, ?)", rgID, tr.id, tr.trackNum, tr.discNum, ) if err != nil { @@ -368,6 +400,7 @@ func TestSearchFTS_SpecialCharacters(t *testing.T) { // Verify at least one AC/DC track is present. found := false + for _, r := range results { if r.Artist == "AC/DC" { found = true @@ -432,6 +465,7 @@ func TestSearchFTS_Diacritics(t *testing.T) { } found := false + for _, r := range results { if r.Artist == "Beyoncé" { found = true @@ -489,6 +523,7 @@ func TestSearchFTSByFilename(t *testing.T) { } found := false + for _, r := range results { if r.Title == "Bohemian Rhapsody" { found = true @@ -620,7 +655,9 @@ func TestInsertAndDeleteSearchIndex(t *testing.T) { } // Insert into search index. - if err := db.InsertSearchIndex(1, "/test/track.mp3", "Test Track", "Test Artist", "Test Album"); err != nil { + if err := db.InsertSearchIndex( + 1, "/test/track.mp3", "Test Track", "Test Artist", "Test Album", + ); err != nil { t.Fatalf("InsertSearchIndex: %v", err) } @@ -781,11 +818,13 @@ func TestMigrationsApplied(t *testing.T) { if !rows.Next() { _ = rows.Close() + t.Fatal("PRAGMA user_version: no row returned") } if err := rows.Scan(&version); err != nil { _ = rows.Close() + t.Fatalf("scan user_version: %v", err) } diff --git a/backend/database/testhelper.go b/backend/database/testhelper.go index 0bd00b7..b07f869 100644 --- a/backend/database/testhelper.go +++ b/backend/database/testhelper.go @@ -63,7 +63,7 @@ func NewTestDB(t *testing.T) *DB { queries := sqlcgen.New(db) - t.Cleanup(func() { db.Close() }) + t.Cleanup(func() { _ = db.Close() }) return &DB{ db: db, diff --git a/backend/events/cmd/genevents/main.go b/backend/events/cmd/genevents/main.go index 61804da..edf6141 100644 --- a/backend/events/cmd/genevents/main.go +++ b/backend/events/cmd/genevents/main.go @@ -32,6 +32,7 @@ func main() { if *output == "" || *output == "/dev/stdout" { fmt.Print(ts) + return } @@ -57,6 +58,7 @@ type constEntry struct { // groups in declaration order. func parseEvents(path string) ([]constGroup, error) { fset := token.NewFileSet() + f, err := parser.ParseFile(fset, path, nil, parser.ParseComments) if err != nil { return nil, fmt.Errorf("parse %s: %w", path, err) @@ -82,11 +84,14 @@ func parseEvents(path string) ([]constGroup, error) { if !ok { continue } + for i, name := range vs.Names { if i >= len(vs.Values) { continue } + bl, ok := vs.Values[i].(*ast.BasicLit) + if !ok || bl.Kind != token.STRING { continue } @@ -110,6 +115,7 @@ func parseEvents(path string) ([]constGroup, error) { func cleanComment(s string) string { s = strings.TrimSpace(s) s = strings.TrimSuffix(s, ".") + return s } @@ -126,6 +132,7 @@ func generateTypeScript(groups []constGroup) string { if g.Comment != "" { b.WriteString(" // " + g.Comment + "\n") } + for _, c := range g.Consts { b.WriteString(fmt.Sprintf(" %s: %q,\n", c.Name, c.Value)) } @@ -146,20 +153,26 @@ func generateTypeScript(groups []constGroup) string { // then renames it into place for atomic replacement. func writeAtomic(path, data string) error { dir := filepath.Dir(path) + tmp, err := os.CreateTemp(dir, ".genevents-*.tmp") if err != nil { return err } + tmpName := tmp.Name() if _, err := tmp.WriteString(data); err != nil { - tmp.Close() - os.Remove(tmpName) + _ = tmp.Close() + _ = os.Remove(tmpName) + return err } + if err := tmp.Close(); err != nil { - os.Remove(tmpName) + _ = os.Remove(tmpName) + return err } + return os.Rename(tmpName, path) } diff --git a/backend/favorites/config_test.go b/backend/favorites/config_test.go index 737dc3d..8b1605e 100644 --- a/backend/favorites/config_test.go +++ b/backend/favorites/config_test.go @@ -31,6 +31,7 @@ func TestFavoritesConfig_Validate_InvalidIconStyle(t *testing.T) { t.Parallel() c := &Config{IconStyle: "diamond"} + err := c.Validate() if err == nil { t.Fatal("Validate() expected error for unknown icon style, got nil") diff --git a/backend/library/library.go b/backend/library/library.go index ef0aa96..9adac80 100644 --- a/backend/library/library.go +++ b/backend/library/library.go @@ -229,6 +229,7 @@ func (l *Library) Scan() (*ScanMetrics, error) { "count", len(existingFiles), "library-directory", l.conf.DirectoryPath, ) + workChan := make(chan scanWork, 100) resultChan := make(chan importResult, 100) @@ -531,10 +532,14 @@ func (l *Library) Scan() (*ScanMetrics, error) { // point so it is safe to close. thumbStart := time.Now() - runtime.EventsEmit(l.ctx, events.LibraryScanProgress, - ScanProgress{Phase: "thumbnails", Total: totalFiles, - Processed: a + s + u, Added: a, Skipped: s, Updated: u}, - ) + runtime.EventsEmit(l.ctx, events.LibraryScanProgress, ScanProgress{ + Phase: "thumbnails", + Total: totalFiles, + Processed: a + s + u, + Added: a, + Skipped: s, + Updated: u, + }) close(thumbChan) thumbWg.Wait() @@ -542,10 +547,10 @@ func (l *Library) Scan() (*ScanMetrics, error) { metrics.ThumbnailWallClock = time.Since(thumbStart) // --- Phase 5: orphan cleanup --- - runtime.EventsEmit(l.ctx, events.LibraryScanProgress, - ScanProgress{Phase: "orphans", Total: totalFiles, - Processed: a + s + u, Added: a, Skipped: s, Updated: u}, - ) + runtime.EventsEmit(l.ctx, events.LibraryScanProgress, ScanProgress{ + Phase: "orphans", Total: totalFiles, + Processed: a + s + u, Added: a, Skipped: s, Updated: u, + }) orphanStart := time.Now() diff --git a/backend/library/scan_test.go b/backend/library/scan_test.go index 97ec792..2a760cf 100644 --- a/backend/library/scan_test.go +++ b/backend/library/scan_test.go @@ -396,7 +396,10 @@ func TestCachedLinkArtist(t *testing.T) { lib.cachedLinkArtist(q, cache, metrics, "Queen", ac.ID) if len(cache.linkedCredits) != 1 { - t.Errorf("linkedCredits after duplicate = %d, want 1 (should skip)", len(cache.linkedCredits)) + t.Errorf( + "linkedCredits after duplicate = %d, want 1 (should skip)", + len(cache.linkedCredits), + ) } } @@ -536,6 +539,7 @@ func TestResolveReleaseGroup(t *testing.T) { // Cache key is composite: "albumName\x00artistCreditID". cacheKey := fmt.Sprintf("%s\x00%d", "A Night at the Opera", ac.ID) cachedRG := cache.releaseGroups[cacheKey] + if !cachedRG.CoverArtID.Valid { t.Error("expected CoverArtID to be set after update") } @@ -616,7 +620,9 @@ func TestOrphanDeletion(t *testing.T) { } // Add FTS search index entry. - if err := db.InsertSearchIndex(af.ID, "/music/test.mp3", "Test Song", "Test Artist", ""); err != nil { + if err := db.InsertSearchIndex( + af.ID, "/music/test.mp3", "Test Song", "Test Artist", "", + ); err != nil { t.Fatalf("insert search index: %v", err) } @@ -651,11 +657,12 @@ func TestOrphanDeletion(t *testing.T) { // become stale but harmless (they reference a non-existent // audio_file ID, so JOINs return no results). // ClearSearchIndex (used during full rescan) handles bulk cleanup. + // DeleteSearchIndex on contentless FTS5 is expected to error. + // Not a fatal error — documents the contentless FTS5 limitation. err = db.DeleteSearchIndex(af.ID) if err == nil { t.Log("DeleteSearchIndex succeeded (unexpected for contentless FTS5)") } - // Not a fatal error — documents the contentless FTS5 limitation. } // --------------------------------------------------------------------------- @@ -705,7 +712,10 @@ func TestEntityCache_EmptyFields(t *testing.T) { } if albumACID.Int64 != trackAC.ID { - t.Errorf("empty AlbumArtist should reuse track credit: got %d, want %d", albumACID.Int64, trackAC.ID) + t.Errorf( + "empty AlbumArtist should reuse track credit: got %d, want %d", + albumACID.Int64, trackAC.ID, + ) } // resolveAlbumArtistCredit when AlbumArtist matches Artist also reuses. @@ -716,6 +726,9 @@ func TestEntityCache_EmptyFields(t *testing.T) { sameACID := lib.resolveAlbumArtistCredit(q, cache, metrics, sameTags, trackAC.ID) if sameACID.Int64 != trackAC.ID { - t.Errorf("matching AlbumArtist should reuse track credit: got %d, want %d", sameACID.Int64, trackAC.ID) + t.Errorf( + "matching AlbumArtist should reuse track credit: got %d, want %d", + sameACID.Int64, trackAC.ID, + ) } } diff --git a/backend/player/volume_test.go b/backend/player/volume_test.go index 659fa0d..b887a28 100644 --- a/backend/player/volume_test.go +++ b/backend/player/volume_test.go @@ -126,8 +126,11 @@ func TestUserVolume_ToVolume_Roundtrip(t *testing.T) { diff := int(roundtripped) - int(i) if diff < -1 || diff > 1 { - t.Errorf("Roundtrip UserVolume(%d) -> Volume(%f) -> UserVolume(%d): drift %d exceeds ±1", - i, vol, roundtripped, diff) + t.Errorf( + "Roundtrip UserVolume(%d) -> Volume(%f) -> UserVolume(%d): "+ + "drift %d exceeds ±1", + i, vol, roundtripped, diff, + ) } } @@ -138,8 +141,11 @@ func TestUserVolume_ToVolume_Roundtrip(t *testing.T) { roundtripped := vol.ToUserVolume() if roundtripped != uv { - t.Errorf("Exact roundtrip UserVolume(%d) -> Volume(%f) -> UserVolume(%d): want exact match", - uv, vol, roundtripped) + t.Errorf( + "Exact roundtrip UserVolume(%d) -> Volume(%f) -> "+ + "UserVolume(%d): want exact match", + uv, vol, roundtripped, + ) } } } diff --git a/backend/queue/navigation_test.go b/backend/queue/navigation_test.go index 90dfee0..adcb6c0 100644 --- a/backend/queue/navigation_test.go +++ b/backend/queue/navigation_test.go @@ -14,7 +14,7 @@ func newTestQueueDirect(tracks int, currentIndex int) *Queue { } q.tracks = make([]Track, tracks) - for i := 0; i < tracks; i++ { + for i := range tracks { q.tracks[i] = Track{FilePath: "/test/track.mp3", Position: int64(i)} } @@ -135,11 +135,15 @@ func TestGenerateShuffleOrder_Properties(t *testing.T) { // Property 2: current track is at shuffleOrder[0]. if q.shuffleOrder[0] != tc.currentIdx { - t.Errorf("shuffleOrder[0]: got %d, want %d (currentIndex)", q.shuffleOrder[0], tc.currentIdx) + t.Errorf( + "shuffleOrder[0]: got %d, want %d (currentIndex)", + q.shuffleOrder[0], tc.currentIdx, + ) } // Property 3: all indices present (no duplicates, no missing). seen := make(map[int]bool, tc.trackCount) + for _, idx := range q.shuffleOrder { if idx < 0 || idx >= tc.trackCount { t.Errorf("shuffleOrder contains out-of-range index: %d", idx) @@ -153,7 +157,10 @@ func TestGenerateShuffleOrder_Properties(t *testing.T) { } if len(seen) != tc.trackCount { - t.Errorf("unique indices in shuffleOrder: got %d, want %d", len(seen), tc.trackCount) + t.Errorf( + "unique indices in shuffleOrder: got %d, want %d", + len(seen), tc.trackCount, + ) } }) } @@ -177,6 +184,7 @@ func TestNextIndex_ShuffleMode(t *testing.T) { // Advance to index 4 and get next. q.currentIndex = 4 got = q.nextIndex() + if got != 0 { t.Errorf("nextIndex (shuffle, pos 2): got %d, want 0", got) } @@ -184,6 +192,7 @@ func TestNextIndex_ShuffleMode(t *testing.T) { // At the end of shuffle order with RepeatOff. q.currentIndex = 1 // last in shuffleOrder got = q.nextIndex() + if got != -1 { t.Errorf("nextIndex (shuffle, end, repeatOff): got %d, want -1", got) } @@ -191,7 +200,11 @@ func TestNextIndex_ShuffleMode(t *testing.T) { // At the end of shuffle order with RepeatAll. q.repeatMode = RepeatAll got = q.nextIndex() + if got != 2 { - t.Errorf("nextIndex (shuffle, end, repeatAll): got %d, want 2 (wraps to shuffleOrder[0])", got) + t.Errorf( + "nextIndex (shuffle, end, repeatAll): got %d, want 2 "+ + "(wraps to shuffleOrder[0])", got, + ) } } diff --git a/backend/queue/persistence_test.go b/backend/queue/persistence_test.go index 7db257d..483c4a4 100644 --- a/backend/queue/persistence_test.go +++ b/backend/queue/persistence_test.go @@ -35,7 +35,10 @@ func TestSaveState_RestoreState_Roundtrip(t *testing.T) { // Each track's FilePath, Title, Artist. for i := range s1.Tracks { if s2.Tracks[i].FilePath != s1.Tracks[i].FilePath { - t.Errorf("track[%d] FilePath: got %q, want %q", i, s2.Tracks[i].FilePath, s1.Tracks[i].FilePath) + t.Errorf( + "track[%d] FilePath: got %q, want %q", + i, s2.Tracks[i].FilePath, s1.Tracks[i].FilePath, + ) } if s2.Tracks[i].Title != s1.Tracks[i].Title { @@ -43,7 +46,10 @@ func TestSaveState_RestoreState_Roundtrip(t *testing.T) { } if s2.Tracks[i].Artist != s1.Tracks[i].Artist { - t.Errorf("track[%d] Artist: got %q, want %q", i, s2.Tracks[i].Artist, s1.Tracks[i].Artist) + t.Errorf( + "track[%d] Artist: got %q, want %q", + i, s2.Tracks[i].Artist, s1.Tracks[i].Artist, + ) } } @@ -71,7 +77,10 @@ func TestSaveState_RestoreState_Roundtrip(t *testing.T) { } else { for i := range q.shuffleOrder { if q2.shuffleOrder[i] != q.shuffleOrder[i] { - t.Errorf("shuffleOrder[%d]: got %d, want %d", i, q2.shuffleOrder[i], q.shuffleOrder[i]) + t.Errorf( + "shuffleOrder[%d]: got %d, want %d", + i, q2.shuffleOrder[i], q.shuffleOrder[i], + ) } } } diff --git a/backend/queue/queue_test.go b/backend/queue/queue_test.go index 5d5cb3f..7b7b7a0 100644 --- a/backend/queue/queue_test.go +++ b/backend/queue/queue_test.go @@ -16,6 +16,7 @@ type mockTrackLoader struct { func (m *mockTrackLoader) LoadFile(filePath string) error { m.loadedFile = filePath + return nil } @@ -53,7 +54,7 @@ func seedAudioFiles(t *testing.T, db *database.DB, count int) []string { paths := make([]string, count) - for i := 0; i < count; i++ { + for i := range count { recID := i + 1 afID := i + 1 fp := fmt.Sprintf("/test/track%d.mp3", i+1) @@ -68,7 +69,9 @@ func seedAudioFiles(t *testing.T, db *database.DB, count int) []string { } _, err = db.ExecContext( - "INSERT OR IGNORE INTO audio_files (id, file_path, length_milliseconds, file_type_id, recording_id) VALUES (?, ?, 180000, 0, ?)", + "INSERT OR IGNORE INTO audio_files (id, file_path, "+ + "length_milliseconds, file_type_id, recording_id) "+ + "VALUES (?, ?, 180000, 0, ?)", afID, fp, recID, ) if err != nil { @@ -292,7 +295,10 @@ func TestRemoveTrack_RemoveCurrentTrack(t *testing.T) { // After removing currentIndex=2, index should be clamped to valid range. if state.CurrentIndex < 0 || state.CurrentIndex >= len(state.Tracks) { - t.Errorf("currentIndex out of range: got %d, track count %d", state.CurrentIndex, len(state.Tracks)) + t.Errorf( + "currentIndex out of range: got %d, track count %d", + state.CurrentIndex, len(state.Tracks), + ) } } diff --git a/backend/theme/config_test.go b/backend/theme/config_test.go index 1ba2e98..15dcf84 100644 --- a/backend/theme/config_test.go +++ b/backend/theme/config_test.go @@ -49,6 +49,7 @@ func TestThemeConfig_Validate_InvalidHexColor(t *testing.T) { t.Parallel() c := &Config{AccentColor: tt.color, BackgroundShade: BackgroundDark} + err := c.Validate() if err == nil { t.Error("Validate() expected error for invalid hex color, got nil") @@ -61,6 +62,7 @@ func TestThemeConfig_Validate_InvalidBackgroundShade(t *testing.T) { t.Parallel() c := &Config{AccentColor: "#ffd43b", BackgroundShade: "neon"} + err := c.Validate() if err == nil { t.Fatal("Validate() expected error for unknown shade, got nil")