diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index d979566b380..639c43aa82a 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -4,7 +4,7 @@ name: Playwright Tests on: pull_request: - branches: [main] + branches: [main, stable3*] jobs: test: diff --git a/package-lock.json b/package-lock.json index b7c13a288a8..0b99f6dd267 100644 --- a/package-lock.json +++ b/package-lock.json @@ -97,7 +97,7 @@ "@nextcloud/eslint-config": "^8.4.2", "@nextcloud/prettier-config": "^1.2.0", "@nextcloud/vite-config": "^1.7.2", - "@playwright/test": "^1.56.1", + "@playwright/test": "^1.58.2", "@types/markdown-it": "^14.1.2", "@vitest/coverage-v8": "^3.2.4", "@vue/test-utils": "^1.3.0 <2", @@ -4414,13 +4414,13 @@ } }, "node_modules/@playwright/test": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz", - "integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz", + "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright": "1.56.1" + "playwright": "1.58.2" }, "bin": { "playwright": "cli.js" @@ -15639,13 +15639,13 @@ } }, "node_modules/playwright": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz", - "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", + "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.56.1" + "playwright-core": "1.58.2" }, "bin": { "playwright": "cli.js" @@ -15658,9 +15658,9 @@ } }, "node_modules/playwright-core": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz", - "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", "dev": true, "license": "Apache-2.0", "bin": { @@ -23772,12 +23772,12 @@ "dev": true }, "@playwright/test": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz", - "integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.58.2.tgz", + "integrity": "sha512-akea+6bHYBBfA9uQqSYmlJXn61cTa+jbO87xVLCWbTqbWadRVmhxlXATaOjOgcBaWU4ePo0wB41KMFv3o35IXA==", "dev": true, "requires": { - "playwright": "1.56.1" + "playwright": "1.58.2" } }, "@popperjs/core": { @@ -31557,13 +31557,13 @@ } }, "playwright": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz", - "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.58.2.tgz", + "integrity": "sha512-vA30H8Nvkq/cPBnNw4Q8TWz1EJyqgpuinBcHET0YVJVFldr8JDNiU9LaWAE1KqSkRYazuaBhTpB5ZzShOezQ6A==", "dev": true, "requires": { "fsevents": "2.3.2", - "playwright-core": "1.56.1" + "playwright-core": "1.58.2" }, "dependencies": { "fsevents": { @@ -31576,9 +31576,9 @@ } }, "playwright-core": { - "version": "1.56.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz", - "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==", + "version": "1.58.2", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.58.2.tgz", + "integrity": "sha512-yZkEtftgwS8CsfYo7nm0KE8jsvm6i/PTgVtB8DL726wNf6H2IMsDuxCpJj59KDaxCtSnrWan2AeDqM7JBaultg==", "dev": true }, "pluralize": { diff --git a/package.json b/package.json index 95f0f5c8273..938702f1799 100644 --- a/package.json +++ b/package.json @@ -117,7 +117,7 @@ "@nextcloud/eslint-config": "^8.4.2", "@nextcloud/prettier-config": "^1.2.0", "@nextcloud/vite-config": "^1.7.2", - "@playwright/test": "^1.56.1", + "@playwright/test": "^1.58.2", "@types/markdown-it": "^14.1.2", "@vitest/coverage-v8": "^3.2.4", "@vue/test-utils": "^1.3.0 <2", diff --git a/playwright.config.ts b/playwright.config.ts index f1703309101..e28e2c34e03 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -31,28 +31,31 @@ export default defineConfig({ }, projects: [ - // Our global setup to configure the Nextcloud docker container - { - name: 'setup', - testMatch: /setup\.ts$/, - }, - { name: 'chromium', use: { ...devices['Desktop Chrome'], }, - dependencies: ['setup'], }, ], webServer: { // Starts the Nextcloud docker container command: 'npm run start:nextcloud', + // we use sigterm to notify the script to stop the container + // if it does not respond, we force kill it after 10 seconds + gracefulShutdown: { + signal: 'SIGTERM', + timeout: 10000, + }, reuseExistingServer: !process.env.CI, - url: 'http://127.0.0.1:8089', stderr: 'pipe', stdout: 'pipe', + url: 'http://127.0.0.1:8089', timeout: 5 * 60 * 1000, // max. 5 minutes for creating the container + wait: { + // we wait for this line to appear in the output of the webserver until consider it done + stdout: /Nextcloud is now ready to use/, + }, }, }) diff --git a/playwright/e2e/versions.spec.ts b/playwright/e2e/versions.spec.ts index 594919c2036..d2607b7d6b9 100644 --- a/playwright/e2e/versions.spec.ts +++ b/playwright/e2e/versions.spec.ts @@ -59,9 +59,7 @@ test.describe('Versions with distant timestamps', () => { .getByRole('menuitem', { name: 'Compare to current version' }) .click() const oldVersion = page.getByRole('textbox') - const current = page.locator( - '.viewer__content .viewer__file--active .ProseMirror', - ) + const current = page.locator('.ProseMirror[contenteditable="true"]') await expect(oldVersion.getByRole('heading', { name: 'V1' })).toBeVisible() await expect(current.getByRole('heading', { name: 'V3' })).toBeVisible() }) diff --git a/playwright/start-nextcloud-server.mjs b/playwright/start-nextcloud-server.mjs index 2719c52ea3c..e36cdaedaa8 100644 --- a/playwright/start-nextcloud-server.mjs +++ b/playwright/start-nextcloud-server.mjs @@ -1,37 +1,49 @@ -/** - * SPDX-FileCopyrightText: 2024 Ferdinand Thiessen - * SPDX-License-Identifier: AGPL-3.0-or-later +/*! + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: MIT */ -import { startNextcloud, stopNextcloud } from '@nextcloud/e2e-test-server/docker' +import { + configureNextcloud, + startNextcloud, + stopNextcloud, + waitOnNextcloud, +} from '@nextcloud/e2e-test-server/docker' import { readFileSync } from 'fs' +import { execSync } from 'node:child_process' -const start = async () => { - return await startNextcloud(getBranch(), true, { +async function start() { + const appinfo = readFileSync('appinfo/info.xml').toString() + const maxVersion = appinfo.match( + //, + )?.[1] + + let branch = 'master' + if (maxVersion) { + const refs = execSync('git ls-remote --refs').toString('utf-8') + branch = refs.includes(`refs/heads/stable${maxVersion}`) + ? `stable${maxVersion}` + : branch + } + + return await startNextcloud(branch, true, { exposePort: 8089, }) } -const getBranch = () => { - try { - const appinfo = readFileSync('appinfo/info.xml').toString() - const maxVersion = appinfo.match( - //, - )?.[1] - return maxVersion ? `stable${maxVersion}` : undefined - } catch (err) { - if (err.code === 'ENOENT') { - console.warn('No appinfo/info.xml found. Using default server banch.') - } - } +async function stop() { + process.stderr.write('Stopping Nextcloud server…\n') + await stopNextcloud() + process.exit(0) } +process.on('SIGTERM', stop) +process.on('SIGINT', stop) + // Start the Nextcloud docker container -await start() -// Listen for process to exit (tests done) and shut down the docker container -process.on('beforeExit', (code) => { - stopNextcloud() -}) +const ip = await start() +await waitOnNextcloud(ip) +await configureNextcloud(['text', 'viewer']) // Idle to wait for shutdown while (true) { diff --git a/playwright/support/setup.ts b/playwright/support/setup.ts deleted file mode 100644 index 6d188b440a4..00000000000 --- a/playwright/support/setup.ts +++ /dev/null @@ -1,18 +0,0 @@ -/** - * SPDX-FileCopyrightText: 2024 Ferdinand Thiessen - * SPDX-License-Identifier: AGPL-3.0-or-later - */ - -import { configureNextcloud } from '@nextcloud/e2e-test-server' -import { test as setup } from '@playwright/test' - -/** - * We use this to ensure Nextcloud is configured correctly before running our tests - * - * This can not be done in the webserver startup process, - * as that only checks for the URL to be accessible which happens already before everything is configured. - */ -setup('Configure Nextcloud', async () => { - const appsToInstall = ['text', 'viewer'] - await configureNextcloud(appsToInstall) -}) diff --git a/src/components/Menu/ActionInsertLink.vue b/src/components/Menu/ActionInsertLink.vue index 1ec7600d8eb..80deeabb0a3 100644 --- a/src/components/Menu/ActionInsertLink.vue +++ b/src/components/Menu/ActionInsertLink.vue @@ -42,6 +42,7 @@