resize_test.go RawHistoryFolder

1package term
2
3import (
4	"errors"
5	"os"
6	"syscall"
7	"testing"
8	"time"
9
10	"github.com/bnema/vev/internal/domain"
11)
12
13func TestResizeLoop_CoalescesBurstToOneEmission(t *testing.T) {
14	// Fill the signal channel with a burst before the loop starts
15	// consuming: draining is synchronous and deterministic here since
16	// nothing else sends concurrently.
17	sig := make(chan os.Signal, 8)
18	for range 5 {
19		sig <- syscall.SIGWINCH
20	}
21
22	out := make(chan domain.Geometry)
23	quit := make(chan struct{})
24
25	var calls int
26	getGeometry := func() (domain.Geometry, error) {
27		calls++
28		return domain.Geometry{Size: domain.Size{Cols: 80, Rows: 24}, PixelWidth: 800, PixelHeight: 480}, nil
29	}
30
31	go resizeLoop(sig, out, quit, getGeometry)
32
33	got := <-out
34	want := domain.Geometry{Size: domain.Size{Cols: 80, Rows: 24}, PixelWidth: 800, PixelHeight: 480}
35	if got != want {
36		t.Fatalf("emitted size = %+v, want %+v", got, want)
37	}
38
39	select {
40	case sz2, ok := <-out:
41		t.Fatalf("unexpected second emission (ok=%v): %+v", ok, sz2)
42	case <-time.After(50 * time.Millisecond):
43	}
44
45	if calls != 1 {
46		t.Fatalf("getSize called %d times, want 1 (burst should coalesce)", calls)
47	}
48
49	close(quit)
50	if _, ok := <-out; ok {
51		t.Fatalf("expected out to be closed after quit")
52	}
53}
54
55func TestResizeLoop_GetSizeErrorSkipsEmission(t *testing.T) {
56	sig := make(chan os.Signal) // unbuffered: sends rendezvous with the loop's receive
57	out := make(chan domain.Geometry)
58	quit := make(chan struct{})
59
60	var calls int
61	firstGetSize := make(chan struct{})
62	getGeometry := func() (domain.Geometry, error) {
63		calls++
64		if calls == 1 {
65			close(firstGetSize)
66			return domain.Geometry{}, errors.New("boom")
67		}
68		return domain.Geometry{Size: domain.Size{Cols: 10, Rows: 5}}, nil
69	}
70
71	go resizeLoop(sig, out, quit, getGeometry)
72
73	sig <- syscall.SIGWINCH // errors; no emission
74	<-firstGetSize          // wait until the failed signal has been handled
75	sig <- syscall.SIGWINCH // succeeds
76
77	got := <-out
78	want := domain.Geometry{Size: domain.Size{Cols: 10, Rows: 5}}
79	if got != want {
80		t.Fatalf("emitted size = %+v, want %+v", got, want)
81	}
82	if calls != 2 {
83		t.Fatalf("getSize called %d times, want 2", calls)
84	}
85
86	close(quit)
87	if _, ok := <-out; ok {
88		t.Fatalf("expected out to be closed after quit")
89	}
90}
91
92func TestResizeLoop_QuitClosesOutImmediately(t *testing.T) {
93	sig := make(chan os.Signal)
94	out := make(chan domain.Geometry)
95	quit := make(chan struct{})
96
97	getGeometry := func() (domain.Geometry, error) {
98		t.Fatalf("getGeometry should not be called")
99		return domain.Geometry{}, nil
100	}
101
102	go resizeLoop(sig, out, quit, getGeometry)
103	close(quit)
104
105	select {
106	case _, ok := <-out:
107		if ok {
108			t.Fatalf("expected out to be closed, got a value")
109		}
110	case <-time.After(time.Second):
111		t.Fatalf("out was not closed after quit")
112	}
113}
114
115func TestDrainSignals_RemovesQueuedSignalsOnly(t *testing.T) {
116	sig := make(chan os.Signal, 4)
117	sig <- syscall.SIGWINCH
118	sig <- syscall.SIGWINCH
119	sig <- syscall.SIGWINCH
120
121	drainSignals(sig)
122
123	select {
124	case s := <-sig:
125		t.Fatalf("expected sig to be empty after drain, got %v", s)
126	default:
127	}
128}

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 12

Tags 11

↑↓ moveenter openesc close