From 3e3ad89645610098a0ca7a0457d2c164b159071d Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Thu, 30 Apr 2026 20:49:11 -0400 Subject: [PATCH] fix: T16 verification cleanups MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - golangci-lint: errcheck on resp.Body.Close in Lidarr client + revive unused-parameter in delete_test.go - coverage: 2 error-branch tests added to lidarrquarantine.Service (DeleteFile + DeleteViaLidarr track-not-found paths) bring per-package coverage to 81.4% (target >=80%) - search/tracks.test.ts: same TrackMenu name-collision fix T13 applied to TrackRow.test.ts — exact-string button match instead of regex --- internal/lidarr/delete.go | 2 +- internal/lidarr/delete_test.go | 2 +- internal/lidarr/lookup_mbid.go | 4 +- internal/lidarrquarantine/service_test.go | 41 +++++++++++++++++++++ web/src/routes/search/tracks/tracks.test.ts | 11 +++++- 5 files changed, 54 insertions(+), 6 deletions(-) diff --git a/internal/lidarr/delete.go b/internal/lidarr/delete.go index 2a060320..9755c680 100644 --- a/internal/lidarr/delete.go +++ b/internal/lidarr/delete.go @@ -64,6 +64,6 @@ func (c *Client) DeleteAlbum(ctx context.Context, lidarrAlbumID int, deleteFiles if err != nil { return err } - resp.Body.Close() + _ = resp.Body.Close() return nil } diff --git a/internal/lidarr/delete_test.go b/internal/lidarr/delete_test.go index db8d3822..eb0edf0d 100644 --- a/internal/lidarr/delete_test.go +++ b/internal/lidarr/delete_test.go @@ -203,7 +203,7 @@ func TestDeleteAlbum_NetworkErrorReturnsErrUnreachable(t *testing.T) { } func TestDeleteAlbum_ZeroIDRejected(t *testing.T) { - c, srv := newTestClient(func(w http.ResponseWriter, _ *http.Request) { + c, srv := newTestClient(func(_ http.ResponseWriter, _ *http.Request) { t.Error("server should not be called with zero id") }) defer srv.Close() diff --git a/internal/lidarr/lookup_mbid.go b/internal/lidarr/lookup_mbid.go index ecfc0e08..b6e17781 100644 --- a/internal/lidarr/lookup_mbid.go +++ b/internal/lidarr/lookup_mbid.go @@ -18,7 +18,7 @@ func (c *Client) LookupArtistByMBID(ctx context.Context, mbid string) (LidarrArt if err != nil { return LidarrArtist{}, err } - defer resp.Body.Close() + defer func() { _ = resp.Body.Close() }() var rows []LidarrArtist if err := json.NewDecoder(resp.Body).Decode(&rows); err != nil { @@ -41,7 +41,7 @@ func (c *Client) LookupAlbumByMBID(ctx context.Context, mbid string) (LidarrAlbu if err != nil { return LidarrAlbum{}, err } - defer resp.Body.Close() + defer func() { _ = resp.Body.Close() }() var rows []LidarrAlbum if err := json.NewDecoder(resp.Body).Decode(&rows); err != nil { diff --git a/internal/lidarrquarantine/service_test.go b/internal/lidarrquarantine/service_test.go index a0708765..cca8e26c 100644 --- a/internal/lidarrquarantine/service_test.go +++ b/internal/lidarrquarantine/service_test.go @@ -491,3 +491,44 @@ func TestDeleteViaLidarr_LidarrAlbumNotFound(t *testing.T) { t.Errorf("err = %v, want ErrLidarrAlbumNotFound", err) } } + +func TestDeleteFile_TrackNotFound(t *testing.T) { + pool := newPool(t) + user := seedUser(t, pool, "alice") + var bogus pgtype.UUID + bogus.Bytes = [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + bogus.Valid = true + + svc := NewService(pool, lidarrconfig.New(pool), nil) + _, err := svc.DeleteFile(context.Background(), bogus, user.ID) + if !errors.Is(err, ErrTrackNotFound) { + t.Errorf("err = %v, want ErrTrackNotFound", err) + } +} + +func TestDeleteViaLidarr_TrackNotFound(t *testing.T) { + pool := newPool(t) + user := seedUser(t, pool, "alice") + + stub := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusOK) + })) + t.Cleanup(stub.Close) + cfg := lidarrconfig.New(pool) + if err := cfg.Save(context.Background(), lidarrconfig.Config{ + Enabled: true, BaseURL: stub.URL, APIKey: "k", + }); err != nil { + t.Fatalf("save config: %v", err) + } + clientFn := func() *lidarr.Client { return lidarr.NewClient(stub.URL, "k") } + svc := NewService(pool, cfg, clientFn) + + var bogus pgtype.UUID + bogus.Bytes = [16]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16} + bogus.Valid = true + + _, _, err := svc.DeleteViaLidarr(context.Background(), bogus, user.ID) + if !errors.Is(err, ErrTrackNotFound) { + t.Errorf("err = %v, want ErrTrackNotFound", err) + } +} diff --git a/web/src/routes/search/tracks/tracks.test.ts b/web/src/routes/search/tracks/tracks.test.ts index 4d515483..f64a46fd 100644 --- a/web/src/routes/search/tracks/tracks.test.ts +++ b/web/src/routes/search/tracks/tracks.test.ts @@ -35,6 +35,13 @@ vi.mock('@tanstack/svelte-query', async (orig) => { return { ...actual, useQueryClient: () => ({}) }; }); +vi.mock('$lib/api/quarantine', () => ({ + flagTrack: vi.fn(), + unflagTrack: vi.fn(), + listMyQuarantine: vi.fn().mockResolvedValue([]), + createMyQuarantineQuery: vi.fn() +})); + import TracksOverflow from './+page.svelte'; import { createSearchTracksInfiniteQuery } from '$lib/api/queries'; import { playRadio } from '$lib/player/store.svelte'; @@ -62,7 +69,7 @@ describe('search tracks overflow', () => { mockInfiniteQuery({ pages: [page([track], 1)] }) ); render(TracksOverflow); - expect(screen.getByRole('button', { name: /So What/ })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: 'So What' })).toBeInTheDocument(); }); test('clicking a track row triggers playRadio with the track id', async () => { @@ -70,7 +77,7 @@ describe('search tracks overflow', () => { mockInfiniteQuery({ pages: [page([track], 1)] }) ); render(TracksOverflow); - await fireEvent.click(screen.getByRole('button', { name: /So What/ })); + await fireEvent.click(screen.getByRole('button', { name: 'So What' })); expect(playRadio).toHaveBeenCalledWith('t1'); });