Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/theming/src/components/UserSectionBackground.vue
Original file line number Diff line number Diff line change
Expand Up @@ -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/'))
.setMimeTypeFilter(['image/*'])
.setMultiSelect(false)
.addButton({
label: t('theming', 'Select background'),
Expand Down
27 changes: 27 additions & 0 deletions tests/playwright/e2e/theming/user-settings-background.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

import { expect } from '@playwright/test'
import { test } from '../../support/fixtures/random-user-session.ts'
import { BackgroundFilePickerDialogPage } from '../../support/sections/BackgroundFilePickerDialogPage.ts'
import { mkdir, uploadContent } from '../../support/utils/dav.ts'
import { getBodyThemingSnapshot, pickColor } from '../../support/utils/theming.ts'

test('User can configure background and plain color', async ({ page }) => {
Expand Down Expand Up @@ -32,3 +34,28 @@ test('User can configure background and plain color', async ({ page }) => {
await page.reload()
await expect.poll(async () => (await getBodyThemingSnapshot(page)).backgroundImage).toBe('none')
})

test('User can pick a custom background from their files', {
annotation: { type: 'issue', description: 'https://github.com/nextcloud/server/issues/58645' },
}, async ({ page, user }) => {
await mkdir(page.request, user, '/folder')

// this is a minimal image (1x1 red pixel), encoded as base64
const imageBase64 = 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR4AWL6z8DwHwAAAP//A3ONEwAAAAZJREFUAwAFCgIByRpMngAAAABJRU5ErkJggg=='
// Buffer.alloc(0) did not work when selecting image as background, using base64 image instead
await uploadContent(page.request, user, Buffer.from(imageBase64, 'base64'), 'image/jpeg', '/folder/image.jpg')

await page.goto('settings/user/theming')
await page.getByRole('heading', { name: 'Background and color' }).waitFor({ state: 'visible' })

await page.getByRole('button', { name: 'Custom background' }).click()

const filePicker = new BackgroundFilePickerDialogPage(page)
await filePicker.openFolder('folder')
await filePicker.selectFile('image.jpg')
await filePicker.confirm()

await expect(page.getByRole('button', { name: 'Custom background', pressed: true })).toBeVisible()
// backgroundImage is like this: "url(\"<nc-instance>/apps/theming/background?v=<hash>\")"
await expect.poll(async () => (await getBodyThemingSnapshot(page)).backgroundImage).toContain('/apps/theming/background?')
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

import type { Locator, Page } from '@playwright/test'

/**
* The file-picker dialog opened by the "Custom background" card/button on
* Personal settings > Appearance and accessibility > Background and color
*/
export class BackgroundFilePickerDialogPage {
constructor(private readonly page: Page) {}

/** The open file-picker dialog. */
dialog(): Locator {
return this.page.getByRole('dialog')
}

/**
* Returns a row (file or folder) from inside the picker.
*/
getRow(name: string): Locator {
return this.dialog().getByTestId('row-name').filter({ hasText: name })
}

/** Navigate into a folder. */
async openFolder(name: string): Promise<void> {
await this.getRow(name).click()
}

/** Select a file row. */
async selectFile(name: string): Promise<void> {
await this.getRow(name).click()
}

/** Confirm the current selection as the new background. */
async confirm(): Promise<void> {
await this.dialog().getByRole('button', { name: 'Select background', exact: true }).click()
}
}
Loading