detached a1f6bdf

test(web): cover g sequences in the jstest suite

commit
a1f6bdf96df4207f0816dc61cf840c2a6ddbc20d
author
brice · · 2026-10-22 07:30 UTC
parent
ab716d9
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +8 -7
R internal/adapters/web/keyboard_test.js → internal/adapters/web/jstest/keyboard.test.mjs +5 -6 renamed, 85% similar
@@ -1,10 +1,9 @@
1-// Run with node --test internal/adapters/web/keyboard_test.js.
21 // Exercise the production key handler without a browser or dependencies.
3-const { test } = require('node:test');
4-const assert = require('node:assert/strict');
5-const { readFileSync } = require('node:fs');
6-const { runInNewContext } = require('node:vm');
7-const source = readFileSync(__dirname + '/static/js/ermite.js', 'utf8');
2+import assert from 'node:assert/strict';
3+import { readFileSync } from 'node:fs';
4+import { test } from 'node:test';
5+import { runInNewContext } from 'node:vm';
6+const source = readFileSync(new URL('../static/js/ermite.js', import.meta.url), 'utf8');
87 function keyboard({ off = false, typing = false, dialog = false } = {}) {
98 let handler;
109 const fired = [];
@@ -1,10 +1,9 @@
1-// Run with node --test internal/adapters/web/keyboard_test.js.
2 // Exercise the production key handler without a browser or dependencies.1 // Exercise the production key handler without a browser or dependencies.
3-const { test } = require('node:test');2+import assert from 'node:assert/strict';
4-const assert = require('node:assert/strict');3+import { readFileSync } from 'node:fs';
5-const { readFileSync } = require('node:fs');4+import { test } from 'node:test';
6-const { runInNewContext } = require('node:vm');5+import { runInNewContext } from 'node:vm';
7-const source = readFileSync(__dirname + '/static/js/ermite.js', 'utf8');6+const source = readFileSync(new URL('../static/js/ermite.js', import.meta.url), 'utf8');
8 function keyboard({ off = false, typing = false, dialog = false } = {}) {7 function keyboard({ off = false, typing = false, dialog = false } = {}) {
9 let handler;8 let handler;
10 const fired = [];9 const fired = [];
M internal/adapters/web/jstest/keys.test.mjs +3 -1
@@ -17,9 +17,11 @@ function page({ owner = true, off = false, typing = false, dialog = false } = {}
1717 return fired;
1818 };
1919 }
20-test('Shift+I opens inbox while lowercase i retains the issues tab', () => {
20+test('Shift+I opens inbox while issues need the g i sequence', () => {
2121 const press = page();
2222 assert.deepEqual(press('I'), ['inbox']);
23+ assert.deepEqual(press('i'), ['inbox']);
24+ press('g');
2325 assert.deepEqual(press('i'), ['inbox', 'i']);
2426 });
2527 test('inbox shortcut respects preference, fields, dialogs, and owner target', () => {
@@ -17,9 +17,11 @@ function page({ owner = true, off = false, typing = false, dialog = false } = {}
17 return fired;17 return fired;
18 };18 };
19 }19 }
20-test('Shift+I opens inbox while lowercase i retains the issues tab', () => {20+test('Shift+I opens inbox while issues need the g i sequence', () => {
21 const press = page();21 const press = page();
22 assert.deepEqual(press('I'), ['inbox']);22 assert.deepEqual(press('I'), ['inbox']);
23+ assert.deepEqual(press('i'), ['inbox']);
24+ press('g');
23 assert.deepEqual(press('i'), ['inbox', 'i']);25 assert.deepEqual(press('i'), ['inbox', 'i']);
24 });26 });
25 test('inbox shortcut respects preference, fields, dialogs, and owner target', () => {27 test('inbox shortcut respects preference, fields, dialogs, and owner target', () => {

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