v0.33.2 57f21d6

accessibility_handler_test.go RawHistoryFolder

1package cef
2
3import (
4	"testing"
5
6	purecef "github.com/bnema/purego-cef/cef"
7	cefmocks "github.com/bnema/purego-cef/cef/mocks"
8	"github.com/stretchr/testify/assert"
9	"github.com/stretchr/testify/require"
10)
11
12type stubCEFValue struct{}
13
14func (stubCEFValue) IsValid() bool                               { return true }
15func (stubCEFValue) IsOwned() bool                               { return false }
16func (stubCEFValue) IsReadOnly() bool                            { return true }
17func (stubCEFValue) IsSame(purecef.Value) bool                   { return false }
18func (stubCEFValue) IsEqual(purecef.Value) bool                  { return false }
19func (stubCEFValue) Copy() purecef.Value                         { return stubCEFValue{} }
20func (stubCEFValue) GetType() purecef.ValueType                  { return 0 }
21func (stubCEFValue) GetBool() int32                              { return 0 }
22func (stubCEFValue) GetInt() int32                               { return 0 }
23func (stubCEFValue) GetDouble() float64                          { return 0 }
24func (stubCEFValue) GetString() string                           { return "" }
25func (stubCEFValue) GetBinary() purecef.BinaryValue              { return nil }
26func (stubCEFValue) GetDictionary() purecef.DictionaryValue      { return nil }
27func (stubCEFValue) GetList() purecef.ListValue                  { return nil }
28func (stubCEFValue) SetNull() int32                              { return 0 }
29func (stubCEFValue) SetBool(int32) int32                         { return 0 }
30func (stubCEFValue) SetInt(int32) int32                          { return 0 }
31func (stubCEFValue) SetDouble(float64) int32                     { return 0 }
32func (stubCEFValue) SetString(string) int32                      { return 0 }
33func (stubCEFValue) SetBinary(purecef.BinaryValue) int32         { return 0 }
34func (stubCEFValue) SetDictionary(purecef.DictionaryValue) int32 { return 0 }
35func (stubCEFValue) SetList(purecef.ListValue) int32             { return 0 }
36
37func TestRenderHandlerExposesAccessibilityAtWrapTime(t *testing.T) {
38	h := &dumberRenderHandler{a11y: newAccessibilityHandler(nil)}
39	if h.GetAccessibilityHandler() == nil {
40		t.Fatal("CEF would omit the accessibility override at wrap time")
41	}
42}
43
44func TestRenderHandlerExposesAccessibilityWhenMainExists(t *testing.T) {
45	// Must fail open (nil) when a11y was not installed, even if main exists —
46	// never fall back to h.main.GetAccessibilityHandler().
47	mainHandler := cefmocks.NewMockRenderHandler(t)
48	h := &dumberRenderHandler{main: mainHandler, a11y: nil}
49	assert.Nil(t, h.GetAccessibilityHandler())
50	mainHandler.AssertNotCalled(t, "GetAccessibilityHandler")
51
52	h.a11y = newAccessibilityHandler(nil)
53	require.NotNil(t, h.GetAccessibilityHandler())
54	mainHandler.AssertNotCalled(t, "GetAccessibilityHandler")
55}
56
57func TestNewDumberRenderHandlerInstallsNonNilAccessibilityHandler(t *testing.T) {
58	require.Nil(t, newDumberRenderHandler(nil))
59
60	wv := &WebView{viewBridge: &Cef2gtkAdapter{}}
61	rh := newDumberRenderHandler(wv)
62	require.NotNil(t, rh)
63	require.NotNil(t, rh.GetAccessibilityHandler())
64
65	handler, ok := rh.GetAccessibilityHandler().(*accessibilityHandler)
66	require.True(t, ok)
67	assert.Nil(t, handler.sink)
68}
69
70func TestAccessibilityHandler_NilSinkSkipsWriteJSON(t *testing.T) {
71	calls := 0
72	handler, ok := newAccessibilityHandler(nil).(*accessibilityHandler)
73	require.True(t, ok)
74	handler.writeJSON = func(purecef.Value, purecef.JsonWriterOptions) string {
75		calls++
76		return `{"unexpected":true}`
77	}
78
79	handler.OnAccessibilityTreeChange(stubCEFValue{})
80	handler.OnAccessibilityLocationChange(stubCEFValue{})
81	assert.Equal(t, 0, calls)
82}
83
84func TestAccessibilityHandler_NilValueIgnored(t *testing.T) {
85	calls := 0
86	var got []accessibilityPayload
87	handler, ok := newAccessibilityHandler(func(p accessibilityPayload) bool {
88		got = append(got, p)
89		return true
90	}).(*accessibilityHandler)
91	require.True(t, ok)
92	handler.writeJSON = func(purecef.Value, purecef.JsonWriterOptions) string {
93		calls++
94		return `{}`
95	}
96
97	handler.OnAccessibilityTreeChange(nil)
98	handler.OnAccessibilityLocationChange(nil)
99	assert.Equal(t, 0, calls)
100	assert.Empty(t, got)
101}
102
103func TestAccessibilityHandler_TreeAndLocationWriteJSONOnce(t *testing.T) {
104	var writeCalls []string
105	var got []accessibilityPayload
106	handler, ok := newAccessibilityHandler(func(p accessibilityPayload) bool {
107		got = append(got, p)
108		return true
109	}).(*accessibilityHandler)
110	require.True(t, ok)
111	handler.writeJSON = func(value purecef.Value, options purecef.JsonWriterOptions) string {
112		require.Equal(t, purecef.JsonWriterOptionsJsonWriterDefault, options)
113		require.NotNil(t, value)
114		writeCalls = append(writeCalls, "write")
115		return `{"ok":true}`
116	}
117
118	handler.OnAccessibilityTreeChange(stubCEFValue{})
119	handler.OnAccessibilityLocationChange(stubCEFValue{})
120
121	require.Len(t, writeCalls, 2)
122	require.Len(t, got, 2)
123	assert.Equal(t, accessibilityCaptureKindTree, got[0].Kind)
124	assert.Equal(t, `{"ok":true}`, got[0].JSON)
125	assert.Equal(t, len(`{"ok":true}`), got[0].Bytes)
126	assert.GreaterOrEqual(t, got[0].SerializeNanos, int64(0))
127	assert.Equal(t, accessibilityCaptureKindLocation, got[1].Kind)
128	assert.Equal(t, `{"ok":true}`, got[1].JSON)
129	assert.Equal(t, len(`{"ok":true}`), got[1].Bytes)
130	assert.GreaterOrEqual(t, got[1].SerializeNanos, int64(0))
131}
132
133func TestAccessibilityHandler_ProductionNoCaptureZeroWriteJSON(t *testing.T) {
134	calls := 0
135
136	// Factory/production path without DUMBER_A11Y_CAPTURE=1: worker stays nil,
137	// sink is truly nil, WriteJson must not run.
138	wv := &WebView{viewBridge: &Cef2gtkAdapter{}}
139	rh := newDumberRenderHandler(wv)
140	require.NotNil(t, rh)
141
142	handler, ok := rh.GetAccessibilityHandler().(*accessibilityHandler)
143	require.True(t, ok)
144	require.Nil(t, handler.sink)
145	handler.writeJSON = func(purecef.Value, purecef.JsonWriterOptions) string {
146		calls++
147		return `{}`
148	}
149
150	handler.OnAccessibilityTreeChange(stubCEFValue{})
151	handler.OnAccessibilityLocationChange(stubCEFValue{})
152	assert.Equal(t, 0, calls)
153}

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