feat(offscreen): record proposal_made/action_taken/proposal_dismissed
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"keel/internal/ai"
|
||||
"keel/internal/harness"
|
||||
"keel/internal/memory"
|
||||
"keel/internal/tasks"
|
||||
)
|
||||
|
||||
@@ -138,3 +139,75 @@ func TestUnknownCommandErrors(t *testing.T) {
|
||||
t.Fatal("unknown command should error")
|
||||
}
|
||||
}
|
||||
|
||||
// newTestModeMem is newTestMode with an injected in-memory Store.
|
||||
func newTestModeMem(t *testing.T, ft *fakeTasks, backend ai.Backend, mem *memory.Fake) *Mode {
|
||||
t.Helper()
|
||||
svc := harness.Services{
|
||||
AI: ai.NewService(backend),
|
||||
Tasks: ft,
|
||||
Memory: mem,
|
||||
Clock: func() time.Time { return time.Unix(1000, 0) },
|
||||
Notify: func() {},
|
||||
}
|
||||
return New(svc)
|
||||
}
|
||||
|
||||
// waitEvent polls the fake until an event of kind appears, or fails after 2s.
|
||||
func waitEvent(t *testing.T, f *memory.Fake, kind string) memory.Event {
|
||||
t.Helper()
|
||||
deadline := time.Now().Add(2 * time.Second)
|
||||
for time.Now().Before(deadline) {
|
||||
for _, e := range f.Events() {
|
||||
if e.Kind == kind {
|
||||
return e
|
||||
}
|
||||
}
|
||||
time.Sleep(5 * time.Millisecond)
|
||||
}
|
||||
t.Fatalf("event %q never recorded (events: %+v)", kind, f.Events())
|
||||
return memory.Event{}
|
||||
}
|
||||
|
||||
func TestProposeRecordsProposalMade(t *testing.T) {
|
||||
mem := memory.NewFake()
|
||||
m := newTestModeMem(t, &fakeTasks{}, okBackend(), mem)
|
||||
if err := m.Command(context.Background(), "start", nil); err != nil {
|
||||
t.Fatalf("start: %v", err)
|
||||
}
|
||||
waitStatus(t, m, statusProposed)
|
||||
|
||||
ev := waitEvent(t, mem, "proposal_made")
|
||||
if ev.Data["next_action"] != "call mum" || ev.Data["proposal_id"] == "" {
|
||||
t.Fatalf("proposal_made data = %+v", ev.Data)
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfirmRecordsActionTakenWithSameID(t *testing.T) {
|
||||
mem := memory.NewFake()
|
||||
m := newTestModeMem(t, &fakeTasks{}, okBackend(), mem)
|
||||
_ = m.Command(context.Background(), "start", nil)
|
||||
waitStatus(t, m, statusProposed)
|
||||
made := waitEvent(t, mem, "proposal_made")
|
||||
|
||||
if err := m.Command(context.Background(), "confirm", nil); err != nil {
|
||||
t.Fatalf("confirm: %v", err)
|
||||
}
|
||||
taken := waitEvent(t, mem, "action_taken")
|
||||
if taken.Data["proposal_id"] != made.Data["proposal_id"] {
|
||||
t.Fatalf("action_taken id %v != proposal_made id %v", taken.Data["proposal_id"], made.Data["proposal_id"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestDismissRecordsProposalDismissed(t *testing.T) {
|
||||
mem := memory.NewFake()
|
||||
m := newTestModeMem(t, &fakeTasks{}, okBackend(), mem)
|
||||
_ = m.Command(context.Background(), "start", nil)
|
||||
waitStatus(t, m, statusProposed)
|
||||
_ = waitEvent(t, mem, "proposal_made")
|
||||
|
||||
if err := m.Command(context.Background(), "dismiss", nil); err != nil {
|
||||
t.Fatalf("dismiss: %v", err)
|
||||
}
|
||||
_ = waitEvent(t, mem, "proposal_dismissed")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user