| 🛟 Updated. 28d5985 k33g 4h ago | 1 | package ui |
| 2 | |
| 3 | import "testing" |
| 4 | |
| 5 | func TestRectEdgesAndEmptiness(t *testing.T) { |
| 6 | r := Rect{X: 2, Y: 3, W: 10, H: 5} |
| 7 | |
| 8 | if got := r.Right(); got != 12 { |
| 9 | t.Errorf("Right() = %d, want 12", got) |
| 10 | } |
| 11 | if got := r.Bottom(); got != 8 { |
| 12 | t.Errorf("Bottom() = %d, want 8", got) |
| 13 | } |
| 14 | if r.IsEmpty() { |
| 15 | t.Error("IsEmpty() = true on a rectangle with a size") |
| 16 | } |
| 17 | for _, empty := range []Rect{{W: 0, H: 5}, {W: 5, H: 0}, {W: -1, H: 5}} { |
| 18 | if !empty.IsEmpty() { |
| 19 | t.Errorf("IsEmpty() = false for %+v", empty) |
| 20 | } |
| 21 | } |
| 22 | } |
| 23 | |
| 24 | func TestRectContainsExcludesTheFarEdges(t *testing.T) { |
| 25 | r := Rect{X: 1, Y: 1, W: 3, H: 2} |
| 26 | |
| 27 | inside := [][2]int{{1, 1}, {3, 2}, {2, 1}} |
| 28 | for _, p := range inside { |
| 29 | if !r.Contains(p[0], p[1]) { |
| 30 | t.Errorf("Contains(%d, %d) = false, want true", p[0], p[1]) |
| 31 | } |
| 32 | } |
| 33 | |
| 34 | outside := [][2]int{{0, 1}, {4, 1}, {1, 0}, {1, 3}} |
| 35 | for _, p := range outside { |
| 36 | if r.Contains(p[0], p[1]) { |
| 37 | t.Errorf("Contains(%d, %d) = true, want false", p[0], p[1]) |
| 38 | } |
| 39 | } |
| 40 | } |
| 41 | |
| 42 | func TestRectIntersect(t *testing.T) { |
| 43 | tests := []struct { |
| 44 | name string |
| 45 | a, b Rect |
| 46 | want Rect |
| 47 | }{ |
| 48 | { |
| 49 | name: "overlapping", |
| 50 | a: Rect{X: 0, Y: 0, W: 10, H: 10}, |
| 51 | b: Rect{X: 5, Y: 5, W: 10, H: 10}, |
| 52 | want: Rect{X: 5, Y: 5, W: 5, H: 5}, |
| 53 | }, |
| 54 | { |
| 55 | name: "one inside the other", |
| 56 | a: Rect{X: 0, Y: 0, W: 10, H: 10}, |
| 57 | b: Rect{X: 2, Y: 2, W: 3, H: 3}, |
| 58 | want: Rect{X: 2, Y: 2, W: 3, H: 3}, |
| 59 | }, |
| 60 | { |
| 61 | name: "touching but not overlapping", |
| 62 | a: Rect{X: 0, Y: 0, W: 5, H: 5}, |
| 63 | b: Rect{X: 5, Y: 0, W: 5, H: 5}, |
| 64 | want: Rect{X: 5, Y: 0}, |
| 65 | }, |
| 66 | { |
| 67 | name: "wholly apart", |
| 68 | a: Rect{X: 0, Y: 0, W: 2, H: 2}, |
| 69 | b: Rect{X: 10, Y: 10, W: 2, H: 2}, |
| 70 | want: Rect{X: 10, Y: 10}, |
| 71 | }, |
| 72 | } |
| 73 | |
| 74 | for _, tc := range tests { |
| 75 | t.Run(tc.name, func(t *testing.T) { |
| 76 | got := tc.a.Intersect(tc.b) |
| 77 | if got != tc.want { |
| 78 | t.Errorf("Intersect() = %+v, want %+v", got, tc.want) |
| 79 | } |
| 80 | if tc.want.IsEmpty() && !got.IsEmpty() { |
| 81 | t.Error("the intersection should be empty") |
| 82 | } |
| 83 | }) |
| 84 | } |
| 85 | } |
| 86 | |
| 87 | func TestRectInsetMoveAndWithSize(t *testing.T) { |
| 88 | r := Rect{X: 5, Y: 5, W: 20, H: 10} |
| 89 | |
| 90 | if got := r.Inset(1, 1); got != (Rect{X: 6, Y: 6, W: 18, H: 8}) { |
| 91 | t.Errorf("Inset(1, 1) = %+v", got) |
| 92 | } |
| 93 | if got := r.Move(-2, 3); got != (Rect{X: 3, Y: 8, W: 20, H: 10}) { |
| 94 | t.Errorf("Move(-2, 3) = %+v", got) |
| 95 | } |
| 96 | if got := r.WithSize(4, 4); got != (Rect{X: 5, Y: 5, W: 4, H: 4}) { |
| 97 | t.Errorf("WithSize(4, 4) = %+v", got) |
| 98 | } |
| 99 | } |
| 100 | |
| 101 | func TestRectCenteredIn(t *testing.T) { |
| 102 | outer := Rect{X: 0, Y: 0, W: 80, H: 24} |
| 103 | |
| 104 | got := Rect{W: 20, H: 10}.CenteredIn(outer) |
| 105 | |
| 106 | if got != (Rect{X: 30, Y: 7, W: 20, H: 10}) { |
| 107 | t.Errorf("CenteredIn() = %+v, want it centred", got) |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | func TestRectClampIntoMovesWithoutResizing(t *testing.T) { |
| 112 | outer := Rect{X: 0, Y: 1, W: 80, H: 23} |
| 113 | |
| 114 | tests := []struct { |
| 115 | name string |
| 116 | give Rect |
| 117 | want Rect |
| 118 | }{ |
| 119 | {"past the right edge", Rect{X: 75, Y: 5, W: 20, H: 5}, Rect{X: 60, Y: 5, W: 20, H: 5}}, |
| 120 | {"past the bottom", Rect{X: 0, Y: 22, W: 10, H: 5}, Rect{X: 0, Y: 19, W: 10, H: 5}}, |
| 121 | {"above the top", Rect{X: 0, Y: -3, W: 10, H: 5}, Rect{X: 0, Y: 1, W: 10, H: 5}}, |
| 122 | {"already inside", Rect{X: 4, Y: 4, W: 10, H: 5}, Rect{X: 4, Y: 4, W: 10, H: 5}}, |
| 123 | } |
| 124 | |
| 125 | for _, tc := range tests { |
| 126 | t.Run(tc.name, func(t *testing.T) { |
| 127 | got := tc.give.ClampInto(outer) |
| 128 | if got != tc.want { |
| 129 | t.Errorf("ClampInto() = %+v, want %+v", got, tc.want) |
| 130 | } |
| 131 | if got.W != tc.give.W || got.H != tc.give.H { |
| 132 | t.Error("ClampInto resized the rectangle; it must only move it") |
| 133 | } |
| 134 | }) |
| 135 | } |
| 136 | } |
| 137 | |
| 138 | func TestClampIntoAWindowLargerThanTheScreenStaysAtTheOrigin(t *testing.T) { |
| 139 | outer := Rect{X: 0, Y: 0, W: 20, H: 10} |
| 140 | |
| 141 | got := Rect{X: 5, Y: 5, W: 100, H: 100}.ClampInto(outer) |
| 142 | |
| 143 | if got.X != 0 || got.Y != 0 { |
| 144 | t.Errorf("ClampInto() = %+v, want it pinned to the top-left corner", got) |
| 145 | } |
| 146 | } |