Files
Agent-System-Backend/internal/genui/auto_test.go
T
weichenandCursor 6ff7fa9bd7
ci / vet-and-test (pull_request) Successful in 1m4s
Add Generative UI auto-present opt-in with budget and cooldown
Why: Known-boundary follow-up: owner opt-in auto page suggestions on
semantic task events without self-trigger from surface revisions.
Evidence: go test ./internal/genui/ ./internal/runmgr/ ./internal/settings/ ./internal/app/
Impact: Default-off settings key; material/plan/todo/document hooks nudge present.
Refs: docs/proposals/2026-10-12-generative-ui-auto-trigger.md

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-12 03:44:47 +00:00

54 lines
1.7 KiB
Go

package genui
import (
"testing"
"time"
)
func TestAutoDefaultOff(t *testing.T) {
a := NewAuto(func(string) bool { return true }, func(string) bool { return false }, nil)
if ok, skip := a.Try("alice", "c1", "plan"); ok || skip != "opt_in_off" {
t.Fatalf("want opt_in_off, got ok=%v skip=%q", ok, skip)
}
}
func TestAutoRequiresActivation(t *testing.T) {
a := NewAuto(func(string) bool { return false }, func(string) bool { return true }, nil)
if ok, skip := a.Try("alice", "c1", "plan"); ok || skip != "activation_off" {
t.Fatalf("want activation_off, got ok=%v skip=%q", ok, skip)
}
}
func TestAutoBudgetAndCooldown(t *testing.T) {
var exhausted int
now := time.Unix(1_700_000_000, 0).UTC()
a := NewAuto(func(string) bool { return true }, func(string) bool { return true },
func(owner, kind, detail string) {
if kind == "genui.auto_present_exhausted" {
exhausted++
}
})
a.now = func() time.Time { return now }
for i := 0; i < AutoBudgetPerHour; i++ {
ok, skip := a.Try("alice", "c1", "plan")
if !ok {
t.Fatalf("shot %d should pass, skip=%q", i, skip)
}
now = now.Add(AutoCooldown + time.Second)
}
if ok, skip := a.Try("alice", "c1", "plan"); ok || skip != "budget" || exhausted != 1 {
t.Fatalf("want budget exhausted, ok=%v skip=%q exhausted=%d", ok, skip, exhausted)
}
// 冷却:同一时刻第二次拒绝
a2 := NewAuto(func(string) bool { return true }, func(string) bool { return true }, nil)
a2.now = func() time.Time { return now }
if ok, _ := a2.Try("alice", "c2", "art"); !ok {
t.Fatal("first should pass")
}
if ok, skip := a2.Try("alice", "c2", "art"); ok || skip != "cooldown" {
t.Fatalf("want cooldown, got ok=%v skip=%q", ok, skip)
}
}