chore(e2e): implement Phase 6 integration testing with agent skills
Complete Phase 6 of Playwright E2E testing plan with comprehensive integration tests covering cross-feature workflows and system integration. Integration Tests Added: proxy-acl-integration.spec.ts - ACL with proxy host integration proxy-certificate.spec.ts - SSL certificate lifecycle tests proxy-dns-integration.spec.ts - DNS challenge provider integration security-suite-integration.spec.ts - Cerberus security suite tests backup-restore-e2e.spec.ts - Full backup/restore workflow import-to-production.spec.ts - Caddyfile/CrowdSec import flows multi-feature-workflows.spec.ts - Complex multi-step scenarios Agent Skills Created: docker-rebuild-e2e.SKILL.md - Rebuild E2E Docker environment test-e2e-playwright-debug.SKILL.md - Run/debug Playwright tests Supporting scripts for skill execution Test Infrastructure Improvements: TestDataManager for namespace-based test isolation Fixed route paths: /backups → /tasks/backups Domain uniqueness via UUID namespacing Improved selector reliability with role-based queries Results: 648 tests passing, 98 skipped, 97.5% statement coverage
This commit is contained in:
@@ -37,6 +37,9 @@ Agent Skills are self-documenting, AI-discoverable task definitions that combine
|
||||
| [test-backend-unit](./test-backend-unit.SKILL.md) | test | Run fast Go unit tests without coverage | ✅ Active |
|
||||
| [test-frontend-coverage](./test-frontend-coverage.SKILL.md) | test | Run frontend tests with coverage reporting | ✅ Active |
|
||||
| [test-frontend-unit](./test-frontend-unit.SKILL.md) | test | Run fast frontend unit tests without coverage | ✅ Active |
|
||||
| [test-e2e-playwright](./test-e2e-playwright.SKILL.md) | test | Run Playwright E2E tests with browser selection | ✅ Active |
|
||||
| [test-e2e-playwright-debug](./test-e2e-playwright-debug.SKILL.md) | test | Run E2E tests in headed/debug mode for troubleshooting | ✅ Active |
|
||||
| [test-e2e-playwright-coverage](./test-e2e-playwright-coverage.SKILL.md) | test | Run E2E tests with coverage collection | ✅ Active |
|
||||
|
||||
### Integration Testing Skills
|
||||
|
||||
@@ -76,6 +79,7 @@ Agent Skills are self-documenting, AI-discoverable task definitions that combine
|
||||
|------------|----------|-------------|--------|
|
||||
| [docker-start-dev](./docker-start-dev.SKILL.md) | docker | Start development Docker Compose environment | ✅ Active |
|
||||
| [docker-stop-dev](./docker-stop-dev.SKILL.md) | docker | Stop development Docker Compose environment | ✅ Active |
|
||||
| [docker-rebuild-e2e](./docker-rebuild-e2e.SKILL.md) | docker | Rebuild Docker image and restart E2E Playwright container | ✅ Active |
|
||||
| [docker-prune](./docker-prune.SKILL.md) | docker | Clean up unused Docker resources | ✅ Active |
|
||||
|
||||
## Usage
|
||||
|
||||
+314
@@ -0,0 +1,314 @@
|
||||
#!/usr/bin/env bash
|
||||
# Docker: Rebuild E2E Environment - Execution Script
|
||||
#
|
||||
# Rebuilds the Docker image and restarts the Playwright E2E testing
|
||||
# environment with fresh code and optionally clean state.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Source helper scripts
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SKILLS_SCRIPTS_DIR="$(cd "${SCRIPT_DIR}/../scripts" && pwd)"
|
||||
|
||||
# shellcheck source=../scripts/_logging_helpers.sh
|
||||
source "${SKILLS_SCRIPTS_DIR}/_logging_helpers.sh"
|
||||
# shellcheck source=../scripts/_error_handling_helpers.sh
|
||||
source "${SKILLS_SCRIPTS_DIR}/_error_handling_helpers.sh"
|
||||
# shellcheck source=../scripts/_environment_helpers.sh
|
||||
source "${SKILLS_SCRIPTS_DIR}/_environment_helpers.sh"
|
||||
|
||||
# Project root is 3 levels up from this script
|
||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
|
||||
|
||||
# Docker compose file for Playwright E2E tests
|
||||
COMPOSE_FILE=".docker/compose/docker-compose.playwright.yml"
|
||||
CONTAINER_NAME="charon-playwright"
|
||||
IMAGE_NAME="charon:local"
|
||||
HEALTH_TIMEOUT=60
|
||||
HEALTH_INTERVAL=5
|
||||
|
||||
# Default parameter values
|
||||
NO_CACHE=false
|
||||
CLEAN=false
|
||||
PROFILE=""
|
||||
|
||||
# Parse command-line arguments
|
||||
parse_arguments() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--no-cache)
|
||||
NO_CACHE=true
|
||||
shift
|
||||
;;
|
||||
--clean)
|
||||
CLEAN=true
|
||||
shift
|
||||
;;
|
||||
--profile=*)
|
||||
PROFILE="${1#*=}"
|
||||
shift
|
||||
;;
|
||||
--profile)
|
||||
PROFILE="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
log_warning "Unknown argument: $1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Show help message
|
||||
show_help() {
|
||||
cat << EOF
|
||||
Usage: run.sh [OPTIONS]
|
||||
|
||||
Rebuild Docker image and restart E2E Playwright container.
|
||||
|
||||
Options:
|
||||
--no-cache Force rebuild without Docker cache
|
||||
--clean Remove test volumes for fresh state
|
||||
--profile=PROFILE Docker Compose profile to enable
|
||||
(security-tests, notification-tests)
|
||||
-h, --help Show this help message
|
||||
|
||||
Environment Variables:
|
||||
DOCKER_NO_CACHE Force rebuild without cache (default: false)
|
||||
SKIP_VOLUME_CLEANUP Preserve test data volumes (default: false)
|
||||
|
||||
Examples:
|
||||
run.sh # Standard rebuild
|
||||
run.sh --no-cache # Force complete rebuild
|
||||
run.sh --clean # Rebuild with fresh volumes
|
||||
run.sh --profile=security-tests # Enable CrowdSec for testing
|
||||
run.sh --no-cache --clean # Complete fresh rebuild
|
||||
EOF
|
||||
}
|
||||
|
||||
# Stop existing containers
|
||||
stop_containers() {
|
||||
log_step "STOP" "Stopping existing E2E containers"
|
||||
|
||||
local compose_cmd="docker compose -f ${COMPOSE_FILE}"
|
||||
|
||||
# Add profile if specified
|
||||
if [[ -n "${PROFILE}" ]]; then
|
||||
compose_cmd="${compose_cmd} --profile ${PROFILE}"
|
||||
fi
|
||||
|
||||
# Stop and remove containers
|
||||
if ${compose_cmd} ps -q 2>/dev/null | grep -q .; then
|
||||
log_info "Stopping containers..."
|
||||
${compose_cmd} down --remove-orphans || true
|
||||
else
|
||||
log_info "No running containers to stop"
|
||||
fi
|
||||
}
|
||||
|
||||
# Clean volumes if requested
|
||||
clean_volumes() {
|
||||
if [[ "${CLEAN}" != "true" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
if [[ "${SKIP_VOLUME_CLEANUP:-false}" == "true" ]]; then
|
||||
log_warning "Skipping volume cleanup (SKIP_VOLUME_CLEANUP=true)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
log_step "CLEAN" "Removing test volumes"
|
||||
|
||||
local volumes=(
|
||||
"playwright_data"
|
||||
"playwright_caddy_data"
|
||||
"playwright_caddy_config"
|
||||
"playwright_crowdsec_data"
|
||||
"playwright_crowdsec_config"
|
||||
)
|
||||
|
||||
for vol in "${volumes[@]}"; do
|
||||
# Try both prefixed and unprefixed volume names
|
||||
for prefix in "compose_" ""; do
|
||||
local full_name="${prefix}${vol}"
|
||||
if docker volume inspect "${full_name}" &>/dev/null; then
|
||||
log_info "Removing volume: ${full_name}"
|
||||
docker volume rm "${full_name}" || true
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
log_success "Volumes cleaned"
|
||||
}
|
||||
|
||||
# Build Docker image
|
||||
build_image() {
|
||||
log_step "BUILD" "Building Docker image: ${IMAGE_NAME}"
|
||||
|
||||
local build_args=("-t" "${IMAGE_NAME}" ".")
|
||||
|
||||
if [[ "${NO_CACHE}" == "true" ]] || [[ "${DOCKER_NO_CACHE:-false}" == "true" ]]; then
|
||||
log_info "Building with --no-cache"
|
||||
build_args=("--no-cache" "${build_args[@]}")
|
||||
fi
|
||||
|
||||
log_command "docker build ${build_args[*]}"
|
||||
|
||||
if ! docker build "${build_args[@]}"; then
|
||||
error_exit "Docker build failed"
|
||||
fi
|
||||
|
||||
log_success "Image built successfully: ${IMAGE_NAME}"
|
||||
}
|
||||
|
||||
# Start containers
|
||||
start_containers() {
|
||||
log_step "START" "Starting E2E containers"
|
||||
|
||||
local compose_cmd="docker compose -f ${COMPOSE_FILE}"
|
||||
|
||||
# Add profile if specified
|
||||
if [[ -n "${PROFILE}" ]]; then
|
||||
log_info "Enabling profile: ${PROFILE}"
|
||||
compose_cmd="${compose_cmd} --profile ${PROFILE}"
|
||||
fi
|
||||
|
||||
log_command "${compose_cmd} up -d"
|
||||
|
||||
if ! ${compose_cmd} up -d; then
|
||||
error_exit "Failed to start containers"
|
||||
fi
|
||||
|
||||
log_success "Containers started"
|
||||
}
|
||||
|
||||
# Wait for container health
|
||||
wait_for_health() {
|
||||
log_step "HEALTH" "Waiting for container to be healthy"
|
||||
|
||||
local elapsed=0
|
||||
local healthy=false
|
||||
|
||||
while [[ ${elapsed} -lt ${HEALTH_TIMEOUT} ]]; do
|
||||
local health_status
|
||||
health_status=$(docker inspect --format='{{.State.Health.Status}}' "${CONTAINER_NAME}" 2>/dev/null || echo "unknown")
|
||||
|
||||
case "${health_status}" in
|
||||
healthy)
|
||||
healthy=true
|
||||
break
|
||||
;;
|
||||
unhealthy)
|
||||
log_error "Container is unhealthy"
|
||||
docker logs "${CONTAINER_NAME}" --tail 20
|
||||
error_exit "Container health check failed"
|
||||
;;
|
||||
starting)
|
||||
log_info "Health status: starting (${elapsed}s/${HEALTH_TIMEOUT}s)"
|
||||
;;
|
||||
*)
|
||||
log_info "Health status: ${health_status} (${elapsed}s/${HEALTH_TIMEOUT}s)"
|
||||
;;
|
||||
esac
|
||||
|
||||
sleep "${HEALTH_INTERVAL}"
|
||||
elapsed=$((elapsed + HEALTH_INTERVAL))
|
||||
done
|
||||
|
||||
if [[ "${healthy}" != "true" ]]; then
|
||||
log_error "Container did not become healthy in ${HEALTH_TIMEOUT}s"
|
||||
docker logs "${CONTAINER_NAME}" --tail 50
|
||||
error_exit "Health check timeout"
|
||||
fi
|
||||
|
||||
log_success "Container is healthy"
|
||||
}
|
||||
|
||||
# Verify environment
|
||||
verify_environment() {
|
||||
log_step "VERIFY" "Verifying E2E environment"
|
||||
|
||||
# Check container is running
|
||||
if ! docker ps --filter "name=${CONTAINER_NAME}" --format "{{.Names}}" | grep -q "${CONTAINER_NAME}"; then
|
||||
error_exit "Container ${CONTAINER_NAME} is not running"
|
||||
fi
|
||||
|
||||
# Test health endpoint
|
||||
log_info "Testing health endpoint..."
|
||||
if curl -sf http://localhost:8080/api/v1/health &>/dev/null; then
|
||||
log_success "Health endpoint responding"
|
||||
else
|
||||
log_warning "Health endpoint not responding (may need more time)"
|
||||
fi
|
||||
|
||||
# Show container status
|
||||
log_info "Container status:"
|
||||
docker ps --filter "name=charon-playwright" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
||||
}
|
||||
|
||||
# Show summary
|
||||
show_summary() {
|
||||
log_step "SUMMARY" "E2E environment ready"
|
||||
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo " E2E Environment Ready"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo ""
|
||||
echo " Application URL: http://localhost:8080"
|
||||
echo " Health Check: http://localhost:8080/api/v1/health"
|
||||
echo " Container: ${CONTAINER_NAME}"
|
||||
echo ""
|
||||
echo " Run E2E tests:"
|
||||
echo " .github/skills/scripts/skill-runner.sh test-e2e-playwright"
|
||||
echo ""
|
||||
echo " Run in debug mode:"
|
||||
echo " .github/skills/scripts/skill-runner.sh test-e2e-playwright-debug"
|
||||
echo ""
|
||||
echo " View logs:"
|
||||
echo " docker logs ${CONTAINER_NAME} -f"
|
||||
echo ""
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
parse_arguments "$@"
|
||||
|
||||
# Validate environment
|
||||
log_step "ENVIRONMENT" "Validating prerequisites"
|
||||
validate_docker_environment || error_exit "Docker is not available"
|
||||
check_command_exists "docker" "Docker is required"
|
||||
|
||||
# Validate project structure
|
||||
log_step "VALIDATION" "Checking project structure"
|
||||
cd "${PROJECT_ROOT}"
|
||||
check_file_exists "Dockerfile" "Dockerfile is required"
|
||||
check_file_exists "${COMPOSE_FILE}" "Playwright compose file is required"
|
||||
|
||||
# Log configuration
|
||||
log_step "CONFIG" "Rebuild configuration"
|
||||
log_info "No cache: ${NO_CACHE}"
|
||||
log_info "Clean volumes: ${CLEAN}"
|
||||
log_info "Profile: ${PROFILE:-<none>}"
|
||||
log_info "Compose file: ${COMPOSE_FILE}"
|
||||
|
||||
# Execute rebuild steps
|
||||
stop_containers
|
||||
clean_volumes
|
||||
build_image
|
||||
start_containers
|
||||
wait_for_health
|
||||
verify_environment
|
||||
show_summary
|
||||
|
||||
log_success "E2E environment rebuild complete"
|
||||
}
|
||||
|
||||
# Run main with all arguments
|
||||
main "$@"
|
||||
@@ -0,0 +1,300 @@
|
||||
---
|
||||
# agentskills.io specification v1.0
|
||||
name: "docker-rebuild-e2e"
|
||||
version: "1.0.0"
|
||||
description: "Rebuild Docker image and restart E2E Playwright container with fresh code and clean state"
|
||||
author: "Charon Project"
|
||||
license: "MIT"
|
||||
tags:
|
||||
- "docker"
|
||||
- "e2e"
|
||||
- "playwright"
|
||||
- "rebuild"
|
||||
- "testing"
|
||||
compatibility:
|
||||
os:
|
||||
- "linux"
|
||||
- "darwin"
|
||||
shells:
|
||||
- "bash"
|
||||
requirements:
|
||||
- name: "docker"
|
||||
version: ">=24.0"
|
||||
optional: false
|
||||
- name: "docker-compose"
|
||||
version: ">=2.0"
|
||||
optional: false
|
||||
environment_variables:
|
||||
- name: "DOCKER_NO_CACHE"
|
||||
description: "Set to 'true' to force a complete rebuild without cache"
|
||||
default: "false"
|
||||
required: false
|
||||
- name: "SKIP_VOLUME_CLEANUP"
|
||||
description: "Set to 'true' to preserve test data volumes"
|
||||
default: "false"
|
||||
required: false
|
||||
parameters:
|
||||
- name: "no-cache"
|
||||
type: "boolean"
|
||||
description: "Force rebuild without Docker cache"
|
||||
default: "false"
|
||||
required: false
|
||||
- name: "clean"
|
||||
type: "boolean"
|
||||
description: "Remove test volumes for a completely fresh state"
|
||||
default: "false"
|
||||
required: false
|
||||
- name: "profile"
|
||||
type: "string"
|
||||
description: "Docker Compose profile to enable (security-tests, notification-tests)"
|
||||
default: ""
|
||||
required: false
|
||||
outputs:
|
||||
- name: "exit_code"
|
||||
type: "integer"
|
||||
description: "0 on success, non-zero on failure"
|
||||
metadata:
|
||||
category: "docker"
|
||||
subcategory: "e2e"
|
||||
execution_time: "long"
|
||||
risk_level: "low"
|
||||
ci_cd_safe: true
|
||||
requires_network: true
|
||||
idempotent: true
|
||||
---
|
||||
|
||||
# Docker: Rebuild E2E Environment
|
||||
|
||||
## Overview
|
||||
|
||||
Rebuilds the Charon Docker image and restarts the Playwright E2E testing environment with fresh code. This skill handles the complete lifecycle: stopping existing containers, optionally cleaning volumes, rebuilding the image, and starting fresh containers with health check verification.
|
||||
|
||||
**Use this skill when:**
|
||||
- You've made code changes and need to test them in E2E tests
|
||||
- E2E tests are failing due to stale container state
|
||||
- You need a clean slate for debugging
|
||||
- The container is in an inconsistent state
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Docker Engine installed and running
|
||||
- Docker Compose V2 installed
|
||||
- Dockerfile in repository root
|
||||
- `.docker/compose/docker-compose.playwright.yml` file
|
||||
- Network access for pulling base images (if needed)
|
||||
- Sufficient disk space for image rebuild
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
Rebuild image and restart E2E container:
|
||||
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e
|
||||
```
|
||||
|
||||
### Force Rebuild (No Cache)
|
||||
|
||||
Rebuild from scratch without Docker cache:
|
||||
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e --no-cache
|
||||
```
|
||||
|
||||
### Clean Rebuild
|
||||
|
||||
Remove test volumes and rebuild with fresh state:
|
||||
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e --clean
|
||||
```
|
||||
|
||||
### With Security Testing Services
|
||||
|
||||
Enable CrowdSec for security testing:
|
||||
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e --profile=security-tests
|
||||
```
|
||||
|
||||
### With Notification Testing Services
|
||||
|
||||
Enable MailHog for email testing:
|
||||
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e --profile=notification-tests
|
||||
```
|
||||
|
||||
### Full Clean Rebuild with All Services
|
||||
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e --no-cache --clean --profile=security-tests
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Required | Default | Description |
|
||||
|-----------|------|----------|---------|-------------|
|
||||
| no-cache | boolean | No | false | Force rebuild without Docker cache |
|
||||
| clean | boolean | No | false | Remove test volumes for fresh state |
|
||||
| profile | string | No | "" | Docker Compose profile to enable |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| DOCKER_NO_CACHE | No | false | Force rebuild without cache |
|
||||
| SKIP_VOLUME_CLEANUP | No | false | Preserve test data volumes |
|
||||
|
||||
## What This Skill Does
|
||||
|
||||
1. **Stop Existing Containers**: Gracefully stops any running Playwright containers
|
||||
2. **Clean Volumes** (if `--clean`): Removes test data volumes for fresh state
|
||||
3. **Rebuild Image**: Builds `charon:local` image from Dockerfile
|
||||
4. **Start Containers**: Starts the Playwright compose environment
|
||||
5. **Wait for Health**: Verifies container health before returning
|
||||
6. **Report Status**: Outputs container status and connection info
|
||||
|
||||
## Docker Compose Configuration
|
||||
|
||||
This skill uses `.docker/compose/docker-compose.playwright.yml` which includes:
|
||||
|
||||
- **charon-app**: Main application container on port 8080
|
||||
- **crowdsec** (profile: security-tests): Security bouncer for WAF testing
|
||||
- **mailhog** (profile: notification-tests): Email testing service
|
||||
|
||||
### Volumes Created
|
||||
|
||||
| Volume | Purpose |
|
||||
|--------|---------|
|
||||
| playwright_data | Application data and SQLite database |
|
||||
| playwright_caddy_data | Caddy server data |
|
||||
| playwright_caddy_config | Caddy configuration |
|
||||
| playwright_crowdsec_data | CrowdSec data (if enabled) |
|
||||
| playwright_crowdsec_config | CrowdSec config (if enabled) |
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: Quick Rebuild After Code Change
|
||||
|
||||
```bash
|
||||
# Rebuild and restart after making backend changes
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e
|
||||
|
||||
# Run E2E tests
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright
|
||||
```
|
||||
|
||||
### Example 2: Debug Failing Tests with Clean State
|
||||
|
||||
```bash
|
||||
# Complete clean rebuild
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e --clean --no-cache
|
||||
|
||||
# Run specific test in debug mode
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug --grep="failing-test"
|
||||
```
|
||||
|
||||
### Example 3: Test Security Features
|
||||
|
||||
```bash
|
||||
# Start with CrowdSec enabled
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e --profile=security-tests
|
||||
|
||||
# Run security-related E2E tests
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright --grep="security"
|
||||
```
|
||||
|
||||
## Health Check Verification
|
||||
|
||||
After starting, the skill waits for the health check to pass:
|
||||
|
||||
```bash
|
||||
# Health endpoint checked
|
||||
curl -sf http://localhost:8080/api/v1/health
|
||||
```
|
||||
|
||||
The skill will:
|
||||
- Wait up to 60 seconds for container to be healthy
|
||||
- Check every 5 seconds
|
||||
- Report final health status
|
||||
- Exit with error if health check fails
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Docker Build Failed
|
||||
```
|
||||
Error: docker build failed
|
||||
```
|
||||
**Solution**: Check Dockerfile syntax, ensure all COPY sources exist
|
||||
|
||||
#### Port Already in Use
|
||||
```
|
||||
Error: bind: address already in use
|
||||
```
|
||||
**Solution**: Stop conflicting services on port 8080
|
||||
|
||||
#### Health Check Timeout
|
||||
```
|
||||
Error: Container did not become healthy in 60s
|
||||
```
|
||||
**Solution**: Check container logs with `docker logs charon-playwright`
|
||||
|
||||
#### Volume Permission Issues
|
||||
```
|
||||
Error: permission denied
|
||||
```
|
||||
**Solution**: Run with `--clean` to recreate volumes with proper permissions
|
||||
|
||||
## Verifying the Environment
|
||||
|
||||
After the skill completes, verify the environment:
|
||||
|
||||
```bash
|
||||
# Check container status
|
||||
docker ps --filter "name=charon-playwright"
|
||||
|
||||
# Check logs
|
||||
docker logs charon-playwright --tail 50
|
||||
|
||||
# Test health endpoint
|
||||
curl http://localhost:8080/api/v1/health
|
||||
|
||||
# Check database state
|
||||
docker exec charon-playwright sqlite3 /app/data/charon.db ".tables"
|
||||
```
|
||||
|
||||
## Related Skills
|
||||
|
||||
- [test-e2e-playwright](./test-e2e-playwright.SKILL.md) - Run E2E tests
|
||||
- [test-e2e-playwright-debug](./test-e2e-playwright-debug.SKILL.md) - Debug E2E tests
|
||||
- [docker-start-dev](./docker-start-dev.SKILL.md) - Start development environment
|
||||
- [docker-stop-dev](./docker-stop-dev.SKILL.md) - Stop development environment
|
||||
- [docker-prune](./docker-prune.SKILL.md) - Clean up Docker resources
|
||||
|
||||
## Key File Locations
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `Dockerfile` | Main application Dockerfile |
|
||||
| `.docker/compose/docker-compose.playwright.yml` | E2E test compose config |
|
||||
| `playwright.config.js` | Playwright test configuration |
|
||||
| `tests/` | E2E test files |
|
||||
| `playwright/.auth/user.json` | Stored authentication state |
|
||||
|
||||
## Notes
|
||||
|
||||
- **Build Time**: Full rebuild takes 2-5 minutes depending on cache
|
||||
- **Disk Space**: Image is ~500MB, volumes add ~100MB
|
||||
- **Network**: Base images may need to be pulled on first run
|
||||
- **Idempotent**: Safe to run multiple times
|
||||
- **CI/CD Safe**: Designed for use in automated pipelines
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2026-01-21
|
||||
**Maintained by**: Charon Project Team
|
||||
**Compose File**: `.docker/compose/docker-compose.playwright.yml`
|
||||
+289
@@ -0,0 +1,289 @@
|
||||
#!/usr/bin/env bash
|
||||
# Test E2E Playwright Debug - Execution Script
|
||||
#
|
||||
# Runs Playwright E2E tests in headed/debug mode with slow motion,
|
||||
# optional Inspector, and trace collection for troubleshooting.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# Source helper scripts
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SKILLS_SCRIPTS_DIR="$(cd "${SCRIPT_DIR}/../scripts" && pwd)"
|
||||
|
||||
# shellcheck source=../scripts/_logging_helpers.sh
|
||||
source "${SKILLS_SCRIPTS_DIR}/_logging_helpers.sh"
|
||||
# shellcheck source=../scripts/_error_handling_helpers.sh
|
||||
source "${SKILLS_SCRIPTS_DIR}/_error_handling_helpers.sh"
|
||||
# shellcheck source=../scripts/_environment_helpers.sh
|
||||
source "${SKILLS_SCRIPTS_DIR}/_environment_helpers.sh"
|
||||
|
||||
# Project root is 3 levels up from this script
|
||||
PROJECT_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)"
|
||||
|
||||
# Default parameter values
|
||||
FILE=""
|
||||
GREP=""
|
||||
SLOWMO=500
|
||||
INSPECTOR=false
|
||||
PROJECT="chromium"
|
||||
|
||||
# Parse command-line arguments
|
||||
parse_arguments() {
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case "$1" in
|
||||
--file=*)
|
||||
FILE="${1#*=}"
|
||||
shift
|
||||
;;
|
||||
--file)
|
||||
FILE="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--grep=*)
|
||||
GREP="${1#*=}"
|
||||
shift
|
||||
;;
|
||||
--grep)
|
||||
GREP="${2:-}"
|
||||
shift 2
|
||||
;;
|
||||
--slowmo=*)
|
||||
SLOWMO="${1#*=}"
|
||||
shift
|
||||
;;
|
||||
--slowmo)
|
||||
SLOWMO="${2:-500}"
|
||||
shift 2
|
||||
;;
|
||||
--inspector)
|
||||
INSPECTOR=true
|
||||
shift
|
||||
;;
|
||||
--project=*)
|
||||
PROJECT="${1#*=}"
|
||||
shift
|
||||
;;
|
||||
--project)
|
||||
PROJECT="${2:-chromium}"
|
||||
shift 2
|
||||
;;
|
||||
-h|--help)
|
||||
show_help
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
log_warning "Unknown argument: $1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
}
|
||||
|
||||
# Show help message
|
||||
show_help() {
|
||||
cat << EOF
|
||||
Usage: run.sh [OPTIONS]
|
||||
|
||||
Run Playwright E2E tests in debug mode for troubleshooting.
|
||||
|
||||
Options:
|
||||
--file=FILE Specific test file to run (relative to tests/)
|
||||
--grep=PATTERN Filter tests by title pattern (regex)
|
||||
--slowmo=MS Delay between actions in milliseconds (default: 500)
|
||||
--inspector Open Playwright Inspector for step-by-step debugging
|
||||
--project=PROJECT Browser to use: chromium, firefox, webkit (default: chromium)
|
||||
-h, --help Show this help message
|
||||
|
||||
Environment Variables:
|
||||
PLAYWRIGHT_BASE_URL Application URL to test (default: http://localhost:8080)
|
||||
PWDEBUG Set to '1' for Inspector mode
|
||||
DEBUG Verbose logging (e.g., 'pw:api')
|
||||
|
||||
Examples:
|
||||
run.sh # Debug all tests in Chromium
|
||||
run.sh --file=login.spec.ts # Debug specific file
|
||||
run.sh --grep="login" # Debug tests matching pattern
|
||||
run.sh --inspector # Open Playwright Inspector
|
||||
run.sh --slowmo=1000 # Slower execution
|
||||
run.sh --file=test.spec.ts --inspector # Combine options
|
||||
EOF
|
||||
}
|
||||
|
||||
# Validate project parameter
|
||||
validate_project() {
|
||||
local valid_projects=("chromium" "firefox" "webkit")
|
||||
local project_lower
|
||||
project_lower=$(echo "${PROJECT}" | tr '[:upper:]' '[:lower:]')
|
||||
|
||||
for valid in "${valid_projects[@]}"; do
|
||||
if [[ "${project_lower}" == "${valid}" ]]; then
|
||||
PROJECT="${project_lower}"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
|
||||
error_exit "Invalid project '${PROJECT}'. Valid options: chromium, firefox, webkit"
|
||||
}
|
||||
|
||||
# Validate test file if specified
|
||||
validate_test_file() {
|
||||
if [[ -z "${FILE}" ]]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
local test_path="${PROJECT_ROOT}/tests/${FILE}"
|
||||
|
||||
# Handle if user provided full path
|
||||
if [[ "${FILE}" == tests/* ]]; then
|
||||
test_path="${PROJECT_ROOT}/${FILE}"
|
||||
FILE="${FILE#tests/}"
|
||||
fi
|
||||
|
||||
if [[ ! -f "${test_path}" ]]; then
|
||||
log_error "Test file not found: ${test_path}"
|
||||
log_info "Available test files:"
|
||||
ls -1 "${PROJECT_ROOT}/tests/"*.spec.ts 2>/dev/null | xargs -n1 basename || true
|
||||
error_exit "Invalid test file"
|
||||
fi
|
||||
}
|
||||
|
||||
# Build Playwright command arguments
|
||||
build_playwright_args() {
|
||||
local args=()
|
||||
|
||||
# Always run headed in debug mode
|
||||
args+=("--headed")
|
||||
|
||||
# Add project
|
||||
args+=("--project=${PROJECT}")
|
||||
|
||||
# Add grep filter if specified
|
||||
if [[ -n "${GREP}" ]]; then
|
||||
args+=("--grep=${GREP}")
|
||||
fi
|
||||
|
||||
# Always collect traces in debug mode
|
||||
args+=("--trace=on")
|
||||
|
||||
# Run single worker for clarity
|
||||
args+=("--workers=1")
|
||||
|
||||
# No retries in debug mode
|
||||
args+=("--retries=0")
|
||||
|
||||
echo "${args[*]}"
|
||||
}
|
||||
|
||||
# Main execution
|
||||
main() {
|
||||
parse_arguments "$@"
|
||||
|
||||
# Validate environment
|
||||
log_step "ENVIRONMENT" "Validating prerequisites"
|
||||
validate_node_environment "18.0" || error_exit "Node.js 18+ is required"
|
||||
check_command_exists "npx" "npx is required (part of Node.js installation)"
|
||||
|
||||
# Validate project structure
|
||||
log_step "VALIDATION" "Checking project structure"
|
||||
cd "${PROJECT_ROOT}"
|
||||
validate_project_structure "tests" "playwright.config.js" "package.json" || error_exit "Invalid project structure"
|
||||
|
||||
# Validate parameters
|
||||
validate_project
|
||||
validate_test_file
|
||||
|
||||
# Set environment variables
|
||||
export PLAYWRIGHT_HTML_OPEN="${PLAYWRIGHT_HTML_OPEN:-never}"
|
||||
set_default_env "PLAYWRIGHT_BASE_URL" "http://localhost:8080"
|
||||
|
||||
# Enable Inspector if requested
|
||||
if [[ "${INSPECTOR}" == "true" ]]; then
|
||||
export PWDEBUG=1
|
||||
log_info "Playwright Inspector enabled"
|
||||
fi
|
||||
|
||||
# Log configuration
|
||||
log_step "CONFIG" "Debug configuration"
|
||||
log_info "Project: ${PROJECT}"
|
||||
log_info "Test file: ${FILE:-<all tests>}"
|
||||
log_info "Grep filter: ${GREP:-<none>}"
|
||||
log_info "Slow motion: ${SLOWMO}ms"
|
||||
log_info "Inspector: ${INSPECTOR}"
|
||||
log_info "Base URL: ${PLAYWRIGHT_BASE_URL}"
|
||||
|
||||
# Build command arguments
|
||||
local playwright_args
|
||||
playwright_args=$(build_playwright_args)
|
||||
|
||||
# Determine test path
|
||||
local test_target=""
|
||||
if [[ -n "${FILE}" ]]; then
|
||||
test_target="tests/${FILE}"
|
||||
fi
|
||||
|
||||
# Build full command
|
||||
local full_cmd="npx playwright test ${playwright_args}"
|
||||
if [[ -n "${test_target}" ]]; then
|
||||
full_cmd="${full_cmd} ${test_target}"
|
||||
fi
|
||||
|
||||
# Add slowMo via environment (Playwright config reads this)
|
||||
export PLAYWRIGHT_SLOWMO="${SLOWMO}"
|
||||
|
||||
log_step "EXECUTION" "Running Playwright in debug mode"
|
||||
log_info "Slow motion: ${SLOWMO}ms delay between actions"
|
||||
log_info "Traces will be captured for all tests"
|
||||
echo ""
|
||||
log_command "${full_cmd}"
|
||||
echo ""
|
||||
|
||||
# Create a temporary config that includes slowMo
|
||||
local temp_config="${PROJECT_ROOT}/.playwright-debug-config.js"
|
||||
cat > "${temp_config}" << EOF
|
||||
// Temporary debug config - auto-generated
|
||||
import baseConfig from './playwright.config.js';
|
||||
|
||||
export default {
|
||||
...baseConfig,
|
||||
use: {
|
||||
...baseConfig.use,
|
||||
launchOptions: {
|
||||
slowMo: ${SLOWMO},
|
||||
},
|
||||
trace: 'on',
|
||||
},
|
||||
workers: 1,
|
||||
retries: 0,
|
||||
};
|
||||
EOF
|
||||
|
||||
# Run tests with temporary config
|
||||
local exit_code=0
|
||||
# shellcheck disable=SC2086
|
||||
if npx playwright test --config="${temp_config}" --headed --project="${PROJECT}" ${GREP:+--grep="${GREP}"} ${test_target}; then
|
||||
log_success "Debug tests completed successfully"
|
||||
else
|
||||
exit_code=$?
|
||||
log_warning "Debug tests completed with failures (exit code: ${exit_code})"
|
||||
fi
|
||||
|
||||
# Clean up temporary config
|
||||
rm -f "${temp_config}"
|
||||
|
||||
# Output helpful information
|
||||
log_step "ARTIFACTS" "Test artifacts"
|
||||
log_info "HTML Report: ${PROJECT_ROOT}/playwright-report/index.html"
|
||||
log_info "Test Results: ${PROJECT_ROOT}/test-results/"
|
||||
|
||||
# Show trace info if tests ran
|
||||
if [[ -d "${PROJECT_ROOT}/test-results" ]] && find "${PROJECT_ROOT}/test-results" -name "trace.zip" -type f 2>/dev/null | head -1 | grep -q .; then
|
||||
log_info ""
|
||||
log_info "View traces with:"
|
||||
log_info " npx playwright show-trace test-results/<test-name>/trace.zip"
|
||||
fi
|
||||
|
||||
exit "${exit_code}"
|
||||
}
|
||||
|
||||
# Run main with all arguments
|
||||
main "$@"
|
||||
@@ -0,0 +1,383 @@
|
||||
---
|
||||
# agentskills.io specification v1.0
|
||||
name: "test-e2e-playwright-debug"
|
||||
version: "1.0.0"
|
||||
description: "Run Playwright E2E tests in headed/debug mode for troubleshooting with slowMo and trace collection"
|
||||
author: "Charon Project"
|
||||
license: "MIT"
|
||||
tags:
|
||||
- "testing"
|
||||
- "e2e"
|
||||
- "playwright"
|
||||
- "debug"
|
||||
- "troubleshooting"
|
||||
compatibility:
|
||||
os:
|
||||
- "linux"
|
||||
- "darwin"
|
||||
shells:
|
||||
- "bash"
|
||||
requirements:
|
||||
- name: "node"
|
||||
version: ">=18.0"
|
||||
optional: false
|
||||
- name: "npx"
|
||||
version: ">=1.0"
|
||||
optional: false
|
||||
environment_variables:
|
||||
- name: "PLAYWRIGHT_BASE_URL"
|
||||
description: "Base URL of the Charon application under test"
|
||||
default: "http://localhost:8080"
|
||||
required: false
|
||||
- name: "PWDEBUG"
|
||||
description: "Enable Playwright Inspector (set to '1' for step-by-step debugging)"
|
||||
default: ""
|
||||
required: false
|
||||
- name: "DEBUG"
|
||||
description: "Enable verbose Playwright logging (e.g., 'pw:api')"
|
||||
default: ""
|
||||
required: false
|
||||
parameters:
|
||||
- name: "file"
|
||||
type: "string"
|
||||
description: "Specific test file to run (relative to tests/ directory)"
|
||||
default: ""
|
||||
required: false
|
||||
- name: "grep"
|
||||
type: "string"
|
||||
description: "Filter tests by title pattern (regex)"
|
||||
default: ""
|
||||
required: false
|
||||
- name: "slowmo"
|
||||
type: "number"
|
||||
description: "Slow down operations by specified milliseconds"
|
||||
default: "500"
|
||||
required: false
|
||||
- name: "inspector"
|
||||
type: "boolean"
|
||||
description: "Open Playwright Inspector for step-by-step debugging"
|
||||
default: "false"
|
||||
required: false
|
||||
- name: "project"
|
||||
type: "string"
|
||||
description: "Browser project to run (chromium, firefox, webkit)"
|
||||
default: "chromium"
|
||||
required: false
|
||||
outputs:
|
||||
- name: "playwright-report"
|
||||
type: "directory"
|
||||
description: "HTML test report directory"
|
||||
path: "playwright-report/"
|
||||
- name: "test-results"
|
||||
type: "directory"
|
||||
description: "Test artifacts, screenshots, and traces"
|
||||
path: "test-results/"
|
||||
metadata:
|
||||
category: "test"
|
||||
subcategory: "e2e-debug"
|
||||
execution_time: "variable"
|
||||
risk_level: "low"
|
||||
ci_cd_safe: false
|
||||
requires_network: true
|
||||
idempotent: true
|
||||
---
|
||||
|
||||
# Test E2E Playwright Debug
|
||||
|
||||
## Overview
|
||||
|
||||
Runs Playwright E2E tests in headed/debug mode for troubleshooting. This skill provides enhanced debugging capabilities including:
|
||||
|
||||
- **Headed Mode**: Visible browser window to watch test execution
|
||||
- **Slow Motion**: Configurable delay between actions for observation
|
||||
- **Playwright Inspector**: Step-by-step debugging with breakpoints
|
||||
- **Trace Collection**: Always captures traces for post-mortem analysis
|
||||
- **Single Test Focus**: Run individual tests or test files
|
||||
|
||||
**Use this skill when:**
|
||||
- Debugging failing E2E tests
|
||||
- Understanding test flow and interactions
|
||||
- Developing new E2E tests
|
||||
- Investigating flaky tests
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Node.js 18.0 or higher installed and in PATH
|
||||
- Playwright browsers installed (`npx playwright install chromium`)
|
||||
- Charon application running at localhost:8080 (use `docker-rebuild-e2e` skill)
|
||||
- Display available (X11 or Wayland on Linux, native on macOS)
|
||||
- Test files in `tests/` directory
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Debug Mode
|
||||
|
||||
Run all tests in headed mode with slow motion:
|
||||
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug
|
||||
```
|
||||
|
||||
### Debug Specific Test File
|
||||
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug --file=login.spec.ts
|
||||
```
|
||||
|
||||
### Debug Test by Name Pattern
|
||||
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug --grep="should login with valid credentials"
|
||||
```
|
||||
|
||||
### With Playwright Inspector
|
||||
|
||||
Open the Playwright Inspector for step-by-step debugging:
|
||||
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug --inspector
|
||||
```
|
||||
|
||||
### Custom Slow Motion
|
||||
|
||||
Adjust the delay between actions (in milliseconds):
|
||||
|
||||
```bash
|
||||
# Slower for detailed observation
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug --slowmo=1000
|
||||
|
||||
# Faster but still visible
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug --slowmo=200
|
||||
```
|
||||
|
||||
### Different Browser
|
||||
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug --project=firefox
|
||||
```
|
||||
|
||||
### Combined Options
|
||||
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug \
|
||||
--file=dashboard.spec.ts \
|
||||
--grep="navigation" \
|
||||
--slowmo=750 \
|
||||
--project=chromium
|
||||
```
|
||||
|
||||
## Parameters
|
||||
|
||||
| Parameter | Type | Required | Default | Description |
|
||||
|-----------|------|----------|---------|-------------|
|
||||
| file | string | No | "" | Specific test file to run |
|
||||
| grep | string | No | "" | Filter tests by title pattern |
|
||||
| slowmo | number | No | 500 | Delay between actions (ms) |
|
||||
| inspector | boolean | No | false | Open Playwright Inspector |
|
||||
| project | string | No | chromium | Browser to use |
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Required | Default | Description |
|
||||
|----------|----------|---------|-------------|
|
||||
| PLAYWRIGHT_BASE_URL | No | http://localhost:8080 | Application URL |
|
||||
| PWDEBUG | No | "" | Set to "1" for Inspector mode |
|
||||
| DEBUG | No | "" | Verbose logging (e.g., "pw:api") |
|
||||
|
||||
## Debugging Techniques
|
||||
|
||||
### Using Playwright Inspector
|
||||
|
||||
The Inspector provides:
|
||||
- **Step-through Execution**: Execute one action at a time
|
||||
- **Locator Playground**: Test and refine selectors
|
||||
- **Call Log**: View all Playwright API calls
|
||||
- **Console**: Access browser console
|
||||
|
||||
```bash
|
||||
# Enable Inspector
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug --inspector
|
||||
```
|
||||
|
||||
In the Inspector:
|
||||
1. Use **Resume** to continue to next action
|
||||
2. Use **Step** to execute one action
|
||||
3. Use the **Locator** tab to test selectors
|
||||
4. Check **Console** for JavaScript errors
|
||||
|
||||
### Adding Breakpoints in Tests
|
||||
|
||||
Add `await page.pause()` in your test code:
|
||||
|
||||
```typescript
|
||||
test('debug this test', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.pause(); // Opens Inspector here
|
||||
await page.click('button');
|
||||
});
|
||||
```
|
||||
|
||||
### Verbose Logging
|
||||
|
||||
Enable detailed Playwright API logging:
|
||||
|
||||
```bash
|
||||
DEBUG=pw:api .github/skills/scripts/skill-runner.sh test-e2e-playwright-debug
|
||||
```
|
||||
|
||||
### Screenshot on Failure
|
||||
|
||||
Tests automatically capture screenshots on failure. Find them in:
|
||||
```
|
||||
test-results/<test-name>/
|
||||
├── test-failed-1.png
|
||||
├── trace.zip
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Analyzing Traces
|
||||
|
||||
Traces are always captured in debug mode. View them with:
|
||||
|
||||
```bash
|
||||
# Open trace viewer for a specific test
|
||||
npx playwright show-trace test-results/<test-name>/trace.zip
|
||||
|
||||
# Or view in browser
|
||||
npx playwright show-trace --port 9322
|
||||
```
|
||||
|
||||
Traces include:
|
||||
- DOM snapshots at each step
|
||||
- Network requests/responses
|
||||
- Console logs
|
||||
- Screenshots
|
||||
- Action timeline
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: Debug Login Flow
|
||||
|
||||
```bash
|
||||
# Rebuild environment with clean state
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e --clean
|
||||
|
||||
# Debug login tests
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug \
|
||||
--file=login.spec.ts \
|
||||
--slowmo=800
|
||||
```
|
||||
|
||||
### Example 2: Investigate Flaky Test
|
||||
|
||||
```bash
|
||||
# Run with Inspector to step through
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug \
|
||||
--grep="flaky test name" \
|
||||
--inspector
|
||||
|
||||
# After identifying the issue, view the trace
|
||||
npx playwright show-trace test-results/*/trace.zip
|
||||
```
|
||||
|
||||
### Example 3: Develop New Test
|
||||
|
||||
```bash
|
||||
# Run in headed mode while developing
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug \
|
||||
--file=new-feature.spec.ts \
|
||||
--slowmo=500
|
||||
```
|
||||
|
||||
### Example 4: Cross-Browser Debug
|
||||
|
||||
```bash
|
||||
# Debug in Firefox
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug \
|
||||
--project=firefox \
|
||||
--grep="cross-browser issue"
|
||||
```
|
||||
|
||||
## Test File Locations
|
||||
|
||||
| Path | Description |
|
||||
|------|-------------|
|
||||
| `tests/` | All E2E test files |
|
||||
| `tests/auth.setup.ts` | Authentication setup |
|
||||
| `tests/login.spec.ts` | Login flow tests |
|
||||
| `tests/dashboard.spec.ts` | Dashboard tests |
|
||||
| `tests/dns-records.spec.ts` | DNS management tests |
|
||||
| `playwright/.auth/` | Stored auth state |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### No Browser Window Opens
|
||||
|
||||
**Linux**: Ensure X11/Wayland display is available
|
||||
```bash
|
||||
echo $DISPLAY # Should show :0 or similar
|
||||
```
|
||||
|
||||
**Remote/SSH**: Use X11 forwarding or VNC
|
||||
```bash
|
||||
ssh -X user@host
|
||||
```
|
||||
|
||||
**WSL2**: Install and configure WSLg or X server
|
||||
|
||||
### Test Times Out
|
||||
|
||||
Increase timeout for debugging:
|
||||
```bash
|
||||
# In your test file
|
||||
test.setTimeout(120000); // 2 minutes
|
||||
```
|
||||
|
||||
### Inspector Doesn't Open
|
||||
|
||||
Ensure PWDEBUG is set:
|
||||
```bash
|
||||
PWDEBUG=1 npx playwright test --headed
|
||||
```
|
||||
|
||||
### Cannot Find Test File
|
||||
|
||||
Check the file exists:
|
||||
```bash
|
||||
ls -la tests/*.spec.ts
|
||||
```
|
||||
|
||||
Use relative path from tests/ directory:
|
||||
```bash
|
||||
--file=login.spec.ts # Not tests/login.spec.ts
|
||||
```
|
||||
|
||||
## Common Issues and Solutions
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| "Target closed" | Application crashed - check container logs |
|
||||
| "Element not found" | Use Inspector to verify selector |
|
||||
| "Timeout exceeded" | Increase timeout or check if element is hidden |
|
||||
| "Net::ERR_CONNECTION_REFUSED" | Ensure Docker container is running |
|
||||
| Flaky test | Add explicit waits or use Inspector to find race condition |
|
||||
|
||||
## Related Skills
|
||||
|
||||
- [test-e2e-playwright](./test-e2e-playwright.SKILL.md) - Run tests normally
|
||||
- [docker-rebuild-e2e](./docker-rebuild-e2e.SKILL.md) - Rebuild E2E environment
|
||||
- [test-e2e-playwright-coverage](./test-e2e-playwright-coverage.SKILL.md) - Run with coverage
|
||||
|
||||
## Notes
|
||||
|
||||
- **Not CI/CD Safe**: Headed mode requires a display
|
||||
- **Resource Usage**: Browser windows consume significant memory
|
||||
- **Slow Motion**: Default 500ms delay; adjust based on needs
|
||||
- **Traces**: Always captured for post-mortem analysis
|
||||
- **Single Worker**: Runs one test at a time for clarity
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: 2026-01-21
|
||||
**Maintained by**: Charon Project Team
|
||||
**Test Directory**: `tests/`
|
||||
@@ -87,6 +87,18 @@ The skill runs non-interactively by default (HTML report does not auto-open), ma
|
||||
- Charon application running (default: `http://localhost:8080`)
|
||||
- Test files in `tests/` directory
|
||||
|
||||
### Quick Start: Ensure E2E Environment is Ready
|
||||
|
||||
Before running tests, ensure the Docker E2E environment is running:
|
||||
|
||||
```bash
|
||||
# Start/rebuild E2E Docker container (recommended before testing)
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e
|
||||
|
||||
# Or for a complete clean rebuild:
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e --clean --no-cache
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
@@ -240,19 +252,88 @@ tests/
|
||||
### Common Errors
|
||||
|
||||
#### Error: Target page, context or browser has been closed
|
||||
**Solution**: Ensure the application is running at the configured base URL
|
||||
**Solution**: Ensure the application is running at the configured base URL. Rebuild if needed:
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e
|
||||
```
|
||||
|
||||
#### Error: page.goto: net::ERR_CONNECTION_REFUSED
|
||||
**Solution**: Start the Charon application before running tests
|
||||
**Solution**: Start the Charon application before running tests:
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e
|
||||
```
|
||||
|
||||
#### Error: browserType.launch: Executable doesn't exist
|
||||
**Solution**: Run `npx playwright install` to install browser binaries
|
||||
|
||||
#### Error: Timeout waiting for selector
|
||||
**Solution**: The application may be slow or in an unexpected state. Try:
|
||||
```bash
|
||||
# Rebuild with clean state
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e --clean
|
||||
|
||||
# Or debug the test to see what's happening
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug --grep="failing test"
|
||||
```
|
||||
|
||||
#### Error: Authentication state is stale
|
||||
**Solution**: Remove stored auth and let setup recreate it:
|
||||
```bash
|
||||
rm -rf playwright/.auth/user.json
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright
|
||||
```
|
||||
|
||||
## Troubleshooting Workflow
|
||||
|
||||
When E2E tests fail, follow this workflow:
|
||||
|
||||
1. **Check container health**:
|
||||
```bash
|
||||
docker ps --filter "name=charon-playwright"
|
||||
docker logs charon-playwright --tail 50
|
||||
```
|
||||
|
||||
2. **Verify the application is accessible**:
|
||||
```bash
|
||||
curl -sf http://localhost:8080/api/v1/health
|
||||
```
|
||||
|
||||
3. **Rebuild with clean state if needed**:
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh docker-rebuild-e2e --clean
|
||||
```
|
||||
|
||||
4. **Debug specific failing test**:
|
||||
```bash
|
||||
.github/skills/scripts/skill-runner.sh test-e2e-playwright-debug --grep="test name"
|
||||
```
|
||||
|
||||
5. **View the HTML report for details**:
|
||||
```bash
|
||||
npx playwright show-report --port 9323
|
||||
```
|
||||
|
||||
## Key File Locations
|
||||
|
||||
| Path | Purpose |
|
||||
|------|---------|
|
||||
| `tests/` | All E2E test files |
|
||||
| `tests/auth.setup.ts` | Authentication setup fixture |
|
||||
| `playwright.config.js` | Playwright configuration |
|
||||
| `playwright/.auth/user.json` | Stored authentication state |
|
||||
| `playwright-report/` | HTML test reports |
|
||||
| `test-results/` | Test artifacts and traces |
|
||||
| `.docker/compose/docker-compose.playwright.yml` | E2E Docker compose config |
|
||||
| `Dockerfile` | Application Docker image |
|
||||
|
||||
## Related Skills
|
||||
|
||||
- test-frontend-unit - Frontend unit tests with Vitest
|
||||
- docker-start-dev - Start development environment
|
||||
- integration-test-all - Run all integration tests
|
||||
- [docker-rebuild-e2e](./docker-rebuild-e2e.SKILL.md) - Rebuild Docker image and restart E2E container
|
||||
- [test-e2e-playwright-debug](./test-e2e-playwright-debug.SKILL.md) - Debug E2E tests in headed mode
|
||||
- [test-e2e-playwright-coverage](./test-e2e-playwright-coverage.SKILL.md) - Run E2E tests with coverage
|
||||
- [test-frontend-unit](./test-frontend-unit.SKILL.md) - Frontend unit tests with Vitest
|
||||
- [docker-start-dev](./docker-start-dev.SKILL.md) - Start development environment
|
||||
- [integration-test-all](./integration-test-all.SKILL.md) - Run all integration tests
|
||||
|
||||
## Notes
|
||||
|
||||
|
||||
Reference in New Issue
Block a user