map_animation_test.go RawHistoryFolder

1package core_test
2
3import (
4	"testing"
5	"time"
6
7	"github.com/bnema/neferwl/internal/ports"
8)
9
10// A window that maps through the owner loop appears: the scene right after
11// the map shows it invisible at 90 %, a frame later it is in between, and it
12// settles exactly; its neighbour slides over. The client is configured once
13// per window. With animations off the first scene is the final one.
14func TestMapAnimates(t *testing.T) {
15	r := startSwipe(t, nil)
16	r.mapWindow(t, 1)
17	for len(r.commands) > 0 {
18		<-r.commands
19	}
20	first := r.multiRig.mapWindow(t, 2)[0]
21	w := windowOf(t, first, 2)
22	if w.Fade != 1 || w.Hidden {
23		t.Fatalf("new window right after the map: %+v", w)
24	}
25	if got := rectNow(t, first, 1); got.W != 800 {
26		t.Fatalf("neighbour right after the map is %d wide, want its old 800", got.W)
27	}
28	mid := r.frame(t, 30*time.Millisecond)
29	if m := windowOf(t, mid, 2); !(m.Fade > 0 && m.Fade < 1 && m.Rect.W > w.Rect.W && m.Rect.W < 400) {
30		t.Fatalf("new window on the first frame: %+v (was %+v)", m, w)
31	}
32	if got := rectNow(t, mid, 1).W; got <= 400 || got >= 800 {
33		t.Fatalf("neighbour on the first frame is %d wide, want between 400 and 800", got)
34	}
35	end := r.settle(t)
36	if m := windowOf(t, end, 2); m.Fade != 0 || m.Zoom != 0 || m.Rect.W != 400 {
37		t.Fatalf("settled new window: %+v", m)
38	}
39	if got := rectNow(t, end, 1).W; got != 400 {
40		t.Fatalf("settled neighbour is %d wide", got)
41	}
42	configures := map[ports.WindowID]int{}
43	for len(r.commands) > 0 {
44		if v, ok := (<-r.commands).(ports.ConfigureWindow); ok {
45			configures[v.ID]++
46			if v.Width != 400 {
47				t.Fatalf("configure to %d wide, want the final 400: %+v", v.Width, v)
48			}
49		}
50	}
51	if configures[2] != 1 || configures[1] != 1 {
52		t.Fatalf("configures %v, want one each", configures)
53	}
54}
55
56// With animations off a map shows the final layout at once.
57func TestMapAnimationsOffIsInstant(t *testing.T) {
58	r := startSwipe(t, animationsOff)
59	r.mapWindow(t, 1)
60	s := r.multiRig.mapWindow(t, 2)[0]
61	if w := windowOf(t, s, 2); w.Fade != 0 || w.Zoom != 0 || w.Rect.W != 400 {
62		t.Fatalf("new window: %+v", w)
63	}
64	if got := rectNow(t, s, 1).W; got != 400 {
65		t.Fatalf("neighbour is %d wide, want 400", got)
66	}
67	r.noFrameScene(t)
68}
69
70// A window that goes fullscreen right after its map drops its entrance.
71func TestMapFullscreenRequestDropsEntrance(t *testing.T) {
72	r := startSwipe(t, nil)
73	s := r.multiRig.mapWindow(t, 1)[0]
74	if windowOf(t, s, 1).Fade != 1 {
75		t.Fatal("no entrance to drop")
76	}
77	r.client <- ports.WindowFullscreenRequest{ID: 1, Fullscreen: true, External: true}
78	s = scene(t, r.scenes)
79	if w := windowOf(t, s, 1); w.Fade != 0 || w.Zoom != 0 || !w.Fullscreen {
80		t.Fatalf("fullscreen window still fading: %+v", w)
81	}
82}
83
84// A fullscreen request inside the grace after the map is ignored (Wine at a
85// remembered size): the entrance goes on.
86func TestMapFullscreenRequestWithinGraceKeepsEntrance(t *testing.T) {
87	r := startSwipe(t, nil)
88	s := r.multiRig.mapWindow(t, 1)[0]
89	if windowOf(t, s, 1).Fade != 1 {
90		t.Fatal("no entrance to keep")
91	}
92	r.client <- ports.WindowFullscreenRequest{ID: 1, Fullscreen: true}
93	// The flip is a barrier: the request is handled, a leftover scene dropped.
94	set, ok := r.clk.flip(t, r.frames, r.scenes, 30*time.Millisecond, wide.Name)
95	if !ok {
96		t.Fatal("no frame: the entrance stopped")
97	}
98	if w := windowOf(t, set[0], 1); w.Fullscreen || !(w.Fade > 0 && w.Fade < 1) {
99		t.Fatalf("ignored fullscreen request changed the window: %+v", w)
100	}
101}
102
103func windowOf(t *testing.T, s ports.Scene, id ports.WindowID) ports.SceneWindow {
104	t.Helper()
105	for _, w := range s.Windows {
106		if w.ID == id {
107			return w
108		}
109	}
110	t.Fatalf("window %d not in %+v", id, s.Windows)
111	return ports.SceneWindow{}
112}

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 25

Tags 10

↑↓ moveenter openesc close