github.com/Seikaijyu/gio@v0.0.1/io/router/semantic_test.go (about) 1 // SPDX-License-Identifier: Unlicense OR MIT 2 3 package router 4 5 import ( 6 "fmt" 7 "image" 8 "reflect" 9 "testing" 10 11 "github.com/Seikaijyu/gio/f32" 12 "github.com/Seikaijyu/gio/io/pointer" 13 "github.com/Seikaijyu/gio/io/semantic" 14 "github.com/Seikaijyu/gio/op" 15 "github.com/Seikaijyu/gio/op/clip" 16 ) 17 18 func TestEmptySemantics(t *testing.T) { 19 var r Router 20 tree := r.AppendSemantics(nil) 21 if len(tree) != 1 { 22 t.Errorf("expected 1 semantic node for empty tree, got %d", len(tree)) 23 } 24 } 25 26 func TestSemanticTree(t *testing.T) { 27 var ( 28 ops op.Ops 29 r Router 30 ) 31 t1 := clip.Rect(image.Rect(0, 0, 75, 75)).Push(&ops) 32 semantic.DescriptionOp("child1").Add(&ops) 33 t1.Pop() 34 t2 := clip.Rect(image.Rect(25, 25, 100, 100)).Push(&ops) 35 semantic.DescriptionOp("child2").Add(&ops) 36 t2.Pop() 37 r.Frame(&ops) 38 tests := []struct { 39 x, y float32 40 desc string 41 }{ 42 {24, 24, "child1"}, 43 {50, 50, "child2"}, 44 {100, 100, ""}, 45 } 46 tree := r.AppendSemantics(nil) 47 verifyTree(t, 0, tree[0]) 48 for _, test := range tests { 49 p := f32.Pt(test.x, test.y) 50 id, found := r.SemanticAt(p) 51 if !found { 52 t.Errorf("no semantic node at %v", p) 53 } 54 n, found := lookupNode(tree, id) 55 if !found { 56 t.Errorf("no id %d in semantic tree", id) 57 } 58 if got := n.Desc.Description; got != test.desc { 59 t.Errorf("got semantic description %s at %v, expected %s", got, p, test.desc) 60 } 61 } 62 63 // Verify stable IDs. 64 r.Frame(&ops) 65 tree2 := r.AppendSemantics(nil) 66 if !reflect.DeepEqual(tree, tree2) { 67 fmt.Println("First tree:") 68 printTree(0, tree[0]) 69 fmt.Println("Second tree:") 70 printTree(0, tree2[0]) 71 t.Error("same semantic description lead to differing trees") 72 } 73 } 74 75 func TestSemanticDescription(t *testing.T) { 76 var ops op.Ops 77 pointer.InputOp{Tag: new(int), Kinds: pointer.Press | pointer.Release}.Add(&ops) 78 semantic.DescriptionOp("description").Add(&ops) 79 semantic.LabelOp("label").Add(&ops) 80 semantic.Button.Add(&ops) 81 semantic.EnabledOp(false).Add(&ops) 82 semantic.SelectedOp(true).Add(&ops) 83 var r Router 84 r.Frame(&ops) 85 tree := r.AppendSemantics(nil) 86 got := tree[0].Desc 87 exp := SemanticDesc{ 88 Class: 1, 89 Description: "description", 90 Label: "label", 91 Selected: true, 92 Disabled: true, 93 Gestures: ClickGesture, 94 Bounds: image.Rectangle{Min: image.Point{X: -1e+06, Y: -1e+06}, Max: image.Point{X: 1e+06, Y: 1e+06}}, 95 } 96 if got != exp { 97 t.Errorf("semantic description mismatch:\nGot: %+v\nWant: %+v", got, exp) 98 } 99 } 100 101 func lookupNode(tree []SemanticNode, id SemanticID) (SemanticNode, bool) { 102 for _, n := range tree { 103 if id == n.ID { 104 return n, true 105 } 106 } 107 return SemanticNode{}, false 108 } 109 110 func verifyTree(t *testing.T, parent SemanticID, n SemanticNode) { 111 t.Helper() 112 if n.ParentID != parent { 113 t.Errorf("node %d: got parent %d, want %d", n.ID, n.ParentID, parent) 114 } 115 for _, c := range n.Children { 116 verifyTree(t, n.ID, c) 117 } 118 } 119 120 func printTree(indent int, n SemanticNode) { 121 for i := 0; i < indent; i++ { 122 fmt.Print("\t") 123 } 124 fmt.Printf("%d: %+v\n", n.ID, n.Desc) 125 for _, c := range n.Children { 126 printTree(indent+1, c) 127 } 128 }