package foryou import ( "bytes" "encoding/json" "testing" "github.com/ponzischeme89/memby/server/internal/store" "github.com/ponzischeme89/memby/server/internal/tracearr" ) func TestImportedSessionUsesStableKeyAndRecommendationFingerprint(t *testing.T) { session := tracearr.Session{ ID: "session-1", MediaType: "movie", MediaTitle: "Arrival", ProgressMs: 500, TotalDurationMs: 1000, } session.User.ID = "user-1" session.User.Username = "Matt" first, ok := importedSession(session, "configured-server") if !ok { t.Fatal("session was rejected") } if first.ServerID != "configured-server" || first.SessionID != "session-1" { t.Fatalf("key = %q/%q", first.ServerID, first.SessionID) } second, _ := importedSession(session, "configured-server") if !bytes.Equal(first.SourceFingerprint, second.SourceFingerprint) { t.Fatal("unchanged session did not produce a stable fingerprint") } session.ProgressMs = 750 updated, _ := importedSession(session, "configured-server") if bytes.Equal(first.SourceFingerprint, updated.SourceFingerprint) { t.Fatal("updated progress was not detected by the fingerprint") } } func TestBuildPreparedRowsUsesMultipleSourcesAndDeduplicatesTitles(t *testing.T) { items := make([]store.PreparedForYouItem, 0, 120) for i := 0; i < 120; i++ { sourceID, sourceTitle := "six-feet-under", "Six Feet Under" genre := "Drama" if i%2 == 1 { sourceID, sourceTitle = "arrival", "Arrival" genre = "Science Fiction" } id := "item-" + itoaForTest(i) items = append(items, store.PreparedForYouItem{ ItemID: id, BaseRank: i + 1, Payload: json.RawMessage(`{"Id":"` + id + `"}`), CompatibilityScore: 0.8, CompatibilityLabel: "Direct plays well on this TV", RecommendationReason: "Because you finished " + sourceTitle, ReasonGenre: genre, ReasonSourceItemID: sourceID, ReasonSourceTitle: sourceTitle, }) } rows := buildPreparedRows(items, 0, 4) if len(rows) < 4 { t.Fatalf("expected several prepared rows, got %d", len(rows)) } titles := map[string]bool{} itemIDs := map[string]bool{} for _, row := range rows { titles[row.Title] = true for _, raw := range row.Items { var item struct { ID string `json:"Id"` } if err := json.Unmarshal(raw, &item); err != nil { t.Fatal(err) } if itemIDs[item.ID] { t.Fatalf("item %q appeared in more than one row", item.ID) } itemIDs[item.ID] = true } } if !titles["Because you finished Six Feet Under"] || !titles["Because you finished Arrival"] { t.Fatalf("completed-title rows = %+v", titles) } } func TestBuildPreparedRowsKeepsASingleGenuinePickup(t *testing.T) { rows := buildPreparedRows([]store.PreparedForYouItem{{ ItemID: "show-1", BaseRank: 1, Payload: json.RawMessage(`{"Id":"show-1"}`), ReasonKind: "pick-up", RecommendationReason: "You left this in season 1 ยท pick it up again", }}, 0, 4) if len(rows) != 1 || rows[0].ID != "for-you:pick-up" || rows[0].Title != "Pick these up again" || len(rows[0].Items) != 1 { t.Fatalf("pickup rows = %+v", rows) } } func itoaForTest(value int) string { if value == 0 { return "0" } var digits [20]byte position := len(digits) for value > 0 { position-- digits[position] = byte('0' + value%10) value /= 10 } return string(digits[position:]) }