Files
goodbuddy/src/main/shortcut-settings-service.test.ts
T

217 lines
5.8 KiB
TypeScript

import { describe, expect, it, vi } from 'vitest'
import {
areShortcutAcceleratorsEquivalent,
type GlobalShortcutSettings
} from '../shared/shortcut'
import { ShortcutSettingsService } from './shortcut-settings-service'
function createFixture(
initial: GlobalShortcutSettings = {
enabled: true,
accelerator: 'CommandOrControl+Shift+Space'
},
platform = 'win32'
) {
let persisted = { ...initial }
const store = {
get: vi.fn(async () => ({ ...persisted })),
update: vi.fn(async (input: unknown) => {
persisted = input as GlobalShortcutSettings
return { ...persisted }
})
}
const registered = new Set<string>()
const conflicts = new Set<string>()
const registry = {
register: vi.fn((accelerator: string) => {
if (
conflicts.has(accelerator) ||
[...registered].some((current) =>
areShortcutAcceleratorsEquivalent(
current,
accelerator,
platform
)
)
) {
return false
}
registered.add(accelerator)
return true
}),
unregister: vi.fn((accelerator: string) => {
registered.delete(accelerator)
})
}
const service = new ShortcutSettingsService(
store,
registry,
vi.fn(),
platform
)
return {
service,
store,
registry,
registered,
conflicts,
getPersisted: () => persisted
}
}
describe('ShortcutSettingsService', () => {
it('registers the persisted shortcut at startup and reports display state', async () => {
const { service, registered } = createFixture()
await expect(service.initialize()).resolves.toMatchObject({
registered: true,
registeredAccelerator: 'CommandOrControl+Shift+Space',
displayAccelerator: 'Ctrl+Shift+Space',
status: 'registered'
})
expect(registered).toEqual(
new Set(['CommandOrControl+Shift+Space'])
)
})
it('keeps the old working registration and setting after a conflict', async () => {
const fixture = createFixture()
await fixture.service.initialize()
fixture.conflicts.add('Control+Alt+K')
await expect(
fixture.service.update({
enabled: true,
accelerator: 'Control+Alt+K'
})
).resolves.toMatchObject({
ok: false,
error: 'conflict',
snapshot: {
settings: {
enabled: true,
accelerator: 'CommandOrControl+Shift+Space'
},
registered: true,
status: 'registered'
}
})
expect(fixture.store.update).not.toHaveBeenCalled()
expect(fixture.registered).toEqual(
new Set(['CommandOrControl+Shift+Space'])
)
})
it.each(['disabled', 'conflict', 'failed'] as const)('reports an unavailable shortcut at startup when %s', async (status) => {
const fixture = createFixture({
enabled: status !== 'disabled',
accelerator: 'CommandOrControl+Shift+Space'
})
if (status === 'conflict') fixture.registry.register.mockReturnValueOnce(false)
if (status === 'failed') fixture.registry.register.mockImplementationOnce(() => { throw new Error('Registration failed') })
await expect(fixture.service.initialize()).resolves.toMatchObject({
registered: false,
displayAccelerator: 'Ctrl+Shift+Space',
status
})
expect(fixture.service.getSnapshot().registeredAccelerator).toBeUndefined()
if (status === 'disabled') expect(fixture.registry.register).not.toHaveBeenCalled()
})
it.each([
[
'win32',
'CommandOrControl+Shift+Space',
'Control+Shift+Space'
],
[
'linux',
'CmdOrCtrl+Shift+Space',
'Control+Shift+Space'
],
[
'darwin',
'CommandOrControl+Shift+Space',
'Command+Shift+Space'
]
])(
'updates physically equivalent aliases on %s without self-conflict',
async (platform, initialAccelerator, nextAccelerator) => {
const fixture = createFixture(
{
enabled: true,
accelerator: initialAccelerator
},
platform
)
await fixture.service.initialize()
fixture.registry.register.mockClear()
await expect(
fixture.service.update({
enabled: true,
accelerator: nextAccelerator
})
).resolves.toMatchObject({
ok: true,
snapshot: {
settings: { accelerator: nextAccelerator },
registeredAccelerator: initialAccelerator,
status: 'registered'
}
})
expect(fixture.registry.register).not.toHaveBeenCalled()
expect(fixture.getPersisted().accelerator).toBe(nextAccelerator)
expect(fixture.registered).toEqual(
new Set([initialAccelerator])
)
}
)
it('rolls back a newly registered shortcut when persistence fails', async () => {
const fixture = createFixture()
await fixture.service.initialize()
fixture.store.update.mockRejectedValueOnce(new Error('disk full'))
await expect(
fixture.service.update({
enabled: true,
accelerator: 'Control+Alt+K'
})
).resolves.toMatchObject({
ok: false,
error: 'save-failed',
snapshot: {
settings: {
accelerator: 'CommandOrControl+Shift+Space'
},
registeredAccelerator: 'CommandOrControl+Shift+Space'
}
})
expect(fixture.registered).toEqual(
new Set(['CommandOrControl+Shift+Space'])
)
})
it('persists disabling before removing the working registration', async () => {
const fixture = createFixture()
await fixture.service.initialize()
await expect(
fixture.service.update({
enabled: false,
accelerator: 'CommandOrControl+Shift+Space'
})
).resolves.toMatchObject({
ok: true,
snapshot: {
registered: false,
status: 'disabled'
}
})
expect(fixture.getPersisted().enabled).toBe(false)
expect(fixture.registered).toEqual(new Set())
})
})