Files
orca/src/main/keybindings/keybinding-file.test.ts
T
Neil 6408e49dbd Add customizable keyboard shortcuts (#2581)
* Add customizable keyboard shortcuts

- Add customizable keybindings
- Fix keybinding customization bypasses

* Keep shortcut UI labels dynamic

* Fix keybinding review gaps

* Improve shortcut recording UX

* Include settings section metadata in search

* Polish shortcut settings editor

* Tighten shortcut settings rows

* Clarify keybindings file card

* Clear settings search on section select

* Remove keybindings file helper copy
2026-05-21 19:10:16 -07:00

228 lines
6.3 KiB
TypeScript

import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'fs'
import { tmpdir } from 'os'
import { join } from 'path'
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
import {
getUserKeybindingsPath,
migrateLegacyKeybindings,
readKeybindingFile,
writeKeybindingOverride
} from './keybinding-file'
describe('keybinding-file', () => {
let dir: string
let filePath: string
beforeEach(() => {
dir = mkdtempSync(join(tmpdir(), 'orca-keybindings-'))
filePath = join(dir, 'keybindings.json')
})
afterEach(() => {
rmSync(dir, { recursive: true, force: true })
})
it('resolves the user-facing keybindings path under ~/.orca', () => {
expect(getUserKeybindingsPath('/home/test')).toBe(
join('/home/test', '.orca', 'keybindings.json')
)
})
it('returns an empty snapshot when the file does not exist', () => {
expect(readKeybindingFile(filePath, 'linux')).toMatchObject({
exists: false,
platform: 'linux',
overrides: {},
diagnostics: []
})
})
it('parses common and platform-specific overrides', () => {
writeFileSync(
filePath,
JSON.stringify({
version: 1,
keybindings: {
'worktree.quickOpen': 'Mod+Shift+P',
'view.tasks': null
},
platforms: {
linux: {
'terminal.paste': ['Ctrl+Shift+V', 'Shift+Insert'],
'terminal.search': 'Ctrl+Shift+F'
},
darwin: {
'terminal.search': 'Mod+F'
}
}
}),
'utf8'
)
expect(readKeybindingFile(filePath, 'linux')).toMatchObject({
exists: true,
overrides: {
'worktree.quickOpen': ['Mod+Shift+P'],
'view.tasks': [],
'terminal.paste': ['Ctrl+Shift+V', 'Shift+Insert'],
'terminal.search': ['Ctrl+Shift+F']
},
diagnostics: []
})
})
it('accepts bare keys for actions that explicitly opt in', () => {
writeFileSync(
filePath,
JSON.stringify({
keybindings: {
'fileExplorer.delete': 'Delete'
}
}),
'utf8'
)
expect(readKeybindingFile(filePath, 'linux')).toMatchObject({
overrides: {
'fileExplorer.delete': ['Delete']
},
diagnostics: []
})
})
it('ignores invalid, unknown, and conflicting manual edits', () => {
writeFileSync(
filePath,
JSON.stringify({
keybindings: {
unknownAction: 'Ctrl+Alt+U',
'terminal.search': 'not-a-keybinding',
'view.tasks': 'Mod+P'
}
}),
'utf8'
)
const snapshot = readKeybindingFile(filePath, 'linux')
expect(snapshot.overrides).toEqual({})
expect(snapshot.diagnostics.map((diagnostic) => diagnostic.severity)).toEqual([
'warning',
'error',
'error'
])
})
it('writes active-platform overrides while preserving other platforms', () => {
writeFileSync(
filePath,
JSON.stringify({
version: 1,
keybindings: {
'worktree.quickOpen': 'Mod+Shift+P'
},
platforms: {
darwin: {
'terminal.search': 'Mod+F'
}
}
}),
'utf8'
)
writeKeybindingOverride(filePath, 'linux', 'terminal.search', ['Ctrl+Shift+F'])
const written = JSON.parse(readFileSync(filePath, 'utf8')) as {
keybindings: Record<string, unknown>
platforms: Record<string, Record<string, unknown>>
}
expect(written.keybindings['worktree.quickOpen']).toBe('Mod+Shift+P')
expect(written.platforms.darwin['terminal.search']).toBe('Mod+F')
expect(written.platforms.linux['terminal.search']).toEqual(['Ctrl+Shift+F'])
})
it('migrates root-level legacy overrides before writing settings edits', () => {
writeFileSync(
filePath,
JSON.stringify({
version: 1,
'worktree.quickOpen': 'Mod+Shift+P',
platforms: {
darwin: {
'terminal.search': 'Mod+F'
}
}
}),
'utf8'
)
writeKeybindingOverride(filePath, 'linux', 'terminal.search', ['Ctrl+Shift+F'])
const written = JSON.parse(readFileSync(filePath, 'utf8')) as {
keybindings: Record<string, unknown>
platforms: Record<string, Record<string, unknown>>
'worktree.quickOpen'?: unknown
}
expect(written['worktree.quickOpen']).toBeUndefined()
expect(written.keybindings['worktree.quickOpen']).toEqual(['Mod+Shift+P'])
expect(written.platforms.darwin['terminal.search']).toBe('Mod+F')
expect(readKeybindingFile(filePath, 'linux').overrides).toEqual({
'worktree.quickOpen': ['Mod+Shift+P'],
'terminal.search': ['Ctrl+Shift+F']
})
})
it('rejects writes that would conflict with another effective shortcut', () => {
expect(() => writeKeybindingOverride(filePath, 'linux', 'view.tasks', ['Mod+P'])).toThrow(
'conflicts with another shortcut'
)
expect(readKeybindingFile(filePath, 'linux').overrides).toEqual({})
})
it('validates write inputs at the file boundary', () => {
expect(() => writeKeybindingOverride(filePath, 'linux', 'unknown.action', [])).toThrow(
'Unknown keybinding action'
)
expect(() => writeKeybindingOverride(filePath, 'linux', 'view.tasks', 'Ctrl+Alt+T')).toThrow(
'Use a string array or null.'
)
})
it('resets only the active platform override', () => {
writeFileSync(
filePath,
JSON.stringify({
keybindings: {
'terminal.search': 'Ctrl+Alt+F'
},
platforms: {
linux: {
'terminal.search': 'Ctrl+Shift+F'
}
}
}),
'utf8'
)
writeKeybindingOverride(filePath, 'linux', 'terminal.search', null)
const snapshot = readKeybindingFile(filePath, 'linux')
expect(snapshot.commonOverrides).toEqual({
'terminal.search': ['Ctrl+Alt+F']
})
expect(snapshot.platformOverrides.linux).toEqual({})
expect(snapshot.overrides).toEqual({
'terminal.search': ['Ctrl+Alt+F']
})
})
it('migrates legacy settings once when no file exists', () => {
migrateLegacyKeybindings(filePath, 'linux', { 'view.tasks': ['Ctrl+Alt+T'] })
migrateLegacyKeybindings(filePath, 'linux', { 'view.tasks': ['Ctrl+Alt+X'] })
expect(readKeybindingFile(filePath, 'linux').overrides).toEqual({
'view.tasks': ['Ctrl+Alt+T']
})
})
})