| 1 | package bot |
| 2 | |
| 3 | import ( |
| 4 | "path/filepath" |
| 5 | "strings" |
| 6 | "testing" |
| 7 | "time" |
| 8 | |
| 9 | "reasonix/internal/control" |
| 10 | "reasonix/internal/event" |
| 11 | "reasonix/internal/sessioninbox" |
| 12 | ) |
| 13 | |
| 14 | func TestCollectAppendDeduplicatesPlatformRedelivery(t *testing.T) { |
| 15 | dir := t.TempDir() |
| 16 | ctrl := control.New(control.Options{ |
| 17 | SessionPath: filepath.Join(dir, "s.jsonl"), |
| 18 | SessionDir: dir, |
| 19 | Sink: event.Discard, |
| 20 | }) |
| 21 | t.Cleanup(ctrl.Close) |
| 22 | first := InboundMessage{ |
| 23 | Platform: PlatformFeishu, ChatType: ChatDM, ChatID: "chat-1", |
| 24 | UserID: "user-1", MessageID: "msg-1", Text: "first request", |
| 25 | } |
| 26 | rec, err := enqueueViaInbox(ctrl, first, sessioninbox.IntentFollowup) |
| 27 | if err != nil { |
| 28 | t.Fatal(err) |
| 29 | } |
| 30 | second := first |
| 31 | second.MessageID = "msg-2" |
| 32 | second.Text = "second request" |
| 33 | for range 2 { |
| 34 | got, err := collectAppend(ctrl, second, time.Minute) |
| 35 | if err != nil { |
| 36 | t.Fatal(err) |
| 37 | } |
| 38 | if got.ItemID != rec.ItemID { |
| 39 | t.Fatalf("collect item = %q, want %q", got.ItemID, rec.ItemID) |
| 40 | } |
| 41 | } |
| 42 | _, env, err := ctrl.ReadInboxItem(rec.ItemID) |
| 43 | if err != nil { |
| 44 | t.Fatal(err) |
| 45 | } |
| 46 | if strings.Count(env.SubmitText, "second request") != 1 { |
| 47 | t.Fatalf("redelivered collect body = %q", env.SubmitText) |
| 48 | } |
| 49 | recovered := botMessageFromEnvelope(env, InboundMessage{}) |
| 50 | if recovered.Platform != second.Platform || recovered.ChatID != second.ChatID || recovered.MessageID != second.MessageID { |
| 51 | t.Fatalf("durable route metadata was not updated: %+v", recovered) |
| 52 | } |
| 53 | } |
| 54 |