#!/bin/bash # visual-regression.sh - Script for visual regression testing # Usage: ./bin/visual-regression.sh [capture|compare|report] [--threshold=5] [--page=login] set -e # Colors for output GREEN='\033[0;32m' YELLOW='\033[0;33m' RED='\033[0;31m' NC='\033[0m' # No Color # Default settings ACTION="" DIFF_THRESHOLD=5 PAGE_FILTER="" CURRENT_DATE=$(date +"%Y-%m-%d") BASELINE_DIR="tests/e2e/visual-regression/baseline" CURRENT_DIR="tests/e2e/visual-regression/current" DIFF_DIR="tests/e2e/visual-regression/diff" REPORT_DIR="tests/e2e/visual-regression/reports" # Parse arguments for arg in "$@"; do case $arg in capture|compare|report) ACTION="$arg" shift ;; --threshold=*) DIFF_THRESHOLD="${arg#*=}" shift ;; --page=*) PAGE_FILTER="${arg#*=}" shift ;; esac done # Check if action is provided if [ -z "$ACTION" ]; then echo -e "${RED}Error: No action specified. Use: capture, compare, or report${NC}" exit 1 fi echo -e "${GREEN}=== Visual Regression Testing - ${ACTION} ===${NC}" # Check if we're in the right directory if [ ! -d "tests/e2e" ]; then echo -e "${RED}Error: Please run this script from the wordpress-dev directory${NC}" exit 1 fi # Check if ImageMagick is installed if ! command -v compare &> /dev/null; then echo -e "${RED}Error: ImageMagick not found. Please install it to use this script.${NC}" echo "On macOS: brew install imagemagick" echo "On Ubuntu: sudo apt-get install imagemagick" exit 1 fi # Create directory structure mkdir -p "$BASELINE_DIR" "$CURRENT_DIR" "$DIFF_DIR" "$REPORT_DIR" # Function to capture screenshots for visual regression capture_screenshots() { echo -e "\n${YELLOW}Capturing screenshots for visual regression testing...${NC}" # Create a temporary Playwright test file TEMP_TEST="tests/e2e/visual-regression-temp.spec.ts" echo "Creating test file: $TEMP_TEST" cat > "$TEMP_TEST" << 'EOF' import { test } from '@playwright/test'; import { LoginPage } from './pages/LoginPage'; import { DashboardPage } from './pages/DashboardPage'; import { TEST_USERS } from './data/test-users'; // Critical pages to capture test('Capture critical pages for visual regression', async ({ page }) => { // Get target directory from environment variable const targetDir = process.env.SCREENSHOT_DIR || 'tests/e2e/visual-regression/current'; console.log(`Capturing screenshots to: ${targetDir}`); // Login page const loginPage = new LoginPage(page); await loginPage.navigate(); await page.waitForLoadState('networkidle'); await page.screenshot({ path: `${targetDir}/login-page.png`, fullPage: true }); console.log('Captured login page'); // Login with test user await loginPage.login(TEST_USERS.trainer.username, TEST_USERS.trainer.password); // Dashboard page const dashboardPage = new DashboardPage(page); await dashboardPage.waitForDashboard(); await page.waitForLoadState('networkidle'); await page.screenshot({ path: `${targetDir}/dashboard-page.png`, fullPage: true }); console.log('Captured dashboard page'); // Events list if (await dashboardPage.isEventsTableVisible()) { await dashboardPage.filterEvents('all'); await page.waitForLoadState('networkidle'); await page.screenshot({ path: `${targetDir}/events-list.png`, fullPage: true }); console.log('Captured events list'); } // Create event page await dashboardPage.clickCreateEvent(); await page.waitForLoadState('networkidle'); await page.screenshot({ path: `${targetDir}/create-event-page.png`, fullPage: true }); console.log('Captured create event page'); // Certificate report page (if available) try { await page.goto('/certificates-report/'); await page.waitForLoadState('networkidle'); await page.screenshot({ path: `${targetDir}/certificate-report-page.png`, fullPage: true }); console.log('Captured certificate report page'); } catch (error) { console.log('Certificate report page not available'); } console.log('Screenshot capture complete'); }); EOF # Run the test with the appropriate directory echo -e "${YELLOW}Running screenshot capture...${NC}" if [ -n "$PAGE_FILTER" ]; then echo "Capturing only ${PAGE_FILTER} page" SCREENSHOT_DIR="$CURRENT_DIR" npx playwright test "$TEMP_TEST" --grep="$PAGE_FILTER" else SCREENSHOT_DIR="$CURRENT_DIR" npx playwright test "$TEMP_TEST" fi # Clean up rm "$TEMP_TEST" echo -e "${GREEN}Screenshots captured successfully to ${CURRENT_DIR}${NC}" } # Function to establish baseline screenshots establish_baseline() { echo -e "\n${YELLOW}Establishing baseline screenshots...${NC}" # Check if baseline directory is empty if [ -z "$(ls -A "$BASELINE_DIR" 2>/dev/null)" ]; then echo "Baseline directory is empty, capturing baseline screenshots..." # Set SCREENSHOT_DIR to baseline for the capture script SCREENSHOT_DIR="$BASELINE_DIR" capture_screenshots else echo "Baseline already exists. Use --force to overwrite." # Optionally copy current screenshots to baseline read -p "Copy current screenshots to baseline? (y/n) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then cp "$CURRENT_DIR"/*.png "$BASELINE_DIR"/ 2>/dev/null || true echo "Current screenshots copied to baseline." fi fi } # Function to compare screenshots compare_screenshots() { echo -e "\n${YELLOW}Comparing screenshots against baseline...${NC}" # Check if baseline exists if [ -z "$(ls -A "$BASELINE_DIR" 2>/dev/null)" ]; then echo -e "${RED}Error: No baseline screenshots found. Run with 'capture' action first.${NC}" return 1 fi # Check if current screenshots exist if [ -z "$(ls -A "$CURRENT_DIR" 2>/dev/null)" ]; then echo -e "${RED}Error: No current screenshots found. Run with 'capture' action first.${NC}" return 1 fi # Create comparison report file REPORT_FILE="$REPORT_DIR/visual-diff-report-${CURRENT_DATE}.md" echo "# Visual Regression Test Report - ${CURRENT_DATE}" > "$REPORT_FILE" echo "" >> "$REPORT_FILE" echo "| Page | Diff % | Status | Diff Image |" >> "$REPORT_FILE" echo "|------|--------|--------|------------|" >> "$REPORT_FILE" FAILURE_COUNT=0 SUCCESS_COUNT=0 # Loop through each baseline image for baseline in "$BASELINE_DIR"/*.png; do filename=$(basename "$baseline") # If page filter is specified, only process that page if [ -n "$PAGE_FILTER" ] && [[ ! "$filename" == *"$PAGE_FILTER"* ]]; then continue fi current="$CURRENT_DIR/$filename" diff="$DIFF_DIR/$filename" # Skip if current image doesn't exist if [ ! -f "$current" ]; then echo -e "${YELLOW}Warning: Current screenshot ${filename} not found, skipping...${NC}" continue fi # Compare images echo -e "Comparing ${filename}..." compare_output=$(compare -metric AE "$baseline" "$current" "$diff" 2>&1 || true) # Get the pixel difference and calculate percentage pixel_diff=$(echo "$compare_output" | grep -o '[0-9]\+' || echo "0") total_pixels=$(identify -format "%w*%h" "$baseline" | bc) diff_percentage=$(echo "scale=2; $pixel_diff * 100 / $total_pixels" | bc) # Log the difference if (( $(echo "$diff_percentage > $DIFF_THRESHOLD" | bc -l) )); then echo -e "${RED}✗ ${filename} differs by ${diff_percentage}% (threshold: ${DIFF_THRESHOLD}%)${NC}" status="❌ Failed" FAILURE_COUNT=$((FAILURE_COUNT + 1)) else echo -e "${GREEN}✓ ${filename} passed (${diff_percentage}% difference)${NC}" status="✅ Passed" SUCCESS_COUNT=$((SUCCESS_COUNT + 1)) fi # Add to report echo "| ${filename} | ${diff_percentage}% | ${status} |  |" >> "$REPORT_FILE" done # Add summary to report echo "" >> "$REPORT_FILE" echo "## Summary" >> "$REPORT_FILE" echo "" >> "$REPORT_FILE" echo "- **Date:** ${CURRENT_DATE}" >> "$REPORT_FILE" echo "- **Total Comparisons:** $((SUCCESS_COUNT + FAILURE_COUNT))" >> "$REPORT_FILE" echo "- **Passed:** ${SUCCESS_COUNT}" >> "$REPORT_FILE" echo "- **Failed:** ${FAILURE_COUNT}" >> "$REPORT_FILE" echo "- **Threshold:** ${DIFF_THRESHOLD}%" >> "$REPORT_FILE" # Output summary echo -e "\n${GREEN}Comparison complete:${NC}" echo "Total: $((SUCCESS_COUNT + FAILURE_COUNT))" echo "Passed: ${SUCCESS_COUNT}" echo "Failed: ${FAILURE_COUNT}" echo "Report: ${REPORT_FILE}" # Return success/failure if [ $FAILURE_COUNT -eq 0 ]; then return 0 else return 1 fi } # Function to generate a visual regression report generate_report() { echo -e "\n${YELLOW}Generating visual regression report...${NC}" # Check if we have diff images if [ -z "$(ls -A "$DIFF_DIR" 2>/dev/null)" ]; then echo -e "${RED}Error: No diff images found. Run with 'compare' action first.${NC}" return 1 fi # Create an HTML report HTML_REPORT="$REPORT_DIR/visual-diff-report-${CURRENT_DATE}.html" cat > "$HTML_REPORT" << EOF
Date: ${CURRENT_DATE}
Threshold: ${DIFF_THRESHOLD}%
EOF # Add comparison sections for diff in "$DIFF_DIR"/*.png; do if [ -f "$diff" ]; then filename=$(basename "$diff") baseline="$BASELINE_DIR/$filename" current="$CURRENT_DIR/$filename" # Skip if baseline or current image doesn't exist if [ ! -f "$baseline" ] || [ ! -f "$current" ]; then continue } # Get the pixel difference and calculate percentage compare_output=$(compare -metric AE "$baseline" "$current" "$diff" 2>&1 || true) pixel_diff=$(echo "$compare_output" | grep -o '[0-9]\+' || echo "0") total_pixels=$(identify -format "%w*%h" "$baseline" | bc) diff_percentage=$(echo "scale=2; $pixel_diff * 100 / $total_pixels" | bc) # Determine status if (( $(echo "$diff_percentage > $DIFF_THRESHOLD" | bc -l) )); then status_class="fail" status_text="Failed" status_style="fail-status" else status_class="pass" status_text="Passed" status_style="pass-status" fi # Add to HTML report cat >> "$HTML_REPORT" << EOFDifference: ${diff_percentage}% - ${status_text}
Baseline
Current
Diff