main 3d41bc5

destination_test.go RawHistoryFolder

1package app
2
3import (
4	"os"
5	"path/filepath"
6	"strings"
7	"testing"
8
9	"github.com/stretchr/testify/assert"
10	"github.com/stretchr/testify/require"
11
12	"github.com/bnema/nefercap/internal/adapters/cli"
13	"github.com/bnema/nefercap/internal/adapters/config"
14	"github.com/bnema/nefercap/internal/ports"
15)
16
17// A bad configured directory fails before the selector opens, for every
18// directory the command can reach.
19func TestCheckDirsBeforeSelector(t *testing.T) {
20	root := t.TempDir()
21	file := filepath.Join(root, "file")
22	require.NoError(t, os.WriteFile(file, nil, 0o600))
23	good := filepath.Join(root, "good")
24	for _, tc := range []struct {
25		name     string
26		options  cli.Options
27		settings config.Settings
28		wantKey  string // config key named in the error; empty means no error
29	}{
30		{"all-in-one bad video dir", cli.Options{Command: cli.AllInOne}, config.Settings{VideoDir: file, ScreenshotDir: good}, "video.dir"},
31		{"all-in-one bad screenshot dir", cli.Options{Command: cli.AllInOne}, config.Settings{VideoDir: good, ScreenshotDir: file}, "screenshot.dir"},
32		{"all-in-one clipboard skips screenshot dir", cli.Options{Command: cli.AllInOne}, config.Settings{VideoDir: good, ScreenshotDir: file, Output: config.OutputClipboard}, ""},
33		{"shot ignores video dir", cli.Options{Command: cli.Shot}, config.Settings{VideoDir: file, ScreenshotDir: good}, ""},
34		{"rec ignores screenshot dir", cli.Options{Command: cli.Rec}, config.Settings{VideoDir: good, ScreenshotDir: file}, ""},
35		{"rec bad video dir", cli.Options{Command: cli.Rec}, config.Settings{VideoDir: file}, "video.dir"},
36		{"explicit -file skips dirs", cli.Options{Command: cli.Shot, Path: "x.png"}, config.Settings{ScreenshotDir: file}, ""},
37	} {
38		t.Run(tc.name, func(t *testing.T) {
39			err := checkDirs(tc.options, tc.settings)
40			if tc.wantKey != "" {
41				assert.ErrorContains(t, err, tc.wantKey+":")
42			} else {
43				assert.NoError(t, err)
44			}
45		})
46	}
47}
48
49func TestAssignScreenshotDestination(t *testing.T) {
50	dir := filepath.Join(t.TempDir(), "shots")
51	for _, tc := range []struct {
52		name      string
53		output    config.ScreenshotOutput
54		options   cli.Options
55		wantFile  bool // a file in dir
56		wantPath  string
57		clipboard bool
58	}{
59		{"file default", config.OutputFile, cli.Options{}, true, "", false},
60		{"file+clipboard", config.OutputFileClipboard, cli.Options{}, true, "", true},
61		{"clipboard only", config.OutputClipboard, cli.Options{}, false, "", true},
62		{"-file overrides clipboard config", config.OutputClipboard, cli.Options{Path: "x.png"}, false, "x.png", false},
63		{"-file overrides file+clipboard", config.OutputFileClipboard, cli.Options{Path: "x.png"}, false, "x.png", false},
64		{"-clipboard overrides file config", config.OutputFile, cli.Options{Clipboard: true}, false, "", true},
65		{"-clipboard -file", config.OutputFile, cli.Options{Clipboard: true, Path: "x.png"}, false, "x.png", true},
66	} {
67		t.Run(tc.name, func(t *testing.T) {
68			sel := ports.Selection{Mode: ports.Screenshot}
69			require.NoError(t, assignDestination(&sel, tc.options, config.Settings{Output: tc.output, ScreenshotDir: dir}))
70			assert.Equal(t, tc.clipboard, sel.Clipboard)
71			if tc.wantFile {
72				assert.Equal(t, dir, filepath.Dir(sel.Path))
73				assert.True(t, strings.HasSuffix(sel.Path, ".png"))
74			} else {
75				assert.Equal(t, tc.wantPath, sel.Path)
76			}
77		})
78	}
79	info, err := os.Stat(dir)
80	require.NoError(t, err)
81	assert.Equal(t, os.FileMode(0o700), info.Mode().Perm())
82}
83
84func TestAssignVideoDestination(t *testing.T) {
85	dir := filepath.Join(t.TempDir(), "vids")
86	settings := config.Settings{Output: config.OutputClipboard, VideoDir: dir}
87	sel := ports.Selection{Mode: ports.Record}
88	require.NoError(t, assignDestination(&sel, cli.Options{}, settings))
89	assert.Equal(t, dir, filepath.Dir(sel.Path), "video.dir applies; screenshot.output does not")
90	assert.True(t, strings.HasSuffix(sel.Path, ".mp4"))
91	assert.False(t, sel.Clipboard)
92	sel = ports.Selection{Mode: ports.Record}
93	require.NoError(t, assignDestination(&sel, cli.Options{Path: "v.mp4"}, settings))
94	assert.Equal(t, "v.mp4", sel.Path)
95}

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 2

Tags 9

↑↓ moveenter openesc close