Reset master to testing content
This commit is contained in:
1 parent
0f2587b719
commit
42afa2a56c
1483 files changed
+145308
-938069
No files matched your search
@@ -0,0 +1,170 @@
|
||||
// Copyright (c) 2026 Storm Dragon
|
||||
// Authors: Storm Dragon, Angus Kola
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package review
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.stormux.org/storm/cthulhu/internal/atspi"
|
||||
)
|
||||
|
||||
func TestFlatReviewRetainsHealthyContentAndReportsOmissions(t *testing.T) {
|
||||
for _, issue := range []atspi.VisibleText{
|
||||
{Limited: true, Issue: atspi.TextCharacterLimit},
|
||||
{Issue: atspi.TextProviderFailure},
|
||||
} {
|
||||
bad := flatNode("/bad", "", 0, 30)
|
||||
bad.Snapshot.Name = "Unavailable object name must not replace its text"
|
||||
bad.Text = issue
|
||||
good := flatNode("/good", "Readable content", 0, 0)
|
||||
cursor := &FlatCursor{}
|
||||
if err := cursor.Refresh(context.Background(), flatTree(t, good, bad), objectID("/good")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
position, _, err := cursor.Read(Line, 0)
|
||||
if err != nil || position.Text != "Readable content" || cursor.completeness.OmittedObjects != 1 {
|
||||
t.Fatalf("partial review = %+v, %+v, %v", position, cursor.completeness, err)
|
||||
}
|
||||
if _, moved, err := cursor.Read(Line, 1); err != nil || moved {
|
||||
t.Fatalf("omitted object's name became content: moved=%v err=%v", moved, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlatReviewReportsUnavailableChildrenWithoutDroppingParentText(t *testing.T) {
|
||||
parent := flatNode("/parent", "Parent text", 0, 0)
|
||||
parent.ChildrenUnavailable = true
|
||||
cursor := &FlatCursor{}
|
||||
if err := cursor.Refresh(context.Background(), flatTree(t, parent), parent.Snapshot.ID()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
position, _, err := cursor.Read(Line, 0)
|
||||
if err != nil || position.Text != "Parent text" || cursor.completeness.UnavailableSubtrees != 1 {
|
||||
t.Fatalf("partial subtree = %+v, %+v, %v", position, cursor.completeness, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlatReviewReportsUnavailableChildrenWithoutComponentBounds(t *testing.T) {
|
||||
parent := node("/parent", "")
|
||||
parent.Geometry = atspi.Geometry{VisibilityKnown: true, Visible: true, Showing: true}
|
||||
parent.ChildrenUnavailable = true
|
||||
good := flatNode("/good", "Readable", 0, 0)
|
||||
cursor := &FlatCursor{}
|
||||
if err := cursor.Refresh(context.Background(), flatTree(t, parent, good), good.Snapshot.ID()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if cursor.completeness.UnavailableSubtrees != 1 {
|
||||
t.Fatalf("missing component bounds hid a failed subtree: %+v", cursor.completeness)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlatReviewAnchorsPrunedFocusAtDisplayedParent(t *testing.T) {
|
||||
before := flatNode("/before", "Unrelated first line", 0, 0)
|
||||
parent := flatNode("/parent", "Focused parent text", 0, 30)
|
||||
leaf := node("/leaf", "")
|
||||
parent.Children = []atspi.ObjectID{leaf.Snapshot.ID()}
|
||||
root := flatNode("/window", "", 0, 0)
|
||||
root.Text = atspi.VisibleText{}
|
||||
root.Geometry.Bounds.Height = 100
|
||||
root.Snapshot.Role = "frame"
|
||||
root.Children = []atspi.ObjectID{before.Snapshot.ID(), parent.Snapshot.ID()}
|
||||
tree, err := atspi.NewAccessibleTree(root.Snapshot.ID(), []atspi.TreeNode{root, before, parent, leaf})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cursor := &FlatCursor{}
|
||||
if err := cursor.Refresh(context.Background(), tree, leaf.Snapshot.ID()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
position, _, err := cursor.Read(Line, 0)
|
||||
if err != nil || position.Object != parent.Snapshot.ID() || position.Text != "Focused parent text" {
|
||||
t.Fatalf("pruned focus anchor = %+v, %v", position, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlatWorkerWarnsOnceAndClearsRecoveredCompleteness(t *testing.T) {
|
||||
capturer := &fakeCapturer{calls: make(chan captureCall, 1)}
|
||||
worker, cancel := startWorker(t, capturer, time.Second)
|
||||
defer cancel()
|
||||
defer worker.Stop(context.Background())
|
||||
good := flatNode("/good", "Readable", 0, 0)
|
||||
bad := flatNode("/bad", "Unavailable", 0, 30)
|
||||
bad.Text = atspi.VisibleText{Limited: true}
|
||||
tree := flatTree(t, good, bad)
|
||||
worker.SyncFocus(good.Snapshot.ID())
|
||||
worker.ReadFlat(Line, 0)
|
||||
call := <-capturer.calls
|
||||
call.result <- captureResult{tree: tree}
|
||||
for index := 0; index < 2; index++ {
|
||||
if index != 0 {
|
||||
worker.ReadFlat(Character, 0)
|
||||
}
|
||||
result := waitResult(t, worker)
|
||||
if result.Err != nil || !result.FlatCompleteness.Incomplete() || result.FlatWarning != (index == 0) {
|
||||
t.Fatalf("partial result %d: %+v", index, result)
|
||||
}
|
||||
}
|
||||
bad = flatNode("/bad", "Recovered", 0, 30)
|
||||
fresh := flatTree(t, good, bad)
|
||||
snapshot, err := fresh.ReviewWindow(context.Background(), good.Snapshot.ID())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := tree.Replace(objectID("/window"), snapshot.Nodes); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
worker.ReadFlat(Line, 1)
|
||||
result := waitResult(t, worker)
|
||||
if result.Err != nil || result.FlatCompleteness.Incomplete() || result.FlatWarning || result.FlatPosition.Text != "Recovered" {
|
||||
t.Fatalf("recovery result = %+v", result)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlatReviewCompositeControlKeepsLabelBesideChildAction(t *testing.T) {
|
||||
for _, role := range []string{"page tab", "menu item"} {
|
||||
for _, withLabel := range []bool{false, true} {
|
||||
t.Run(role+map[bool]string{false: " action only", true: " with text label"}[withLabel], func(t *testing.T) {
|
||||
parent := flatNode("/parent", "", 0, 0)
|
||||
parent.Snapshot.Role, parent.Snapshot.Name = role, "Primary label"
|
||||
parent.Text = atspi.VisibleText{Known: true}
|
||||
child := flatNode("/child", "", 150, 0)
|
||||
child.Geometry.Bounds.Width = 20
|
||||
child.Snapshot.Role, child.Snapshot.Name = "button", "Close"
|
||||
child.Text = atspi.VisibleText{}
|
||||
parent.Children = []atspi.ObjectID{child.Snapshot.ID()}
|
||||
nodes := []atspi.TreeNode{parent, child}
|
||||
if withLabel {
|
||||
label := flatNode("/label", "Primary label", 0, 0)
|
||||
label.Snapshot.Role = "static"
|
||||
label.Geometry.Bounds.Width = 100
|
||||
label.Text.Ranges[0].Bounds = label.Geometry.Bounds
|
||||
parent.Children = append(parent.Children, label.Snapshot.ID())
|
||||
nodes[0] = parent
|
||||
nodes = append(nodes, label)
|
||||
}
|
||||
lines, status, err := build_flat_layout(context.Background(), nodes)
|
||||
if err != nil || status.Incomplete() {
|
||||
t.Fatalf("layout: %+v %v", status, err)
|
||||
}
|
||||
names, actions := 0, 0
|
||||
for _, line := range lines {
|
||||
for _, zone := range line.zones {
|
||||
if zone.text == "Primary label" {
|
||||
names++
|
||||
}
|
||||
if zone.text == "Close" {
|
||||
actions++
|
||||
}
|
||||
}
|
||||
}
|
||||
if names != 1 || actions != 1 {
|
||||
t.Fatalf("label count=%d action count=%d", names, actions)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user