Skip to content

frontend unit+e2e tests #5

frontend unit+e2e tests

frontend unit+e2e tests #5

Workflow file for this run

name: Frontend Tests
on:
push:
branches: [main, dev]
paths:
- 'frontend/**'
- '.github/workflows/frontend-tests.yml'
pull_request:
branches: [main, dev]
paths:
- 'frontend/**'
- '.github/workflows/frontend-tests.yml'
workflow_dispatch:
jobs:
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
defaults:
run:
working-directory: frontend
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install dependencies
run: npm ci
- name: Run unit tests
run: npm test
- name: Run tests with coverage
run: npm run test:coverage
- name: Upload coverage report
uses: actions/upload-artifact@v4
if: always()
with:
name: frontend-coverage
path: frontend/coverage/
e2e-tests:
name: E2E Tests
runs-on: ubuntu-latest
needs: unit-tests
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
- name: Install frontend dependencies
working-directory: frontend
run: npm ci
- name: Install Playwright browsers
working-directory: frontend
run: npx playwright install chromium
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Install yq
run: |
sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/local/bin/yq
sudo chmod +x /usr/local/bin/yq
- name: Setup Kubernetes (k3s)
run: |
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable=traefik --tls-san host.docker.internal" sh -
mkdir -p $HOME/.kube
sudo k3s kubectl config view --raw > $HOME/.kube/config
sudo chmod 600 $HOME/.kube/config
timeout 90 bash -c 'until sudo k3s kubectl cluster-info; do sleep 5; done'
- name: Create kubeconfig for CI
run: |
cat > backend/kubeconfig.yaml <<EOF
apiVersion: v1
kind: Config
clusters:
- name: ci-cluster
cluster:
server: https://host.docker.internal:6443
insecure-skip-tls-verify: true
users:
- name: ci-user
user:
token: "ci-token"
contexts:
- name: ci
context:
cluster: ci-cluster
user: ci-user
current-context: ci
EOF
- name: Pre-pull base images
run: |
docker pull python:3.12-slim &
docker pull ghcr.io/astral-sh/uv:0.9.18 &
docker pull node:22-alpine &
docker pull confluentinc/cp-kafka:7.5.0 &
docker pull confluentinc/cp-zookeeper:7.5.0 &
docker pull mongo:8.0 &
docker pull redis:7-alpine &
wait
- name: Modify Docker Compose for CI
run: |
cp docker-compose.yaml docker-compose.ci.yaml
yq eval '.services.backend.environment += ["TESTING=true"]' -i docker-compose.ci.yaml
yq eval '.services.backend.environment += ["MONGO_ROOT_USER=root"]' -i docker-compose.ci.yaml
yq eval '.services.backend.environment += ["MONGO_ROOT_PASSWORD=rootpassword"]' -i docker-compose.ci.yaml
yq eval '.services.backend.environment += ["OTEL_SDK_DISABLED=true"]' -i docker-compose.ci.yaml
yq eval '.services.backend.volumes = [.services.backend.volumes[] | select(. != "./backend:/app")]' -i docker-compose.ci.yaml
yq eval '.services."k8s-worker".volumes = [.services."k8s-worker".volumes[] | select(. != "./backend:/app:ro")]' -i docker-compose.ci.yaml
yq eval '.services."pod-monitor".volumes = [.services."pod-monitor".volumes[] | select(. != "./backend:/app:ro")]' -i docker-compose.ci.yaml
yq eval '.services."result-processor".volumes = [.services."result-processor".volumes[] | select(. != "./backend:/app:ro")]' -i docker-compose.ci.yaml
yq eval 'del(.services.kafka.environment.KAFKA_OPTS)' -i docker-compose.ci.yaml
yq eval 'del(.services.zookeeper.environment.KAFKA_OPTS)' -i docker-compose.ci.yaml
yq eval 'del(.services.zookeeper.environment.ZOOKEEPER_AUTH_PROVIDER_1)' -i docker-compose.ci.yaml
yq eval '.services.kafka.volumes = [.services.kafka.volumes[] | select(. | contains("jaas.conf") | not)]' -i docker-compose.ci.yaml
yq eval '.services.zookeeper.volumes = [.services.zookeeper.volumes[] | select(. | contains("/etc/kafka") | not)]' -i docker-compose.ci.yaml
yq eval '.services.zookeeper.environment.ZOOKEEPER_4LW_COMMANDS_WHITELIST = "ruok,srvr"' -i docker-compose.ci.yaml
yq eval 'del(.services.zookeeper.healthcheck)' -i docker-compose.ci.yaml
yq eval '.services.kafka.depends_on.zookeeper.condition = "service_started"' -i docker-compose.ci.yaml
yq eval 'select(.services."cert-generator".extra_hosts == null).services."cert-generator".extra_hosts = []' -i docker-compose.ci.yaml
yq eval '.services."cert-generator".extra_hosts += ["host.docker.internal:host-gateway"]' -i docker-compose.ci.yaml
yq eval '.services."cert-generator".environment += ["CI=true"]' -i docker-compose.ci.yaml
yq eval '.services."cert-generator".volumes += [env(HOME) + "/.kube/config:/root/.kube/config:ro"]' -i docker-compose.ci.yaml
- name: Build services
uses: docker/bake-action@v6
with:
source: .
files: docker-compose.ci.yaml
load: true
set: |
*.cache-from=type=gha,scope=buildkit-${{ github.repository }}-${{ github.ref_name }}
*.cache-from=type=gha,scope=buildkit-${{ github.repository }}-main
*.cache-to=type=gha,mode=max,scope=buildkit-${{ github.repository }}-${{ github.ref_name }}
env:
BUILDKIT_PROGRESS: plain
- name: Start services
run: |
docker compose -f docker-compose.ci.yaml up -d --remove-orphans
docker compose -f docker-compose.ci.yaml ps
- name: Wait for backend
run: |
curl --retry 60 --retry-delay 5 --retry-all-errors -ksf https://127.0.0.1:443/api/v1/health/live
- name: Wait for frontend
run: |
curl --retry 30 --retry-delay 5 --retry-all-errors -ksf https://127.0.0.1:5001/ || true
- name: Run E2E tests
working-directory: frontend
env:
CI: true
run: npx playwright test --reporter=html
- name: Upload Playwright report
uses: actions/upload-artifact@v4
if: always()
with:
name: playwright-report
path: frontend/playwright-report/
- name: Collect logs on failure
if: failure()
run: |
mkdir -p logs
docker compose -f docker-compose.ci.yaml logs > logs/docker-compose.log
docker compose -f docker-compose.ci.yaml logs frontend > logs/frontend.log
docker compose -f docker-compose.ci.yaml logs backend > logs/backend.log
- name: Upload logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: e2e-test-logs
path: logs/