#!/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="firefox" # 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: firefox) -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 Firefox 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}" export PLAYWRIGHT_SKIP_SECURITY_DEPS="${PLAYWRIGHT_SKIP_SECURITY_DEPS:-1}" # Debug runs should not start the Vite dev server by default export PLAYWRIGHT_COVERAGE="${PLAYWRIGHT_COVERAGE:-0}" set_default_env "PLAYWRIGHT_BASE_URL" "http://127.0.0.1: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:-}" log_info "Grep filter: ${GREP:-}" 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//trace.zip" fi exit "${exit_code}" } # Run main with all arguments main "$@"