v0.13.0 976176a

workspace_navigation_test.go RawHistoryFolder

1package browser
2
3import (
4	"testing"
5
6	"github.com/diamondburned/gotk4/pkg/gtk/v4"
7)
8
9// TestFocusNeighborVerticalSplit tests basic tree structure validation
10// Note: Full geometry-based navigation testing requires integration tests with real GTK widgets
11func TestFocusNeighborVerticalSplit(t *testing.T) {
12	t.Skip("Structural neighbor navigation requires real GTK widgets for geometry calculations")
13}
14
15// TestFocusNeighborHorizontalSplit tests basic tree structure validation
16// Note: Full geometry-based navigation testing requires integration tests with real GTK widgets
17func TestFocusNeighborHorizontalSplit(t *testing.T) {
18	t.Skip("Structural neighbor navigation requires real GTK widgets for geometry calculations")
19}
20
21// TestPaneNodeStructure verifies basic pane node relationships
22func TestPaneNodeStructure(t *testing.T) {
23	root := &paneNode{
24		orientation: gtk.OrientationVertical,
25		isLeaf:      false,
26	}
27
28	child1 := &paneNode{
29		parent: root,
30		isLeaf: true,
31	}
32
33	child2 := &paneNode{
34		parent: root,
35		isLeaf: true,
36	}
37
38	root.left = child1
39	root.right = child2
40
41	// Verify parent-child relationships
42	if child1.parent != root {
43		t.Errorf("child1.parent should be root")
44	}
45
46	if child2.parent != root {
47		t.Errorf("child2.parent should be root")
48	}
49
50	// Verify root children
51	if root.left != child1 {
52		t.Errorf("root.left should be child1")
53	}
54
55	if root.right != child2 {
56		t.Errorf("root.right should be child2")
57	}
58
59	// Verify leaf status
60	if !child1.isLeaf {
61		t.Errorf("child1 should be a leaf")
62	}
63
64	if !child2.isLeaf {
65		t.Errorf("child2 should be a leaf")
66	}
67
68	if root.isLeaf {
69		t.Errorf("root should not be a leaf")
70	}
71}
72
73// TestMapDirection verifies direction mapping to GTK orientation
74func TestMapDirection(t *testing.T) {
75	tests := []struct {
76		direction     string
77		orientation   gtk.Orientation
78		existingFirst bool
79	}{
80		{DirectionDown, gtk.OrientationVertical, true},
81		{DirectionUp, gtk.OrientationVertical, false},
82		{DirectionRight, gtk.OrientationHorizontal, true},
83		{DirectionLeft, gtk.OrientationHorizontal, false},
84	}
85
86	for _, tt := range tests {
87		t.Run(tt.direction, func(t *testing.T) {
88			orientation, existingFirst := mapDirection(tt.direction)
89
90			if orientation != tt.orientation {
91				t.Errorf("mapDirection(%q) orientation = %v, want %v",
92					tt.direction, orientation, tt.orientation)
93			}
94
95			if existingFirst != tt.existingFirst {
96				t.Errorf("mapDirection(%q) existingFirst = %v, want %v",
97					tt.direction, existingFirst, tt.existingFirst)
98			}
99		})
100	}
101}
102
103// TestInvalidDirections verifies handling of invalid directions
104func TestInvalidDirections(t *testing.T) {
105	wm := &WorkspaceManager{}
106
107	invalidDirections := []string{
108		"",
109		"unknown",
110		"diagonal",
111	}
112
113	for _, direction := range invalidDirections {
114		t.Run(direction, func(t *testing.T) {
115			success := wm.FocusNeighbor(direction)
116			if success {
117				t.Errorf("Expected FocusNeighbor(%q) to return false, got true", direction)
118			}
119		})
120	}
121}
122
123// TestCaseSensitiveDirections verifies that direction strings are case-insensitive
124func TestCaseSensitiveDirections(t *testing.T) {
125	wm := &WorkspaceManager{}
126
127	// These should be accepted (case insensitive), but will return false
128	// because there's no active pane to navigate from
129	validDirections := []string{
130		"UP",
131		"Down",
132		"LEFT",
133		"Right",
134		DirectionUp,
135		DirectionDown,
136		DirectionLeft,
137		DirectionRight,
138	}
139
140	for _, direction := range validDirections {
141		t.Run(direction, func(t *testing.T) {
142			// Should not panic or error, just return false since no panes exist
143			_ = wm.FocusNeighbor(direction)
144		})
145	}
146}

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 8

Tags 42

↑↓ moveenter openesc close