100 lines
3.0 KiB
Go
100 lines
3.0 KiB
Go
package atspi
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestNativeCurrentLine(t *testing.T) {
|
|
if os.Getenv("CTHULHU_NATIVE_CURRENT_LINE") != "1" {
|
|
t.Skip("requires private Xvfb and AT-SPI")
|
|
}
|
|
ctx, cancel := context.WithTimeout(context.Background(), 25*time.Second)
|
|
defer cancel()
|
|
adapter := New()
|
|
if err := adapter.Start(ctx); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer adapter.Stop(context.Background())
|
|
fixture := exec.CommandContext(ctx, "/usr/bin/python3", "-u", "../../tests/current_line_fixture.py")
|
|
fixture.Stderr = os.Stderr
|
|
stdin, _ := fixture.StdinPipe()
|
|
stdout, _ := fixture.StdoutPipe()
|
|
if err := fixture.Start(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer func() { stdin.Close(); fixture.Wait() }()
|
|
scanner := bufio.NewScanner(stdout)
|
|
ready := func() {
|
|
t.Helper()
|
|
if !scanner.Scan() || scanner.Text() != "ready" {
|
|
t.Fatalf("fixture not ready: %q %v", scanner.Text(), scanner.Err())
|
|
}
|
|
}
|
|
ready()
|
|
var focus ObjectID
|
|
lastControl := ""
|
|
for _, probe := range []struct {
|
|
control, text string
|
|
offset int
|
|
want string
|
|
password bool
|
|
}{
|
|
{"entry", "Café 猫 complete", 7, "Café 猫 complete", false},
|
|
{"text", "First\nSecond café 猫\nThird", 11, "Second café 猫", false},
|
|
{"entry", "Final line", 10, "Final line", false},
|
|
{"text", "First\n\nLast", 6, "", false},
|
|
{"entry", "", 0, "", false},
|
|
{"text", "Final\n", 6, "", false},
|
|
{"password", "private test text", 5, "", true},
|
|
{"button", "", 0, "Example button", false},
|
|
} {
|
|
command, _ := json.Marshal(map[string]any{"action": "focus", "control": probe.control, "text": probe.text, "offset": probe.offset})
|
|
fmt.Fprintln(stdin, string(command))
|
|
ready()
|
|
if probe.control != lastControl {
|
|
for {
|
|
select {
|
|
case event := <-adapter.Events():
|
|
if event.Type == "object:state-changed:focused" && event.Detail1 == 1 &&
|
|
(event.Source.Name == map[string]string{"entry": "Entry", "text": "Text", "password": "Password", "button": "Example button"}[probe.control]) {
|
|
focus = event.Source.ID()
|
|
goto focused
|
|
}
|
|
case <-ctx.Done():
|
|
t.Fatal(ctx.Err())
|
|
}
|
|
}
|
|
}
|
|
focused:
|
|
lastControl = probe.control
|
|
content, err := adapter.ReadFocusedLine(ctx, focus)
|
|
if probe.password {
|
|
if err == nil || content.Text != "" || content.Snapshot.Name != "" {
|
|
t.Fatalf("password report: %+v %v", content, err)
|
|
}
|
|
continue
|
|
}
|
|
if err != nil || strings.TrimRight(content.Text, "\r\n") != probe.want {
|
|
t.Fatalf("%s offset %d: %+v %v, want %q", probe.control, probe.offset, content, err, probe.want)
|
|
}
|
|
if probe.control != "button" {
|
|
fmt.Fprintf(stdin, "{\"action\":\"caret\",\"control\":%q}\n", probe.control)
|
|
if !scanner.Scan() || scanner.Text() != fmt.Sprint(probe.offset) {
|
|
t.Fatalf("caret moved: %q, want %d", scanner.Text(), probe.offset)
|
|
}
|
|
ready()
|
|
}
|
|
}
|
|
if _, err := adapter.ReadFocusedLine(ctx, ObjectID{BusName: focus.BusName, Path: "/stale"}); err == nil {
|
|
t.Fatal("accepted stale native focus")
|
|
}
|
|
}
|