Some checks failed
build-packages / resolve bundled mosh-client (push) Has been cancelled
build-packages / resolve bundled et-client (push) Has been cancelled
build-packages / build-macos (push) Has been cancelled
build-packages / build-windows (push) Has been cancelled
build-packages / build-linux-x64 (push) Has been cancelled
build-packages / build-linux-arm64 (push) Has been cancelled
build-packages / release (push) Has been cancelled
build-packages / update Nix release metadata (push) Has been cancelled
build-packages / bump homebrew tap (push) Has been cancelled
test / lint-and-test (push) Has been cancelled
AI automation / Route event (push) Has been cancelled
AI automation / Hand reopened issue to maintainers (push) Has been cancelled
AI automation / Clean source issue state (push) Has been cancelled
AI automation / Reconcile handoffs (push) Has been cancelled
AI automation / Classify issue (push) Has been cancelled
AI automation / Claude Code smoke (push) Has been cancelled
AI automation / Review issue follow-up (push) Has been cancelled
AI automation / Publish issue follow-up (push) Has been cancelled
AI automation / Implement with Claude Code (push) Has been cancelled
AI automation / Publish implement PR (push) Has been cancelled
AI automation / Continue queued issue comments (push) Has been cancelled
AI automation / Codex review loop (push) Has been cancelled
AI automation / Publish Codex fix (push) Has been cancelled
AI automation / Clear Codex dispatch marker (push) Has been cancelled
AI automation / Own PR re-request Codex (push) Has been cancelled
AI automation / External PR re-request Codex (push) Has been cancelled
AI automation / Poll Codex reaction / retry (push) Has been cancelled
build-et-binaries / build-linux-x64 (push) Has been cancelled
build-et-binaries / build-linux-arm64 (push) Has been cancelled
build-et-binaries / build-macos-universal (push) Has been cancelled
build-et-binaries / build-windows-x64 (push) Has been cancelled
build-et-binaries / release (push) Has been cancelled
141 lines
3.4 KiB
TypeScript
141 lines
3.4 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
|
|
import {
|
|
areCustomKeyBindingsEqual,
|
|
nextCustomKeyBindingsSyncVersion,
|
|
parseCustomKeyBindingsStorageRecord,
|
|
resetCustomKeyBinding,
|
|
serializeCustomKeyBindingsStorageRecord,
|
|
shouldApplyIncomingCustomKeyBindingsRecord,
|
|
updateCustomKeyBinding,
|
|
} from './customKeyBindings.ts';
|
|
|
|
test('parses legacy stored custom key bindings without sync metadata', () => {
|
|
const parsed = parseCustomKeyBindingsStorageRecord('{"open":{"mac":"Cmd+K"}}');
|
|
|
|
assert.deepEqual(parsed, {
|
|
version: 0,
|
|
origin: 'legacy',
|
|
bindings: {
|
|
open: { mac: 'Cmd+K' },
|
|
},
|
|
});
|
|
});
|
|
|
|
test('round-trips versioned stored custom key bindings', () => {
|
|
const raw = serializeCustomKeyBindingsStorageRecord({
|
|
version: 42,
|
|
origin: 'window-b',
|
|
bindings: {
|
|
open: { pc: 'Ctrl+K' },
|
|
},
|
|
});
|
|
|
|
assert.deepEqual(parseCustomKeyBindingsStorageRecord(raw), {
|
|
version: 42,
|
|
origin: 'window-b',
|
|
bindings: {
|
|
open: { pc: 'Ctrl+K' },
|
|
},
|
|
});
|
|
});
|
|
|
|
test('parses plain IPC custom key binding sync payloads', () => {
|
|
const parsed = parseCustomKeyBindingsStorageRecord({
|
|
version: 7,
|
|
origin: 'window-a',
|
|
bindings: {
|
|
open: { pc: 'Ctrl+K' },
|
|
},
|
|
});
|
|
|
|
assert.deepEqual(parsed, {
|
|
version: 7,
|
|
origin: 'window-a',
|
|
bindings: {
|
|
open: { pc: 'Ctrl+K' },
|
|
},
|
|
});
|
|
});
|
|
|
|
test('next sync version is monotonic even within the same millisecond', () => {
|
|
assert.equal(nextCustomKeyBindingsSyncVersion(100, 90), 101);
|
|
assert.equal(nextCustomKeyBindingsSyncVersion(100, 150), 150);
|
|
});
|
|
|
|
test('newer incoming records apply and older ones are ignored', () => {
|
|
assert.equal(
|
|
shouldApplyIncomingCustomKeyBindingsRecord(
|
|
{ version: 10, origin: 'window-a' },
|
|
{ version: 11, origin: 'window-b' },
|
|
),
|
|
true,
|
|
);
|
|
assert.equal(
|
|
shouldApplyIncomingCustomKeyBindingsRecord(
|
|
{ version: 10, origin: 'window-a' },
|
|
{ version: 10, origin: 'window-a' },
|
|
),
|
|
false,
|
|
);
|
|
assert.equal(
|
|
shouldApplyIncomingCustomKeyBindingsRecord(
|
|
{ version: 10, origin: 'window-b' },
|
|
{ version: 10, origin: 'window-a' },
|
|
),
|
|
false,
|
|
);
|
|
});
|
|
|
|
test('same-version updates converge by origin tie-breaker', () => {
|
|
assert.equal(
|
|
shouldApplyIncomingCustomKeyBindingsRecord(
|
|
{ version: 10, origin: 'window-a' },
|
|
{ version: 10, origin: 'window-b' },
|
|
),
|
|
true,
|
|
);
|
|
});
|
|
|
|
test('update custom key binding keeps other bindings intact', () => {
|
|
const prev = {
|
|
open: { mac: 'Cmd+K' },
|
|
close: { pc: 'Ctrl+W' },
|
|
};
|
|
|
|
const next = updateCustomKeyBinding(prev, 'open', 'pc', 'Ctrl+K');
|
|
|
|
assert.deepEqual(next, {
|
|
open: { mac: 'Cmd+K', pc: 'Ctrl+K' },
|
|
close: { pc: 'Ctrl+W' },
|
|
});
|
|
assert.equal(areCustomKeyBindingsEqual(prev, {
|
|
open: { mac: 'Cmd+K' },
|
|
close: { pc: 'Ctrl+W' },
|
|
}), true);
|
|
});
|
|
|
|
test('resetting one side of a shortcut does not mutate the previous bindings', () => {
|
|
const prev = {
|
|
open: { mac: 'Cmd+K', pc: 'Ctrl+K' },
|
|
};
|
|
|
|
const next = resetCustomKeyBinding(prev, 'open', 'mac');
|
|
|
|
assert.deepEqual(next, {
|
|
open: { pc: 'Ctrl+K' },
|
|
});
|
|
assert.deepEqual(prev, {
|
|
open: { mac: 'Cmd+K', pc: 'Ctrl+K' },
|
|
});
|
|
});
|
|
|
|
test('resetting the last side removes the binding entry entirely', () => {
|
|
const next = resetCustomKeyBinding({
|
|
open: { mac: 'Cmd+K' },
|
|
}, 'open', 'mac');
|
|
|
|
assert.deepEqual(next, {});
|
|
});
|