fix: keep Cua foreground actions on the target window
This commit is contained in:
1 parent
889a951c9b
commit
6de0b1b276
13 files changed
+327
-31
No files matched your search
@@ -0,0 +1,95 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestForegroundActivatesBeforeInputAndDoesNotRestore(t *testing.T) {
|
||||
var calls []string
|
||||
foreground := int64(10) // The user's foreground app, e.g. Codex.
|
||||
call := func(name string, args obj) (obj, error) {
|
||||
calls = append(calls, name)
|
||||
if name == "bring_to_front" {
|
||||
if len(args) != 2 || num(args["window_id"]) != 20 {
|
||||
t.Fatal("activation changed the target or forwarded input arguments")
|
||||
}
|
||||
foreground = 20
|
||||
return obj{"structuredContent": obj{"landed_on_target": true}}, nil
|
||||
}
|
||||
// Simulate upstream's activate/act/restore: it now saves the target,
|
||||
// not the user's previous app, as its restore destination.
|
||||
previous := foreground
|
||||
foreground = 20
|
||||
foreground = previous
|
||||
return obj{"structuredContent": obj{"effect": "unverifiable"}}, nil
|
||||
}
|
||||
r, err := callWithForeground(call, "press_key", obj{"pid": 2, "window_id": 20, "key": "t", "delivery_mode": "foreground"}, func() int64 { return foreground })
|
||||
if err != nil || r["isError"] == true || foreground != 20 || !reflect.DeepEqual(calls, []string{"bring_to_front", "press_key"}) {
|
||||
t.Fatalf("foreground handoff failed: %v %v %v %v", calls, foreground, r, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnconfirmedActivationNeverSendsInput(t *testing.T) {
|
||||
for _, mode := range []string{"refused", "raised_only", "lost_focus", "transport"} {
|
||||
t.Run(mode, func(t *testing.T) {
|
||||
calls := 0
|
||||
r, err := callWithForeground(func(name string, _ obj) (obj, error) {
|
||||
calls++
|
||||
if name != "bring_to_front" {
|
||||
t.Fatal("input sent without focus")
|
||||
}
|
||||
if mode == "transport" {
|
||||
return nil, errors.New("disconnected")
|
||||
}
|
||||
return obj{"isError": mode == "refused", "structuredContent": obj{"raised": true, "landed_on_target": mode != "raised_only"}}, nil
|
||||
}, "click", obj{"pid": 2, "window_id": 20, "delivery_mode": "foreground"}, func() int64 {
|
||||
if mode == "lost_focus" {
|
||||
return 10
|
||||
}
|
||||
return 20
|
||||
})
|
||||
rec := object(object(r["structuredContent"])["artemis"])
|
||||
if err != nil || calls != 1 || r["isError"] != true || rec["execution"] != "not_started" || rec["retryable"] != false {
|
||||
t.Fatalf("unsafe activation handling: %v %v", r, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackgroundAndObservationsNeverActivate(t *testing.T) {
|
||||
for _, name := range []string{"get_window_state", "verify_state", "save_screenshot", "click"} {
|
||||
var calls []string
|
||||
_, err := callWithForeground(func(tool string, _ obj) (obj, error) {
|
||||
calls = append(calls, tool)
|
||||
return obj{}, nil
|
||||
}, name, obj{"pid": 2, "window_id": 20}, func() int64 { t.Fatal("unexpected focus probe"); return 0 })
|
||||
if err != nil || !reflect.DeepEqual(calls, []string{name}) {
|
||||
t.Fatal(calls, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestUncertainInputIsNotReplayed(t *testing.T) {
|
||||
calls := 0
|
||||
_, err := callWithForeground(func(name string, _ obj) (obj, error) {
|
||||
calls++
|
||||
if name == "bring_to_front" {
|
||||
return obj{"structuredContent": obj{"landed_on_target": true}}, nil
|
||||
}
|
||||
return nil, errors.New("input reply lost")
|
||||
}, "type_text", obj{"pid": 2, "window_id": 20, "delivery_mode": "foreground"}, func() int64 { return 20 })
|
||||
if calls != 2 || err == nil {
|
||||
t.Fatal(calls, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCaptureRecordsFocusWithoutHidingBackgroundEvidence(t *testing.T) {
|
||||
r := obj{"content": []any{obj{"type": "image", "data": "original"}}}
|
||||
annotateCaptureFocus(r, 20, 20, 10)
|
||||
s := object(object(r["structuredContent"])["capture_focus"])
|
||||
if s["changed_during_capture"] != true || s["target_foreground_after"] != false || len(items(r["content"])) != 2 || object(items(r["content"])[0])["data"] != "original" {
|
||||
t.Fatal(r)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user