v0.36.0 1fb2421

accessibility_test.go RawHistoryFolder

1// SPDX-License-Identifier: AGPL-3.0-or-later
2
3package web
4
5import (
6	"testing"
7
8	"github.com/stretchr/testify/assert"
9)
10
11func TestIssueFieldAccessibility(t *testing.T) {
12	for _, field := range []string{"title", "body", "author"} {
13		t.Run(field, func(t *testing.T) {
14			html := renderToString(t, IssueForm(Layout{}, IssueFormPage{ErrorField: field, Error: "Too long"}))
15			assert.Contains(t, html, `id="issue-`+field+`" aria-describedby="issue-`+field+`-count issue-`+field+`-error" aria-invalid="true"`)
16			assert.Contains(t, html, `<p id="issue-`+field+`-error" class="f-error" role="alert">Too long</p>`)
17			for _, f := range []string{"title", "body", "author"} {
18				assert.Contains(t, html, `<output id="issue-`+f+`-count" aria-live="off"`)
19			}
20		})
21	}
22}
23
24func TestHintAccessibility(t *testing.T) {
25	html := renderToString(t, Hint(Layout{Live: true, LiveURL: "/events"}))
26	assert.Contains(t, html, `<div class="hint"><span aria-hidden="true" class="hint-nav"`)
27	assert.Contains(t, html, `<span role="status" aria-live="polite"><span class="hint-sel"`)
28	assert.Contains(t, html, `</span></span><span class="hint-live" role="status"`)
29}
30
31func TestPaletteAccessibilityWithoutNavigationItems(t *testing.T) {
32	html := renderToString(t, OverlayCmd(nil))
33	// The shortcut preference action is always present, even with no targets.
34	assert.Contains(t, html, `aria-expanded="true"`)
35	assert.Contains(t, html, `aria-activedescendant="cmd-o0"`)
36	assert.Contains(t, html, `id="cmd-o0" role="option" aria-selected="true" data-cursor`)
37	assert.Contains(t, html, `<a role="presentation" data-fire="keys">`)
38	assert.Contains(t, html, `aria-label="Close (esc)"`)
39	assert.NotContains(t, html, ` href=`)
40	assert.NotContains(t, html, `tabindex="-1"`)
41}
42
43func TestFinderStatusOutsideHiddenResults(t *testing.T) {
44	html := renderToString(t, Tree(Layout{}, TreePage{}))
45	assert.Contains(t, html, `<p id="finder-status" class="dim" role="status"></p><div id="finder" class="tree-card" hidden>`)
46}
47
48func TestPaletteNavigationOptionsAccessibility(t *testing.T) {
49	html := renderToString(t, OverlayCmd([]CmdItem{{Kind: "section", Label: "Files", Href: "/files"}}))
50	assert.Contains(t, html, `<a role="presentation" data-href="/files">`)
51	assert.NotContains(t, html, ` href=`)
52	assert.NotContains(t, html, `tabindex="-1"`)
53}

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 4

Tags 45

↑↓ moveenter openesc close