v0.14.0 815fb98

ci_pull_test.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package usecase_test
4
5import (
6	"testing"
7
8	"github.com/stretchr/testify/assert"
9	"github.com/stretchr/testify/require"
10
11	"bnema.dev/ermite-actions/workflow"
12	"bnema.dev/ermite/internal/domain"
13	"bnema.dev/ermite/internal/usecase"
14)
15
16func parsePR(t *testing.T, on string) *workflow.Workflow {
17	t.Helper()
18	wf, errs := workflow.Parse("pr.yml", []byte("on:\n"+on+"\njobs:\n  j:\n    runs-on: x\n    steps:\n      - run: 'true'\n"))
19	require.Empty(t, errs)
20	return wf
21}
22
23func TestMatchPullRequestTypes(t *testing.T) {
24	def := parsePR(t, "  pull_request:\n")
25	for action, want := range map[string]bool{"opened": true, "synchronize": true, "reopened": true, "closed": false} {
26		assert.Equal(t, want, usecase.MatchPullRequest(def, action, "main", nil, false), "default types, "+action)
27	}
28	closed := parsePR(t, "  pull_request:\n    types: [closed]\n")
29	assert.True(t, usecase.MatchPullRequest(closed, "closed", "main", nil, false))
30	assert.False(t, usecase.MatchPullRequest(closed, "opened", "main", nil, false))
31	both := parsePR(t, "  pull_request:\n    types: [opened, closed]\n")
32	assert.True(t, usecase.MatchPullRequest(both, "opened", "main", nil, false))
33	assert.True(t, usecase.MatchPullRequest(both, "closed", "main", nil, false))
34	assert.False(t, usecase.MatchPullRequest(both, "synchronize", "main", nil, false))
35	assert.False(t, usecase.MatchPullRequest(parsePR(t, "  push:\n"), "opened", "main", nil, false), "no pull_request event")
36	assert.True(t, usecase.MatchPullRequest(parsePR(t, "  [push, pull_request]\n"), "opened", "main", nil, false))
37}
38
39func TestMatchPullRequestFilters(t *testing.T) {
40	wf := parsePR(t, "  pull_request:\n    branches: [main, 'release/**']\n    paths: ['src/**', '!src/gen/**']\n")
41	files := func(f ...string) []string { return f }
42	assert.True(t, usecase.MatchPullRequest(wf, "opened", "main", files("src/a.go"), false))
43	assert.True(t, usecase.MatchPullRequest(wf, "opened", "release/1.2", files("README.md", "src/b.go"), false))
44	assert.False(t, usecase.MatchPullRequest(wf, "opened", "dev", files("src/a.go"), false), "the base branch is filtered")
45	assert.False(t, usecase.MatchPullRequest(wf, "opened", "main", files("README.md"), false), "the changed files are filtered")
46	assert.False(t, usecase.MatchPullRequest(wf, "opened", "main", files("src/gen/x.go"), false))
47	assert.True(t, usecase.MatchPullRequest(wf, "opened", "main", nil, true), "an unavailable list passes the paths filter")
48
49	ignore := parsePR(t, "  pull_request:\n    branches-ignore: [wip]\n    paths-ignore: ['docs/**']\n")
50	assert.True(t, usecase.MatchPullRequest(ignore, "synchronize", "main", files("docs/a.md", "x.go"), false))
51	assert.False(t, usecase.MatchPullRequest(ignore, "synchronize", "main", files("docs/a.md"), false))
52	assert.False(t, usecase.MatchPullRequest(ignore, "synchronize", "wip", files("x.go"), false))
53}
54
55func TestPullFilesLink(t *testing.T) {
56	const base = "http://x/pulls/1/files"
57	assert.Empty(t, usecase.PullFilesLink(base, 1, 30, 0))
58	assert.Empty(t, usecase.PullFilesLink(base, 1, 30, 30))
59	assert.Equal(t, `<http://x/pulls/1/files?per_page=30&page=2>; rel="next", <http://x/pulls/1/files?per_page=30&page=3>; rel="last"`, usecase.PullFilesLink(base, 1, 30, 61))
60	assert.Equal(t,
61		`<http://x/pulls/1/files?per_page=30&page=3>; rel="next", <http://x/pulls/1/files?per_page=30&page=3>; rel="last", <http://x/pulls/1/files?per_page=30&page=1>; rel="first", <http://x/pulls/1/files?per_page=30&page=1>; rel="prev"`,
62		usecase.PullFilesLink(base, 2, 30, 61))
63	last := usecase.PullFilesLink(base, 3, 30, 61)
64	assert.NotContains(t, last, "next")
65	assert.Contains(t, last, `page=2>; rel="prev"`)
66	beyond := usecase.PullFilesLink(base, 9, 30, 61)
67	assert.NotContains(t, beyond, "next")
68	assert.Contains(t, beyond, `page=3>; rel="prev"`)
69}
70
71func TestFilePatch(t *testing.T) {
72	f := domain.FileDiff{Hunks: []domain.Hunk{
73		{OldStart: 1, OldLines: 2, NewStart: 1, NewLines: 2, Header: "func x()", Lines: []domain.Line{
74			{Kind: domain.LineContext, Text: "a"}, {Kind: domain.LineDeletion, Text: "b"}, {Kind: domain.LineAddition, Text: "c", NoNewlineAtEOF: true},
75		}},
76		{OldStart: 9, OldLines: 1, NewStart: 9, NewLines: 1, Lines: []domain.Line{{Kind: domain.LineAddition, Text: "z"}}},
77	}}
78	got, ok := usecase.FilePatch(f)
79	require.True(t, ok)
80	assert.Equal(t, "@@ -1,2 +1,2 @@ func x()\n a\n-b\n+c\n\\ No newline at end of file\n@@ -9 +9 @@\n+z", got)
81	_, ok = usecase.FilePatch(domain.FileDiff{Binary: true, Hunks: f.Hunks})
82	assert.False(t, ok, "binary")
83	_, ok = usecase.FilePatch(domain.FileDiff{Truncated: true})
84	assert.False(t, ok, "truncated")
85	_, ok = usecase.FilePatch(domain.FileDiff{Status: domain.FileRenamed})
86	assert.False(t, ok, "a pure rename has no hunk")
87}

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 44

↑↓ moveenter openesc close