Owner Finish control on the Series detail page: confirm-gated finish, instant un-finish (#158)

This commit is contained in:
2026-08-22 17:06:45 +07:00
parent 77e3f710ec
commit 948ecae2cc
10 changed files with 390 additions and 7 deletions
+54
View File
@@ -394,3 +394,57 @@ func TestAdminSeriesCarriesForcePollAt(t *testing.T) {
t.Fatalf("row = %+v, want ForcePollAt 5000", page.Rows)
}
}
// SetSeriesFinished is the owner's finish stamp write: finishing writes the
// given ms, un-finishing writes zero — the one undo, the same shape as the
// correction stamp. Touching a missing series is not an error: the row may
// have been orphaned, and the caller's read decides what exists.
func TestSetSeriesFinishedStampsAndClears(t *testing.T) {
s := newTestStore(t)
seedAdminSeries(t, s, seriesSeed{key: "asura:x", url: "u", checkedAt: 9000, bookmarks: 1})
if err := s.SetSeriesFinished("asura", "x", 42); err != nil {
t.Fatalf("SetSeriesFinished: %v", err)
}
var got int64
if err := s.db.QueryRow(
`SELECT finished_at FROM series WHERE site = 'asura' AND series_id = 'x'`).Scan(&got); err != nil {
t.Fatalf("read finished_at: %v", err)
}
if got != 42 {
t.Fatalf("finished_at = %d, want 42", got)
}
if err := s.SetSeriesFinished("asura", "x", 0); err != nil {
t.Fatalf("SetSeriesFinished un-finish: %v", err)
}
if err := s.db.QueryRow(
`SELECT finished_at FROM series WHERE site = 'asura' AND series_id = 'x'`).Scan(&got); err != nil {
t.Fatalf("read finished_at after un-finish: %v", err)
}
if got != 0 {
t.Fatalf("finished_at = %d, want 0 (un-finish writes zero)", got)
}
if err := s.SetSeriesFinished("asura", "ghost", 42); err != nil {
t.Fatalf("SetSeriesFinished missing: %v", err)
}
}
// The admin projection carries the finish stamp so the web layer can render
// the finished state without a second read.
func TestAdminSeriesCarriesFinishedAt(t *testing.T) {
s := newTestStore(t)
seedAdminSeries(t, s, seriesSeed{key: "asura:x", url: "u", checkedAt: 1000, bookmarks: 1})
if err := s.SetSeriesFinished("asura", "x", 5000); err != nil {
t.Fatalf("SetSeriesFinished: %v", err)
}
page, err := s.SeriesPage(SeriesFilter{})
if err != nil {
t.Fatalf("SeriesPage: %v", err)
}
if len(page.Rows) != 1 || page.Rows[0].FinishedAt != 5000 {
t.Fatalf("row = %+v, want FinishedAt 5000", page.Rows)
}
}