detached 75c4828

test(adapters): wait for focus and skip truncated reads in timing-sensitive tests (#8)

commit
75c48282798e9b2c48a5e28f00e17cd71ce8074e
author
bnema · · 2026-09-27 05:59 UTC
committer
GitHub · · 2026-09-27 05:59 UTC
parent
368d496
signature
GPG UnverifiedB5690EEEBB952194 The key is unknown
2 files · +14 -12
M internal/adapters/config/watch_test.go +12 -6
@@ -50,15 +50,21 @@ func TestWatch(t *testing.T) {
5050 }
5151 }
5252 write(path, "background = #000000\n")
53+ // receive waits for want. A slow machine may pause longer than the
54+ // debounce between WriteFile's truncation and its write: the
55+ // watcher then reads an empty file first, which is skipped here.
5356 receive := func(want string) {
5457 t.Helper()
55- select {
56- case c := <-out:
57- if c.Config.Background.Color != want {
58- t.Fatalf("color %s, want %s", c.Config.Background.Color, want)
58+ deadline := time.After(time.Second)
59+ for {
60+ select {
61+ case c := <-out:
62+ if c.Config.Background.Color == want {
63+ return
64+ }
65+ case <-deadline:
66+ t.Fatalf("no config change to %s", want)
5967 }
60- case <-time.After(time.Second):
61- t.Fatal("no config change")
6268 }
6369 }
6470 receive("#000000")
@@ -50,15 +50,21 @@ func TestWatch(t *testing.T) {
50 }50 }
51 }51 }
52 write(path, "background = #000000\n")52 write(path, "background = #000000\n")
53+ // receive waits for want. A slow machine may pause longer than the
54+ // debounce between WriteFile's truncation and its write: the
55+ // watcher then reads an empty file first, which is skipped here.
53 receive := func(want string) {56 receive := func(want string) {
54 t.Helper()57 t.Helper()
55- select {58+ deadline := time.After(time.Second)
56- case c := <-out:59+ for {
57- if c.Config.Background.Color != want {60+ select {
58- t.Fatalf("color %s, want %s", c.Config.Background.Color, want)61+ case c := <-out:
62+ if c.Config.Background.Color == want {
63+ return
64+ }
65+ case <-deadline:
66+ t.Fatalf("no config change to %s", want)
59 }67 }
60- case <-time.After(time.Second):
61- t.Fatal("no config change")
62 }68 }
63 }69 }
64 receive("#000000")70 receive("#000000")
M internal/adapters/wayland/activation_test.go +2 -6
@@ -95,9 +95,7 @@ func TestActivationNeedsFocusedRequester(t *testing.T) {
9595
9696 // The focused client's token activates, once.
9797 commands <- ports.FocusWindow{ID: first.ID}
98- if err := c.Roundtrip(); err != nil {
99- t.Fatal(err)
100- }
98+ waitFocus(t, s, first.ID)
10199 token = newToken(t, c, manager)
102100 requestProtocol(t, c, manager, xdgactivation.ActivationV1RequestActivate, token, surf)
103101 activated(t, events, second.ID)
@@ -120,9 +118,7 @@ func TestActivationAcrossClients(t *testing.T) {
120118 managerA := bindProtocol(t, a, "xdg_activation_v1")
121119 managerB := bindProtocol(t, b, "xdg_activation_v1")
122120 commands <- ports.FocusWindow{ID: winA.ID}
123- if err := a.Roundtrip(); err != nil {
124- t.Fatal(err)
125- }
121+ waitFocus(t, s, winA.ID)
126122 token := newToken(t, b, managerB)
127123 requestProtocol(t, b, managerB, xdgactivation.ActivationV1RequestActivate, token, surfB)
128124 noActivation(t, b, events)
@@ -95,9 +95,7 @@ func TestActivationNeedsFocusedRequester(t *testing.T) {
95 95
96 // The focused client's token activates, once.96 // The focused client's token activates, once.
97 commands <- ports.FocusWindow{ID: first.ID}97 commands <- ports.FocusWindow{ID: first.ID}
98- if err := c.Roundtrip(); err != nil {98+ waitFocus(t, s, first.ID)
99- t.Fatal(err)
100- }
101 token = newToken(t, c, manager)99 token = newToken(t, c, manager)
102 requestProtocol(t, c, manager, xdgactivation.ActivationV1RequestActivate, token, surf)100 requestProtocol(t, c, manager, xdgactivation.ActivationV1RequestActivate, token, surf)
103 activated(t, events, second.ID)101 activated(t, events, second.ID)
@@ -120,9 +118,7 @@ func TestActivationAcrossClients(t *testing.T) {
120 managerA := bindProtocol(t, a, "xdg_activation_v1")118 managerA := bindProtocol(t, a, "xdg_activation_v1")
121 managerB := bindProtocol(t, b, "xdg_activation_v1")119 managerB := bindProtocol(t, b, "xdg_activation_v1")
122 commands <- ports.FocusWindow{ID: winA.ID}120 commands <- ports.FocusWindow{ID: winA.ID}
123- if err := a.Roundtrip(); err != nil {121+ waitFocus(t, s, winA.ID)
124- t.Fatal(err)
125- }
126 token := newToken(t, b, managerB)122 token := newToken(t, b, managerB)
127 requestProtocol(t, b, managerB, xdgactivation.ActivationV1RequestActivate, token, surfB)123 requestProtocol(t, b, managerB, xdgactivation.ActivationV1RequestActivate, token, surfB)
128 noActivation(t, b, events)124 noActivation(t, b, events)

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 26

Tags 10

↑↓ moveenter openesc close