v0.29.0 21b3150

standalone_runtime_test.go RawHistoryFolder

1package ui
2
3import (
4	"context"
5	"errors"
6	"testing"
7
8	urlutil "github.com/bnema/dumber/internal/domain/url"
9)
10
11func TestHandleStandaloneOmniboxNavigation_UsesFreshBrowserWindowForHTTP(t *testing.T) {
12	browserURL := ""
13	externalURL := ""
14	err := handleStandaloneOmniboxNavigation(&Dependencies{
15		LaunchBrowserURL: func(_ context.Context, uri string) error {
16			browserURL = uri
17			return nil
18		},
19		LaunchExternalURL: func(uri string) {
20			externalURL = uri
21		},
22	}, context.Background(), "https://example.com")
23
24	if err != nil {
25		t.Fatalf("expected no error, got %v", err)
26	}
27	if browserURL != "https://example.com" {
28		t.Fatalf("expected browser launcher to receive URL, got %q", browserURL)
29	}
30	if externalURL != "" {
31		t.Fatalf("expected external launcher to be unused, got %q", externalURL)
32	}
33}
34
35func TestHandleStandaloneOmniboxNavigation_UsesExternalLauncherForCustomScheme(t *testing.T) {
36	browserURL := ""
37	externalURL := ""
38	err := handleStandaloneOmniboxNavigation(&Dependencies{
39		LaunchBrowserURL: func(_ context.Context, uri string) error {
40			browserURL = uri
41			return nil
42		},
43		LaunchExternalURL: func(uri string) {
44			externalURL = uri
45		},
46	}, context.Background(), "vscode://file/tmp/demo")
47
48	if err != nil {
49		t.Fatalf("expected no error, got %v", err)
50	}
51	if externalURL != "vscode://file/tmp/demo" {
52		t.Fatalf("expected external launcher to receive URL, got %q", externalURL)
53	}
54	if browserURL != "" {
55		t.Fatalf("expected browser launcher to be unused, got %q", browserURL)
56	}
57}
58
59func TestHandleStandaloneOmniboxNavigation_UsesExternalLauncherForMailto(t *testing.T) {
60	browserURL := ""
61	externalURL := ""
62	err := handleStandaloneOmniboxNavigation(&Dependencies{
63		LaunchBrowserURL: func(_ context.Context, uri string) error {
64			browserURL = uri
65			return nil
66		},
67		LaunchExternalURL: func(uri string) {
68			externalURL = uri
69		},
70	}, context.Background(), "mailto:foo@example.com")
71
72	if err != nil {
73		t.Fatalf("expected no error, got %v", err)
74	}
75	if externalURL != "mailto:foo@example.com" {
76		t.Fatalf("expected external launcher to receive URL, got %q", externalURL)
77	}
78	if browserURL != "" {
79		t.Fatalf("expected browser launcher to be unused, got %q", browserURL)
80	}
81}
82
83func TestHandleStandaloneOmniboxNavigation_ReturnsBrowserLaunchError(t *testing.T) {
84	wantErr := context.DeadlineExceeded
85
86	err := handleStandaloneOmniboxNavigation(&Dependencies{
87		LaunchBrowserURL: func(context.Context, string) error {
88			return wantErr
89		},
90	}, context.Background(), "https://example.com")
91
92	if err == nil {
93		t.Fatal("expected browser launch error")
94	}
95	if !errors.Is(err, wantErr) {
96		t.Fatalf("expected error %v, got %v", wantErr, err)
97	}
98}
99
100func TestStandaloneExternalSchemeRules_HTTPIsNotExternal(t *testing.T) {
101	if urlutil.IsExternalScheme("https://example.com") {
102		t.Fatalf("expected http url to stay in dumber")
103	}
104}
105
106func TestStandaloneExternalSchemeRules_CustomSchemeIsExternal(t *testing.T) {
107	if !urlutil.IsExternalScheme("spotify://track/123") {
108		t.Fatalf("expected custom scheme to be external")
109	}
110}
111
112func TestStandaloneExternalSchemeRules_InternalSchemesStayInternal(t *testing.T) {
113	for _, rawURL := range []string{"dumb://history", "dumb://error", "file:///tmp/demo", "about:blank", "data:text/plain,hi"} {
114		if urlutil.IsExternalScheme(rawURL) {
115			t.Fatalf("expected %q to stay internal", rawURL)
116		}
117	}
118}

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