返回 DeepSeek-Reasonix
interject_test.go
根目录 / internal / cli / interject_test.go
1 package cli
2
3 import (
4 "testing"
5
6 tea "charm.land/bubbletea/v2"
7
8 "reasonix/internal/control"
9 "reasonix/internal/event"
10 "reasonix/internal/sessioninbox"
11 )
12
13 type busyInboxController struct {
14 control.SessionAPI
15 }
16
17 func (c *busyInboxController) Running() bool { return true }
18
19 func (c *busyInboxController) TryEnqueueFollowup(req control.InboxRequest) (sessioninbox.InboxReceipt, error) {
20 return c.EnqueueInbox(req)
21 }
22
23 func TestInterjectQueuesWhileRunningWithoutOverwrite(t *testing.T) {
24 m := newInboxTestChatTUI(t)
25 m.state = tuiRunning
26
27 m.input.SetValue("first")
28 m0, _ := m.update(tea.KeyPressMsg{Code: tea.KeyEnter})
29 m = m0.(chatTUI)
30
31 m.input.SetValue("second")
32 m0, _ = m.update(tea.KeyPressMsg{Code: tea.KeyEnter})
33 m = m0.(chatTUI)
34
35 m.input.SetValue("")
36 m0, _ = m.update(tea.KeyPressMsg{Code: tea.KeyEnter})
37 m = m0.(chatTUI)
38
39 got := m.inboxBodies()
40 if want := []string{"first", "second"}; len(got) != len(want) || got[0] != want[0] || got[1] != want[1] {
41 t.Fatalf("inbox = %v, want %v (second must not overwrite first; empty must not queue)", got, want)
42 }
43 if m.state != tuiRunning {
44 t.Fatalf("queuing input must not change state; got %v", m.state)
45 }
46 }
47
48 func TestInterjectLeavesQueueOnTurnDoneForControllerDispatch(t *testing.T) {
49 r := &blockingTurnRunner{started: make(chan struct{})}
50 dir := t.TempDir()
51 ctrl := newOwnedTestController(t, control.Options{Runner: r, Sink: event.Discard, SessionDir: dir, Label: "test"})
52 ctrl.EnsureSessionPath()
53 m := newChatTUI(ctrl, "", make(chan event.Event, 8), 80)
54 m.ctrl = &busyInboxController{SessionAPI: ctrl}
55 m.state = tuiRunning
56 m.seedInbox("first", "second")
57
58 // CLI no longer dequeues on TurnDone; durable items stay until the controller
59 // admits and acks them. Pause so dispatch does not immediately consume.
60 _ = m.ctrl.SetInboxPaused(true)
61 m0, _ := m.update(agentEventMsg(event.Event{Kind: event.TurnDone}))
62 m = m0.(chatTUI)
63
64 got := m.inboxBodies()
65 if len(got) != 2 || got[0] != "first" || got[1] != "second" {
66 t.Fatalf("TurnDone must not drop durable inbox items; got %v", got)
67 }
68 }
69
70 func newInboxTestChatTUI(t *testing.T) chatTUI {
71 t.Helper()
72 dir := t.TempDir()
73 ctrl := newOwnedTestController(t, control.Options{SessionDir: dir, Label: "test", Sink: event.Discard})
74 ctrl.EnsureSessionPath()
75 m := newTestChatTUI()
76 m.ctrl = &busyInboxController{SessionAPI: ctrl}
77 return m
78 }
79
79 lines GO