v0.3.0 da0887c

color_test.go RawHistoryFolder

1package tray
2
3import "testing"
4
5// pixmap builds an ARGB32 icon from pixels of the given colors, n of each.
6func pixmap(colors map[[4]uint8]int) []byte {
7	var b []byte
8	for c, n := range colors {
9		for range n {
10			b = append(b, c[:]...)
11		}
12	}
13	return b
14}
15
16func TestDominant(t *testing.T) {
17	var h histogram
18	// A blue logo with a larger grey outline and a transparent background.
19	got, ok := h.dominant(pixmap(map[[4]uint8]int{
20		{255, 30, 60, 200}:   40, // blue
21		{255, 128, 128, 128}: 100,
22		{0, 255, 0, 0}:       500, // transparent red
23	}))
24	if !ok || got != (RGB{30, 60, 200}) {
25		t.Fatalf("dominant = %v, %v", got, ok)
26	}
27	if _, ok := h.dominant(pixmap(map[[4]uint8]int{{255, 200, 200, 200}: 10})); ok {
28		t.Fatal("a grey icon has no dominant color")
29	}
30	if _, ok := h.dominant(nil); ok {
31		t.Fatal("an empty icon has no dominant color")
32	}
33	icon := pixmap(map[[4]uint8]int{{255, 30, 60, 200}: 1024})
34	if allocs := testing.AllocsPerRun(50, func() { h.dominant(icon) }); allocs != 0 {
35		t.Fatalf("dominant allocates %v times", allocs)
36	}
37}
38
39func TestDominantLargeIcon(t *testing.T) {
40	// 512x512 of one saturated color: summing every pixel would overflow.
41	var h histogram
42	icon := pixmap(map[[4]uint8]int{{255, 250, 20, 20}: 512 * 512})
43	if got, ok := h.dominant(icon); !ok || got != (RGB{250, 20, 20}) {
44		t.Fatalf("dominant = %v, %v", got, ok)
45	}
46}
47
48func TestDominantLargeIconOffColumns(t *testing.T) {
49	// 512x512, transparent but for a red logo in columns 10..49: a stride of
50	// 64 pixels would sample only columns 0, 64, 128... and miss it.
51	const side = 512
52	icon := make([]byte, 0, side*side*4)
53	for range side {
54		for x := range side {
55			if x >= 10 && x < 50 {
56				icon = append(icon, 255, 250, 20, 20)
57			} else {
58				icon = append(icon, 0, 0, 0, 0)
59			}
60		}
61	}
62	var h histogram
63	if got, ok := h.dominant(icon); !ok || got != (RGB{250, 20, 20}) {
64		t.Fatalf("dominant = %v, %v", got, ok)
65	}
66}
67
68func TestReadable(t *testing.T) {
69	bg, fg := RGB{0x1e, 0x1e, 0x2e}, RGB{0xcd, 0xd6, 0xf4}
70	dark := RGB{0x17, 0x1a, 0x21} // Steam's near-black blue
71	got := readable(dark, bg, fg)
72	if contrast(got, bg) < 3 {
73		t.Fatalf("readable(%v) = %v, contrast %.2f", dark, got, contrast(got, bg))
74	}
75	bright := RGB{0xf9, 0xe2, 0xaf}
76	if readable(bright, bg, fg) != bright {
77		t.Fatal("a readable color must not change")
78	}
79}

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 5

Tags 4

↑↓ moveenter openesc close