turbo-editors/turbo-corepublic Fork 0
v1.0.2
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-core.git
git clone ssh://git@rickub.com/turbo-editors/turbo-core.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

maximize_test.go · 286 lines · 8.7 KBGo Blame HistoryRaw
🛟 Updated. 28d5985 k33g 21h ago1package ui
2
3import (
4 "strings"
5 "testing"
6)
7
8// framedWindow returns a window on a desktop — which is what gives it a
9// working maximise box — with the desktop filling the given area.
10func framedWindow(t *testing.T, area, bounds Rect) (*Desktop, *Window) {
11 t.Helper()
12
13 d := NewDesktop()
14 d.SetBounds(area)
15
16 w := NewWindow("main.go", nil)
17 d.Add(w)
18 w.SetBounds(bounds)
19 return d, w
20}
21
22// titleBar draws a window onto a simulated screen and returns its top row.
23func titleBar(t *testing.T, w *Window, width, height int) string {
24 t.Helper()
25
26 screen, root := newTestScreen(t, width, height)
27 w.SetActive(true)
28 w.Draw(root, testTheme(t))
29 screen.Show()
30
31 return screenLines(t, screen)[0]
32}
33
34func TestTheCloseBoxIsAnX(t *testing.T) {
35 // It closes the window, so it says so. The block character it used to be
36 // now means "maximise" on the other side of the same frame.
37 if closeBoxLabel != "[x]" {
38 t.Errorf("closeBoxLabel = %q, want [x]", closeBoxLabel)
39 }
40 if maximizeBoxLabel != "[■]" {
41 t.Errorf("maximizeBoxLabel = %q, want [■]", maximizeBoxLabel)
42 }
43}
44
45func TestAWindowOnADesktopDrawsBothBoxes(t *testing.T) {
46 _, w := framedWindow(t, Rect{W: 40, H: 12}, Rect{W: 30, H: 8})
47
48 bar := titleBar(t, w, 40, 12)
49
50 if !strings.Contains(bar, closeBoxLabel) {
51 t.Errorf("the title bar is %q, want a close box", bar)
52 }
53 if !strings.Contains(bar, maximizeBoxLabel) {
54 t.Errorf("the title bar is %q, want a maximise box", bar)
55 }
56}
57
58func TestAWindowWithNowhereToMaximiseIntoDrawsNoBox(t *testing.T) {
59 // A window that was never added to a desktop has no OnMaximize, and a
60 // button that could do nothing is worse than no button.
61 w := NewWindow("main.go", nil)
62 w.SetBounds(Rect{W: 30, H: 8})
63
64 bar := titleBar(t, w, 40, 12)
65
66 if strings.Contains(bar, maximizeBoxLabel) {
67 t.Errorf("the title bar is %q, want no maximise box", bar)
68 }
69 if !strings.Contains(bar, closeBoxLabel) {
70 t.Errorf("the title bar is %q, want the close box regardless", bar)
71 }
72}
73
74func TestTheBoxShowsWhatPressingItWillDo(t *testing.T) {
75 area := Rect{W: 40, H: 12}
76 d, w := framedWindow(t, area, Rect{W: 30, H: 8})
77
78 if bar := titleBar(t, w, 40, 12); !strings.Contains(bar, maximizeBoxLabel) {
79 t.Errorf("a normal window shows %q, want the maximise box", bar)
80 }
81
82 d.ToggleMaximize(w)
83
84 bar := titleBar(t, w, 40, 12)
85 if !strings.Contains(bar, restoreBoxLabel) {
86 t.Errorf("a maximised window shows %q, want the restore box", bar)
87 }
88 if strings.Contains(bar, maximizeBoxLabel) {
89 t.Errorf("a maximised window still shows the maximise box: %q", bar)
90 }
91}
92
93func TestClickingTheMaximiseBoxFillsTheDesktopAndClickingItAgainRestores(t *testing.T) {
94 area := Rect{X: 0, Y: 1, W: 40, H: 12}
95 bounds := Rect{X: 2, Y: 3, W: 30, H: 6}
96 _, w := framedWindow(t, area, bounds)
97
98 pressMaximizeBox(w)
99 if got := w.Bounds(); got != area {
100 t.Fatalf("Bounds() = %+v, want the whole desktop %+v", got, area)
101 }
102 if !w.Maximized() {
103 t.Error("the window does not know it is maximised")
104 }
105
106 pressMaximizeBox(w)
107 if got := w.Bounds(); got != bounds {
108 t.Errorf("Bounds() = %+v, want the size it had before %+v", got, bounds)
109 }
110 if w.Maximized() {
111 t.Error("the window still thinks it is maximised")
112 }
113}
114
115func TestTheMaximiseBoxIsNotTheCloseBox(t *testing.T) {
116 // Both are three cells on the same row. Landing on the wrong one would
117 // close a window somebody meant to enlarge.
118 closed := 0
119 area := Rect{W: 40, H: 12}
120 _, w := framedWindow(t, area, Rect{W: 30, H: 8})
121 w.OnClose = func() bool { closed++; return true }
122
123 pressMaximizeBox(w)
124
125 if closed != 0 {
126 t.Error("pressing the maximise box closed the window")
127 }
128 if !w.Maximized() {
129 t.Error("pressing the maximise box did not maximise the window")
130 }
131}
132
133func TestPressingBesideTheMaximiseBoxMovesTheWindowInstead(t *testing.T) {
134 area := Rect{W: 40, H: 12}
135 _, w := framedWindow(t, area, Rect{W: 30, H: 8})
136
137 // One column to the left of the box is title bar, which drags.
138 w.HandleMouse(clickEvent(w.Bounds().Right()-maximizeOffset-1, w.Bounds().Y))
139
140 if w.Maximized() {
141 t.Error("a click one cell short of the box maximised the window")
142 }
143 if !w.Dragging() {
144 t.Error("a click on the title bar did not start a move")
145 }
146}
147
148func TestRestoringAWindowThatWasNeverMaximisedDoesNothing(t *testing.T) {
149 bounds := Rect{X: 2, Y: 3, W: 30, H: 6}
150 w := NewWindow("main.go", nil)
151 w.SetBounds(bounds)
152
153 w.Restore()
154
155 if got := w.Bounds(); got != bounds {
156 t.Errorf("Bounds() = %+v, want it left alone at %+v", got, bounds)
157 }
158}
159
160func TestMaximisingTwiceKeepsTheOriginalSize(t *testing.T) {
161 // The second call must not record the maximised bounds as the ones to go
162 // back to, or restoring would do nothing at all.
163 area := Rect{W: 40, H: 12}
164 bounds := Rect{X: 2, Y: 3, W: 30, H: 6}
165 w := NewWindow("main.go", nil)
166 w.SetBounds(bounds)
167
168 w.Maximize(area)
169 w.Maximize(area)
170 w.Restore()
171
172 if got := w.Bounds(); got != bounds {
173 t.Errorf("Bounds() = %+v, want %+v", got, bounds)
174 }
175}
176
177func TestAMaximisedWindowFollowsATerminalThatShrinks(t *testing.T) {
178 // Without the restore rectangle following the desktop, pressing the box
179 // after a shrink would put the window partly off the screen.
180 before := Rect{W: 80, H: 22}
181 after := Rect{W: 40, H: 12}
182 d, w := framedWindow(t, before, Rect{X: 10, Y: 2, W: 60, H: 18})
183
184 d.ToggleMaximize(w)
185 d.SetBounds(after)
186
187 if got := w.Bounds(); got != after {
188 t.Errorf("a maximised window is %+v, want the new desktop %+v", got, after)
189 }
190
191 d.ToggleMaximize(w)
192 restored := w.Bounds()
193 if restored.Right() > after.Right() || restored.Bottom() > after.Bottom() {
194 t.Errorf("restored to %+v, which sticks out of the desktop %+v", restored, after)
195 }
196}
197
198func TestTilingAWindowForgetsThatItWasMaximised(t *testing.T) {
199 // Its box must go back to offering to maximise: the rectangle it would
200 // restore to is not where the window is any more.
201 area := Rect{W: 40, H: 12}
202 d, w := framedWindow(t, area, Rect{W: 30, H: 8})
203 d.ToggleMaximize(w)
204
205 d.Tile()
206
207 if w.Maximized() {
208 t.Error("a tiled window still calls itself maximised")
209 }
210}
211
212func TestCascadingAWindowForgetsThatItWasMaximised(t *testing.T) {
213 area := Rect{W: 40, H: 12}
214 d, w := framedWindow(t, area, Rect{W: 30, H: 8})
215 d.ToggleMaximize(w)
216
217 d.Cascade()
218
219 if w.Maximized() {
220 t.Error("a cascaded window still calls itself maximised")
221 }
222}
223
224func TestTheTitleNeverRunsIntoTheFurniture(t *testing.T) {
225 // The margin kept for the boxes and the number is arithmetic that is easy
226 // to get wrong by one, and getting it wrong overwrites the number or the
227 // box with a letter. This checks it rather than trusting the sum.
228 for width := 16; width <= 60; width++ {
229 for _, title := range []string{"a", "main.go", "a-rather-long-file-name.go", strings.Repeat("x", 80)} {
230 w := NewWindow(title, nil)
231 d := NewDesktop()
232 d.SetBounds(Rect{W: width, H: 10})
233 d.Add(w)
234 w.SetBounds(Rect{W: width, H: 6})
235 w.SetNumber(7)
236
237 bar := []rune(titleBar(t, w, width, 10))
238 assertFurnitureIntact(t, bar, width, title)
239 }
240 }
241}
242
243// assertFurnitureIntact checks that a drawn title bar still has its close box,
244// its number and its maximise box where they belong — and, the part that
245// actually catches an off-by-one, that the title stops short of them.
246//
247// Checking the furniture alone proves very little: drawNumber runs after
248// drawTitleBar, so the number is painted over whatever the title left there
249// and always looks right. What goes wrong is the other way round — the title
250// loses its last character to the number, reading "main.g7".
251func assertFurnitureIntact(t *testing.T, bar []rune, width int, title string) {
252 t.Helper()
253
254 if got := string(bar[2 : 2+boxWidth]); got != closeBoxLabel {
255 t.Fatalf("width %d, title %q: the close box reads %q", width, title, got)
256 }
257 if got := bar[width-numberOffset]; got != '7' {
258 t.Fatalf("width %d, title %q: the number cell holds %q", width, title, string(got))
259 }
260 from := width - maximizeOffset
261 if got := string(bar[from : from+boxWidth]); got != maximizeBoxLabel {
262 t.Fatalf("width %d, title %q: the maximise box reads %q", width, title, got)
263 }
264
265 // The title always ends in a space, so the cell before the number is one
266 // of those or bare frame. A letter there means the title reached the
267 // number and lost a character to it.
268 if got := bar[width-numberOffset-1]; !isFrameOrSpace(got) {
269 t.Fatalf("width %d, title %q: %q sits against the number, so the title was clipped by it",
270 width, title, string(got))
271 }
272 if got := bar[4+1]; !isFrameOrSpace(got) {
273 t.Fatalf("width %d, title %q: %q sits against the close box", width, title, string(got))
274 }
275}
276
277// isFrameOrSpace reports whether a cell of the top frame holds no title text.
278func isFrameOrSpace(r rune) bool {
279 return r == ' ' || r == '═' || r == '─'
280}
281
282// pressMaximizeBox clicks the middle of the maximise box.
283func pressMaximizeBox(w *Window) {
284 bounds := w.Bounds()
285 w.HandleMouse(clickEvent(bounds.Right()-maximizeOffset+1, bounds.Y))
286}