Files
cthulhu/internal/atspi/mouse_review_native_test.go

82 lines
2.3 KiB
Go

// Copyright (c) 2026 Storm Dragon
// Authors: Storm Dragon, Angus Kola
// SPDX-License-Identifier: GPL-3.0-or-later
package atspi
import (
"context"
"os"
"os/exec"
"strconv"
"testing"
"time"
"git.stormux.org/storm/cthulhu/internal/platform/xorg"
)
func TestNativeMouseReviewPointerAndHitTest(t *testing.T) {
if os.Getenv("CTHULHU_NATIVE_MOUSE_REVIEW") != "1" {
t.Skip("requires private GTK and Xorg fixture")
}
ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second)
defer cancel()
adapter := New()
if err := adapter.Start(ctx); err != nil {
t.Fatal(err)
}
defer func() {
stopCtx, stop := context.WithTimeout(context.Background(), 3*time.Second)
defer stop()
if err := adapter.Stop(stopCtx); err != nil {
t.Errorf("stop adapter: %v", err)
}
}()
tree, err := adapter.CaptureDesktop(ctx)
if err != nil {
t.Fatal(err)
}
pointer := xorg.OpenPointerReader()
if pointer == nil {
t.Fatal("X pointer reader unavailable")
}
defer pointer.Close()
for _, item := range []struct {
name, role string
protected bool
}{
{"Caret review probe", "text", false},
{"Protected text probe", "password text", true},
} {
ref := findNamedReference(t, tree, item.name)
if !ref.Valid() {
t.Fatalf("%s absent", item.name)
}
geometry, err := tree.Geometry(ref)
if err != nil || !geometry.BoundsKnown {
t.Fatalf("%s geometry: %+v, %v", item.name, geometry, err)
}
x := int(geometry.Bounds.X + min(25, geometry.Bounds.Width/2))
y := int(geometry.Bounds.Y + geometry.Bounds.Height/2)
if out, err := exec.Command("xdotool", "mousemove", strconv.Itoa(x), strconv.Itoa(y)).CombinedOutput(); err != nil {
t.Fatalf("move pointer: %s: %v", out, err)
}
position := pointer.Read()
if !position.Known || position.PID <= 0 || position.X != x || position.Y != y {
t.Fatalf("%s pointer = %+v", item.name, position)
}
point, err := adapter.ReviewAtPoint(ctx, position.X, position.Y, position.PID)
if err != nil {
t.Fatal(err)
}
if point.Snapshot.Role != item.role || point.Snapshot.Name != item.name || !point.Window.Valid() {
t.Fatalf("%s hit test = %+v", item.name, point)
}
if item.protected && (point.Word != "" || point.Line != "") {
t.Fatalf("password content exposed: %+v", point)
}
if !item.protected && (point.Line == "" || point.Offset < 0) {
t.Fatalf("entry text missing: %+v", point)
}
}
}