refactor: use singleton mock pattern for useDialogStore in escape test (#8538)

## Summary

Refactors `keybindingService.escape.test.ts` to use the singleton mock
pattern with reactive state, following project testing guidance.

## Changes

- **What**: Replaced `vi.fn(() => ({dialogStack: []}))` anti-pattern
with `reactive()` array defined inline in `vi.mock()` factory. Tests now
use array mutation (`.push()`, `.length = 0`) instead of
`mockReturnValue` calls.

## Review Focus

Pattern aligns with docs/testing/unit-testing.md section "Mocking
Composables with Reactive State".

Fixes #8467

┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-8538-refactor-use-singleton-mock-pattern-for-useDialogStore-in-escape-test-2fb6d73d3650812a95c6e223e38d50ad)
by [Unito](https://www.unito.io)
This commit is contained in:
Christian Byrne
2026-02-01 22:09:10 -08:00
committed by GitHub
parent eaa3ff1579
commit e1385b0d18

View File

@@ -1,4 +1,5 @@
import { createPinia, setActivePinia } from 'pinia'
import { markRaw, reactive } from 'vue'
import { beforeEach, describe, expect, it, vi } from 'vitest'
import { CORE_KEYBINDINGS } from '@/platform/keybindings/defaults'
@@ -10,17 +11,33 @@ import { useCommandStore } from '@/stores/commandStore'
import type { DialogInstance } from '@/stores/dialogStore'
import { useDialogStore } from '@/stores/dialogStore'
function createTestDialogInstance(
key: string,
overrides: Partial<DialogInstance> = {}
): DialogInstance {
return {
key,
visible: true,
component: markRaw({ template: '<div />' }),
contentProps: {},
dialogComponentProps: {},
priority: 0,
...overrides
}
}
vi.mock('@/platform/settings/settingStore', () => ({
useSettingStore: vi.fn(() => ({
get: vi.fn(() => [])
}))
}))
vi.mock('@/stores/dialogStore', () => ({
useDialogStore: vi.fn(() => ({
dialogStack: []
}))
}))
vi.mock('@/stores/dialogStore', () => {
const dialogStack = reactive<DialogInstance[]>([])
return {
useDialogStore: () => ({ dialogStack })
}
})
vi.mock('@/scripts/app', () => ({
app: {
@@ -40,11 +57,8 @@ describe('keybindingService - Escape key handling', () => {
mockCommandExecute = vi.fn()
commandStore.execute = mockCommandExecute
vi.mocked(useDialogStore).mockReturnValue({
dialogStack: [] as DialogInstance[]
} as Partial<ReturnType<typeof useDialogStore>> as ReturnType<
typeof useDialogStore
>)
const dialogStore = useDialogStore()
dialogStore.dialogStack.length = 0
keybindingService = useKeybindingService()
keybindingService.registerCoreKeybindings()
@@ -76,12 +90,6 @@ describe('keybindingService - Escape key handling', () => {
}
it('should execute Escape keybinding when no dialogs are open', async () => {
vi.mocked(useDialogStore).mockReturnValue({
dialogStack: [] as DialogInstance[]
} as Partial<ReturnType<typeof useDialogStore>> as ReturnType<
typeof useDialogStore
>)
const event = createKeyboardEvent('Escape')
await keybindingService.keybindHandler(event)
@@ -89,11 +97,8 @@ describe('keybindingService - Escape key handling', () => {
})
it('should NOT execute Escape keybinding when dialogs are open', async () => {
vi.mocked(useDialogStore).mockReturnValue({
dialogStack: [{ key: 'test-dialog' } as DialogInstance]
} as Partial<ReturnType<typeof useDialogStore>> as ReturnType<
typeof useDialogStore
>)
const dialogStore = useDialogStore()
dialogStore.dialogStack.push(createTestDialogInstance('test-dialog'))
keybindingService = useKeybindingService()
@@ -104,11 +109,8 @@ describe('keybindingService - Escape key handling', () => {
})
it('should execute Escape keybinding with modifiers regardless of dialog state', async () => {
vi.mocked(useDialogStore).mockReturnValue({
dialogStack: [{ key: 'test-dialog' } as DialogInstance]
} as Partial<ReturnType<typeof useDialogStore>> as ReturnType<
typeof useDialogStore
>)
const dialogStore = useDialogStore()
dialogStore.dialogStack.push(createTestDialogInstance('test-dialog'))
const keybindingStore = useKeybindingStore()
keybindingStore.addDefaultKeybinding(