Skip to content

Commit 4125a2b

Browse files
max-nextcloudsusnux
authored andcommitted
test: docker tooling with playwright
Signed-off-by: Max <max@nextcloud.com>
1 parent 89652f2 commit 4125a2b

10 files changed

Lines changed: 339 additions & 3 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,7 @@ typings/
6565
/dist
6666
cypress/screenshots
6767
cypress/videos
68+
69+
# playwright artifacts
70+
test-results/
71+
playwright-report/

README.md

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,29 @@ In particular cypress specific utils such as selectors will be dropped unless th
2525

2626
### Playwright
2727

28-
This repository does not include playwritght configurations or examples yet.
28+
1. Copy `playwright.config.mjs` and `playwright` folder from this repository!
29+
2. Add the `@playwright/test` dependency:
30+
```
31+
npm install --save-dev '@playwright/test'
32+
```
33+
3. Add the `start:nextcloud` script to your package.json
34+
```json
35+
{
36+
"start:nextcloud": "node playwright/start-nextcloud-server.mjs",
37+
}
38+
```
39+
4. Install chromium for playwright:
40+
```
41+
npx playwright install chromium --only-shell
42+
```
43+
5. Run playwright tests:
44+
```
45+
npx playwright test
46+
```
47+
6. Add `.github/workflows/playwright.yml` to your repository!
48+
7. Write your own tests!
49+
2950

30-
Please take a look at the [forms app](https://github.com/nextcloud/forms) for an example of using `@nextlcloud/e2e-test-server` with playwright.
3151

3252
### Cypress
3353

package-lock.json

Lines changed: 98 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@
6464
"cypress": "npm run cypress:e2e && npm run cypress:component",
6565
"cypress:e2e": "cypress run --e2e",
6666
"cypress:component": "cypress run --component",
67-
"cypress:gui": "cypress open"
67+
"cypress:gui": "cypress open",
68+
"start:nextcloud": "node playwright/start-nextcloud-server.mjs"
6869
},
6970
"repository": {
7071
"type": "git",
@@ -87,6 +88,7 @@
8788
"@cypress/code-coverage": "^3.12.39",
8889
"@nextcloud/upload": "^1.1.1",
8990
"@nextcloud/webpack-vue-config": "^6.0.1",
91+
"@playwright/test": "^1.50.1",
9092
"@rollup/plugin-commonjs": "^28.0.1",
9193
"@rollup/plugin-node-resolve": "^16.0.0",
9294
"@rollup/plugin-typescript": "^12.1.1",

playwright.config.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { defineConfig, devices } from '@playwright/test'
7+
8+
/**
9+
* See https://playwright.dev/docs/test-configuration.
10+
*/
11+
export default defineConfig({
12+
testDir: './playwright',
13+
14+
/* Run tests in files in parallel */
15+
fullyParallel: true,
16+
/* Fail the build on CI if you accidentally left test.only in the source code. */
17+
forbidOnly: !!process.env.CI,
18+
/* Retry on CI only */
19+
retries: process.env.CI ? 2 : 0,
20+
/* Opt out of parallel tests on CI. */
21+
workers: process.env.CI ? 1 : undefined,
22+
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
23+
reporter: process.env.CI ? 'github' : 'html',
24+
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
25+
use: {
26+
/* Base URL to use in actions like `await page.goto('./')`. */
27+
baseURL: 'http://localhost:8089/index.php/',
28+
29+
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
30+
trace: 'on-first-retry',
31+
},
32+
33+
projects: [
34+
// Our global setup to configure the Nextcloud docker container
35+
{
36+
name: 'setup',
37+
testMatch: /setup\.ts$/,
38+
},
39+
40+
{
41+
name: 'chromium',
42+
use: {
43+
...devices['Desktop Chrome'],
44+
},
45+
dependencies: ['setup'],
46+
},
47+
],
48+
49+
webServer: {
50+
// Starts the Nextcloud docker container
51+
command: 'npm run start:nextcloud',
52+
reuseExistingServer: !process.env.CI,
53+
url: 'http://127.0.0.1:8089',
54+
stderr: 'pipe',
55+
stdout: 'pipe',
56+
timeout: 5 * 60 * 1000, // max. 5 minutes for creating the container
57+
},
58+
})

playwright/e2e/random-user.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2024 Ferdinand Thiessen <opensource@fthiessen.de>
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { expect } from '@playwright/test'
7+
import { test } from '../support/fixtures/random-user'
8+
9+
test.beforeEach(async ({ page }) => {
10+
await page.goto('apps/files')
11+
await page.waitForURL(/apps\/files/)
12+
})
13+
14+
test('Random user is authenticated', async ({ page }) => {
15+
await expect(page.getByLabel('Settings menu')).toBeVisible()
16+
})
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2024 Ferdinand Thiessen <opensource@fthiessen.de>
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { startNextcloud, stopNextcloud } from '../dist/docker.mjs'
7+
import { readFileSync } from 'fs'
8+
9+
const start = async () => {
10+
return await startNextcloud(getBranch(), true, {
11+
exposePort: 8089,
12+
})
13+
}
14+
15+
const getBranch = () => {
16+
try {
17+
const appinfo = readFileSync('appinfo/info.xml').toString()
18+
const maxVersion = appinfo.match(
19+
/<nextcloud min-version="\d+" max-version="(\d\d+)" \/>/,
20+
)?.[1]
21+
return maxVersion ? `stable${maxVersion}` : undefined
22+
} catch (err) {
23+
if (err.code === 'ENOENT') {
24+
console.warn('No appinfo/info.xml found. Using default server banch.')
25+
}
26+
}
27+
}
28+
29+
// Start the Nextcloud docker container
30+
await start()
31+
// Listen for process to exit (tests done) and shut down the docker container
32+
process.on('beforeExit', (code) => {
33+
stopNextcloud()
34+
})
35+
36+
// Idle to wait for shutdown
37+
while (true) {
38+
await new Promise((resolve) => setTimeout(resolve, 5000))
39+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2024 Ferdinand Thiessen <opensource@fthiessen.de>
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { test as base } from '@playwright/test'
7+
import { createRandomUser, login } from '../utils/session'
8+
9+
/**
10+
* This test fixture ensures a new random user is created and used for the test (current page)
11+
*/
12+
export const test = base.extend({
13+
page: async ({ browser, baseURL }, use) => {
14+
// Important: make sure we authenticate in a clean environment by unsetting storage state.
15+
const page = await browser.newPage({
16+
storageState: undefined,
17+
baseURL,
18+
})
19+
20+
const uid = await createRandomUser()
21+
await login(page.request, uid, uid)
22+
23+
await use(page)
24+
await page.close()
25+
},
26+
})

playwright/support/setup.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* SPDX-FileCopyrightText: 2024 Ferdinand Thiessen <opensource@fthiessen.de>
3+
* SPDX-License-Identifier: AGPL-3.0-or-later
4+
*/
5+
6+
import { test as setup } from '@playwright/test'
7+
import { configureNextcloud } from '../../dist'
8+
9+
/**
10+
* We use this to ensure Nextcloud is configured correctly before running our tests
11+
*
12+
* This can not be done in the webserver startup process,
13+
* as that only checks for the URL to be accessible which happens already before everything is configured.
14+
*/
15+
setup('Configure Nextcloud', async () => {
16+
const appsToInstall = []
17+
await configureNextcloud(appsToInstall)
18+
})

0 commit comments

Comments
 (0)