fix(server,web): forward-fix CI lint + vitest failures
- gofmt -s on system.go, system_cron.go, api.go - rename unused r → _ in 3 fetcher_test.go HTTP handlers - TrackRow +queue test uses /add .* to queue/i (track-aware aria-label from #377) - /library/artists page test mocks likes + tanstack-query (ArtistCard now embeds LikeButton) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
+8
-8
@@ -29,15 +29,15 @@ func Mount(r chi.Router, pool *pgxpool.Pool, logger *slog.Logger, events *playev
|
|||||||
rng := rand.New(rand.NewSource(rand.Int63()))
|
rng := rand.New(rand.NewSource(rand.Int63()))
|
||||||
h := &handlers{
|
h := &handlers{
|
||||||
pool: pool, logger: logger, events: events, recCfg: recCfg,
|
pool: pool, logger: logger, events: events, recCfg: recCfg,
|
||||||
rng: rng.Float64,
|
rng: rng.Float64,
|
||||||
lidarrCfg: lidarrCfg,
|
lidarrCfg: lidarrCfg,
|
||||||
lidarrRequests: lidarrReqs,
|
lidarrRequests: lidarrReqs,
|
||||||
lidarrQuarantine: lidarrQuar,
|
lidarrQuarantine: lidarrQuar,
|
||||||
tracks: tracksSvc,
|
tracks: tracksSvc,
|
||||||
playlists: playlistsSvc,
|
playlists: playlistsSvc,
|
||||||
coverart: coverEnricher,
|
coverart: coverEnricher,
|
||||||
coverArtBackfillCap: coverBackfillCap,
|
coverArtBackfillCap: coverBackfillCap,
|
||||||
dataDir: dataDir,
|
dataDir: dataDir,
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Route("/api", func(api chi.Router) {
|
r.Route("/api", func(api chi.Router) {
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ func TestFetcher_Success(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFetcher_NotFound(t *testing.T) {
|
func TestFetcher_NotFound(t *testing.T) {
|
||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||||
http.Error(w, "not found", http.StatusNotFound)
|
http.Error(w, "not found", http.StatusNotFound)
|
||||||
}))
|
}))
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
@@ -50,7 +50,7 @@ func TestFetcher_NotFound(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFetcher_5xxIsTransient(t *testing.T) {
|
func TestFetcher_5xxIsTransient(t *testing.T) {
|
||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||||
http.Error(w, "boom", http.StatusInternalServerError)
|
http.Error(w, "boom", http.StatusInternalServerError)
|
||||||
}))
|
}))
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
@@ -81,7 +81,7 @@ func TestFetcher_SendsUserAgent(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFetcher_RateLimitSpacesCalls(t *testing.T) {
|
func TestFetcher_RateLimitSpacesCalls(t *testing.T) {
|
||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||||
_, _ = w.Write([]byte("ok"))
|
_, _ = w.Write([]byte("ok"))
|
||||||
}))
|
}))
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|||||||
@@ -82,12 +82,12 @@ const systemMixLength = 25
|
|||||||
// JitterMagnitude is 0 because daily determinism comes from tieBreakHash;
|
// JitterMagnitude is 0 because daily determinism comes from tieBreakHash;
|
||||||
// any randomness would defeat the within-day stability invariant.
|
// any randomness would defeat the within-day stability invariant.
|
||||||
var systemMixWeights = recommendation.ScoringWeights{
|
var systemMixWeights = recommendation.ScoringWeights{
|
||||||
BaseWeight: 1.0,
|
BaseWeight: 1.0,
|
||||||
LikeBoost: 2.0,
|
LikeBoost: 2.0,
|
||||||
RecencyWeight: 1.0,
|
RecencyWeight: 1.0,
|
||||||
SkipPenalty: 2.0,
|
SkipPenalty: 2.0,
|
||||||
JitterMagnitude: 0.0,
|
JitterMagnitude: 0.0,
|
||||||
ContextWeight: 0.5,
|
ContextWeight: 0.5,
|
||||||
SimilarityWeight: 1.5,
|
SimilarityWeight: 1.5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ import (
|
|||||||
// goroutine. Caller passes a context that's cancelled on graceful shutdown.
|
// goroutine. Caller passes a context that's cancelled on graceful shutdown.
|
||||||
//
|
//
|
||||||
// Lifecycle:
|
// Lifecycle:
|
||||||
// 1. Clear any stale in_flight=true rows from a previously crashed process
|
// 1. Clear any stale in_flight=true rows from a previously crashed process
|
||||||
// (safe at startup: by definition, nothing is running yet).
|
// (safe at startup: by definition, nothing is running yet).
|
||||||
// 2. Run once at startup so users catch up after a server restart without
|
// 2. Run once at startup so users catch up after a server restart without
|
||||||
// waiting up to 24h.
|
// waiting up to 24h.
|
||||||
// 3. Tick every 24h; runOnce on each tick.
|
// 3. Tick every 24h; runOnce on each tick.
|
||||||
// 4. Exit on context cancellation.
|
// 4. Exit on context cancellation.
|
||||||
//
|
//
|
||||||
// Per-user errors are logged but don't halt the loop. Per-cycle errors (e.g.,
|
// Per-user errors are logged but don't halt the loop. Per-cycle errors (e.g.,
|
||||||
// "list active users" failed) are logged but the next tick still fires.
|
// "list active users" failed) are logged but the next tick still fires.
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ describe('TrackRow', () => {
|
|||||||
|
|
||||||
test('+ queue button calls enqueueTrack and does NOT trigger row play', async () => {
|
test('+ queue button calls enqueueTrack and does NOT trigger row play', async () => {
|
||||||
render(TrackRow, { props: { tracks, index: 0 } });
|
render(TrackRow, { props: { tracks, index: 0 } });
|
||||||
await fireEvent.click(screen.getByRole('button', { name: /add to queue/i }));
|
await fireEvent.click(screen.getByRole('button', { name: /add .* to queue/i }));
|
||||||
expect(enqueueTrack).toHaveBeenCalledWith(tracks[0]);
|
expect(enqueueTrack).toHaveBeenCalledWith(tracks[0]);
|
||||||
expect(playQueue).not.toHaveBeenCalled();
|
expect(playQueue).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -20,7 +20,23 @@ vi.mock('$lib/api/queries', () => ({
|
|||||||
})
|
})
|
||||||
}));
|
}));
|
||||||
vi.mock('$lib/api/client', () => ({ api: { get: vi.fn() } }));
|
vi.mock('$lib/api/client', () => ({ api: { get: vi.fn() } }));
|
||||||
vi.mock('$lib/player/store.svelte', () => ({ playQueue: vi.fn() }));
|
vi.mock('$lib/player/store.svelte', () => ({
|
||||||
|
playQueue: vi.fn(),
|
||||||
|
enqueueTracks: vi.fn()
|
||||||
|
}));
|
||||||
|
vi.mock('$lib/api/artists', () => ({
|
||||||
|
listArtistTracks: vi.fn().mockResolvedValue([])
|
||||||
|
}));
|
||||||
|
vi.mock('$lib/api/likes', () => ({
|
||||||
|
createLikedIdsQuery: () =>
|
||||||
|
readable({ data: { track_ids: [], album_ids: [], artist_ids: [] }, isPending: false, isError: false }),
|
||||||
|
likeEntity: vi.fn().mockResolvedValue(undefined),
|
||||||
|
unlikeEntity: vi.fn().mockResolvedValue(undefined)
|
||||||
|
}));
|
||||||
|
vi.mock('@tanstack/svelte-query', async (orig) => {
|
||||||
|
const actual = (await orig()) as Record<string, unknown>;
|
||||||
|
return { ...actual, useQueryClient: () => ({ invalidateQueries: vi.fn() }) };
|
||||||
|
});
|
||||||
|
|
||||||
import Page from './+page.svelte';
|
import Page from './+page.svelte';
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user