Files
minstrel/internal/api/lidarr_test.go
T
bvandeusenandClaude Opus 5.5 77389f88bc
release / govulncheck (push) Successful in 22s
release / web (push) Failing after 24s
release / go (push) Successful in 1m57s
release / integration (push) Successful in 4m1s
release / Attach APK to the Release (tag releases only) (push) Canceled after 0s
release / Build + push container image (push) Canceled after 0s
release / Verify release artifacts (tag releases only) (push) Canceled after 0s
release / android (push) Canceled after 4m38s
release / Build signed APK (releases and dev) (push) Canceled after 4m37s
feat: a release catalogue from MusicBrainz; request search asks it directly (M502 #5519)
Minstrel keeps its own record of what artists have released, read from
MusicBrainz, so the wanted list, search and import no longer need Lidarr.

- internal/musicbrainz: searches (artists, release groups, recordings) and
  browses (an artist's release groups; a group's releases with track lists).
  One process-wide pacer at 1.1s, shared with tag enrichment, because
  MusicBrainz's limit is per address. A 503 throttle is retried.
- Migration 0080: mb_artists, mb_release_groups, mb_artist_release_groups
  (a collaboration belongs to each credited artist), mb_releases,
  mb_release_tracks.
- internal/catalogue: Discography and Releases serve the held copy and
  re-read it when older than 7 or 30 days. An unreachable MusicBrainz
  serves the stale copy, marked. An hourly pass re-reads due artists.
- Art for what isn't held comes through /api/catalogue/art from the
  enabled cover-art sources (Cover Art Archive by release group, then the
  name-based sources) and is kept on disk, so the browser never fetches a
  third-party host. A miss is a 404 and the card shows its icon.
- Request search moves from /api/lidarr/search to /api/catalogue/search,
  with the same response shape. Albums are release groups, and "in
  library" matches albums.release_group_mbid. A 10-minute cache absorbs
  search-as-you-type. Discover suggestions point at the art endpoint
  instead of looking up Lidarr.
- Android calls the new path and loads Discover art through ServerImage.
  Installed builds older than this one lose Discover search until they
  update (no compatibility path, rule 22).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 21:08:22 -04:00

56 lines
1.7 KiB
Go

package api
import (
"context"
"net/http"
"net/http/httptest"
"testing"
"git.fabledsword.com/bvandeusen/minstrel/internal/lidarrconfig"
)
// Helpers shared by the request, quarantine and notification tests. The
// Lidarr search they once sat beside is now the catalogue search
// (catalogue_test.go, M502 #5519).
// resetLidarrState clears lidarr_requests rows and resets lidarr_config
// to the factory-default state (enabled=false, nulls) between tests.
func resetLidarrState(t *testing.T, h *handlers) {
t.Helper()
ctx := context.Background()
if _, err := h.pool.Exec(ctx,
"DELETE FROM lidarr_requests; UPDATE lidarr_config SET enabled=false, base_url=NULL, api_key=NULL WHERE id=1",
); err != nil {
t.Fatalf("resetLidarrState: %v", err)
}
}
// saveLidarrConfig writes a test lidarr_config row pointing at the given stub URL.
func saveLidarrConfig(t *testing.T, h *handlers, baseURL string, enabled bool) {
t.Helper()
svc := lidarrconfig.New(h.pool)
err := svc.Save(context.Background(), lidarrconfig.Config{
Enabled: enabled,
BaseURL: baseURL,
APIKey: "test-key",
DefaultQualityProfileID: 1,
DefaultRootFolderPath: "/music",
})
if err != nil {
t.Fatalf("saveLidarrConfig: %v", err)
}
}
// newLidarrStub creates an httptest.Server that always returns the given body
// with 200 OK for any /api/v1/* path.
func newLidarrStub(t *testing.T, body string) *httptest.Server {
t.Helper()
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(body))
}))
t.Cleanup(srv.Close)
return srv
}