package review import ( "context" "os" "strings" "testing" "time" "git.stormux.org/storm/cthulhu/internal/atspi" ) // Run with a private Xvfb and D-Bus session, a visible Pluma window, and a // short document containing "Alpha beta" on its first line. func TestNativePageTabEditorFlatReview(t *testing.T) { if os.Getenv("CTHULHU_NATIVE_PAGE_TAB_EDITOR") != "1" { t.Skip("requires a private Pluma fixture") } ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() adapter := atspi.New() if err := adapter.Start(ctx); err != nil { t.Fatal(err) } defer adapter.Stop(context.Background()) tree, err := adapter.CaptureDesktop(ctx) if err != nil { t.Fatal(err) } root, err := tree.Root() if err != nil { t.Fatal(err) } var focus atspi.ObjectID queue := []atspi.ObjectReference{root} for len(queue) > 0 { ref := queue[0] queue = queue[1:] snapshot, err := tree.Resolve(ref) if err != nil { t.Fatal(err) } if snapshot.ApplicationName == "pluma" && snapshot.Role == "text" { geometry, err := tree.Geometry(ref) if err != nil { t.Fatal(err) } if geometry.Showing { focus = snapshot.ID() } } for child, ok, err := tree.FirstChild(ref); ok && err == nil; child, ok, err = tree.NextSibling(child) { queue = append(queue, child) } } if !focus.Valid() { t.Fatal("visible Pluma editor not found") } reviewTree, err := adapter.CaptureReviewWindow(ctx, focus) if err != nil { t.Fatal(err) } cursor := &FlatCursor{} if err := cursor.Refresh(ctx, reviewTree, focus); err != nil { t.Fatal(err) } for _, tc := range []struct { unit FlatUnit step int want string }{ {Word, 0, "Alpha"}, {Character, 1, "l"}, {Word, 1, "beta"}, } { position, _, err := cursor.Read(tc.unit, tc.step) if err != nil || position.Object != focus || !position.HasOffset || strings.TrimSpace(position.Text) != tc.want { t.Fatalf("unit=%v step=%d: position=%+v err=%v", tc.unit, tc.step, position, err) } } }