From 407134907885a77bbc8501cfcfd7feb8b2cea4fc Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 22 Oct 2026 19:56:31 +0200 Subject: [PATCH] issue 1858: prove each act and its line in the real store (integration, compiled only) The lead's try runs it: an act and its line kept together, a failed act keeping neither, correct's three writes together, the removal of old lines, and handling gone with its entry. --- .../pgstore_integration_test.go | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/modules/mesh-mail-reader/cmd/mesh-mail-reader/pgstore_integration_test.go b/modules/mesh-mail-reader/cmd/mesh-mail-reader/pgstore_integration_test.go index 3d5eab4e..4009d925 100644 --- a/modules/mesh-mail-reader/cmd/mesh-mail-reader/pgstore_integration_test.go +++ b/modules/mesh-mail-reader/cmd/mesh-mail-reader/pgstore_integration_test.go @@ -269,3 +269,45 @@ func TestPgStoreKeepsTasksPromisesAndReadLater(t *testing.T) { t.Fatalf("after removing task 1: %+v (%v), want task 2 alone, keeping its number, and no read later", all, err) } } + +// 1858/AC4, AC7 through the real store: an act and its line are kept together, a failed act keeps neither, +// correct's three writes go together, old lines are removed, and handling goes with its entry. +func TestPgStoreKeepsEachActWithItsLine(t *testing.T) { + ctx := context.Background() + s := preparedStore(t) + at := time.Date(2026, 10, 22, 9, 0, 0, 0, time.UTC) + id, err := s.AddEntry(ctx, Entry{Account: "work", MessageID: "", Folder: "INBOX", Date: at, Mark: MarkMatters, + Judged: at, Tasks: []Task{{N: 1, Line: "Book the Harbor demo room"}}}) + if err != nil { + t.Fatal(err) + } + if err := s.Act(ctx, Handling{Entry: id, Item: "task 1", Handled: at}, ActionLine{What: ActHandled, Entry: id, Item: "task 1", Mode: "work", At: at}); err != nil { + t.Fatal(err) + } + if err := s.Act(ctx, Handling{Entry: id + 99, Item: ItemMail, Handled: at}, ActionLine{What: ActHandled, Entry: id + 99, Item: ItemMail, Mode: "work", At: at}); err != ErrNotFound { + t.Fatalf("an act on no entry: %v, want ErrNotFound", err) + } + hs, _ := s.Handlings(ctx) + lines, _ := s.Actions(ctx, 10) + if len(hs) != 1 || !hs[0].Handled.Equal(at) || len(lines) != 1 || lines[0].Item != "task 1" { + t.Fatalf("handlings %+v, lines %+v; want the one act and its one line", hs, lines) + } + e, _, _ := s.Entry(ctx, id) + e.Mark = MarkNeither + if _, err := s.CorrectEntry(ctx, e, Lesson{SenderAddress: "lena@harbor.example", Change: "mark: matters -> neither", Made: at}, + ActionLine{What: ActCorrected, Entry: id, Item: ItemMail, Mode: "work", At: at.Add(time.Minute)}); err != nil { + t.Fatal(err) + } + if lessons, _ := s.Lessons(ctx); len(lessons) != 1 { + t.Fatalf("lessons %+v, want the correction's one", lessons) + } + if removed, err := s.RemoveActionsBefore(ctx, at.Add(30*time.Second)); err != nil || removed != 1 { + t.Fatalf("removed %d (%v), want the one line older than the bound", removed, err) + } + if _, err := s.pool.Exec(ctx, `delete from mail_entry where id = $1`, id); err != nil { + t.Fatal(err) + } + if hs, _ := s.Handlings(ctx); len(hs) != 0 { + t.Fatalf("handlings %+v after their entry went, want none", hs) + } +}