Files
minstrel/internal/notifications/render_test.go
T
bvandeusenandClaude Opus 5.5 0f58ebcd6c
release / govulncheck (push) Successful in 14s
release / web (push) Failing after 1m26s
release / go (push) Successful in 1m35s
release / integration (push) Successful in 5m8s
release / android (push) Successful in 5m12s
release / Build signed APK (releases and dev) (push) Successful in 5m26s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Skipped
release / Verify release artifacts (tag releases only) (push) Skipped
feat: duplicates settle themselves: retitled copies across releases link, alike versions on one album are dismissed, and a file in another song's slot is removed so the album is fetched again (M498 #6159-#6162)
The operator's library had 536 groups waiting for review, 2026-10-19. A sample
showed most were one recording under two titles on two releases.

- The headline and the Duplicates count leave out cross-release groups, which
  the resolver keeps and links: the headline read 3,479 when 536 needed review.
- Any group spanning albums is cross_release and is linked as one song,
  whatever its titles say. Nothing is deleted.
- One album, two versions named as such ("Lovesick (Instrumental)") and not
  byte-identical: a new class, distinct, dismissed by the resolver.
- One album, one recording under different song titles (mismatch): the
  album's cached MusicBrainz track list decides. When exactly one slot's song
  is as long as the file and every other slot's song is clearly not, the other
  copies are removed and their tracks marked missing, so the reacquisition
  sweeper wants the album back. Otherwise the group stays for review.
- The duplicates_found notice moves from the sweep to the resolver: it names
  only groups a pass first left for review.
- Resolved automatically lists dismissals and wrong-slot removals beside
  merges.

Migration 0094 adds 'distinct' to the class CHECK (rule 36).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 23:22:38 -04:00

87 lines
4.0 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package notifications
import (
"encoding/json"
"testing"
"github.com/stretchr/testify/require"
)
// render stores p the way Notify does (through Map) and reads it back.
func render(k Kind, p Payload) Rendered {
b, err := json.Marshal(p.Map())
if err != nil {
panic(err)
}
return Render(k, b)
}
func TestRender_EveryKindHasATitleAndALink(t *testing.T) {
for _, k := range Kinds() {
r := Render(k, []byte(`{}`))
require.NotEmpty(t, r.Title, k)
require.NotEqual(t, "Notification", r.Title, "%s falls through to the default", k)
require.NotEmpty(t, r.Link, k)
}
}
func TestRender_RequestCompletedLinksToWhatArrived(t *testing.T) {
require.Equal(t, "/albums/al-1", render(KindRequestCompleted, Payload{Name: "WWW", AlbumID: "al-1", ArtistID: "ar-1"}).Link)
require.Equal(t, "/artists/ar-1", render(KindRequestCompleted, Payload{Name: "Moe Shop", ArtistID: "ar-1"}).Link)
require.Equal(t, "/requests", render(KindRequestCompleted, Payload{Name: "WWW"}).Link)
require.Equal(t, "WWW has arrived.", render(KindRequestCompleted, Payload{Name: "WWW"}).Body)
}
func TestRender_RejectionCarriesTheReasonWhenThereIsOne(t *testing.T) {
require.Equal(t, "WWW was declined.", render(KindRequestRejected, Payload{Name: "WWW"}).Body)
require.Equal(t, "WWW was declined: already owned", render(KindRequestRejected, Payload{Name: "WWW", Reason: "already owned"}).Body)
}
func TestRender_CoalescedCountsReadNaturally(t *testing.T) {
require.Equal(t, "1 track went missing", render(KindTracksMissing, Payload{Count: 1}).Title)
require.Equal(t, "14 tracks went missing", render(KindTracksMissing, Payload{Count: 14}).Title)
require.Equal(t, "Library scan failed", render(KindScanFailed, Payload{Count: 1, Detail: "x"}).Title)
require.Equal(t, "Library scan failed 3 times", render(KindScanFailed, Payload{Count: 3}).Title)
require.Equal(t, "Some tracks went missing", Render(KindTracksMissing, []byte(`{}`)).Title)
}
// M542: a notice says which, not only how many.
func TestRender_NamesWhatChanged(t *testing.T) {
require.Equal(t, "No longer on disk: Weezer – Buddy Holly.",
render(KindTracksMissing, Payload{Count: 1, Items: []string{"Weezer – Buddy Holly"}}).Body)
require.Equal(t, "No longer on disk: A – 1 and B – 2.",
render(KindTracksMissing, Payload{Count: 2, Items: []string{"A – 1", "B – 2"}}).Body)
// Three are named; the rest of the count, not only the rest of the
// stored names, is "more".
require.Equal(t, "Held more than once: A, B, C and 9 more.",
render(KindDuplicatesFound, Payload{Count: 12, Items: []string{"A", "B", "C", "D", "E"}}).Body)
require.Equal(t, "12 new duplicates to review", render(KindDuplicatesFound, Payload{Count: 12}).Title)
require.Equal(t, "Extra copies removed, the right one kept: A and B.",
render(KindDuplicatesResolved, Payload{Count: 2, Items: []string{"A", "B"}}).Body)
require.Equal(t, "Failed to play: Weezer – Buddy Holly (alice).",
render(KindPlaybackErrors, Payload{Count: 1, Items: []string{"Weezer – Buddy Holly (alice)"}}).Body)
}
func TestRender_RowsFromBeforeItemsReadAsTheyDid(t *testing.T) {
require.Equal(t, "Their files are no longer where the library expects them.",
render(KindTracksMissing, Payload{Count: 4}).Body)
require.Equal(t, "Merged 8 duplicate copies.",
render(KindDuplicatesResolved, Payload{Count: 716, Detail: "Merged 8 duplicate copies."}).Body)
}
func TestRender_AScanFailureSaysWhatStopped(t *testing.T) {
r := render(KindScanFailed, Payload{Count: 1, Detail: "scan root \"/music\" unavailable"})
require.Equal(t, `The last scan stopped: scan root "/music" unavailable`, r.Body)
require.Equal(t, "/admin/library", r.Link)
}
func TestRender_AnUnreadablePayloadStillRenders(t *testing.T) {
r := Render(KindRequestApproved, []byte(`not json`))
require.Equal(t, "Request approved", r.Title)
require.Equal(t, "Your request is on its way.", r.Body)
}
func TestPayloadMap_DropsEmptyFields(t *testing.T) {
require.Equal(t, map[string]any{"name": "WWW", "count": float64(2)}, Payload{Name: "WWW", Count: 2}.Map())
}