diff --git a/apps/theming/src/components/UserSectionBackground.vue b/apps/theming/src/components/UserSectionBackground.vue index b06ea89ac9048..055849d4ecad3 100644 --- a/apps/theming/src/components/UserSectionBackground.vue +++ b/apps/theming/src/components/UserSectionBackground.vue @@ -147,7 +147,7 @@ async function pickColor(color?: string) { async function pickFile() { await getFilePickerBuilder(t('theming', 'Select a background from your files')) .allowDirectories(false) - .setFilter((node) => node.mime.startsWith('image/')) + .setFilter((node) => node.type === 'folder' || node.mime?.startsWith('image/')) .setMultiSelect(false) .addButton({ label: t('theming', 'Select background'), diff --git a/apps/theming/src/components/__tests__/UserSectionBackground.spec.ts b/apps/theming/src/components/__tests__/UserSectionBackground.spec.ts new file mode 100644 index 0000000000000..1a3ccffc72f31 --- /dev/null +++ b/apps/theming/src/components/__tests__/UserSectionBackground.spec.ts @@ -0,0 +1,87 @@ +/*! + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { shallowMount } from '@vue/test-utils' +import { describe, expect, it, vi } from 'vitest' +import UserSectionBackground from '../UserSectionBackground.vue' + +type PickerFilter = (node: { type?: string, mime?: string }) => boolean | undefined + +const setFilter = vi.hoisted(() => vi.fn<(filter: PickerFilter) => unknown>()) + +vi.mock('@nextcloud/dialogs', () => ({ + getFilePickerBuilder: vi.fn(() => { + const builder = { + allowDirectories: vi.fn(), + setFilter, + setMultiSelect: vi.fn(), + addButton: vi.fn(), + build: vi.fn(), + } + + builder.allowDirectories.mockReturnValue(builder) + builder.setFilter.mockReturnValue(builder) + builder.setMultiSelect.mockReturnValue(builder) + builder.addButton.mockReturnValue(builder) + builder.build.mockReturnValue({ + pick: vi.fn().mockResolvedValue(undefined), + }) + + return builder + }), +})) + +vi.mock('@nextcloud/initial-state', () => ({ + loadState: vi.fn((_app: string, key: string) => { + switch (key) { + case 'shippedBackgrounds': + return {} + case 'themingDefaults': + return { + backgroundImage: '', + backgroundColor: '#ffffff', + backgroundMime: '', + defaultShippedBackground: '', + } + case 'data': + return { + backgroundImage: '', + backgroundColor: '#ffffff', + backgroundMime: '', + } + case 'userBackgroundImage': + return 'default' + default: + throw new Error(`Unexpected initial state key: ${key}`) + } + }), +})) + +vi.mock('@nextcloud/l10n', () => ({ + t: (_app: string, text: string) => text, +})) + +describe('UserSectionBackground', () => { + it('keeps folders and images while filtering other files', async () => { + const wrapper = shallowMount(UserSectionBackground, { + global: { + stubs: { + NcSettingsSection: { + template: '
', + }, + }, + }, + }) + + await wrapper.get('button[aria-label="Custom background"]').trigger('click') + + expect(setFilter).toHaveBeenCalledOnce() + const filter = setFilter.mock.calls[0]![0] + expect(filter({ type: 'folder' })).toBe(true) + expect(filter({ mime: 'image/png' })).toBe(true) + expect(filter({ mime: 'text/plain' })).toBe(false) + expect(filter({})).toBeFalsy() + }) +})