Read Recent updates afresh per opening and guard their URLs by origin
CI / ci (push) Successful in 8m51s
CI / ci (pull_request) Successful in 8m26s

Address the review of PR #176 (Feature 21, task 96e2dc3f):

- MQ-176-01: useUpdates drops its list as soon as the sheet closes
  (gcTime 0), so each opening reads GET /api/v1/updates afresh and only
  marks seen through the newest of that read, never a cached list.
- MQ-176-02: parseUpdate checks each url with appPath from
  push/notification.ts, by parsed origin, instead of a prefix check that
  tabs and newlines got past; the url kept is the path as parsed.
- MQ-176-03: TestMarkUpdatesSeen asserts updated_at is kept and settings
  subscribers are not told.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-10 12:35:58 -04:00
co-authored by Claude Opus 5.5
parent 74e33a6236
commit 9978e200e6
4 changed files with 128 additions and 20 deletions
+20 -3
View File
@@ -45,6 +45,7 @@ var weekDates = []string{"2026-10-12", "2026-10-13", "2026-10-14", "2026-10-15",
type env struct {
svc *home.Service
st *store.Store
settings *household.SettingsService
notifier *notify.Service
loc *time.Location
}
@@ -116,7 +117,8 @@ func newEnv(t *testing.T) *env {
if err != nil {
t.Fatal(err)
}
svc, err := home.NewService(household.NewSettingsService(st), plans, suggestSvc, shop, notifier)
settings := household.NewSettingsService(st)
svc, err := home.NewService(settings, plans, suggestSvc, shop, notifier)
if err != nil {
t.Fatal(err)
}
@@ -124,7 +126,7 @@ func newEnv(t *testing.T) *env {
if err != nil {
t.Fatal(err)
}
return &env{svc: svc, st: st, notifier: notifier, loc: loc}
return &env{svc: svc, st: st, settings: settings, notifier: notifier, loc: loc}
}
// at reads the Home screen with the clock at the household-local wall
@@ -480,6 +482,15 @@ func TestMarkUpdatesSeen(t *testing.T) {
if !unread() {
t.Fatal("not unread with an event never seen")
}
// The settings were last edited well before: marking updates seen must
// keep that time and tell no settings subscriber.
edited := (store.Timestamp{Time: time.Date(2026, 10, 1, 9, 0, 0, 0, time.UTC)}).String()
if _, err := e.st.Writer.ExecContext(ctx, `UPDATE household_settings SET updated_at = ?`, edited); err != nil {
t.Fatal(err)
}
var notified int
unsubscribe := e.settings.Subscribe(func(household.Settings) { notified++ })
defer unsubscribe()
if err := e.svc.MarkUpdatesSeen(ctx, first); err != nil {
t.Fatal(err)
}
@@ -509,7 +520,7 @@ func TestMarkUpdatesSeen(t *testing.T) {
if err := e.svc.MarkUpdatesSeen(ctx, first); err != nil {
t.Fatal(err)
}
settings, err := household.NewSettingsService(e.st).Get(ctx)
settings, err := e.settings.Get(ctx)
if err != nil {
t.Fatal(err)
}
@@ -519,6 +530,12 @@ func TestMarkUpdatesSeen(t *testing.T) {
if settings.UpdatedBy != nil {
t.Errorf("updated_by = %q, want unset: marking updates seen is not a settings edit", *settings.UpdatedBy)
}
if settings.UpdatedAt != edited {
t.Errorf("updated_at = %s, want %s: marking updates seen is not a settings edit", settings.UpdatedAt, edited)
}
if notified != 0 {
t.Errorf("settings subscribers told %d times, want none: marking updates seen is not a settings edit", notified)
}
// The clock reads 17:00 UTC.
if err := e.svc.MarkUpdatesSeen(ctx, first.Add(2*time.Hour)); !errors.Is(err, home.ErrSeenInFuture) {