From afa17991cac4ad9550321296a8a37677b64f4e23 Mon Sep 17 00:00:00 2001 From: Peter Ringelmann Date: Mon, 22 Jun 2026 16:25:17 +0200 Subject: [PATCH 1/2] fix(settings): correct heading order in account management sidebar Signed-off-by: Peter Ringelmann --- .../components/AppNavigationGroupList.spec.ts | 57 +++++++++++++++++++ .../src/components/AppNavigationGroupList.vue | 28 +++++++++ 2 files changed, 85 insertions(+) create mode 100644 apps/settings/src/components/AppNavigationGroupList.spec.ts diff --git a/apps/settings/src/components/AppNavigationGroupList.spec.ts b/apps/settings/src/components/AppNavigationGroupList.spec.ts new file mode 100644 index 0000000000000..01b53caf27bb3 --- /dev/null +++ b/apps/settings/src/components/AppNavigationGroupList.spec.ts @@ -0,0 +1,57 @@ +/** + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { mount } from '@vue/test-utils' +import { ref } from 'vue' +import { describe, expect, it, vi } from 'vitest' +import NcAppNavigationCaption from '@nextcloud/vue/components/NcAppNavigationCaption' + +// The component builds a real Vuex store via useStore(); mock it so this stays +// a focused component test that controls its own data. +vi.mock('../store/index.js', () => ({ + useStore: () => ({ + getters: { + getServerData: { isAdmin: false, isDelegatedAdmin: false }, + getSortedGroups: [], + getSubAdminGroups: [], + getSearchQuery: '', + }, + commit: vi.fn(), + dispatch: vi.fn(), + }), +})) + +vi.mock('vue-router/composables', async (importActual) => ({ + ...(await importActual()), + useRoute: () => ({ params: {} }), + useRouter: () => ({ push: vi.fn() }), +})) + +vi.mock('../service/groups.ts', () => ({ + searchGroups: () => Promise.resolve([]), +})) + +vi.mock('@vueuse/core', async (importActual) => ({ + ...(await importActual()), + useElementVisibility: () => ref(false), +})) + +import AppNavigationGroupList from './AppNavigationGroupList.vue' + +describe('AppNavigationGroupList', () => { + it('does not expose the group list as a heading (BITV 9.1.3.1a)', () => { + const wrapper = mount(AppNavigationGroupList) + + // The sidebar group list is navigation, not document structure. It must + // not emit a heading, which would sit before the page

in the DOM + // and produce an out-of-order outline (h2 before h1). + const caption = wrapper.findComponent(NcAppNavigationCaption) + expect(caption.exists()).toBe(true) + expect(caption.find('h1,h2,h3,h4,h5,h6').exists()).toBe(false) + + // The "Groups" label is still rendered, just not as a heading. + expect(caption.text()).toContain('Groups') + }) +}) diff --git a/apps/settings/src/components/AppNavigationGroupList.vue b/apps/settings/src/components/AppNavigationGroupList.vue index 86abd6e8ba08b..85ba84fa7fc98 100644 --- a/apps/settings/src/components/AppNavigationGroupList.vue +++ b/apps/settings/src/components/AppNavigationGroupList.vue @@ -46,6 +46,34 @@ class="account-management__group-list" aria-describedby="group-list-desc" data-cy-users-settings-navigation-groups="custom"> + + + + Date: Tue, 23 Jun 2026 13:42:43 +0200 Subject: [PATCH 2/2] test(settings): exclude the group caption from group-row selectors Signed-off-by: Peter Ringelmann --- .../components/AppNavigationGroupList.spec.ts | 5 ++- .../src/components/AppNavigationGroupList.vue | 31 +------------------ cypress/e2e/settings/users_groups.cy.ts | 18 ++++++----- dist/settings-users-3239.js | 4 +-- dist/settings-users-3239.js.map | 2 +- ...ings-vue-settings-apps-users-management.js | 4 +-- ...-vue-settings-apps-users-management.js.map | 2 +- 7 files changed, 19 insertions(+), 47 deletions(-) diff --git a/apps/settings/src/components/AppNavigationGroupList.spec.ts b/apps/settings/src/components/AppNavigationGroupList.spec.ts index 01b53caf27bb3..1b4bd989d6841 100644 --- a/apps/settings/src/components/AppNavigationGroupList.spec.ts +++ b/apps/settings/src/components/AppNavigationGroupList.spec.ts @@ -4,9 +4,10 @@ */ import { mount } from '@vue/test-utils' -import { ref } from 'vue' import { describe, expect, it, vi } from 'vitest' +import { ref } from 'vue' import NcAppNavigationCaption from '@nextcloud/vue/components/NcAppNavigationCaption' +import AppNavigationGroupList from './AppNavigationGroupList.vue' // The component builds a real Vuex store via useStore(); mock it so this stays // a focused component test that controls its own data. @@ -38,8 +39,6 @@ vi.mock('@vueuse/core', async (importActual) => ({ useElementVisibility: () => ref(false), })) -import AppNavigationGroupList from './AppNavigationGroupList.vue' - describe('AppNavigationGroupList', () => { it('does not expose the group list as a heading (BITV 9.1.3.1a)', () => { const wrapper = mount(AppNavigationGroupList) diff --git a/apps/settings/src/components/AppNavigationGroupList.vue b/apps/settings/src/components/AppNavigationGroupList.vue index 85ba84fa7fc98..450596b39c30b 100644 --- a/apps/settings/src/components/AppNavigationGroupList.vue +++ b/apps/settings/src/components/AppNavigationGroupList.vue @@ -5,36 +5,6 @@