Skip to content

Commit 5240852

Browse files
committed
test(installer): migrate end-to-end tests to PlayWright
Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
1 parent fdfd320 commit 5240852

9 files changed

Lines changed: 475 additions & 306 deletions

File tree

.github/workflows/cypress.yml

Lines changed: 1 addition & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -141,56 +141,10 @@ jobs:
141141
matrix:
142142
# Run multiple copies of the current job in parallel
143143
# Please increase the number or runners as your tests suite grows (0 based index for e2e tests)
144-
containers: ['setup', '0', '1', '2', '3']
145-
# Hack as strategy.job-total includes the "setup" and GitHub does not allow math expressions
144+
containers: ['0', '1', '2', '3']
146145
# Always align this number with the total of e2e runners (max. index + 1)
147146
total-containers: [4]
148147

149-
services:
150-
mysql:
151-
# Only start mysql if we are running the setup tests
152-
image: ${{matrix.containers == 'setup' && 'ghcr.io/nextcloud/continuous-integration-mysql-8.4:latest' || ''}} # zizmor: ignore[unpinned-images]
153-
ports:
154-
- '3306/tcp'
155-
env:
156-
MYSQL_ROOT_PASSWORD: rootpassword
157-
MYSQL_USER: oc_autotest
158-
MYSQL_PASSWORD: nextcloud
159-
MYSQL_DATABASE: oc_autotest
160-
options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 10
161-
162-
mariadb:
163-
# Only start mariadb if we are running the setup tests
164-
image: ${{matrix.containers == 'setup' && 'mariadb:11.4' || ''}} # zizmor: ignore[unpinned-images]
165-
ports:
166-
- '3306/tcp'
167-
env:
168-
MYSQL_ROOT_PASSWORD: rootpassword
169-
MYSQL_USER: oc_autotest
170-
MYSQL_PASSWORD: nextcloud
171-
MYSQL_DATABASE: oc_autotest
172-
options: --health-cmd="mariadb-admin ping" --health-interval 5s --health-timeout 2s --health-retries 5
173-
174-
postgres:
175-
# Only start postgres if we are running the setup tests
176-
image: ${{matrix.containers == 'setup' && 'ghcr.io/nextcloud/continuous-integration-postgres-17:latest' || ''}} # zizmor: ignore[unpinned-images]
177-
ports:
178-
- '5432/tcp'
179-
env:
180-
POSTGRES_USER: root
181-
POSTGRES_PASSWORD: rootpassword
182-
POSTGRES_DB: nextcloud
183-
options: --mount type=tmpfs,destination=/var/lib/postgresql/data --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5
184-
185-
oracle:
186-
# Only start oracle if we are running the setup tests
187-
image: ${{matrix.containers == 'setup' && 'ghcr.io/gvenzl/oracle-free:23' || ''}} # zizmor: ignore[unpinned-images]
188-
ports:
189-
- '1521'
190-
env:
191-
ORACLE_PASSWORD: oracle
192-
options: --health-cmd healthcheck.sh --health-interval 20s --health-timeout 10s --health-retries 10
193-
194148
name: runner ${{ matrix.containers }}
195149

196150
steps:
@@ -254,7 +208,6 @@ jobs:
254208
SPLIT: ${{ matrix.total-containers }}
255209
SPLIT_INDEX: ${{ matrix.containers == 'component' && 0 || matrix.containers }}
256210
SPLIT_RANDOM_SEED: ${{ github.run_id }}
257-
SETUP_TESTING: ${{ matrix.containers == 'setup' && 'true' || '' }}
258211

259212
- name: Upload snapshots and videos
260213
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1

.github/workflows/playwright.yml

Lines changed: 115 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,122 @@ jobs:
147147
path: blob-report
148148
retention-days: 1
149149

150+
playwright-installer-tests:
151+
needs: [gate, playwright-setup]
152+
timeout-minutes: 30
153+
name: Playwright tests for installer
154+
runs-on: ubuntu-latest
155+
156+
# The installation-wizard tests exercise every supported database backend, so
157+
# they need reachable database service containers. The Nextcloud container is
158+
# joined to the GitHub Actions network at startup so it can resolve these by
159+
# hostname (see tests/playwright/start-nextcloud-server.js).
160+
services:
161+
mysql:
162+
image: mysql:9.7 # zizmor: ignore[unpinned-images]
163+
ports:
164+
- '3306/tcp'
165+
env:
166+
MYSQL_ROOT_PASSWORD: rootpassword
167+
MYSQL_USER: nextcloud
168+
MYSQL_PASSWORD: nextcloud
169+
MYSQL_DATABASE: nextcloud
170+
options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 10
171+
172+
mariadb:
173+
image: mariadb:12.3 # zizmor: ignore[unpinned-images]
174+
ports:
175+
- '3306/tcp'
176+
env:
177+
MARIADB_ROOT_PASSWORD: rootpassword
178+
MARIADB_USER: nextcloud
179+
MARIADB_PASSWORD: nextcloud
180+
MARIADB_DATABASE: nextcloud
181+
options: --health-cmd="mariadb-admin ping" --health-interval 5s --health-timeout 2s --health-retries 5
182+
183+
postgres:
184+
image: postgres:18 # zizmor: ignore[unpinned-images]
185+
ports:
186+
- '5432/tcp'
187+
env:
188+
POSTGRES_USER: root
189+
POSTGRES_PASSWORD: rootpassword
190+
POSTGRES_DB: nextcloud
191+
options: --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5
192+
193+
oracle:
194+
image: ghcr.io/gvenzl/oracle-free:23 # zizmor: ignore[unpinned-images]
195+
ports:
196+
- '1521'
197+
env:
198+
ORACLE_PASSWORD: oracle
199+
options: --health-cmd healthcheck.sh --health-interval 20s --health-timeout 10s --health-retries 10
200+
201+
steps:
202+
- name: Restore context
203+
id: cache
204+
uses: buildjet/cache/restore@3e70d19e31d6a8030aeddf6ed8dbe601f94d09f4 # v4.0.2
205+
with:
206+
key: playwright-context-${{ github.run_id }}
207+
path: ./
208+
209+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
210+
if: steps.cache.outputs.cache-hit != 'true'
211+
with:
212+
persist-credentials: false
213+
submodules: true # for 3rdparty
214+
215+
- name: Read package.json
216+
if: steps.cache.outputs.cache-hit != 'true'
217+
uses: nextcloud-libraries/parse-package-engines-action@122ae05d4257008180a514e1ddeb0c1b9d094bdd # v0.1.0
218+
id: versions
219+
220+
- name: Set up node
221+
if: steps.cache.outputs.cache-hit != 'true'
222+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
223+
with:
224+
node-version: ${{ steps.versions.outputs.node-version }}
225+
226+
- name: Set up npm
227+
if: steps.cache.outputs.cache-hit != 'true'
228+
run: npm i -g 'npm@${{ steps.versions.outputs.package-manager-version }}'
229+
230+
- name: Install dependencies and build
231+
if: steps.cache.outputs.cache-hit != 'true'
232+
run: |
233+
npm ci
234+
npm run build --if-present
235+
236+
- name: Install Playwright browsers
237+
run: npx playwright install --with-deps
238+
239+
- name: Run Playwright setup tests
240+
run: npm run playwright:setup
241+
env:
242+
PLAYWRIGHT_SETUP: 'true'
243+
244+
- name: Show logs
245+
if: failure()
246+
run: |
247+
for id in $(docker ps -aq); do
248+
docker container inspect "$id" --format '=== Logs for container {{.Name}} ==='
249+
docker logs "$id" >> nextcloud.log
250+
done
251+
echo '=== Nextcloud server logs ==='
252+
docker exec nextcloud-e2e-test-server_server cat data/nextcloud.log || true
253+
254+
- name: Upload blob report to GitHub Actions Artifacts
255+
if: ${{ !cancelled() }}
256+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
257+
with:
258+
name: blob-report-setup
259+
path: blob-report
260+
retention-days: 1
261+
150262
merge-reports:
151263
# Merge reports after playwright-tests, even if some shards have failed
152264
if: ${{ !cancelled() }}
153-
needs: [gate, playwright-tests]
265+
needs: [gate, playwright-tests, playwright-installer-tests]
154266

155267
runs-on: ubuntu-latest-low
156268
steps:
@@ -206,12 +318,12 @@ jobs:
206318
permissions:
207319
contents: none
208320
runs-on: ubuntu-latest-low
209-
needs: [gate, playwright-tests]
321+
needs: [gate, playwright-tests, playwright-installer-tests]
210322

211323
if: always()
212324

213325
name: playwright-test-summary
214326

215327
steps:
216328
- name: Summary status
217-
run: if ${{ needs.playwright-tests.result != 'success' }}; then exit 1; fi
329+
run: if ${{ needs.playwright-tests.result != 'success' || needs.playwright-installer-tests.result != 'success' }}; then exit 1; fi

cypress.config.ts

Lines changed: 3 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
* SPDX-License-Identifier: AGPL-3.0-or-later
55
*/
66

7-
import { configureNextcloud, docker, getContainer, getContainerName, runExec, runOcc, startNextcloud, stopNextcloud, waitOnNextcloud } from '@nextcloud/e2e-test-server'
7+
import { configureNextcloud, getContainerName, runExec, runOcc, startNextcloud, stopNextcloud, waitOnNextcloud } from '@nextcloud/e2e-test-server'
88
import { defineConfig } from 'cypress'
99
import cypressSplit from 'cypress-split'
1010
import vitePreprocessor from 'cypress-vite'
1111
import { existsSync, rmSync } from 'node:fs'
12-
import { dirname, join, resolve } from 'node:path'
12+
import { dirname, resolve } from 'node:path'
1313
import { fileURLToPath } from 'node:url'
1414
import { nodePolyfills } from 'vite-plugin-node-polyfills'
1515

@@ -116,15 +116,7 @@ export default defineConfig({
116116
}
117117
})
118118

119-
// Check if we are running the setup checks
120-
if (process.env.SETUP_TESTING === 'true') {
121-
console.log('Adding setup tests to specPattern 🧮')
122-
config.specPattern = [join(__dirname, 'cypress/e2e/core/setup.ts')]
123-
console.log('└─ Done')
124-
} else {
125-
// If we are not running the setup tests, we need to remove the setup tests from the specPattern
126-
cypressSplit(on, config)
127-
}
119+
cypressSplit(on, config)
128120

129121
const mounts = {
130122
'3rdparty': resolve(__dirname, './3rdparty'),
@@ -163,8 +155,6 @@ export default defineConfig({
163155
})
164156
// Setting container's IP as base Url
165157
config.baseUrl = `http://localhost:${port}/index.php`
166-
// if needed for the setup tests, connect to the actions network
167-
await connectToActionsNetwork()
168158
// make sure not to write into apps but use a local apps folder
169159
runExec(['mkdir', 'apps-cypress'])
170160
runExec(['cp', 'cypress/fixtures/app.config.php', 'config'])
@@ -185,26 +175,3 @@ export default defineConfig({
185175
},
186176
},
187177
})
188-
189-
/**
190-
* Connect the running test container to the GitHub Actions network
191-
*/
192-
async function connectToActionsNetwork() {
193-
if (process.env.SETUP_TESTING !== 'true') {
194-
console.log('├─ Not running setup tests, skipping actions network connection 🌐')
195-
return
196-
}
197-
198-
console.log('├─ Looking for github actions network... 🔍')
199-
const networks = await docker.listNetworks()
200-
const network = networks.find((network) => network.Name.startsWith('github_network'))
201-
if (!network) {
202-
console.log('│ └─ No actions network found ⚠️')
203-
return
204-
}
205-
206-
console.log('│ |─ Found actions network: ' + network.Name)
207-
await docker.getNetwork(network.Id)
208-
.connect({ Container: getContainer().id })
209-
console.log('│ └─ Connected to actions network 🌐')
210-
}

0 commit comments

Comments
 (0)