diff --git a/build/frontend-legacy/package-lock.json b/build/frontend-legacy/package-lock.json index 9440b4b3b5e9d..71dc5d904f838 100644 --- a/build/frontend-legacy/package-lock.json +++ b/build/frontend-legacy/package-lock.json @@ -43,7 +43,7 @@ "core-js": "^3.50.0", "crypto-browserify": "^3.12.1", "debounce": "^3.0.0", - "dompurify": "^3.4.13", + "dompurify": "^3.4.14", "escape-html": "^1.0.3", "focus-trap": "^8.2.2", "is-svg": "^6.1.0", @@ -7958,9 +7958,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -9463,9 +9463,9 @@ } }, "node_modules/dompurify": { - "version": "3.4.13", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.13.tgz", - "integrity": "sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.14.tgz", + "integrity": "sha512-dVoH9z+MY+C9IilgGCk3YfFqjLi3fChm2OiKJMzh6axrJ5qwxqWaZamgmHrpv22CN/KdbZJuGEGgfQoL00LTdg==", "license": "(MPL-2.0 OR Apache-2.0)", "optionalDependencies": { "@types/trusted-types": "^2.0.7" @@ -11390,9 +11390,9 @@ "peer": true }, "node_modules/immutable": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.5.tgz", - "integrity": "sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A==", + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.9.tgz", + "integrity": "sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==", "devOptional": true, "license": "MIT" }, @@ -15162,9 +15162,9 @@ } }, "node_modules/postcss": { - "version": "8.5.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz", - "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==", + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", "funding": [ { "type": "opencollective", @@ -15181,7 +15181,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.12", + "nanoid": "^3.3.17", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -20268,16 +20268,16 @@ } }, "node_modules/workbox-build/node_modules/brace-expansion": { - "version": "5.0.6", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", - "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" }, "engines": { - "node": "18 || 20 || >=22" + "node": "20 || >=22" } }, "node_modules/workbox-build/node_modules/glob": { diff --git a/build/frontend-legacy/package.json b/build/frontend-legacy/package.json index 64ebb83613ec3..3f5e6ba1e8ba1 100644 --- a/build/frontend-legacy/package.json +++ b/build/frontend-legacy/package.json @@ -62,7 +62,7 @@ "core-js": "^3.50.0", "crypto-browserify": "^3.12.1", "debounce": "^3.0.0", - "dompurify": "^3.4.13", + "dompurify": "^3.4.14", "escape-html": "^1.0.3", "focus-trap": "^8.2.2", "is-svg": "^6.1.0", diff --git a/core/css/fixes.scss b/core/css/fixes.scss index ceb4e47455e76..f7e195ad6dc07 100644 --- a/core/css/fixes.scss +++ b/core/css/fixes.scss @@ -9,3 +9,15 @@ border: 0; } +/* ---- LIBRARY FIXES ---- */ + +/** + * TODO: Hotfix for https://github.com/nextcloud-libraries/nextcloud-vue/issues/8783 + * + * NcSelect appends its dropdown to the body, but `--vs-dropdown-z-index` is only + * set on the select itself, so the dropdown falls back to the vue-select default + * of 1000 and ends up behind modals (z-index 9998 and above). + */ +.nc-select__dropdown.vs__dropdown-menu { + --vs-dropdown-z-index: 9999; +} diff --git a/tests/playwright/e2e/files/files-delete.spec.ts b/tests/playwright/e2e/files/files-delete.spec.ts index e22df5e33a545..859c5d293afac 100644 --- a/tests/playwright/e2e/files/files-delete.spec.ts +++ b/tests/playwright/e2e/files/files-delete.spec.ts @@ -14,7 +14,7 @@ test.describe('Files: Delete', () => { const row = filesListPage.getRowForFile('file.txt') await expect(row).toBeVisible() // Preview must finish loading before delete — a loading preview can lock the file - await expect(row.locator('.files-list__row-icon-preview--loaded')).toBeVisible() + await filesListPage.waitForPreviewLoaded('file.txt') const deleteResponse = page.waitForResponse( (r) => r.url().includes('/remote.php/dav/files/') && r.request().method() === 'DELETE', diff --git a/tests/playwright/e2e/files_sharing/public-share/copy-move-rename-files.spec.ts b/tests/playwright/e2e/files_sharing/public-share/copy-move-rename-files.spec.ts index be4f7de657b7f..a34497f7e3b0b 100644 --- a/tests/playwright/e2e/files_sharing/public-share/copy-move-rename-files.spec.ts +++ b/tests/playwright/e2e/files_sharing/public-share/copy-move-rename-files.spec.ts @@ -14,12 +14,15 @@ const SHARE_NAME = 'shared' * by a guest. */ test.describe('files_sharing: Public share - copy, move and rename files', () => { - test.beforeEach(async ({ user, ownerRequest, publicShare }) => { + test.beforeEach(async ({ user, ownerRequest, publicShare, filesListPage }) => { await seedSharedFolder(ownerRequest, user, SHARE_NAME) const share = await createLinkShare(ownerRequest, `/${SHARE_NAME}`, { permissions: BUNDLED_PERMISSIONS.UPLOAD_AND_UPDATE, }) await publicShare.open(share.url) + // Every test moves, copies or renames foo.txt, so its preview has to be + // loaded first — a preview being generated locks the file on the server. + await filesListPage.waitForPreviewLoaded('foo.txt') }) test('can copy a file to another folder', async ({ page, filesListPage, copyMoveDialog }) => { diff --git a/tests/playwright/support/sections/FilesListPage.ts b/tests/playwright/support/sections/FilesListPage.ts index df63836c775f2..36fa974a5ced6 100644 --- a/tests/playwright/support/sections/FilesListPage.ts +++ b/tests/playwright/support/sections/FilesListPage.ts @@ -311,6 +311,17 @@ export class FilesListPage { await moved } + /** + * Wait for a row's preview thumbnail to be loaded. + * + * Generating a preview locks the file on the server, so a MOVE, COPY or + * DELETE issued while the thumbnail is still being fetched fails with a + * `LockedException`. Await this before any action that writes to the file. + */ + async waitForPreviewLoaded(filename: string): Promise { + await expect(this.getRowForFile(filename).locator('.files-list__row-icon-preview--loaded')).toBeVisible() + } + getFavoriteIconForFile(filename: string): Locator { return this.getRowForFile(filename).getByRole('img', { name: 'Favorite' }) }