diff --git a/build/frontend-legacy/package-lock.json b/build/frontend-legacy/package-lock.json index f01221cda99d7..0b9329abcb7ef 100644 --- a/build/frontend-legacy/package-lock.json +++ b/build/frontend-legacy/package-lock.json @@ -29,7 +29,7 @@ "@nextcloud/router": "^3.2.0", "@nextcloud/sharing": "^1.0.0-beta.4", "@nextcloud/upload": "^1.12.0", - "@nextcloud/vue": "^8.41.0", + "@nextcloud/vue": "^8.42.0", "@simplewebauthn/browser": "^13.3.0", "@vue/web-component-wrapper": "^1.3.0", "@vueuse/components": "^11.3.0", @@ -5343,9 +5343,9 @@ } }, "node_modules/@nextcloud/vue": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-8.41.0.tgz", - "integrity": "sha512-537YLnGYkXwTzbjDo2OwRW16sP3et9jcrp0KZeGGmTBJMuI9wRR+WfTTuiHva/UnQ+kNMdfU0aq7lvGrme8OEw==", + "version": "8.42.0", + "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-8.42.0.tgz", + "integrity": "sha512-6sx4GIYWs7Y7vRICooK87l7tCLP+eG1cOWPXWs5Ui4VxIO41KrLmK+MxcabZegw/yA54nrpCClk8Wv3XmoLxdg==", "license": "AGPL-3.0-or-later", "dependencies": { "@floating-ui/dom": "^1.8.0", @@ -5358,7 +5358,7 @@ "@nextcloud/initial-state": "^2.2.0", "@nextcloud/l10n": "^3.4.1", "@nextcloud/logger": "^3.0.3", - "@nextcloud/router": "^3.1.0", + "@nextcloud/router": "^3.2.0", "@nextcloud/sharing": "^0.4.0", "@nextcloud/vue-select": "^3.26.0", "@vueuse/components": "^11.0.0", @@ -5366,7 +5366,7 @@ "blurhash": "^2.0.5", "clone": "^2.1.2", "debounce": "^2.2.0", - "dompurify": "^3.4.13", + "dompurify": "^3.4.17", "emoji-mart-vue-fast": "^15.0.5", "escape-html": "^1.0.3", "floating-vue": "^1.0.0-beta.19", diff --git a/build/frontend-legacy/package.json b/build/frontend-legacy/package.json index 9126e78841883..5d8b4fb69f93c 100644 --- a/build/frontend-legacy/package.json +++ b/build/frontend-legacy/package.json @@ -48,7 +48,7 @@ "@nextcloud/router": "^3.2.0", "@nextcloud/sharing": "^1.0.0-beta.4", "@nextcloud/upload": "^1.12.0", - "@nextcloud/vue": "^8.41.0", + "@nextcloud/vue": "^8.42.0", "@simplewebauthn/browser": "^13.3.0", "@vue/web-component-wrapper": "^1.3.0", "@vueuse/components": "^11.3.0", diff --git a/core/src/tests/components/AppMenu.spec.ts b/core/src/tests/components/AppMenu.spec.ts index 77b2e8174f0ce..da4fce1e3f1a5 100644 --- a/core/src/tests/components/AppMenu.spec.ts +++ b/core/src/tests/components/AppMenu.spec.ts @@ -6,7 +6,7 @@ import type { INavigationEntry } from '../../types/navigation.d.ts' import { mount } from '@vue/test-utils' -import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest' +import { afterEach, beforeEach, describe, expect, it, onTestFinished, vi } from 'vitest' // Hoisted so mocks exist before the SFC's imports run. const initialState = vi.hoisted(() => ({ @@ -234,9 +234,10 @@ describe('core: AppMenu', () => { }) it('returnFocusTarget points at the trigger that opened the popover', async () => { - // focus-trap doesn't activate in jsdom (needs layout), so we can't assert - // on document.activeElement. Instead we call returnFocusTarget() directly - // (the same method NcPopover calls on deactivation). + // jsdom has no layout, so focus-trap finds no tabbable node and falls + // back to the popover root; we can't assert on document.activeElement. + // Instead we call returnFocusTarget() directly (the same method + // NcPopover calls on deactivation). const wrapper = mount(AppMenu, { attachTo: document.body }) await wrapper.get('.app-menu__current-app').trigger('click') @@ -625,6 +626,12 @@ describe('core: AppMenu navigation actions', () => { }) it('focuses the first submenu entry on open and navigates it with arrow keys', async () => { + // jsdom has no layout, so tabbable (used by focus-trap) treats every node + // as hidden and the submenu trap falls back to the popover root. Report a + // box so the trap picks the first entry, as it does in a browser. + const rects = vi.spyOn(HTMLElement.prototype, 'getClientRects') + .mockReturnValue([{}] as unknown as DOMRectList) + onTestFinished(() => rects.mockRestore()) initialState.loadState.mockImplementation(stateWith(fakeApps(), fakeActions(6))) const wrapper = mount(AppMenu, { attachTo: document.body }) await openPopover(wrapper)