Skip to content

Commit eea1d51

Browse files
Merge pull request #8 from opf/isolate-test-launch-to-docker-container
Isolated playwright tests into docker container
2 parents 3c4cea1 + 67105d6 commit eea1d51

16 files changed

Lines changed: 336 additions & 942 deletions

.cursor/skills/tests/SKILL.md

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,15 +127,25 @@ try {
127127
- To run in headed mode, use Playwright’s native CLI flags, e.g.:
128128
- `npx playwright test --headed`
129129
- Default worker configuration:
130-
- Single worker (`workers: 1`) to keep tests predictable and avoid cross-test interference.
131-
- Common commands:
130+
- Single worker (`workers: 1`), overridable via `E2E_WORKERS` or `--workers`.
131+
- **Native (Node.js on host):**
132132
- Run tests: `npx playwright test`
133133
- Run tests headed: `npx playwright test --headed`
134134
- Run tests and open report: `npx playwright test && npx playwright show-report`
135+
- **Docker (zero local Node/browser):**
136+
- Run all tests: `./run-tests.sh` (default `E2E_ENV=local`)
137+
- Target env: `E2E_ENV=edge ./run-tests.sh` or `E2E_ENV=stage ./run-tests.sh`
138+
- Pass Playwright args: `./run-tests.sh --grep @smoke`; force rebuild: `./run-tests.sh --build`
139+
- Reports and traces are bind-mounted to `playwright-report/` and `test-results/` on the host.
140+
141+
## Writing Style
142+
143+
- Keep all documentation, comments, and README files short and precise.
144+
- No emojis, no decorative characters, no redundant explanations.
145+
- Only comment non-obvious logic; do not narrate what the code does.
135146

136147
## Self-Improvement Directive
137148

138-
- After completing significant refactoring, introducing new patterns, or making architectural changes to this E2E codebase:
139-
- Update this `SKILL.md` to reflect the new conventions, helpers, and standards.
140-
- Keep the file concise and focused on project-specific knowledge that future sessions should follow by default.
149+
- After significant refactoring or architectural changes, update this `SKILL.md` to reflect new conventions.
150+
- Keep this file concise and focused on project-specific knowledge.
141151

.dockerignore

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Dependencies and build artifacts (installed in container)
2+
node_modules/
3+
.playwright-browsers/
4+
5+
# Git
6+
.git/
7+
.gitignore
8+
9+
# Reports and results (bind-mounted at runtime)
10+
playwright-report/
11+
test-results/
12+
13+
# Local env (passed via env_file or env at runtime)
14+
.env
15+
.env.*
16+
!.env.example
17+
18+
# IDE and OS
19+
.idea/
20+
.vscode/
21+
.DS_Store
22+
*.log
23+
24+
# Cursor
25+
.cursor/
26+
27+
# Plan files (not needed in image)
28+
*.plan.md

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,6 @@ playwright-report/
1313
test-results/
1414
.playwright-browsers/
1515

16+
docker-compose.override.yml
17+
1618
.DS_Store

.node-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
v24.13.1

Dockerfile

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
ARG PLAYWRIGHT_VERSION=v1.58.2
2+
FROM mcr.microsoft.com/playwright:${PLAYWRIGHT_VERSION}-noble
3+
4+
# Never open or serve report inside container; host opens static report after run
5+
ENV PLAYWRIGHT_HTML_OPEN=never
6+
7+
WORKDIR /app
8+
9+
COPY package.json package-lock.json ./
10+
RUN npm ci --ignore-scripts
11+
12+
COPY . .
13+
14+
ENTRYPOINT ["npx", "playwright", "test"]

README.md

Lines changed: 50 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -1,179 +1,82 @@
11
# E2E Integration Tests
22

3-
Playwright end-to-end tests for OpenProject-Nextcloud-Keycloak integration.
4-
5-
3+
Playwright E2E tests for OpenProject, Nextcloud, and Keycloak integration.
64

75
## Requirements
86

9-
- Node.js 18+
10-
- npm
11-
- Integration cluster deployed via https://github.com/opf/integration-qa-helmfile
12-
- Playwright browsers installed
7+
- Docker (for Docker-based runs), or Node.js 18+ and npm (for native runs)
8+
- Integration cluster via [opf/integration-qa-helmfile](https://github.com/opf/integration-qa-helmfile)
139

1410
## Quick Start
1511

16-
1. **Install dependencies:**
17-
```bash
18-
npm install
19-
npm run playwright:install
20-
```
21-
22-
2. **Ensure local integration cluster is running (for local tests):**
23-
The recommended way to run a full local OpenProject–Nextcloud–Keycloak stack is via the
24-
[`opf/integration-qa-helmfile`](https://github.com/opf/integration-qa-helmfile/tree/main) repo.
25-
Follow its README to `make setup` and `make deploy`, which will provision:
26-
- `https://openproject.test`
27-
- `https://nextcloud.test`
28-
- `https://keycloak.test`
29-
30-
3. **Run tests (native Playwright, headless by default):**
31-
```bash
32-
E2E_ENV=local npx playwright test # local Helm/defaults
33-
E2E_ENV=edge npx playwright test # edge/staging secrets must be exported
34-
E2E_ENV=stage npx playwright test # stage secrets must be exported
35-
```
36-
37-
## Commands
38-
39-
### Run Tests
40-
```bash
41-
# Native Playwright (recommended)
42-
E2E_ENV=local npx playwright test
43-
E2E_ENV=edge npx playwright test
44-
E2E_ENV=stage npx playwright test
45-
46-
# Run tests and automatically open HTML report
47-
E2E_ENV=local npx playwright test && npx playwright show-report
48-
49-
# Override worker count to re-enable parallelism (default is 1)
50-
npx playwright test --workers 4
51-
52-
# npm script shortcuts (thin wrappers around the above)
53-
npm run test:edge # uses E2E_ENV=edge
54-
npm run test:stage # uses E2E_ENV=stage
55-
npm run test:local # uses E2E_ENV=local
56-
57-
# Run in headed mode (non-headless)
58-
npm run test:e2e:headed
59-
npx playwright test --headed
60-
61-
# Run with UI mode
62-
npm run test:e2e:ui
63-
```
64-
65-
### View Results
12+
**Docker (no local Node.js required):**
6613
```bash
67-
# Open last test report (native)
68-
npx playwright show-report
69-
70-
# Or via npm script
71-
npm run report:show
14+
./run-tests.sh
7215
```
7316

74-
### Run Tests by Tag
75-
76-
Use `--grep` to include tags:
17+
**Native:**
7718
```bash
78-
npx playwright test --grep @fast
19+
npm install
20+
npm run playwright:install
21+
E2E_ENV=local npx playwright test
7922
```
8023

81-
Skip a tag with `--grep-invert`:
82-
```bash
83-
npx playwright test --grep-invert @fast
84-
```
24+
## Running Tests
8525

86-
Logical OR (either tag):
87-
```bash
88-
npx playwright test --grep "@fast|@slow"
89-
```
26+
### Docker
9027

91-
Logical AND (both tags via lookahead):
9228
```bash
93-
npx playwright test --grep "(?=.*@fast)(?=.*@slow)"
29+
./run-tests.sh # local, all tests
30+
E2E_ENV=edge ./run-tests.sh # edge environment
31+
E2E_ENV=stage ./run-tests.sh # stage environment
32+
./run-tests.sh --grep @smoke # filter by tag
33+
./run-tests.sh --build # force image rebuild
34+
./run-tests.sh --no-open-report # skip opening report in browser after run
9435
```
9536

96-
## Test Organization & Tags
97-
98-
All tests now live directly under `tests/`:
99-
- `kc-integration.spec.ts` - Keycloak integration (`@smoke`, `@regression`, `@integration`)
100-
- `nc-integration.spec.ts` - Nextcloud integration (`@regression`, `@integration`)
101-
- `op-integration.spec.ts` - OpenProject integration (`@regression`, `@integration`)
102-
103-
All specs run for the single supported setup (`sso-external`). Use `--grep` to target `@smoke`, `@regression`, or `@integration`.
104-
105-
## Test Users
37+
Report opens on your machine after the run. Each run writes to `playwright-report/run-YYYY-MM-DD_HH-mm-ss/` (report in `report/`, plus `results.json`, `junit.xml`). Traces/screenshots/videos stay in `test-results/`. Config is mounted so changes to `playwright.config.ts` apply without rebuilding the image; use `--build` only when deps or Dockerfile change.
10638

107-
Defaults (overridable via env):
108-
- OpenProject admin: `E2E_OP_ADMIN_USER` / `E2E_OP_ADMIN_PASS` (default `admin/admin`)
109-
- Nextcloud admin: `E2E_NC_ADMIN_USER` / `E2E_NC_ADMIN_PASS` (default `admin/admin`)
110-
- Keycloak admin: `E2E_KC_ADMIN_USER` / `E2E_KC_ADMIN_PASS` (default `admin/admin`)
111-
- Keycloak realm users: `E2E_ALICE_USER` / `E2E_ALICE_PASS` (default `alice/1234`), `E2E_BRIAN_USER` / `E2E_BRIAN_PASS` (default `brian/1234`)
39+
Credentials and host overrides go in `.env.local` (gitignored, loaded automatically). If `opnc-root-ca.crt` is in the project root it is mounted and used automatically for self-signed CA.
11240

113-
Import from `e2e/utils/test-users.ts`:
41+
### Native
11442

115-
```typescript
116-
import { OP_ADMIN_USER, NC_ADMIN_USER, ADMIN_USER, ALICE_USER, BRIAN_USER } from '../utils/test-users';
43+
```bash
44+
E2E_ENV=local npx playwright test
45+
E2E_ENV=edge npx playwright test
46+
E2E_ENV=stage npx playwright test
47+
npx playwright test --headed
48+
npx playwright test --workers 4
49+
npx playwright show-report
50+
npm run test:e2e:report # run tests then open report (native)
11751
```
11852

119-
## Test Helpers
53+
npm shortcuts: `npm run test:local`, `test:edge`, `test:stage`, `test:docker`, `report:show`.
12054

121-
Use the helpers in `utils/test-helpers.ts` to keep specs focused on behaviour instead of data setup:
55+
**Report:** Docker: report opens automatically after `./run-tests.sh` (or open `playwright-report/index.html`). Native: `npm run report:show` serves at http://localhost:9323 (bound to 0.0.0.0).
12256

123-
- Ensure a user has admin rights (idempotent):
57+
### Tags
12458

125-
```typescript
126-
import { ensureUserIsAdmin } from '../utils/test-helpers';
127-
128-
const loginIdentifier = ALICE_USER.email ?? `${ALICE_USER.username}@example.com`;
129-
const { userId, updated } = await ensureUserIsAdmin(loginIdentifier);
130-
```
131-
132-
- Ensure a project exists and has a Nextcloud storage configured via API:
133-
134-
```typescript
135-
import { ensureProjectHasNextcloudStorage } from '../utils/test-helpers';
136-
137-
await ensureProjectHasNextcloudStorage('demo-project');
59+
```bash
60+
npx playwright test --grep @smoke
61+
npx playwright test --grep "@smoke|@regression"
13862
```
13963

140-
- Copy the demo project via UI using page objects:
141-
142-
```typescript
143-
import { OpenProjectHomePage } from '../pageobjects/openproject';
144-
145-
const homePage = new OpenProjectHomePage(page);
146-
await homePage.copyDemoProjectViaUi('test');
147-
```
64+
Tags in use: `@smoke`, `@regression`, `@integration`.
14865

14966
## Environment Variables
15067

151-
Hosts (preferred):\
152-
`OPENPROJECT_HOST`, `NEXTCLOUD_HOST`, `KEYCLOAK_HOST`
153-
154-
Versions (optional):\
155-
`OPENPROJECT_VERSION`, `NEXTCLOUD_VERSION`, `INTEGRATION_APP_VERSION`, `KEYCLOAK_VERSION`
156-
157-
Credentials (see Test Users):\
158-
`E2E_OP_ADMIN_USER`, `E2E_OP_ADMIN_PASS`, `E2E_NC_ADMIN_USER`, `E2E_NC_ADMIN_PASS`, `E2E_KC_ADMIN_USER`, `E2E_KC_ADMIN_PASS`, `E2E_ALICE_USER`, `E2E_ALICE_PASS`, `E2E_BRIAN_USER`, `E2E_BRIAN_PASS`
159-
160-
Other controls:\
161-
`SETUP_METHOD` (`sso-external` only), `SETUP_JOB_CHECK=true` to enforce cluster setup-job wait (off by default), `E2E_ENV` to pick env preset.
162-
163-
Local runs: put the above in `.env.local` (already gitignored). CI ignores this file.
164-
165-
**Tests fail to connect?**
166-
- Verify pods are running: `kubectl get pods -n opnc-integration`
167-
- Check port forwarding is active
168-
169-
**Playwright complains about missing browser executable?**
170-
- Make sure you've run `npm run playwright:install` (or `npx playwright install`) after `npm install`.
171-
- Re-run your test command, e.g. `E2E_ENV=local npx playwright test`.
172-
173-
## More Information
174-
175-
- Tests run with a single worker by default (configurable via `--workers`)
176-
- Uses Page Object Model pattern
177-
- Locators stored in JSON files
178-
- See `e2e/utils/locators_guide.md` for locator usage examples
179-
68+
| Variable | Purpose | Default |
69+
|---|---|---|
70+
| `E2E_ENV` | Target environment | `local` |
71+
| `OPENPROJECT_HOST` | OpenProject hostname | per-env default |
72+
| `NEXTCLOUD_HOST` | Nextcloud hostname | per-env default |
73+
| `KEYCLOAK_HOST` | Keycloak hostname | per-env default |
74+
| `E2E_OP_ADMIN_USER/PASS` | OpenProject admin credentials | `admin/admin` |
75+
| `E2E_NC_ADMIN_USER/PASS` | Nextcloud admin credentials | `admin/admin` |
76+
| `E2E_KC_ADMIN_USER/PASS` | Keycloak admin credentials | `admin/admin` |
77+
| `E2E_ALICE_USER/PASS` | Realm user alice | `alice/1234` |
78+
| `E2E_BRIAN_USER/PASS` | Realm user brian | `brian/1234` |
79+
| `E2E_WORKERS` | Worker count | `1` |
80+
| `SETUP_JOB_CHECK` | Wait for K8s setup-job | `false` |
81+
82+
Put variables in `.env.local` for local runs.

docker-compose.yml

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
services:
2+
e2e:
3+
build:
4+
context: .
5+
args:
6+
PLAYWRIGHT_VERSION: ${PLAYWRIGHT_VERSION:-v1.58.2}
7+
env_file:
8+
- path: .env.local
9+
required: false
10+
environment:
11+
- E2E_ENV=${E2E_ENV:-local}
12+
- CI=${CI:-}
13+
- PLAYWRIGHT_HTML_OPEN=never
14+
- E2E_WORKERS=${E2E_WORKERS:-}
15+
- E2E_LOG_LEVEL=${E2E_LOG_LEVEL:-}
16+
- SETUP_METHOD=${SETUP_METHOD:-}
17+
- SETUP_JOB_CHECK=${SETUP_JOB_CHECK:-}
18+
- SKIP_SETUP_JOB_CHECK=${SKIP_SETUP_JOB_CHECK:-}
19+
- KUBERNETES_NAMESPACE=${KUBERNETES_NAMESPACE:-}
20+
- OPENPROJECT_HOST=${OPENPROJECT_HOST:-}
21+
- OPENPROJECT_URL=${OPENPROJECT_URL:-}
22+
- NEXTCLOUD_HOST=${NEXTCLOUD_HOST:-}
23+
- NEXTCLOUD_URL=${NEXTCLOUD_URL:-}
24+
- KEYCLOAK_HOST=${KEYCLOAK_HOST:-}
25+
- KEYCLOAK_URL=${KEYCLOAK_URL:-}
26+
- OPENPROJECT_VERSION=${OPENPROJECT_VERSION:-}
27+
- NEXTCLOUD_VERSION=${NEXTCLOUD_VERSION:-}
28+
- NEXTCLOUD_API_VERSION=${NEXTCLOUD_API_VERSION:-}
29+
- INTEGRATION_APP_VERSION=${INTEGRATION_APP_VERSION:-}
30+
- NEXTCLOUD_TEAM_FOLDERS_VERSION=${NEXTCLOUD_TEAM_FOLDERS_VERSION:-}
31+
- KEYCLOAK_VERSION=${KEYCLOAK_VERSION:-}
32+
- E2E_OP_ADMIN_USER=${E2E_OP_ADMIN_USER:-}
33+
- E2E_OP_ADMIN_PASS=${E2E_OP_ADMIN_PASS:-}
34+
- E2E_NC_ADMIN_USER=${E2E_NC_ADMIN_USER:-}
35+
- E2E_NC_ADMIN_PASS=${E2E_NC_ADMIN_PASS:-}
36+
- E2E_KC_ADMIN_USER=${E2E_KC_ADMIN_USER:-}
37+
- E2E_KC_ADMIN_PASS=${E2E_KC_ADMIN_PASS:-}
38+
- E2E_ALICE_USER=${E2E_ALICE_USER:-}
39+
- E2E_ALICE_PASS=${E2E_ALICE_PASS:-}
40+
- E2E_BRIAN_USER=${E2E_BRIAN_USER:-}
41+
- E2E_BRIAN_PASS=${E2E_BRIAN_PASS:-}
42+
- E2E_KC_REALM=${E2E_KC_REALM:-}
43+
- E2E_KC_NC_CLIENT_ID=${E2E_KC_NC_CLIENT_ID:-}
44+
- E2E_KC_NC_CLIENT_SECRET=${E2E_KC_NC_CLIENT_SECRET:-}
45+
- ALLOW_INSECURE_TLS=${ALLOW_INSECURE_TLS:-}
46+
- NODE_EXTRA_CA_CERTS=${NODE_EXTRA_CA_CERTS:-}
47+
- OPENPROJECT_CA_CERT_PATH=${OPENPROJECT_CA_CERT_PATH:-}
48+
extra_hosts:
49+
# Resolve *.test to Docker host for local Helm
50+
- "openproject.test:host-gateway"
51+
- "nextcloud.test:host-gateway"
52+
- "keycloak.test:host-gateway"
53+
volumes:
54+
- ./tests:/app/tests
55+
- ./test-results:/app/test-results
56+
- ./playwright-report:/app/playwright-report
57+
- ./pageobjects:/app/pageobjects
58+
- ./locators:/app/locators
59+
- ./utils:/app/utils
60+
- ./playwright.config.ts:/app/playwright.config.ts
61+
- ./global-setup.ts:/app/global-setup.ts

0 commit comments

Comments
 (0)