fix(podcasts): page search hits episode titles/descriptions (issue #8)

WHY: the /podcasts search box filtered feed CARDS only (title, display
name, host, publisher, feed description). D14's episode search existed
only as the /api/podcasts/search endpoint and was never wired into the
page — searching 'Quarter' (present only in episode titles) cleared the
grid while 'Trader' (feed metadata) survived.

The page query now consults SearchMyPodcastEpisodes (subscription-scoped
via RLS — the caller's identity) when a query is present; a feed
surfaces when its OWN metadata OR any of its episodes matches, with an
'N matching episode(s)' badge on the card.

PIN: SSR test with a needle that exists only in an episode title — the
feed must surface with the match count.
This commit is contained in:
John O'Keefe committed 2026-10-29 19:49:39 -04:00
1 parent c753780817
commit ffc80f7ba7
5 files changed
+129 -38

No files matched your search

+33
View File
@@ -697,3 +697,36 @@ func TestPodcastOrderFormEncoding(t *testing.T) {
assert.Equal(t, http.StatusBadRequest, formPut(""), "missing order stays rejected (required)")
assert.Equal(t, http.StatusBadRequest, formPut("order=sideways"), "invalid order stays rejected")
}
// ---- issue #8: page search hits EPISODE titles/descriptions too ----
func TestPodcastPageSearchEpisodes(t *testing.T) {
setup := setupTestServer(t)
lib, _ := createPodcastsLibrary(t, setup, "test PageSearch Podcasts")
// Feed title deliberately does NOT contain the needle.
feed, err := setup.DB.CreatePodcastFeed(adminSeedCtx(t, setup), database.CreatePodcastFeedParams{
LibraryID: lib.ID,
FeedUrl: "https://feed.invalid/page-search.xml",
Title: "Trader Tales Show",
})
require.NoError(t, err)
upsertTestEpisode(t, setup, feed, "ps-1", "Zarkorrin Blaster", 1)
subscribeRaw(t, setup, getRegularUserID(t, setup.DB), feed.ID)
// SSR page search: the needle exists only in an EPISODE title.
req, _ := http.NewRequest(http.MethodGet, setup.Server.URL+"/podcasts?q=Zarkorrin", nil)
req.Header.Set("Authorization", "Bearer "+setup.RegularToken)
resp, err := http.DefaultClient.Do(req)
require.NoError(t, err)
defer func() { _ = resp.Body.Close() }()
require.Equal(t, http.StatusOK, resp.StatusCode)
var buf bytes.Buffer
_, _ = buf.ReadFrom(resp.Body)
body := buf.String()
assert.Contains(t, body, "Trader Tales Show",
"PIN: a feed surfaces when an EPISODE matches the query, even when the feed's own metadata does not")
assert.Contains(t, body, "matching episode",
"the match count renders on the card")
}