Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v7

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
uses: docker/login-action@v4
with:
Expand All @@ -66,3 +69,7 @@ jobs:
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
# shared with the e2e-proxy job (tests.yml), which rebuilds the same
# commit from this cache and runs the compose stack on the result
cache-from: type=gha,scope=${{ matrix.component }}
cache-to: type=gha,mode=max,scope=${{ matrix.component }}
110 changes: 108 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,114 @@ jobs:
/tmp/frontend.log
retention-days: 7

# Full stack e2e through the nginx proxy: builds the docker images for this
# commit (sharing the layer cache with the Docker Build workflow), starts the
# production-like compose stack (proxy -> web / backend / keycloak) and runs
# the proxied tests against http://localhost. This catches routing issues
# (e.g. /graphql, /keycloak or /auth/callback misrouted) that the
# dev-server-based e2e job cannot see.
e2e-proxy:
name: E2E (docker stack via nginx proxy)
needs: [backend-lint, frontend]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build backend image
uses: docker/build-push-action@v7
with:
context: backend
push: false
load: true
tags: local/tasks-backend:e2e
cache-from: type=gha,scope=backend
cache-to: type=gha,mode=max,scope=backend

- name: Build web image
uses: docker/build-push-action@v7
with:
context: web
push: false
load: true
tags: local/tasks-web:e2e
cache-from: type=gha,scope=web
cache-to: type=gha,mode=max,scope=web

- name: Build proxy image
uses: docker/build-push-action@v7
with:
context: proxy
push: false
load: true
tags: local/tasks-proxy:e2e
cache-from: type=gha,scope=proxy
cache-to: type=gha,mode=max,scope=proxy

- name: Start the stack
env:
BACKEND_IMAGE: local/tasks-backend:e2e
WEB_IMAGE: local/tasks-web:e2e
PROXY_IMAGE: local/tasks-proxy:e2e
run: docker compose -f docker-compose.e2e.yml up -d

- name: Wait for the stack behind the proxy
run: |
echo "Waiting for keycloak (realm import)..."
timeout 180 bash -c 'until curl -fs http://localhost/keycloak/realms/tasks/.well-known/openid-configuration > /dev/null; do sleep 3; done'
echo "Waiting for the backend (graphql must answer, 5xx means not routed/up yet)..."
timeout 180 bash -c 'until [ "$(curl -s -o /dev/null -w "%{http_code}" -X POST -H "content-type: application/json" -d "{\"query\":\"{ __typename }\"}" http://localhost/graphql)" -lt 500 ]; do sleep 3; done'
echo "Waiting for the frontend..."
timeout 180 bash -c 'until curl -fs http://localhost/ > /dev/null; do sleep 3; done'

- name: Set up Node.js
uses: actions/setup-node@v6
with:
node-version: "20"
cache: "npm"
cache-dependency-path: tests/package-lock.json

- name: Install E2E test dependencies
working-directory: tests
run: npm ci

- name: Install Playwright browsers
working-directory: tests
run: npx playwright install --with-deps chromium

- name: Run proxied E2E tests
working-directory: tests
env:
CI: true
E2E_PROXY_TARGET: "1"
E2E_BASE_URL: http://localhost
run: npx playwright test e2e/proxy-fullstack.spec.ts

- name: Dump stack logs
if: failure()
run: docker compose -f docker-compose.e2e.yml logs --no-color > /tmp/stack.log 2>&1 || true

- name: Upload Playwright report
if: always()
uses: actions/upload-artifact@v7
with:
name: playwright-report-proxy
path: tests/playwright-report/
retention-days: 30

- name: Upload stack logs
if: failure()
uses: actions/upload-artifact@v7
with:
name: proxy-stack-logs
path: /tmp/stack.log
retention-days: 7

ci:
name: CI
needs: [backend-tests, simulator-lint, frontend, e2e-tests]
needs: [backend-tests, simulator-lint, frontend, e2e-tests, e2e-proxy]
if: always()
runs-on: ubuntu-latest
steps:
Expand All @@ -296,7 +401,8 @@ jobs:
if [[ "${{ needs.backend-tests.result }}" != "success" ]] \
|| [[ "${{ needs.simulator-lint.result }}" != "success" ]] \
|| [[ "${{ needs.frontend.result }}" != "success" ]] \
|| [[ "${{ needs.e2e-tests.result }}" != "success" ]]; then
|| [[ "${{ needs.e2e-tests.result }}" != "success" ]] \
|| [[ "${{ needs.e2e-proxy.result }}" != "success" ]]; then
echo "One or more required jobs failed or were skipped."
exit 1
fi
45 changes: 45 additions & 0 deletions E2E_TESTING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,50 @@
# E2E Testing Guide

There are two e2e setups:

1. **Mock-based tests** (most specs under `tests/e2e/`): run the real Next.js
frontend and stub the GraphQL/OIDC network boundary. Fast, deterministic,
no backend required.
2. **Proxied full-stack tests** (`tests/e2e/proxy-fullstack.spec.ts`): run the
production-like docker-compose stack — nginx proxy in front of web, backend
and Keycloak — built from the current commit's Docker images. These catch
routing issues (`/graphql`, `/keycloak/...`, `/auth/callback`) and verify
filtering/sorting against the real query engine.

## Running the Proxied Full-Stack Tests

1. **Build the images for your commit** (or use published ones):
```bash
docker build -t local/tasks-backend:e2e backend
docker build -t local/tasks-web:e2e web
docker build -t local/tasks-proxy:e2e proxy
```

2. **Start the stack** (ephemeral, no persistent volumes):
```bash
BACKEND_IMAGE=local/tasks-backend:e2e \
WEB_IMAGE=local/tasks-web:e2e \
PROXY_IMAGE=local/tasks-proxy:e2e \
docker compose -f docker-compose.e2e.yml up -d
```

3. **Wait for readiness** (Keycloak realm import takes a while):
```bash
curl -fs http://localhost/keycloak/realms/tasks/.well-known/openid-configuration
curl -fs http://localhost/
```

4. **Run the tests against the proxy**:
```bash
cd tests
E2E_PROXY_TARGET=1 E2E_BASE_URL=http://localhost npx playwright test e2e/proxy-fullstack.spec.ts
```

The `E2E_PROXY_TARGET=1` gate keeps these tests skipped during the mock-based
runs. In CI the `e2e-proxy` job (`.github/workflows/tests.yml`) performs these
steps automatically, rebuilding the commit's images from the shared Buildx
cache of the Docker Build workflow.

## Running E2E Tests Locally

### Prerequisites
Expand Down
Empty file added backend/api/export/__init__.py
Empty file.
Loading
Loading