WitNote / internal /bridge /snapshot_extra_test.go
AUXteam's picture
Upload folder using huggingface_hub
6a7089a verified
package bridge
import (
"encoding/json"
"testing"
)
func TestFormatSnapshotCompact_Basic(t *testing.T) {
nodes := []A11yNode{
{Ref: "e0", Role: "button", Name: "Submit"},
{Ref: "e1", Role: "textbox", Name: "Email", Value: "test@pinchtab.com"},
}
got := FormatSnapshotCompact(nodes)
want := "e0:button \"Submit\"\ne1:textbox \"Email\" val=\"test@pinchtab.com\"\n"
if got != want {
t.Errorf("got:\n%s\nwant:\n%s", got, want)
}
}
func TestFormatSnapshotCompact_FocusedDisabled(t *testing.T) {
nodes := []A11yNode{
{Ref: "e0", Role: "button", Name: "OK", Focused: true},
{Ref: "e1", Role: "button", Name: "Cancel", Disabled: true},
{Ref: "e2", Role: "textbox", Focused: true, Disabled: true},
}
got := FormatSnapshotCompact(nodes)
if !contains(got, "e0:button \"OK\" *\n") {
t.Errorf("expected focused marker *, got:\n%s", got)
}
if !contains(got, "e1:button \"Cancel\" -\n") {
t.Errorf("expected disabled marker -, got:\n%s", got)
}
if !contains(got, "e2:textbox * -\n") {
t.Errorf("expected both markers, got:\n%s", got)
}
}
func TestFormatSnapshotCompact_Empty(t *testing.T) {
got := FormatSnapshotCompact(nil)
if got != "" {
t.Errorf("expected empty string, got %q", got)
}
}
func TestFormatSnapshotCompact_NoName(t *testing.T) {
nodes := []A11yNode{{Ref: "e0", Role: "generic"}}
got := FormatSnapshotCompact(nodes)
if got != "e0:generic\n" {
t.Errorf("got %q", got)
}
}
func TestTruncateToTokens_NoTruncation(t *testing.T) {
nodes := []A11yNode{
{Ref: "e0", Role: "button", Name: "OK"},
{Ref: "e1", Role: "link", Name: "Home"},
}
result, truncated := TruncateToTokens(nodes, 1000, "compact")
if truncated {
t.Error("expected no truncation")
}
if len(result) != 2 {
t.Errorf("expected 2 nodes, got %d", len(result))
}
}
func TestTruncateToTokens_Truncates(t *testing.T) {
nodes := make([]A11yNode, 100)
for i := range nodes {
nodes[i] = A11yNode{Ref: "e0", Role: "button", Name: "A long button name here"}
}
result, truncated := TruncateToTokens(nodes, 50, "compact")
if !truncated {
t.Error("expected truncation")
}
if len(result) >= 100 {
t.Errorf("expected fewer than 100 nodes, got %d", len(result))
}
}
func TestTruncateToTokens_Formats(t *testing.T) {
nodes := make([]A11yNode, 50)
for i := range nodes {
nodes[i] = A11yNode{Ref: "e0", Role: "button", Name: "Click me"}
}
jsonResult, _ := TruncateToTokens(nodes, 100, "json")
compactResult, _ := TruncateToTokens(nodes, 100, "compact")
if len(jsonResult) > len(compactResult) {
t.Errorf("JSON should truncate sooner: json=%d compact=%d", len(jsonResult), len(compactResult))
}
}
func TestTruncateToTokens_Empty(t *testing.T) {
result, truncated := TruncateToTokens(nil, 100, "compact")
if truncated {
t.Error("expected no truncation on empty")
}
if len(result) != 0 {
t.Errorf("expected 0 nodes, got %d", len(result))
}
}
func TestFilterSubtree_Found(t *testing.T) {
nodes := []RawAXNode{
{NodeID: "root", BackendDOMNodeID: 1, ChildIDs: []string{"child1", "child2"}},
{NodeID: "child1", BackendDOMNodeID: 2, ChildIDs: []string{"grandchild"}},
{NodeID: "child2", BackendDOMNodeID: 3},
{NodeID: "grandchild", BackendDOMNodeID: 4},
{NodeID: "other", BackendDOMNodeID: 5},
}
result := FilterSubtree(nodes, 2)
if len(result) != 2 {
t.Errorf("expected 2 nodes, got %d", len(result))
}
ids := map[string]bool{}
for _, n := range result {
ids[n.NodeID] = true
}
if !ids["child1"] || !ids["grandchild"] {
t.Errorf("expected child1 and grandchild, got %v", ids)
}
}
func TestFilterSubtree_NotFound(t *testing.T) {
nodes := []RawAXNode{
{NodeID: "root", BackendDOMNodeID: 1},
{NodeID: "child", BackendDOMNodeID: 2},
}
result := FilterSubtree(nodes, 999)
if len(result) != 2 {
t.Errorf("expected all nodes returned, got %d", len(result))
}
}
func TestFilterSubtree_RootScope(t *testing.T) {
nodes := []RawAXNode{
{NodeID: "root", BackendDOMNodeID: 1, ChildIDs: []string{"child"}},
{NodeID: "child", BackendDOMNodeID: 2, ChildIDs: []string{"grandchild"}},
{NodeID: "grandchild", BackendDOMNodeID: 3},
}
result := FilterSubtree(nodes, 1)
if len(result) != 3 {
t.Errorf("expected 3 nodes, got %d", len(result))
}
}
func TestDiffSnapshot_Added(t *testing.T) {
prev := []A11yNode{{Ref: "e0", Role: "button", Name: "OK", NodeID: 1}}
curr := []A11yNode{
{Ref: "e0", Role: "button", Name: "OK", NodeID: 1},
{Ref: "e1", Role: "link", Name: "New", NodeID: 2},
}
added, changed, removed := DiffSnapshot(prev, curr)
if len(added) != 1 || added[0].Name != "New" {
t.Errorf("expected 1 added node, got %v", added)
}
if len(changed) != 0 {
t.Errorf("expected 0 changed, got %d", len(changed))
}
if len(removed) != 0 {
t.Errorf("expected 0 removed, got %d", len(removed))
}
}
func TestDiffSnapshot_Removed(t *testing.T) {
prev := []A11yNode{
{Ref: "e0", Role: "button", Name: "OK", NodeID: 1},
{Ref: "e1", Role: "link", Name: "Old", NodeID: 2},
}
curr := []A11yNode{{Ref: "e0", Role: "button", Name: "OK", NodeID: 1}}
_, _, removed := DiffSnapshot(prev, curr)
if len(removed) != 1 || removed[0].Name != "Old" {
t.Errorf("expected 1 removed node, got %v", removed)
}
}
func TestDiffSnapshot_Changed(t *testing.T) {
prev := []A11yNode{{Ref: "e0", Role: "textbox", Name: "Email", NodeID: 1, Value: "old"}}
curr := []A11yNode{{Ref: "e0", Role: "textbox", Name: "Email", NodeID: 1, Value: "new"}}
_, changed, _ := DiffSnapshot(prev, curr)
if len(changed) != 1 || changed[0].Value != "new" {
t.Errorf("expected 1 changed node, got %v", changed)
}
}
func TestDiffSnapshot_Empty(t *testing.T) {
added, changed, removed := DiffSnapshot(nil, nil)
if len(added)+len(changed)+len(removed) != 0 {
t.Error("expected all empty for nil inputs")
}
}
func TestRawAXValue_String_Normal(t *testing.T) {
v := &RawAXValue{Type: "string", Value: json.RawMessage(`"hello"`)}
if got := v.String(); got != "hello" {
t.Errorf("expected hello, got %q", got)
}
}
func TestRawAXValue_String_Nil(t *testing.T) {
var v *RawAXValue
if got := v.String(); got != "" {
t.Errorf("expected empty, got %q", got)
}
}
func TestRawAXValue_String_NilValue(t *testing.T) {
v := &RawAXValue{Type: "string"}
if got := v.String(); got != "" {
t.Errorf("expected empty, got %q", got)
}
}
func TestRawAXValue_String_NonString(t *testing.T) {
v := &RawAXValue{Type: "number", Value: json.RawMessage(`42`)}
if got := v.String(); got != "42" {
t.Errorf("expected 42, got %q", got)
}
}
func contains(s, substr string) bool {
return len(s) >= len(substr) && searchString(s, substr)
}
func searchString(s, substr string) bool {
for i := 0; i <= len(s)-len(substr); i++ {
if s[i:i+len(substr)] == substr {
return true
}
}
return false
}
func TestFrameIDs_Recursive(t *testing.T) {
tree := rawFrameTree{}
tree.Frame.ID = "root"
tree.ChildFrames = []rawFrameTree{
{Frame: struct {
ID string `json:"id"`
}{ID: "child-1"}},
{
Frame: struct {
ID string `json:"id"`
}{ID: "child-2"},
ChildFrames: []rawFrameTree{{Frame: struct {
ID string `json:"id"`
}{ID: "grandchild"}}},
},
}
got := frameIDs(tree)
want := []string{"root", "child-1", "child-2", "grandchild"}
if len(got) != len(want) {
t.Fatalf("len=%d want %d (%v)", len(got), len(want), got)
}
for i := range want {
if got[i] != want[i] {
t.Fatalf("frameIDs[%d]=%q want %q (all=%v)", i, got[i], want[i], got)
}
}
}