v0.3.0 cf370a0

configure_test.go RawHistoryFolder

1package libinput
2
3import (
4	"bytes"
5	"strings"
6	"testing"
7
8	"github.com/bnema/neferwl/internal/ports"
9	"github.com/bnema/zerowrap"
10)
11
12const (
13	testPad      uintptr = 1
14	testMouse    uintptr = 2
15	testKeyboard uintptr = 3
16)
17
18// Every shared field differs between the two, so a mixed-up route fails.
19var (
20	padCfg   = ports.TouchpadConfig{PointerConfig: ports.PointerConfig{NaturalScroll: true, AccelSpeed: 0.5, AccelProfile: ports.AccelFlat}, Tap: true}
21	mouseCfg = ports.PointerConfig{AccelSpeed: -0.25, AccelProfile: ports.AccelAdaptive, LeftHanded: true}
22)
23
24// newState returns an input state over a device config mock, and a logger
25// writing to the returned buffer.
26func newState(t *testing.T) (*inputState, *mockdeviceConfig, zerowrap.Logger, *bytes.Buffer) {
27	t.Helper()
28	dev := newMockdeviceConfig(t)
29	buf := &bytes.Buffer{}
30	log := zerowrap.New(zerowrap.Config{Level: "debug", Format: "json", Output: buf}).WithField("component", "input")
31	return &inputState{cfg: ports.InputDevicesConfig{Touchpad: padCfg, Mouse: mouseCfg}, dev: dev}, dev, log, buf
32}
33
34func TestConfigure(t *testing.T) {
35	for _, tc := range []struct {
36		name   string
37		dev    uintptr
38		expect func(m *mockdeviceConfig)
39	}{
40		{"touchpad", testPad, func(m *mockdeviceConfig) {
41			m.EXPECT().IsTouchpad(testPad).Return(true)
42			m.EXPECT().SetNaturalScroll(testPad, true).Return(nil).Once()
43			m.EXPECT().SetAccel(testPad, 0.5, ports.AccelFlat).Return(nil).Once()
44			m.EXPECT().SetLeftHanded(testPad, false).Return(nil).Once()
45			m.EXPECT().SetTap(testPad, true).Return(nil).Once()
46		}},
47		// The touchpad settings must not reach the mouse, and a mouse is
48		// never given tapping: SetTap has no expectation.
49		{"mouse", testMouse, func(m *mockdeviceConfig) {
50			m.EXPECT().IsTouchpad(testMouse).Return(false)
51			m.EXPECT().IsPointer(testMouse).Return(true)
52			m.EXPECT().SetNaturalScroll(testMouse, false).Return(nil).Once()
53			m.EXPECT().SetAccel(testMouse, -0.25, ports.AccelAdaptive).Return(nil).Once()
54			m.EXPECT().SetLeftHanded(testMouse, true).Return(nil).Once()
55		}},
56		{"keyboard", testKeyboard, func(m *mockdeviceConfig) {
57			m.EXPECT().IsTouchpad(testKeyboard).Return(false)
58			m.EXPECT().IsPointer(testKeyboard).Return(false)
59		}},
60	} {
61		t.Run(tc.name, func(t *testing.T) {
62			in, dev, log, buf := newState(t)
63			tc.expect(dev)
64			in.configure(tc.dev, log)
65			if buf.Len() != 0 {
66				t.Fatalf("logged: %s", buf)
67			}
68		})
69	}
70}
71
72func TestConfigurable(t *testing.T) {
73	for _, tc := range []struct {
74		name           string
75		touchpad, ptr  bool
76		want, askedPtr bool
77	}{
78		{"touchpad", true, false, true, false},
79		{"mouse", false, true, true, true},
80		{"keyboard", false, false, false, true},
81	} {
82		t.Run(tc.name, func(t *testing.T) {
83			in, dev, _, _ := newState(t)
84			dev.EXPECT().IsTouchpad(testPad).Return(tc.touchpad)
85			if tc.askedPtr {
86				dev.EXPECT().IsPointer(testPad).Return(tc.ptr)
87			}
88			if got := in.configurable(testPad); got != tc.want {
89				t.Fatalf("configurable = %v, want %v", got, tc.want)
90			}
91		})
92	}
93}
94
95func TestConfigureRejectedSettingLogsAndContinues(t *testing.T) {
96	in, dev, log, buf := newState(t)
97	dev.EXPECT().IsTouchpad(testPad).Return(true)
98	dev.EXPECT().SetNaturalScroll(testPad, true).Return(errRejected).Once()
99	dev.EXPECT().Name(testPad).Return("Synaptics").Once()
100	dev.EXPECT().SetAccel(testPad, 0.5, ports.AccelFlat).Return(nil).Once()
101	dev.EXPECT().SetLeftHanded(testPad, false).Return(nil).Once()
102	dev.EXPECT().SetTap(testPad, true).Return(nil).Once()
103	in.configure(testPad, log)
104	out := buf.String()
105	for _, want := range []string{`"device":"Synaptics"`, `"setting":`, `"component":"input"`, `"level":"warn"`} {
106		if !strings.Contains(out, want) {
107			t.Errorf("log %s lacks %s", out, want)
108		}
109	}
110	if n := strings.Count(out, "\n"); n != 1 {
111		t.Errorf("%d log lines, want 1: %s", n, out)
112	}
113}

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