fix: omit status on non-archive writes, skip finished in refresh and scan
This commit is contained in:
@@ -160,3 +160,39 @@ func TestPutStatusValidation(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// A PUT that omits the status field entirely (what a userscript build
|
||||
// predating the column sends) is the actual preserve path — the "" case
|
||||
// above only exercises the fresh-INSERT default and never touches an
|
||||
// existing bucket. This must both keep the archived bucket and still apply
|
||||
// the chapter progress carried in the same request.
|
||||
func TestPutOmittedStatusPreservesArchivedAndAppliesProgress(t *testing.T) {
|
||||
srv := newTestServer(t)
|
||||
|
||||
seed := httptest.NewRequest(http.MethodPut, "/bookmarks/asura:solo",
|
||||
strings.NewReader(`{"title":"Solo","status":"archived"}`))
|
||||
rr := httptest.NewRecorder()
|
||||
srv.ServeHTTP(rr, auth(seed))
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("seed status = %d, want 200 (body %s)", rr.Code, rr.Body.String())
|
||||
}
|
||||
|
||||
req := httptest.NewRequest(http.MethodPut, "/bookmarks/asura:solo",
|
||||
strings.NewReader(`{"title":"Solo","last_chapter":"12","last_chapter_num":12}`))
|
||||
rr = httptest.NewRecorder()
|
||||
srv.ServeHTTP(rr, auth(req))
|
||||
if rr.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want 200 (body %s)", rr.Code, rr.Body.String())
|
||||
}
|
||||
|
||||
var got Bookmark
|
||||
if err := json.Unmarshal(rr.Body.Bytes(), &got); err != nil {
|
||||
t.Fatalf("decode: %v", err)
|
||||
}
|
||||
if got.Status != "archived" {
|
||||
t.Fatalf("stored status = %q, want %q", got.Status, "archived")
|
||||
}
|
||||
if got.LastChapterNum != 12 {
|
||||
t.Fatalf("stored last_chapter_num = %v, want 12", got.LastChapterNum)
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -193,10 +193,11 @@ func scanBookmark(scan func(...any) error) (Bookmark, error) {
|
||||
if latestChapterNum.Valid {
|
||||
b.LatestChapterNum = &latestChapterNum.Float64
|
||||
}
|
||||
// A NULL or empty bucket would leave the row in no list at all, so it
|
||||
// reads as the default rather than being passed through.
|
||||
// A NULL, empty, or unrecognised bucket (e.g. a hand-edited row) would
|
||||
// leave the row in no list at all, so anything outside the three known
|
||||
// buckets reads as the default rather than being passed through.
|
||||
b.Status = status.String
|
||||
if b.Status == "" {
|
||||
if b.Status != statusReading && b.Status != statusArchived && b.Status != statusFinished {
|
||||
b.Status = statusReading
|
||||
}
|
||||
return b, nil
|
||||
|
||||
@@ -760,6 +760,39 @@ func TestUpsertEmptyStatusPreservesStored(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Mirrors the poller's read-modify-write in latest.go: Get the current row,
|
||||
// mutate only the latest-chapter fields, and Upsert the whole struct back.
|
||||
// cur.Status comes from Get (never empty — see scanBookmark), so it must
|
||||
// round-trip through Upsert unchanged rather than being reset.
|
||||
func TestLatestPollRoundTripPreservesArchived(t *testing.T) {
|
||||
store := newTestStore(t)
|
||||
base := Bookmark{
|
||||
Key: "asura:solo", Site: "asura", SeriesID: "solo",
|
||||
Status: statusArchived, UpdatedAt: time.Now().UnixMilli(),
|
||||
}
|
||||
if _, err := store.Upsert(base); err != nil {
|
||||
t.Fatalf("seed: %v", err)
|
||||
}
|
||||
|
||||
cur, found, err := store.Get(base.Key)
|
||||
if err != nil || !found {
|
||||
t.Fatalf("Get: found=%v err=%v", found, err)
|
||||
}
|
||||
|
||||
num := 7.0
|
||||
cur.LatestChapter = "7"
|
||||
cur.LatestChapterNum = &num
|
||||
cur.UpdatedAt = time.Now().UnixMilli()
|
||||
|
||||
stored, err := store.Upsert(cur)
|
||||
if err != nil {
|
||||
t.Fatalf("Upsert: %v", err)
|
||||
}
|
||||
if stored.Status != statusArchived {
|
||||
t.Fatalf("Status = %q, want it preserved as %q", stored.Status, statusArchived)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpsertReplacesStatusWhenGiven(t *testing.T) {
|
||||
store := newTestStore(t)
|
||||
base := Bookmark{
|
||||
|
||||
Reference in New Issue
Block a user