Export reviewed object and flat reading to Remote
This commit is contained in:
1 parent
49be8309fe
commit
c03ffa7409
11 files changed
+425
-10
No files matched your search
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) 2026 Storm Dragon
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package review
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"git.stormux.org/storm/cthulhu/internal/atspi"
|
||||
)
|
||||
|
||||
func TestObjectReviewRetainsDestinationAncestry(t *testing.T) {
|
||||
tree := newTree(t)
|
||||
cursor, _ := NewCursor(tree)
|
||||
cursor.SyncFocus(objectID("/first"))
|
||||
position, moved, err := cursor.Move(NextSibling)
|
||||
if err != nil || !moved || len(position.SourceContext) != 2 ||
|
||||
position.SourceContext[0].ID() != objectID("/second") || position.SourceContext[1].ID() != objectID("/root") {
|
||||
t.Fatal("object review lost destination ancestry", position, err)
|
||||
}
|
||||
// Dirty privacy metadata must not suppress otherwise valid local review.
|
||||
tree.InvalidateSnapshot(objectID("/root"))
|
||||
position, moved, err = cursor.Move(FirstChild)
|
||||
if err != nil || !moved || position.Current.Name != "Grandchild" || len(position.SourceContext) != 0 {
|
||||
t.Fatal("stale ancestry changed local navigation or retained export metadata", position, err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlatReviewRetainsEverySpokenSourceAcrossReplacement(t *testing.T) {
|
||||
tree := flatTree(t, flatNode("/a", "Alpha", 0, 0), flatNode("/b", "Beta", 250, 0))
|
||||
cursor := &FlatCursor{}
|
||||
if err := cursor.Refresh(t.Context(), tree, objectID("/a")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
position, _, err := cursor.Read(Line, 0)
|
||||
if err != nil || position.Text != "Alpha Beta" || len(position.SourceContexts) != 2 {
|
||||
t.Fatal("line lost a contributing zone", position, err)
|
||||
}
|
||||
for i, path := range []string{"/a", "/b"} {
|
||||
context := position.SourceContexts[i]
|
||||
if len(context) != 2 || context[0].ID() != objectID(path) || context[1].Role != "frame" {
|
||||
t.Fatal("line source lost original ancestry", context)
|
||||
}
|
||||
}
|
||||
// Text and ancestry must stay from the same atomic layout capture even if
|
||||
// the live tree changes before the result leaves the worker.
|
||||
window, _ := tree.ReviewWindow(t.Context(), objectID("/a"))
|
||||
window.Nodes[2].Snapshot.Role = "password text"
|
||||
if err := tree.Replace(objectID("/window"), window.Nodes); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
retained, _, err := cursor.Read(Line, 0)
|
||||
if err != nil || retained.Text != position.Text || retained.SourceContexts[1][0].Role == "password text" {
|
||||
t.Fatal("replacement mixed old text with new ancestry", retained, err)
|
||||
}
|
||||
if err := cursor.Refresh(t.Context(), tree, objectID("/a")); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
current, _, _ := cursor.Read(Line, 0)
|
||||
if current.SourceContexts[len(current.SourceContexts)-1][0].Role != "password text" {
|
||||
t.Fatal("refreshed layout retained old privacy metadata", current)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFlatReviewIncludesAncestorsOutsideMenuScope(t *testing.T) {
|
||||
root := node("/root", "")
|
||||
root.Snapshot.Role = "password text"
|
||||
root.Children = []atspi.ObjectID{objectID("/menu")}
|
||||
menu := flatNode("/menu", "", 0, 0)
|
||||
menu.Text.Ranges = nil
|
||||
menu.Snapshot.Role = "menu"
|
||||
menu.Children = []atspi.ObjectID{objectID("/item")}
|
||||
item := flatNode("/item", "Item", 0, 0)
|
||||
tree, err := atspi.NewAccessibleTree(root.Snapshot.ID(), []atspi.TreeNode{root, menu, item})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cursor := &FlatCursor{}
|
||||
if err := cursor.Refresh(t.Context(), tree, item.Snapshot.ID()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
position, _, err := cursor.Read(Word, 0)
|
||||
if err != nil || len(position.SourceContexts) != 1 || len(position.SourceContexts[0]) != 3 ||
|
||||
position.SourceContexts[0][2].Role != "password text" {
|
||||
t.Fatal("menu scope hid a private ancestor", position, err)
|
||||
}
|
||||
tree.InvalidateSnapshot(root.Snapshot.ID())
|
||||
if err := cursor.Refresh(t.Context(), tree, item.Snapshot.ID()); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
position, _, err = cursor.Read(Word, 0)
|
||||
if err != nil || position.Text != "Item" || len(position.SourceContexts[0]) != 0 {
|
||||
t.Fatal("stale outer ancestor changed local text or allowed export", position, err)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user