diff --git a/apps/files/src/services/HotKeysService.spec.ts b/apps/files/src/services/HotKeysService.spec.ts index 3bfdac0bc32..81881d24dbf 100644 --- a/apps/files/src/services/HotKeysService.spec.ts +++ b/apps/files/src/services/HotKeysService.spec.ts @@ -61,7 +61,7 @@ describe('HotKeysService testing', () => { activeStore.setActiveNode(file) window.OCA = { Files: { Sidebar: { open: () => {}, setActiveTab: () => {} } } } - // @ts-expect-error We only mock what needed, we do not need Files.Router.goTo or Files.Navigation + // We only mock what needed, we do not need Files.Router.goTo or Files.Navigation window.OCP = { Files: { Router: { goToRoute: goToRouteMock, params: {}, query: {} } } } initialState = document.createElement('input') @@ -74,26 +74,26 @@ describe('HotKeysService testing', () => { }) it('Pressing d should open the sidebar once', () => { - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'd', code: 'KeyD' })) + dispatchEvent({ key: 'd', code: 'KeyD' }) // Modifier keys should not trigger the action - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'd', code: 'KeyD', ctrlKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'd', code: 'KeyD', altKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'd', code: 'KeyD', shiftKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'd', code: 'KeyD', metaKey: true })) + dispatchEvent({ key: 'd', code: 'KeyD', ctrlKey: true }) + dispatchEvent({ key: 'd', code: 'KeyD', altKey: true }) + dispatchEvent({ key: 'd', code: 'KeyD', shiftKey: true }) + dispatchEvent({ key: 'd', code: 'KeyD', metaKey: true }) expect(sidebarAction.enabled).toHaveReturnedWith(true) expect(sidebarAction.exec).toHaveBeenCalledOnce() }) it('Pressing F2 should rename the file', () => { - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'F2', code: 'F2' })) + dispatchEvent({ key: 'F2', code: 'F2' }) // Modifier keys should not trigger the action - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'F2', code: 'F2', ctrlKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'F2', code: 'F2', altKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'F2', code: 'F2', shiftKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'F2', code: 'F2', metaKey: true })) + dispatchEvent({ key: 'F2', code: 'F2', ctrlKey: true }) + dispatchEvent({ key: 'F2', code: 'F2', altKey: true }) + dispatchEvent({ key: 'F2', code: 'F2', shiftKey: true }) + dispatchEvent({ key: 'F2', code: 'F2', metaKey: true }) expect(renameAction.enabled).toHaveReturnedWith(true) expect(renameAction.exec).toHaveBeenCalledOnce() @@ -101,28 +101,29 @@ describe('HotKeysService testing', () => { it('Pressing s should toggle favorite', () => { vi.spyOn(axios, 'post').mockImplementationOnce(() => Promise.resolve()) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 's', code: 'KeyS' })) + dispatchEvent({ key: 's', code: 'KeyS' }) // Modifier keys should not trigger the action - window.dispatchEvent(new KeyboardEvent('keydown', { key: 's', code: 'KeyS', ctrlKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 's', code: 'KeyS', altKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 's', code: 'KeyS', shiftKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 's', code: 'KeyS', metaKey: true })) + dispatchEvent({ key: 's', code: 'KeyS', ctrlKey: true }) + dispatchEvent({ key: 's', code: 'KeyS', altKey: true }) + dispatchEvent({ key: 's', code: 'KeyS', shiftKey: true }) + dispatchEvent({ key: 's', code: 'KeyS', metaKey: true }) expect(favoriteAction.enabled).toHaveReturnedWith(true) expect(favoriteAction.exec).toHaveBeenCalledOnce() }) it('Pressing Delete should delete the file', async () => { + // @ts-expect-error unit testing vi.spyOn(deleteAction._action, 'exec').mockResolvedValue(() => true) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Delete', code: 'Delete' })) + dispatchEvent({ key: 'Delete', code: 'Delete' }) // Modifier keys should not trigger the action - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Delete', code: 'Delete', ctrlKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Delete', code: 'Delete', altKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Delete', code: 'Delete', shiftKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Delete', code: 'Delete', metaKey: true })) + dispatchEvent({ key: 'Delete', code: 'Delete', ctrlKey: true }) + dispatchEvent({ key: 'Delete', code: 'Delete', altKey: true }) + dispatchEvent({ key: 'Delete', code: 'Delete', shiftKey: true }) + dispatchEvent({ key: 'Delete', code: 'Delete', metaKey: true }) expect(deleteAction.enabled).toHaveReturnedWith(true) expect(deleteAction.exec).toHaveBeenCalledOnce() @@ -132,7 +133,7 @@ describe('HotKeysService testing', () => { expect(goToRouteMock).toHaveBeenCalledTimes(0) window.OCP.Files.Router.query = { dir: '/foo/bar' } - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'ArrowUp', code: 'ArrowUp', altKey: true })) + dispatchEvent({ key: 'ArrowUp', code: 'ArrowUp', altKey: true }) expect(goToRouteMock).toHaveBeenCalledOnce() expect(goToRouteMock.mock.calls[0][2].dir).toBe('/foo') @@ -151,25 +152,34 @@ describe('HotKeysService testing', () => { setTimeout(resolve, 500) }) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'v', code: 'KeyV' })) + dispatchEvent({ key: 'v', code: 'KeyV' }) await waitForUserConfig() expect(userConfigStore.userConfig.grid_view).toBe(!currentGridConfig) // Modifier keys should not trigger the action - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Delete', code: 'Delete', ctrlKey: true })) + dispatchEvent({ key: 'Delete', code: 'Delete', ctrlKey: true }) await waitForUserConfig() expect(userConfigStore.userConfig.grid_view).toBe(!currentGridConfig) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Delete', code: 'Delete', altKey: true })) + dispatchEvent({ key: 'Delete', code: 'Delete', altKey: true }) await waitForUserConfig() expect(userConfigStore.userConfig.grid_view).toBe(!currentGridConfig) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Delete', code: 'Delete', shiftKey: true })) + dispatchEvent({ key: 'Delete', code: 'Delete', shiftKey: true }) await waitForUserConfig() expect(userConfigStore.userConfig.grid_view).toBe(!currentGridConfig) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 'Delete', code: 'Delete', metaKey: true })) + dispatchEvent({ key: 'Delete', code: 'Delete', metaKey: true }) await waitForUserConfig() expect(userConfigStore.userConfig.grid_view).toBe(!currentGridConfig) }) }) + +/** + * Helper to dispatch the correct event. + * + * @param init - KeyboardEvent options + */ +function dispatchEvent(init: KeyboardEventInit) { + document.body.dispatchEvent(new KeyboardEvent('keydown', { ...init, bubbles: true })) +} diff --git a/apps/systemtags/src/services/HotKeysService.spec.ts b/apps/systemtags/src/services/HotKeysService.spec.ts index 2e329444f54..92d9f56f56d 100644 --- a/apps/systemtags/src/services/HotKeysService.spec.ts +++ b/apps/systemtags/src/services/HotKeysService.spec.ts @@ -42,15 +42,24 @@ describe('HotKeysService testing', () => { }) it('Pressing t should open the tag management dialog', () => { - window.dispatchEvent(new KeyboardEvent('keydown', { key: 't', code: 'KeyT' })) + dispatchEvent({ key: 't', code: 'KeyT' }) // Modifier keys should not trigger the action - window.dispatchEvent(new KeyboardEvent('keydown', { key: 't', code: 'KeyT', ctrlKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 't', code: 'KeyT', altKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 't', code: 'KeyT', shiftKey: true })) - window.dispatchEvent(new KeyboardEvent('keydown', { key: 't', code: 'KeyT', metaKey: true })) + dispatchEvent({ key: 't', code: 'KeyT', ctrlKey: true }) + dispatchEvent({ key: 't', code: 'KeyT', altKey: true }) + dispatchEvent({ key: 't', code: 'KeyT', shiftKey: true }) + dispatchEvent({ key: 't', code: 'KeyT', metaKey: true }) expect(bulkSystemTagsAction.enabled).toHaveReturnedWith(true) expect(bulkSystemTagsAction.exec).toHaveBeenCalledOnce() }) }) + +/** + * Helper to dispatch the correct event. + * + * @param init - KeyboardEvent options + */ +function dispatchEvent(init: KeyboardEventInit) { + document.body.dispatchEvent(new KeyboardEvent('keydown', { ...init, bubbles: true })) +} diff --git a/apps/systemtags/src/services/HotKeysService.ts b/apps/systemtags/src/services/HotKeysService.ts index 3661531fcb5..3d447397941 100644 --- a/apps/systemtags/src/services/HotKeysService.ts +++ b/apps/systemtags/src/services/HotKeysService.ts @@ -2,7 +2,7 @@ * SPDX-FileCopyrightText: 2023 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ -import { useHotKey } from '@nextcloud/vue/dist/Composables/useHotKey.js' +import { useHotKey } from '@nextcloud/vue/composables/useHotKey' import { action as manageTagAction } from '../files_actions/bulkSystemTagsAction.ts' import { executeAction } from '../../../files/src/utils/actionUtils.ts'