feat: Add comprehensive testing resilience and monitoring scripts
- Added test-monitor.sh for monitoring test execution metrics and generating reports - Created test-data-manager.sh for robust test data management - Added health-check.sh for comprehensive system health verification - Enhanced overall deployment safety and reliability 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
1bdb4f7de8
commit
27bd8b512c
3 changed files with 1487 additions and 0 deletions
655
wordpress-dev/bin/health-check.sh
Executable file
655
wordpress-dev/bin/health-check.sh
Executable file
|
|
@ -0,0 +1,655 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# health-check.sh - Comprehensive health check for the testing and deployment environment
|
||||||
|
# Usage: ./bin/health-check.sh [--verbose] [--fix] [--ci]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Default settings
|
||||||
|
VERBOSE=false
|
||||||
|
FIX_ISSUES=false
|
||||||
|
CI_MODE=false
|
||||||
|
CURRENT_DATE=$(date +"%Y-%m-%d")
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
for arg in "$@"; do
|
||||||
|
case $arg in
|
||||||
|
--verbose)
|
||||||
|
VERBOSE=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--fix)
|
||||||
|
FIX_ISSUES=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--ci)
|
||||||
|
CI_MODE=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "${GREEN}=== HVAC Community Events Health Check ===${NC}"
|
||||||
|
echo "Checking system health for testing and deployment..."
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Create logs directory
|
||||||
|
mkdir -p logs/health
|
||||||
|
HEALTH_LOG="logs/health/health-check-${CURRENT_DATE}.log"
|
||||||
|
|
||||||
|
# Log function
|
||||||
|
log() {
|
||||||
|
echo "[$(date +"%Y-%m-%d %H:%M:%S")] $1" >> "$HEALTH_LOG"
|
||||||
|
if [ "$VERBOSE" = true ]; then
|
||||||
|
echo "$1"
|
||||||
|
else
|
||||||
|
echo "$2"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check a component and report status
|
||||||
|
check_component() {
|
||||||
|
local component=$1
|
||||||
|
local check_command=$2
|
||||||
|
local fix_command=$3
|
||||||
|
|
||||||
|
echo -e "\n${YELLOW}Checking: ${component}${NC}"
|
||||||
|
log "Checking component: ${component}" "Checking: ${component}..."
|
||||||
|
|
||||||
|
if eval "${check_command}"; then
|
||||||
|
echo -e "${GREEN}✓ ${component} check passed${NC}"
|
||||||
|
log "✓ ${component} check passed"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ ${component} check failed${NC}"
|
||||||
|
log "✗ ${component} check failed"
|
||||||
|
|
||||||
|
if [ -n "$fix_command" ] && [ "$FIX_ISSUES" = true ]; then
|
||||||
|
echo -e "${YELLOW}Attempting to fix: ${component}${NC}"
|
||||||
|
log "Attempting to fix: ${component}" "Attempting to fix..."
|
||||||
|
|
||||||
|
if eval "${fix_command}"; then
|
||||||
|
echo -e "${GREEN}✓ ${component} fixed successfully${NC}"
|
||||||
|
log "✓ ${component} fixed successfully"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Failed to fix: ${component}${NC}"
|
||||||
|
log "✗ Failed to fix: ${component}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check npm dependencies
|
||||||
|
check_npm_dependencies() {
|
||||||
|
log "Checking npm dependencies" "Checking npm dependencies..."
|
||||||
|
|
||||||
|
# Check if package.json exists
|
||||||
|
if [ ! -f "package.json" ]; then
|
||||||
|
log "package.json not found" "package.json not found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if node_modules exists
|
||||||
|
if [ ! -d "node_modules" ]; then
|
||||||
|
log "node_modules not found" "node_modules not found"
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check Playwright installation
|
||||||
|
if ! npm list @playwright/test > /dev/null 2>&1; then
|
||||||
|
log "Playwright not installed properly" "Playwright not installed properly"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "npm dependencies check passed" "npm dependencies ok"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to fix npm dependencies
|
||||||
|
fix_npm_dependencies() {
|
||||||
|
log "Fixing npm dependencies" "Fixing npm dependencies..."
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# Install Playwright browsers
|
||||||
|
npx playwright install
|
||||||
|
|
||||||
|
log "npm dependencies fixed" "npm dependencies fixed"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check test configuration
|
||||||
|
check_test_config() {
|
||||||
|
log "Checking test configuration" "Checking test configuration..."
|
||||||
|
|
||||||
|
# Check if playwright.config.ts exists
|
||||||
|
if [ ! -f "playwright.config.ts" ]; then
|
||||||
|
log "playwright.config.ts not found" "playwright.config.ts not found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if config files exist
|
||||||
|
if [ ! -f "tests/e2e/config/staging-config.ts" ]; then
|
||||||
|
log "staging-config.ts not found" "staging-config.ts not found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Test configuration check passed" "Test configuration ok"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check test data
|
||||||
|
check_test_data() {
|
||||||
|
log "Checking test data" "Checking test data..."
|
||||||
|
|
||||||
|
# Check if test data directory exists
|
||||||
|
if [ ! -d "tests/e2e/data" ]; then
|
||||||
|
log "tests/e2e/data directory not found" "tests/e2e/data directory not found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if essential test data files exist
|
||||||
|
if [ ! -f "tests/e2e/data/test-users.ts" ] || [ ! -f "tests/e2e/data/test-events.ts" ]; then
|
||||||
|
log "Essential test data files missing" "Essential test data files missing"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Test data check passed" "Test data ok"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to fix test data
|
||||||
|
fix_test_data() {
|
||||||
|
log "Fixing test data" "Fixing test data..."
|
||||||
|
|
||||||
|
# Generate test data
|
||||||
|
bash bin/test-data-manager.sh generate
|
||||||
|
|
||||||
|
log "Test data fixed" "Test data fixed"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check page objects
|
||||||
|
check_page_objects() {
|
||||||
|
log "Checking page objects" "Checking page objects..."
|
||||||
|
|
||||||
|
# Check if page object directory exists
|
||||||
|
if [ ! -d "tests/e2e/pages" ]; then
|
||||||
|
log "tests/e2e/pages directory not found" "tests/e2e/pages directory not found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if essential page objects exist
|
||||||
|
if [ ! -f "tests/e2e/pages/BasePage.ts" ] || [ ! -f "tests/e2e/pages/LoginPage.ts" ]; then
|
||||||
|
log "Essential page objects missing" "Essential page objects missing"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check selectors in LoginPage
|
||||||
|
if ! grep -q "input\[name=\"log\"\]" "tests/e2e/pages/LoginPage.ts"; then
|
||||||
|
log "LoginPage.ts missing updated selectors" "LoginPage.ts missing updated selectors"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Page objects check passed" "Page objects ok"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to fix page objects
|
||||||
|
fix_page_objects() {
|
||||||
|
log "Fixing page objects" "Fixing page objects..."
|
||||||
|
|
||||||
|
# Create required directories
|
||||||
|
mkdir -p tests/e2e/pages
|
||||||
|
|
||||||
|
# Fix LoginPage.ts with updated selectors
|
||||||
|
cat > "tests/e2e/pages/LoginPage.ts" << 'EOF'
|
||||||
|
import { Page, expect } from '@playwright/test';
|
||||||
|
import { BasePage } from './BasePage';
|
||||||
|
import { PATHS } from '../config/staging-config';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Page object representing the login page
|
||||||
|
*/
|
||||||
|
export class LoginPage extends BasePage {
|
||||||
|
// Login form elements based on debug analysis
|
||||||
|
private readonly usernameInput = 'input[name="log"]';
|
||||||
|
private readonly passwordInput = 'input[name="pwd"]';
|
||||||
|
private readonly loginButton = 'input[type="submit"]';
|
||||||
|
private readonly rememberMeCheckbox = 'input[name="rememberme"]';
|
||||||
|
private readonly loginError = '.login-error, .login_error, #login_error, .notice-error, .woocommerce-error, .wp-die-message';
|
||||||
|
private readonly forgotPasswordLink = 'a:text("Lost your password?")';
|
||||||
|
private readonly loginForm = 'form#hvac_community_loginform';
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
super(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate to the login page
|
||||||
|
*/
|
||||||
|
async navigate(): Promise<void> {
|
||||||
|
this.log('Navigating to login page');
|
||||||
|
await this.page.goto(PATHS.login);
|
||||||
|
await this.page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
|
// Make sure the form is visible before proceeding
|
||||||
|
await this.page.waitForSelector(this.loginForm, { timeout: 10000 });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alternative name for navigate for backward compatibility
|
||||||
|
*/
|
||||||
|
async navigateToLogin(): Promise<void> {
|
||||||
|
await this.navigate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login with provided credentials
|
||||||
|
* @param username Username or email
|
||||||
|
* @param password Password
|
||||||
|
*/
|
||||||
|
async login(username: string, password: string): Promise<void> {
|
||||||
|
this.log(`Logging in as ${username}`);
|
||||||
|
|
||||||
|
// Wait for form elements to be ready
|
||||||
|
await this.page.waitForSelector(this.usernameInput, { state: 'visible', timeout: 10000 });
|
||||||
|
await this.page.waitForSelector(this.passwordInput, { state: 'visible', timeout: 5000 });
|
||||||
|
await this.page.waitForSelector(this.loginButton, { state: 'visible', timeout: 5000 });
|
||||||
|
|
||||||
|
// Fill in the credentials
|
||||||
|
await this.page.fill(this.usernameInput, username);
|
||||||
|
await this.page.fill(this.passwordInput, password);
|
||||||
|
|
||||||
|
// Click login and wait for navigation
|
||||||
|
await this.page.click(this.loginButton);
|
||||||
|
await this.page.waitForLoadState('networkidle');
|
||||||
|
|
||||||
|
this.log('Login form submitted');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if we're logged in
|
||||||
|
*/
|
||||||
|
async isLoggedIn(): Promise<boolean> {
|
||||||
|
await this.page.waitForLoadState('networkidle');
|
||||||
|
const url = await this.getUrl();
|
||||||
|
return url.includes('hvac-dashboard');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if username field is visible
|
||||||
|
*/
|
||||||
|
async isUsernameFieldVisible(): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await this.page.waitForSelector(this.usernameInput, { state: 'visible', timeout: 5000 });
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get error message if login failed
|
||||||
|
*/
|
||||||
|
async getErrorMessage(): Promise<string | null> {
|
||||||
|
// Check all possible error selectors
|
||||||
|
const errorSelectors = this.loginError.split(', ');
|
||||||
|
|
||||||
|
for (const selector of errorSelectors) {
|
||||||
|
if (await this.page.isVisible(selector)) {
|
||||||
|
return await this.page.textContent(selector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check for any text containing common error messages
|
||||||
|
const pageContent = await this.page.content();
|
||||||
|
if (pageContent.includes('Invalid username') ||
|
||||||
|
pageContent.includes('incorrect password') ||
|
||||||
|
pageContent.includes('Unknown username') ||
|
||||||
|
pageContent.includes('Error:')) {
|
||||||
|
|
||||||
|
// Try to find error message in the page content
|
||||||
|
const errorText = await this.page.evaluate(() => {
|
||||||
|
const errorElements = Array.from(document.querySelectorAll('p, div, span'))
|
||||||
|
.filter(el => el.textContent &&
|
||||||
|
(el.textContent.includes('Invalid') ||
|
||||||
|
el.textContent.includes('Error') ||
|
||||||
|
el.textContent.includes('incorrect') ||
|
||||||
|
el.textContent.includes('Unknown')));
|
||||||
|
|
||||||
|
return errorElements.length > 0 ? errorElements[0].textContent : null;
|
||||||
|
});
|
||||||
|
|
||||||
|
return errorText;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Click on "forgot password" link
|
||||||
|
*/
|
||||||
|
async clickForgotPassword(): Promise<void> {
|
||||||
|
await this.page.click(this.forgotPasswordLink);
|
||||||
|
await this.page.waitForLoadState('networkidle');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle "remember me" checkbox
|
||||||
|
* @param check If true, check the box; if false, uncheck it
|
||||||
|
*/
|
||||||
|
async setRememberMe(check: boolean): Promise<void> {
|
||||||
|
const isChecked = await this.page.isChecked(this.rememberMeCheckbox);
|
||||||
|
if (check !== isChecked) {
|
||||||
|
await this.page.click(this.rememberMeCheckbox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Create BasePage.ts if missing
|
||||||
|
if [ ! -f "tests/e2e/pages/BasePage.ts" ]; then
|
||||||
|
cat > "tests/e2e/pages/BasePage.ts" << 'EOF'
|
||||||
|
import { Page } from '@playwright/test';
|
||||||
|
import { STAGING_URL } from '../config/staging-config';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base page object with common functionality for all pages
|
||||||
|
*/
|
||||||
|
export class BasePage {
|
||||||
|
protected page: Page;
|
||||||
|
|
||||||
|
constructor(page: Page) {
|
||||||
|
this.page = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current URL
|
||||||
|
*/
|
||||||
|
async getUrl(): Promise<string> {
|
||||||
|
return this.page.url();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for page to load completely
|
||||||
|
*/
|
||||||
|
async waitForPageLoad(): Promise<void> {
|
||||||
|
await this.page.waitForLoadState('networkidle');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Log a message with the page class name
|
||||||
|
*/
|
||||||
|
protected log(message: string): void {
|
||||||
|
console.log(`[${this.constructor.name}] ${message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Take a screenshot with a descriptive name
|
||||||
|
*/
|
||||||
|
async takeScreenshot(name: string): Promise<void> {
|
||||||
|
const screenshotName = `${this.constructor.name}-${name}-${Date.now()}.png`;
|
||||||
|
await this.page.screenshot({ path: `screenshots/${screenshotName}` });
|
||||||
|
this.log(`Screenshot saved: ${screenshotName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an element is visible
|
||||||
|
*/
|
||||||
|
async isElementVisible(selector: string): Promise<boolean> {
|
||||||
|
return await this.page.isVisible(selector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Page objects fixed" "Page objects fixed"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check scripts
|
||||||
|
check_scripts() {
|
||||||
|
log "Checking scripts" "Checking scripts..."
|
||||||
|
|
||||||
|
# Check if bin directory exists
|
||||||
|
if [ ! -d "bin" ]; then
|
||||||
|
log "bin directory not found" "bin directory not found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if essential scripts exist and are executable
|
||||||
|
local missing_scripts=0
|
||||||
|
|
||||||
|
# Define essential scripts
|
||||||
|
essential_scripts=(
|
||||||
|
"verify-selectors.sh"
|
||||||
|
"pre-deploy-validation.sh"
|
||||||
|
"auto-recovery.sh"
|
||||||
|
"test-data-manager.sh"
|
||||||
|
)
|
||||||
|
|
||||||
|
for script in "${essential_scripts[@]}"; do
|
||||||
|
if [ ! -f "bin/$script" ] || [ ! -x "bin/$script" ]; then
|
||||||
|
log "Essential script missing or not executable: $script" "Missing script: $script"
|
||||||
|
missing_scripts=$((missing_scripts + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $missing_scripts -gt 0 ]; then
|
||||||
|
log "$missing_scripts essential scripts missing" "$missing_scripts essential scripts missing"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Scripts check passed" "Scripts ok"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check documentation
|
||||||
|
check_documentation() {
|
||||||
|
log "Checking documentation" "Checking documentation..."
|
||||||
|
|
||||||
|
# Check if essential documentation exists
|
||||||
|
local missing_docs=0
|
||||||
|
|
||||||
|
# Define essential documentation
|
||||||
|
essential_docs=(
|
||||||
|
"TESTING.md"
|
||||||
|
"DEPLOYMENT-RESILIENCE.md"
|
||||||
|
"TROUBLESHOOTING.md"
|
||||||
|
"SELECTORS.md"
|
||||||
|
)
|
||||||
|
|
||||||
|
for doc in "${essential_docs[@]}"; do
|
||||||
|
if [ ! -f "$doc" ]; then
|
||||||
|
log "Essential documentation missing: $doc" "Missing doc: $doc"
|
||||||
|
missing_docs=$((missing_docs + 1))
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $missing_docs -gt 0 ]; then
|
||||||
|
log "$missing_docs essential documentation files missing" "$missing_docs essential docs missing"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Documentation check passed" "Documentation ok"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check test results
|
||||||
|
check_test_results() {
|
||||||
|
log "Checking test results" "Checking test results..."
|
||||||
|
|
||||||
|
# Check if test results directory exists
|
||||||
|
if [ ! -d "test-results" ]; then
|
||||||
|
log "No test results found. Tests may not have been run yet." "No test results found"
|
||||||
|
return 0 # Not a failure, tests might not have been run yet
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Count recent test results
|
||||||
|
local recent_results=$(find test-results -type f -name "*.json" -mtime -1 | wc -l)
|
||||||
|
|
||||||
|
if [ $recent_results -eq 0 ]; then
|
||||||
|
log "No recent test results found in the last 24 hours" "No recent test results"
|
||||||
|
return 0 # Not a failure, but worth noting
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check pass rate if we have results
|
||||||
|
local total_tests=$(find test-results -name "*.json" | wc -l)
|
||||||
|
local passed_tests=$(grep -r '"status":"passed"' test-results | wc -l)
|
||||||
|
|
||||||
|
if [ $total_tests -gt 0 ]; then
|
||||||
|
local pass_rate=$((passed_tests * 100 / total_tests))
|
||||||
|
|
||||||
|
log "Test pass rate: $pass_rate% ($passed_tests/$total_tests)" "Test pass rate: $pass_rate%"
|
||||||
|
|
||||||
|
if [ $pass_rate -lt 80 ]; then
|
||||||
|
log "Warning: Test pass rate below 80%" "Warning: Low pass rate"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Test results check passed" "Test results ok"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check staging connectivity
|
||||||
|
check_staging_connectivity() {
|
||||||
|
log "Checking staging connectivity" "Checking staging connectivity..."
|
||||||
|
|
||||||
|
# Ping the staging server (placeholder - update with actual staging URL)
|
||||||
|
if ping -c 1 wordpress-974670-5399585.cloudwaysapps.com &> /dev/null; then
|
||||||
|
log "Staging server is reachable" "Staging server reachable"
|
||||||
|
else
|
||||||
|
log "Warning: Cannot reach staging server" "Warning: Cannot reach staging"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if we can load the staging URL
|
||||||
|
if curl -s --head https://wordpress-974670-5399585.cloudwaysapps.com/ | grep "200 OK" > /dev/null; then
|
||||||
|
log "Staging URL returns 200 OK" "Staging URL OK"
|
||||||
|
else
|
||||||
|
log "Warning: Staging URL not returning 200 OK" "Warning: Staging URL not OK"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Staging connectivity check passed" "Staging connectivity ok"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to check for potential issues
|
||||||
|
check_potential_issues() {
|
||||||
|
log "Checking for potential issues" "Checking for potential issues..."
|
||||||
|
|
||||||
|
# Check for uncommitted changes
|
||||||
|
if [ -n "$(git status --porcelain)" ]; then
|
||||||
|
log "Warning: Uncommitted changes detected" "Warning: Uncommitted changes"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for large files in test results
|
||||||
|
local large_files=$(find test-results -type f -size +10M | wc -l)
|
||||||
|
if [ $large_files -gt 0 ]; then
|
||||||
|
log "Warning: $large_files large files (>10MB) found in test results" "Warning: Large test result files"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check disk space
|
||||||
|
local disk_usage=$(df -h . | awk 'NR==2 {print $5}' | tr -d '%')
|
||||||
|
if [ $disk_usage -gt 90 ]; then
|
||||||
|
log "Warning: Disk usage is high ($disk_usage%)" "Warning: High disk usage"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
log "Potential issues check passed" "No major issues found"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run all checks
|
||||||
|
echo -e "\n${GREEN}=== Running Health Checks ===${NC}"
|
||||||
|
|
||||||
|
check_component "npm dependencies" check_npm_dependencies fix_npm_dependencies
|
||||||
|
NPM_STATUS=$?
|
||||||
|
|
||||||
|
check_component "test configuration" check_test_config
|
||||||
|
CONFIG_STATUS=$?
|
||||||
|
|
||||||
|
check_component "test data" check_test_data fix_test_data
|
||||||
|
DATA_STATUS=$?
|
||||||
|
|
||||||
|
check_component "page objects" check_page_objects fix_page_objects
|
||||||
|
PAGES_STATUS=$?
|
||||||
|
|
||||||
|
check_component "scripts" check_scripts
|
||||||
|
SCRIPTS_STATUS=$?
|
||||||
|
|
||||||
|
check_component "documentation" check_documentation
|
||||||
|
DOCS_STATUS=$?
|
||||||
|
|
||||||
|
check_component "test results" check_test_results
|
||||||
|
RESULTS_STATUS=$?
|
||||||
|
|
||||||
|
check_component "staging connectivity" check_staging_connectivity
|
||||||
|
STAGING_STATUS=$?
|
||||||
|
|
||||||
|
check_component "potential issues" check_potential_issues
|
||||||
|
ISSUES_STATUS=$?
|
||||||
|
|
||||||
|
# Calculate overall health score
|
||||||
|
TOTAL_CHECKS=9
|
||||||
|
PASSED_CHECKS=$((
|
||||||
|
(NPM_STATUS == 0 ? 1 : 0) +
|
||||||
|
(CONFIG_STATUS == 0 ? 1 : 0) +
|
||||||
|
(DATA_STATUS == 0 ? 1 : 0) +
|
||||||
|
(PAGES_STATUS == 0 ? 1 : 0) +
|
||||||
|
(SCRIPTS_STATUS == 0 ? 1 : 0) +
|
||||||
|
(DOCS_STATUS == 0 ? 1 : 0) +
|
||||||
|
(RESULTS_STATUS == 0 ? 1 : 0) +
|
||||||
|
(STAGING_STATUS == 0 ? 1 : 0) +
|
||||||
|
(ISSUES_STATUS == 0 ? 1 : 0)
|
||||||
|
))
|
||||||
|
|
||||||
|
HEALTH_SCORE=$((PASSED_CHECKS * 100 / TOTAL_CHECKS))
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
echo -e "\n${GREEN}=== Health Check Summary ===${NC}"
|
||||||
|
echo -e "Health Score: ${HEALTH_SCORE}% ($PASSED_CHECKS/$TOTAL_CHECKS)"
|
||||||
|
|
||||||
|
if [ $HEALTH_SCORE -eq 100 ]; then
|
||||||
|
echo -e "${GREEN}✓ All health checks passed${NC}"
|
||||||
|
log "All health checks passed. Health Score: 100%" "All health checks passed"
|
||||||
|
exit 0
|
||||||
|
elif [ $HEALTH_SCORE -ge 80 ]; then
|
||||||
|
echo -e "${YELLOW}⚠ Some minor issues detected${NC}"
|
||||||
|
log "Some minor issues detected. Health Score: $HEALTH_SCORE%" "Some minor issues detected"
|
||||||
|
|
||||||
|
if [ "$CI_MODE" = true ]; then
|
||||||
|
echo -e "CI mode enabled, but passing due to acceptable health score"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Significant issues detected${NC}"
|
||||||
|
log "Significant issues detected. Health Score: $HEALTH_SCORE%" "Significant issues detected"
|
||||||
|
|
||||||
|
if [ "$CI_MODE" = true ]; then
|
||||||
|
echo -e "CI mode enabled, failing build due to low health score"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
526
wordpress-dev/bin/test-data-manager.sh
Executable file
526
wordpress-dev/bin/test-data-manager.sh
Executable file
|
|
@ -0,0 +1,526 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# test-data-manager.sh - Script to manage test data for the HVAC Community Events plugin
|
||||||
|
# Usage: ./bin/test-data-manager.sh [generate|verify|cleanup|backup|restore] [--suite=name]
|
||||||
|
|
||||||
|
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=""
|
||||||
|
TEST_SUITE="default"
|
||||||
|
CURRENT_DATE=$(date +"%Y-%m-%d")
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
for arg in "$@"; do
|
||||||
|
case $arg in
|
||||||
|
generate|verify|cleanup|backup|restore)
|
||||||
|
ACTION="$arg"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--suite=*)
|
||||||
|
TEST_SUITE="${arg#*=}"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check if action is provided
|
||||||
|
if [ -z "$ACTION" ]; then
|
||||||
|
echo -e "${RED}Error: No action specified. Use: generate, verify, cleanup, backup, or restore${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}=== Test Data Manager - ${ACTION} ===${NC}"
|
||||||
|
echo "Managing test data for suite: ${TEST_SUITE}"
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Create test data directory structure
|
||||||
|
mkdir -p tests/e2e/data
|
||||||
|
mkdir -p tests/e2e/data/backups
|
||||||
|
|
||||||
|
# Function to generate test data
|
||||||
|
generate_test_data() {
|
||||||
|
echo -e "\n${YELLOW}Generating test data for suite: ${TEST_SUITE}${NC}"
|
||||||
|
|
||||||
|
# Create test users first
|
||||||
|
generate_test_users
|
||||||
|
|
||||||
|
# Create test events based on the suite
|
||||||
|
case $TEST_SUITE in
|
||||||
|
"certificate")
|
||||||
|
generate_certificate_test_data
|
||||||
|
;;
|
||||||
|
"dashboard")
|
||||||
|
generate_dashboard_test_data
|
||||||
|
;;
|
||||||
|
"login")
|
||||||
|
# Login suite only needs users, which are already created
|
||||||
|
echo -e "${GREEN}Login test data created successfully${NC}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
# Default suite includes all test data
|
||||||
|
generate_certificate_test_data
|
||||||
|
generate_dashboard_test_data
|
||||||
|
echo -e "${GREEN}Default test data created successfully${NC}"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to generate test users
|
||||||
|
generate_test_users() {
|
||||||
|
echo -e "${YELLOW}Generating test users...${NC}"
|
||||||
|
|
||||||
|
# Create test users TypeScript file
|
||||||
|
cat > "tests/e2e/data/test-users.ts" << 'EOF'
|
||||||
|
/**
|
||||||
|
* Test users for E2E testing
|
||||||
|
*/
|
||||||
|
export const TEST_USERS = {
|
||||||
|
trainer: {
|
||||||
|
username: 'test_trainer',
|
||||||
|
password: 'Test123!',
|
||||||
|
email: 'test_trainer@example.com',
|
||||||
|
role: 'trainer'
|
||||||
|
},
|
||||||
|
admin: {
|
||||||
|
username: 'admin_trainer',
|
||||||
|
password: 'Admin123!',
|
||||||
|
email: 'admin_trainer@example.com',
|
||||||
|
role: 'administrator'
|
||||||
|
},
|
||||||
|
pending: {
|
||||||
|
username: 'pending_trainer',
|
||||||
|
password: 'Pending123!',
|
||||||
|
email: 'pending_trainer@example.com',
|
||||||
|
role: 'pending'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo -e "${GREEN}Test users created in tests/e2e/data/test-users.ts${NC}"
|
||||||
|
|
||||||
|
# Create shell script to create these users on the server
|
||||||
|
cat > "bin/create-test-users.sh" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
# Create test users for E2E testing
|
||||||
|
|
||||||
|
# Create test_trainer user
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp user create test_trainer test_trainer@example.com --role=subscriber --user_pass=Test123! || wp user update test_trainer --role=subscriber --user_pass=Test123!"
|
||||||
|
|
||||||
|
# Add trainer role
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp user meta update test_trainer wp_capabilities '{\"subscriber\":true,\"trainer\":true}'"
|
||||||
|
|
||||||
|
# Create admin_trainer user
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp user create admin_trainer admin_trainer@example.com --role=administrator --user_pass=Admin123! || wp user update admin_trainer --role=administrator --user_pass=Admin123!"
|
||||||
|
|
||||||
|
# Create pending_trainer user
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp user create pending_trainer pending_trainer@example.com --role=subscriber --user_pass=Pending123! || wp user update pending_trainer --role=subscriber --user_pass=Pending123!"
|
||||||
|
|
||||||
|
# Add pending role
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp user meta update pending_trainer wp_capabilities '{\"subscriber\":true,\"pending_trainer\":true}'"
|
||||||
|
|
||||||
|
echo "Test users created/updated successfully"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x bin/create-test-users.sh
|
||||||
|
echo -e "${YELLOW}Created bin/create-test-users.sh - Update SSH credentials before using${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to generate certificate test data
|
||||||
|
generate_certificate_test_data() {
|
||||||
|
echo -e "${YELLOW}Generating certificate test data...${NC}"
|
||||||
|
|
||||||
|
# Create test events TypeScript file with attendees for certificate testing
|
||||||
|
cat > "tests/e2e/data/test-events.ts" << 'EOF'
|
||||||
|
/**
|
||||||
|
* Test events for E2E testing
|
||||||
|
* Includes event data specifically designed for certificate testing
|
||||||
|
*/
|
||||||
|
export const TEST_EVENTS = {
|
||||||
|
basicEvent: {
|
||||||
|
title: 'Basic HVAC Training',
|
||||||
|
description: 'A basic training event for HVAC technicians.',
|
||||||
|
venue: 'Test Venue',
|
||||||
|
organizer: 'Test Organizer',
|
||||||
|
startDate: getTomorrowDate(),
|
||||||
|
endDate: getTomorrowDate(),
|
||||||
|
startTime: '09:00',
|
||||||
|
endTime: '17:00',
|
||||||
|
cost: '99.99',
|
||||||
|
capacity: '25'
|
||||||
|
},
|
||||||
|
certificateEvent: {
|
||||||
|
title: 'Certificate Training Course',
|
||||||
|
description: 'A training event that issues certificates upon completion.',
|
||||||
|
venue: 'Certificate Test Venue',
|
||||||
|
organizer: 'Certificate Test Organizer',
|
||||||
|
startDate: getYesterdayDate(), // Past event for certificate generation
|
||||||
|
endDate: getYesterdayDate(),
|
||||||
|
startTime: '08:00',
|
||||||
|
endTime: '16:00',
|
||||||
|
cost: '149.99',
|
||||||
|
capacity: '20',
|
||||||
|
issueCertificates: true
|
||||||
|
},
|
||||||
|
multiDayEvent: {
|
||||||
|
title: 'Advanced HVAC Workshop',
|
||||||
|
description: 'A multi-day workshop covering advanced HVAC topics.',
|
||||||
|
venue: 'Advanced Test Venue',
|
||||||
|
organizer: 'Advanced Test Organizer',
|
||||||
|
startDate: getTomorrowDate(),
|
||||||
|
endDate: getFutureDateDays(3), // 3 days in the future
|
||||||
|
startTime: '09:00',
|
||||||
|
endTime: '17:00',
|
||||||
|
cost: '299.99',
|
||||||
|
capacity: '15'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Test attendees for certificate testing
|
||||||
|
export const TEST_ATTENDEES = {
|
||||||
|
complete: {
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Smith',
|
||||||
|
email: 'john.smith@example.com',
|
||||||
|
company: 'HVAC Testing Inc.',
|
||||||
|
checkedIn: true
|
||||||
|
},
|
||||||
|
notCheckedIn: {
|
||||||
|
firstName: 'Jane',
|
||||||
|
lastName: 'Doe',
|
||||||
|
email: 'jane.doe@example.com',
|
||||||
|
company: 'HVAC Services',
|
||||||
|
checkedIn: false
|
||||||
|
},
|
||||||
|
specialChars: {
|
||||||
|
firstName: 'Jörg',
|
||||||
|
lastName: "O'Neill-Müller",
|
||||||
|
email: 'jorg.oneill@example.com',
|
||||||
|
company: 'Special HVAC & Co.',
|
||||||
|
checkedIn: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Helper functions for dates
|
||||||
|
function getTomorrowDate() {
|
||||||
|
const tomorrow = new Date();
|
||||||
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||||
|
return formatDate(tomorrow);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getYesterdayDate() {
|
||||||
|
const yesterday = new Date();
|
||||||
|
yesterday.setDate(yesterday.getDate() - 1);
|
||||||
|
return formatDate(yesterday);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFutureDateDays(days) {
|
||||||
|
const future = new Date();
|
||||||
|
future.setDate(future.getDate() + days);
|
||||||
|
return formatDate(future);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDate(date) {
|
||||||
|
return date.toISOString().split('T')[0]; // YYYY-MM-DD format
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo -e "${GREEN}Certificate test data created in tests/e2e/data/test-events.ts${NC}"
|
||||||
|
|
||||||
|
# Create shell script to create these events on the server
|
||||||
|
cat > "bin/create-test-data-with-checkins.sh" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
# Create test events and attendees for certificate testing
|
||||||
|
|
||||||
|
# Create the certificate test event
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post create --post_type=tribe_events --post_title='Certificate Training Course' --post_content='A training event that issues certificates upon completion.' --post_status=publish --meta_input='{\"_EventStartDate\":\"$(date -d \"yesterday\" +\"%Y-%m-%d 08:00:00\")\",\"_EventEndDate\":\"$(date -d \"yesterday\" +\"%Y-%m-%d 16:00:00\")\",\"_EventVenue\":\"Certificate Test Venue\",\"_EventCost\":\"149.99\",\"_tribe_events_issue_certificates\":\"1\"}' --porcelain"
|
||||||
|
|
||||||
|
# Get the event ID
|
||||||
|
EVENT_ID=$(ssh user@staging-server "cd /path/to/wordpress && wp post list --post_type=tribe_events --post_status=publish --posts_per_page=1 --post_title='Certificate Training Course' --field=ID")
|
||||||
|
|
||||||
|
# Create attendees
|
||||||
|
ATTENDEE1_ID=$(ssh user@staging-server "cd /path/to/wordpress && wp post create --post_type=tribe_attendee --post_title='John Smith' --post_status=publish --meta_input='{\"_tribe_tickets_first_name\":\"John\",\"_tribe_tickets_last_name\":\"Smith\",\"_tribe_tickets_email\":\"john.smith@example.com\",\"_tribe_tickets_checkin\":\"1\",\"_tribe_rsvp_event\":\"$EVENT_ID\",\"_tribe_tickets_attendee_company\":\"HVAC Testing Inc.\"}' --porcelain")
|
||||||
|
|
||||||
|
ATTENDEE2_ID=$(ssh user@staging-server "cd /path/to/wordpress && wp post create --post_type=tribe_attendee --post_title='Jane Doe' --post_status=publish --meta_input='{\"_tribe_tickets_first_name\":\"Jane\",\"_tribe_tickets_last_name\":\"Doe\",\"_tribe_tickets_email\":\"jane.doe@example.com\",\"_tribe_tickets_checkin\":\"0\",\"_tribe_rsvp_event\":\"$EVENT_ID\",\"_tribe_tickets_attendee_company\":\"HVAC Services\"}' --porcelain")
|
||||||
|
|
||||||
|
ATTENDEE3_ID=$(ssh user@staging-server "cd /path/to/wordpress && wp post create --post_type=tribe_attendee --post_title='Jörg O'Neill-Müller' --post_status=publish --meta_input='{\"_tribe_tickets_first_name\":\"Jörg\",\"_tribe_tickets_last_name\":\"O'Neill-Müller\",\"_tribe_tickets_email\":\"jorg.oneill@example.com\",\"_tribe_tickets_checkin\":\"1\",\"_tribe_rsvp_event\":\"$EVENT_ID\",\"_tribe_tickets_attendee_company\":\"Special HVAC & Co.\"}' --porcelain")
|
||||||
|
|
||||||
|
echo "Certificate test data created successfully"
|
||||||
|
echo "Event ID: $EVENT_ID"
|
||||||
|
echo "Attendees: $ATTENDEE1_ID, $ATTENDEE2_ID, $ATTENDEE3_ID"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x bin/create-test-data-with-checkins.sh
|
||||||
|
echo -e "${YELLOW}Created bin/create-test-data-with-checkins.sh - Update SSH credentials before using${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to generate dashboard test data
|
||||||
|
generate_dashboard_test_data() {
|
||||||
|
echo -e "${YELLOW}Generating dashboard test data...${NC}"
|
||||||
|
|
||||||
|
# Create additional test events for dashboard testing
|
||||||
|
cat > "bin/create-test-events-admin.sh" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
# Create test events for dashboard testing
|
||||||
|
|
||||||
|
# Create multiple events with different statuses
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post create --post_type=tribe_events --post_title='Published HVAC Training' --post_content='A published training event for dashboard testing.' --post_status=publish --meta_input='{\"_EventStartDate\":\"$(date -d \"+5 days\" +\"%Y-%m-%d 09:00:00\")\",\"_EventEndDate\":\"$(date -d \"+5 days\" +\"%Y-%m-%d 17:00:00\")\",\"_EventVenue\":\"Dashboard Test Venue\",\"_EventCost\":\"99.99\"}' --porcelain"
|
||||||
|
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post create --post_type=tribe_events --post_title='Draft HVAC Training' --post_content='A draft training event for dashboard testing.' --post_status=draft --meta_input='{\"_EventStartDate\":\"$(date -d \"+7 days\" +\"%Y-%m-%d 09:00:00\")\",\"_EventEndDate\":\"$(date -d \"+7 days\" +\"%Y-%m-%d 17:00:00\")\",\"_EventVenue\":\"Dashboard Test Venue\",\"_EventCost\":\"79.99\"}' --porcelain"
|
||||||
|
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post create --post_type=tribe_events --post_title='Private HVAC Training' --post_content='A private training event for dashboard testing.' --post_status=private --meta_input='{\"_EventStartDate\":\"$(date -d \"+10 days\" +\"%Y-%m-%d 09:00:00\")\",\"_EventEndDate\":\"$(date -d \"+10 days\" +\"%Y-%m-%d 17:00:00\")\",\"_EventVenue\":\"Dashboard Test Venue\",\"_EventCost\":\"129.99\"}' --porcelain"
|
||||||
|
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post create --post_type=tribe_events --post_title='Pending HVAC Training' --post_content='A pending training event for dashboard testing.' --post_status=pending --meta_input='{\"_EventStartDate\":\"$(date -d \"+15 days\" +\"%Y-%m-%d 09:00:00\")\",\"_EventEndDate\":\"$(date -d \"+15 days\" +\"%Y-%m-%d 17:00:00\")\",\"_EventVenue\":\"Dashboard Test Venue\",\"_EventCost\":\"149.99\"}' --porcelain"
|
||||||
|
|
||||||
|
# Create a past event
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post create --post_type=tribe_events --post_title='Past HVAC Training' --post_content='A past training event for dashboard testing.' --post_status=publish --meta_input='{\"_EventStartDate\":\"$(date -d \"-3 days\" +\"%Y-%m-%d 09:00:00\")\",\"_EventEndDate\":\"$(date -d \"-3 days\" +\"%Y-%m-%d 17:00:00\")\",\"_EventVenue\":\"Dashboard Test Venue\",\"_EventCost\":\"99.99\"}' --porcelain"
|
||||||
|
|
||||||
|
echo "Dashboard test events created successfully"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x bin/create-test-events-admin.sh
|
||||||
|
echo -e "${YELLOW}Created bin/create-test-events-admin.sh - Update SSH credentials before using${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to verify test data
|
||||||
|
verify_test_data() {
|
||||||
|
echo -e "\n${YELLOW}Verifying test data for suite: ${TEST_SUITE}${NC}"
|
||||||
|
|
||||||
|
# Verify test user files exist
|
||||||
|
if [ -f "tests/e2e/data/test-users.ts" ]; then
|
||||||
|
echo -e "${GREEN}✓ Test users file exists${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Test users file missing${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify test events files exist
|
||||||
|
if [ -f "tests/e2e/data/test-events.ts" ]; then
|
||||||
|
echo -e "${GREEN}✓ Test events file exists${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Test events file missing${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Verify test data on server (if scripts exist)
|
||||||
|
if [ -f "bin/verify-test-data.sh" ]; then
|
||||||
|
echo -e "${YELLOW}Running server-side test data verification...${NC}"
|
||||||
|
bash bin/verify-test-data.sh
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Creating server-side verification script...${NC}"
|
||||||
|
|
||||||
|
# Create verification script
|
||||||
|
cat > "bin/verify-test-data.sh" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
# Verify test data exists on the server
|
||||||
|
|
||||||
|
# Check test users
|
||||||
|
echo "Verifying test users..."
|
||||||
|
TEST_TRAINER=$(ssh user@staging-server "cd /path/to/wordpress && wp user get test_trainer --field=ID 2>/dev/null || echo 'missing'")
|
||||||
|
ADMIN_TRAINER=$(ssh user@staging-server "cd /path/to/wordpress && wp user get admin_trainer --field=ID 2>/dev/null || echo 'missing'")
|
||||||
|
PENDING_TRAINER=$(ssh user@staging-server "cd /path/to/wordpress && wp user get pending_trainer --field=ID 2>/dev/null || echo 'missing'")
|
||||||
|
|
||||||
|
if [ "$TEST_TRAINER" != "missing" ] && [ "$ADMIN_TRAINER" != "missing" ]; then
|
||||||
|
echo "✓ Test users verified"
|
||||||
|
else
|
||||||
|
echo "✗ Test users missing"
|
||||||
|
echo " - test_trainer: ${TEST_TRAINER}"
|
||||||
|
echo " - admin_trainer: ${ADMIN_TRAINER}"
|
||||||
|
echo " - pending_trainer: ${PENDING_TRAINER}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check test events
|
||||||
|
echo "Verifying test events..."
|
||||||
|
CERTIFICATE_EVENT=$(ssh user@staging-server "cd /path/to/wordpress && wp post list --post_type=tribe_events --post_status=publish --posts_per_page=1 --post_title='Certificate Training Course' --field=ID 2>/dev/null || echo 'missing'")
|
||||||
|
DASHBOARD_EVENTS=$(ssh user@staging-server "cd /path/to/wordpress && wp post list --post_type=tribe_events --field=ID | wc -l 2>/dev/null || echo '0'")
|
||||||
|
|
||||||
|
if [ "$CERTIFICATE_EVENT" != "missing" ] && [ "$DASHBOARD_EVENTS" -gt 0 ]; then
|
||||||
|
echo "✓ Test events verified"
|
||||||
|
echo " - Certificate event: ${CERTIFICATE_EVENT}"
|
||||||
|
echo " - Total events: ${DASHBOARD_EVENTS}"
|
||||||
|
else
|
||||||
|
echo "✗ Test events missing"
|
||||||
|
echo " - Certificate event: ${CERTIFICATE_EVENT}"
|
||||||
|
echo " - Total events: ${DASHBOARD_EVENTS}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check attendees
|
||||||
|
echo "Verifying test attendees..."
|
||||||
|
if [ "$CERTIFICATE_EVENT" != "missing" ]; then
|
||||||
|
ATTENDEES=$(ssh user@staging-server "cd /path/to/wordpress && wp post list --post_type=tribe_attendee --meta_key=_tribe_rsvp_event --meta_value=${CERTIFICATE_EVENT} --field=ID 2>/dev/null | wc -l || echo '0'")
|
||||||
|
|
||||||
|
if [ "$ATTENDEES" -gt 0 ]; then
|
||||||
|
echo "✓ Test attendees verified: ${ATTENDEES} attendees found"
|
||||||
|
else
|
||||||
|
echo "✗ Test attendees missing for certificate event"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Test data verification complete"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x bin/verify-test-data.sh
|
||||||
|
echo -e "${YELLOW}Created bin/verify-test-data.sh - Update SSH credentials before using${NC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to cleanup test data
|
||||||
|
cleanup_test_data() {
|
||||||
|
echo -e "\n${YELLOW}Cleaning up test data for suite: ${TEST_SUITE}${NC}"
|
||||||
|
|
||||||
|
# Check if cleanup script exists
|
||||||
|
if [ -f "bin/cleanup-test-data.sh" ]; then
|
||||||
|
echo -e "${YELLOW}Running test data cleanup...${NC}"
|
||||||
|
bash bin/cleanup-test-data.sh
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Creating cleanup script...${NC}"
|
||||||
|
|
||||||
|
# Create cleanup script
|
||||||
|
cat > "bin/cleanup-test-data.sh" << 'EOF'
|
||||||
|
#!/bin/bash
|
||||||
|
# Clean up test data from the server
|
||||||
|
|
||||||
|
echo "Cleaning up test data..."
|
||||||
|
|
||||||
|
# Clean up test events
|
||||||
|
echo "Removing test events..."
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post delete \$(wp post list --post_type=tribe_events --post_title='Certificate Training Course' --field=ID) --force 2>/dev/null || echo 'No certificate event to remove'"
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post delete \$(wp post list --post_type=tribe_events --post_title='Published HVAC Training' --field=ID) --force 2>/dev/null || echo 'No published event to remove'"
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post delete \$(wp post list --post_type=tribe_events --post_title='Draft HVAC Training' --field=ID) --force 2>/dev/null || echo 'No draft event to remove'"
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post delete \$(wp post list --post_type=tribe_events --post_title='Private HVAC Training' --field=ID) --force 2>/dev/null || echo 'No private event to remove'"
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post delete \$(wp post list --post_type=tribe_events --post_title='Pending HVAC Training' --field=ID) --force 2>/dev/null || echo 'No pending event to remove'"
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post delete \$(wp post list --post_type=tribe_events --post_title='Past HVAC Training' --field=ID) --force 2>/dev/null || echo 'No past event to remove'"
|
||||||
|
|
||||||
|
# Clean up attendees - remove all test attendees
|
||||||
|
echo "Removing test attendees..."
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post delete \$(wp post list --post_type=tribe_attendee --meta_key=_tribe_tickets_email --meta_value='john.smith@example.com' --field=ID) --force 2>/dev/null || echo 'No John Smith attendee to remove'"
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post delete \$(wp post list --post_type=tribe_attendee --meta_key=_tribe_tickets_email --meta_value='jane.doe@example.com' --field=ID) --force 2>/dev/null || echo 'No Jane Doe attendee to remove'"
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp post delete \$(wp post list --post_type=tribe_attendee --meta_key=_tribe_tickets_email --meta_value='jorg.oneill@example.com' --field=ID) --force 2>/dev/null || echo 'No Jorg attendee to remove'"
|
||||||
|
|
||||||
|
# Keep test users (just reset their data)
|
||||||
|
echo "Resetting test users..."
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp user meta delete test_trainer hvac_test_data 2>/dev/null || echo 'No test data to remove for test_trainer'"
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp user meta delete admin_trainer hvac_test_data 2>/dev/null || echo 'No test data to remove for admin_trainer'"
|
||||||
|
ssh user@staging-server "cd /path/to/wordpress && wp user meta delete pending_trainer hvac_test_data 2>/dev/null || echo 'No test data to remove for pending_trainer'"
|
||||||
|
|
||||||
|
echo "Test data cleanup complete"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x bin/cleanup-test-data.sh
|
||||||
|
echo -e "${YELLOW}Created bin/cleanup-test-data.sh - Update SSH credentials before using${NC}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to backup test data
|
||||||
|
backup_test_data() {
|
||||||
|
echo -e "\n${YELLOW}Backing up test data for suite: ${TEST_SUITE}${NC}"
|
||||||
|
|
||||||
|
# Create backup directory
|
||||||
|
BACKUP_DIR="tests/e2e/data/backups/${CURRENT_DATE}_${TEST_SUITE}"
|
||||||
|
mkdir -p "$BACKUP_DIR"
|
||||||
|
|
||||||
|
# Backup test user data
|
||||||
|
if [ -f "tests/e2e/data/test-users.ts" ]; then
|
||||||
|
cp "tests/e2e/data/test-users.ts" "$BACKUP_DIR/"
|
||||||
|
echo -e "${GREEN}✓ Test users backed up${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backup test event data
|
||||||
|
if [ -f "tests/e2e/data/test-events.ts" ]; then
|
||||||
|
cp "tests/e2e/data/test-events.ts" "$BACKUP_DIR/"
|
||||||
|
echo -e "${GREEN}✓ Test events backed up${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Backup any other test data files
|
||||||
|
if [ -f "tests/e2e/data/test-config.ts" ]; then
|
||||||
|
cp "tests/e2e/data/test-config.ts" "$BACKUP_DIR/"
|
||||||
|
echo -e "${GREEN}✓ Test config backed up${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Compress backup
|
||||||
|
tar -czf "$BACKUP_DIR.tar.gz" "$BACKUP_DIR"
|
||||||
|
echo -e "${GREEN}Backup created: ${BACKUP_DIR}.tar.gz${NC}"
|
||||||
|
|
||||||
|
# Remove uncompressed backup
|
||||||
|
rm -rf "$BACKUP_DIR"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to restore test data
|
||||||
|
restore_test_data() {
|
||||||
|
echo -e "\n${YELLOW}Restoring test data for suite: ${TEST_SUITE}${NC}"
|
||||||
|
|
||||||
|
# Find most recent backup for the suite
|
||||||
|
LATEST_BACKUP=$(ls -t tests/e2e/data/backups/*_${TEST_SUITE}.tar.gz 2>/dev/null | head -1)
|
||||||
|
|
||||||
|
if [ -z "$LATEST_BACKUP" ]; then
|
||||||
|
echo -e "${RED}No backup found for suite: ${TEST_SUITE}${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${YELLOW}Restoring from backup: ${LATEST_BACKUP}${NC}"
|
||||||
|
|
||||||
|
# Create temp directory
|
||||||
|
TEMP_DIR="tests/e2e/data/temp_restore"
|
||||||
|
mkdir -p "$TEMP_DIR"
|
||||||
|
|
||||||
|
# Extract backup
|
||||||
|
tar -xzf "$LATEST_BACKUP" -C "$TEMP_DIR"
|
||||||
|
|
||||||
|
# Find extracted directory
|
||||||
|
EXTRACTED_DIR=$(find "$TEMP_DIR" -type d -depth 1)
|
||||||
|
|
||||||
|
# Restore files
|
||||||
|
if [ -f "$EXTRACTED_DIR/test-users.ts" ]; then
|
||||||
|
cp "$EXTRACTED_DIR/test-users.ts" "tests/e2e/data/"
|
||||||
|
echo -e "${GREEN}✓ Test users restored${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$EXTRACTED_DIR/test-events.ts" ]; then
|
||||||
|
cp "$EXTRACTED_DIR/test-events.ts" "tests/e2e/data/"
|
||||||
|
echo -e "${GREEN}✓ Test events restored${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$EXTRACTED_DIR/test-config.ts" ]; then
|
||||||
|
cp "$EXTRACTED_DIR/test-config.ts" "tests/e2e/data/"
|
||||||
|
echo -e "${GREEN}✓ Test config restored${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up
|
||||||
|
rm -rf "$TEMP_DIR"
|
||||||
|
echo -e "${GREEN}Restore completed from: ${LATEST_BACKUP}${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Execute action
|
||||||
|
case $ACTION in
|
||||||
|
"generate")
|
||||||
|
generate_test_data
|
||||||
|
;;
|
||||||
|
"verify")
|
||||||
|
verify_test_data
|
||||||
|
;;
|
||||||
|
"cleanup")
|
||||||
|
cleanup_test_data
|
||||||
|
;;
|
||||||
|
"backup")
|
||||||
|
backup_test_data
|
||||||
|
;;
|
||||||
|
"restore")
|
||||||
|
restore_test_data
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}Invalid action: ${ACTION}${NC}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo -e "\n${GREEN}=== Test Data Manager Complete ===${NC}"
|
||||||
|
echo "Action '${ACTION}' completed for suite: ${TEST_SUITE}"
|
||||||
|
exit 0
|
||||||
306
wordpress-dev/bin/test-monitor.sh
Executable file
306
wordpress-dev/bin/test-monitor.sh
Executable file
|
|
@ -0,0 +1,306 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# test-monitor.sh - Script to monitor test execution and generate reports
|
||||||
|
# Usage: ./bin/test-monitor.sh [--store] [--notify] [--threshold=80]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[0;33m'
|
||||||
|
RED='\033[0;31m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Default settings
|
||||||
|
STORE_RESULTS=false
|
||||||
|
SEND_NOTIFICATIONS=false
|
||||||
|
SUCCESS_THRESHOLD=80
|
||||||
|
CURRENT_DATE=$(date +"%Y-%m-%d")
|
||||||
|
|
||||||
|
# Parse arguments
|
||||||
|
for arg in "$@"; do
|
||||||
|
case $arg in
|
||||||
|
--store)
|
||||||
|
STORE_RESULTS=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--notify)
|
||||||
|
SEND_NOTIFICATIONS=true
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--threshold=*)
|
||||||
|
SUCCESS_THRESHOLD="${arg#*=}"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -e "${GREEN}=== Test Monitoring Dashboard ===${NC}"
|
||||||
|
echo "Analyzing test results and performance metrics..."
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# Create monitoring directory structure
|
||||||
|
mkdir -p monitoring/data
|
||||||
|
mkdir -p monitoring/reports
|
||||||
|
mkdir -p monitoring/alerts
|
||||||
|
|
||||||
|
# Generate a unique run ID
|
||||||
|
RUN_ID=$(date +"%Y%m%d%H%M%S")
|
||||||
|
REPORT_FILE="monitoring/reports/test-report-${RUN_ID}.md"
|
||||||
|
DATA_FILE="monitoring/data/test-data-${RUN_ID}.json"
|
||||||
|
|
||||||
|
# Function to analyze Playwright test results
|
||||||
|
analyze_test_results() {
|
||||||
|
echo -e "\n${YELLOW}Analyzing test results...${NC}"
|
||||||
|
|
||||||
|
# Check if test results directory exists
|
||||||
|
if [ ! -d "test-results" ]; then
|
||||||
|
echo -e "${RED}No test results found.${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Count passed and failed tests
|
||||||
|
TOTAL_TESTS=$(find test-results -name "*.json" | wc -l)
|
||||||
|
PASSED_TESTS=$(grep -r '"status":"passed"' test-results | wc -l)
|
||||||
|
FAILED_TESTS=$(grep -r '"status":"failed"' test-results | wc -l)
|
||||||
|
SKIPPED_TESTS=$(grep -r '"status":"skipped"' test-results | wc -l)
|
||||||
|
|
||||||
|
# Calculate success rate
|
||||||
|
if [ $TOTAL_TESTS -gt 0 ]; then
|
||||||
|
SUCCESS_RATE=$((PASSED_TESTS * 100 / TOTAL_TESTS))
|
||||||
|
else
|
||||||
|
SUCCESS_RATE=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Analyze test duration
|
||||||
|
AVERAGE_DURATION=$(grep -r '"duration":' test-results | awk -F'"duration":' '{sum+=$2; count++} END {print sum/count/1000}')
|
||||||
|
|
||||||
|
# Find slowest tests
|
||||||
|
SLOWEST_TESTS=$(grep -r '"duration":' test-results | sort -nr -k2 | head -5)
|
||||||
|
|
||||||
|
# Find most frequent failures
|
||||||
|
FAILURE_PATTERNS=$(grep -r "Error:" test-results | sort | uniq -c | sort -nr | head -5)
|
||||||
|
|
||||||
|
# Output results
|
||||||
|
echo -e "\n${GREEN}Test Results Summary:${NC}"
|
||||||
|
echo -e "Total Tests: ${TOTAL_TESTS}"
|
||||||
|
echo -e "Passed: ${PASSED_TESTS}"
|
||||||
|
echo -e "Failed: ${FAILED_TESTS}"
|
||||||
|
echo -e "Skipped: ${SKIPPED_TESTS}"
|
||||||
|
echo -e "Success Rate: ${SUCCESS_RATE}%"
|
||||||
|
echo -e "Average Duration: ${AVERAGE_DURATION} seconds"
|
||||||
|
|
||||||
|
# Store results if enabled
|
||||||
|
if [ "$STORE_RESULTS" = true ]; then
|
||||||
|
# Create JSON data
|
||||||
|
cat > "$DATA_FILE" << EOF
|
||||||
|
{
|
||||||
|
"runId": "${RUN_ID}",
|
||||||
|
"date": "${CURRENT_DATE}",
|
||||||
|
"totalTests": ${TOTAL_TESTS},
|
||||||
|
"passedTests": ${PASSED_TESTS},
|
||||||
|
"failedTests": ${FAILED_TESTS},
|
||||||
|
"skippedTests": ${SKIPPED_TESTS},
|
||||||
|
"successRate": ${SUCCESS_RATE},
|
||||||
|
"averageDuration": ${AVERAGE_DURATION}
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
echo -e "${GREEN}Test data stored in ${DATA_FILE}${NC}"
|
||||||
|
|
||||||
|
# Create markdown report
|
||||||
|
cat > "$REPORT_FILE" << EOF
|
||||||
|
# Test Execution Report - ${CURRENT_DATE}
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
- **Run ID**: ${RUN_ID}
|
||||||
|
- **Date**: ${CURRENT_DATE}
|
||||||
|
- **Total Tests**: ${TOTAL_TESTS}
|
||||||
|
- **Passed**: ${PASSED_TESTS}
|
||||||
|
- **Failed**: ${FAILED_TESTS}
|
||||||
|
- **Skipped**: ${SKIPPED_TESTS}
|
||||||
|
- **Success Rate**: ${SUCCESS_RATE}%
|
||||||
|
- **Average Duration**: ${AVERAGE_DURATION} seconds
|
||||||
|
|
||||||
|
## Slowest Tests
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
${SLOWEST_TESTS}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Common Failure Patterns
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
${FAILURE_PATTERNS}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## Recommendations
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Add recommendations based on results
|
||||||
|
if [ $SUCCESS_RATE -lt $SUCCESS_THRESHOLD ]; then
|
||||||
|
cat >> "$REPORT_FILE" << EOF
|
||||||
|
- **Critical Issue**: Success rate below threshold (${SUCCESS_THRESHOLD}%)
|
||||||
|
- Run the auto-recovery script: \`./bin/auto-recovery.sh\`
|
||||||
|
- Check recent code changes that might have affected tests
|
||||||
|
- Verify selector stability with \`./bin/verify-selectors.sh\`
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
cat >> "$REPORT_FILE" << EOF
|
||||||
|
- Success rate above threshold (${SUCCESS_THRESHOLD}%)
|
||||||
|
- Continue monitoring test performance
|
||||||
|
- Consider optimizing slow tests
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -e "${GREEN}Test report generated: ${REPORT_FILE}${NC}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Send notifications if enabled and below threshold
|
||||||
|
if [ "$SEND_NOTIFICATIONS" = true ] && [ $SUCCESS_RATE -lt $SUCCESS_THRESHOLD ]; then
|
||||||
|
generate_alert "${SUCCESS_RATE}" "${FAILED_TESTS}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Return success/failure based on threshold
|
||||||
|
if [ $SUCCESS_RATE -ge $SUCCESS_THRESHOLD ]; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to generate historical trends
|
||||||
|
generate_trends() {
|
||||||
|
echo -e "\n${YELLOW}Generating historical trends...${NC}"
|
||||||
|
|
||||||
|
# Check if we have historical data
|
||||||
|
if [ $(find monitoring/data -name "test-data-*.json" | wc -l) -lt 2 ]; then
|
||||||
|
echo -e "${YELLOW}Not enough historical data for trend analysis.${NC}"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract success rates from historical data
|
||||||
|
SUCCESS_TREND=$(grep -r '"successRate":' monitoring/data | sort | tail -10 | awk -F'"successRate":' '{print $2}' | tr -d ',' | tr '\n' ',')
|
||||||
|
|
||||||
|
# Extract dates from historical data
|
||||||
|
DATE_TREND=$(grep -r '"date":' monitoring/data | sort | tail -10 | awk -F'"date":"' '{print $2}' | tr -d '",' | tr '\n' ',')
|
||||||
|
|
||||||
|
echo -e "\n${GREEN}Historical Trend:${NC}"
|
||||||
|
echo -e "Recent Success Rates: ${SUCCESS_TREND}"
|
||||||
|
echo -e "Dates: ${DATE_TREND}"
|
||||||
|
|
||||||
|
# Determine trend direction
|
||||||
|
LATEST_RATE=$(echo $SUCCESS_TREND | awk -F',' '{print $(NF-1)}')
|
||||||
|
PREVIOUS_RATE=$(echo $SUCCESS_TREND | awk -F',' '{print $(NF-2)}')
|
||||||
|
|
||||||
|
if [ -n "$LATEST_RATE" ] && [ -n "$PREVIOUS_RATE" ]; then
|
||||||
|
if [ $LATEST_RATE -gt $PREVIOUS_RATE ]; then
|
||||||
|
echo -e "${GREEN}Trend: Improving ↑${NC}"
|
||||||
|
elif [ $LATEST_RATE -lt $PREVIOUS_RATE ]; then
|
||||||
|
echo -e "${RED}Trend: Declining ↓${NC}"
|
||||||
|
else
|
||||||
|
echo -e "${YELLOW}Trend: Stable →${NC}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to generate alerts
|
||||||
|
generate_alert() {
|
||||||
|
local success_rate=$1
|
||||||
|
local failed_tests=$2
|
||||||
|
|
||||||
|
echo -e "\n${YELLOW}Generating alert...${NC}"
|
||||||
|
|
||||||
|
# Create alert file
|
||||||
|
ALERT_FILE="monitoring/alerts/alert-${RUN_ID}.md"
|
||||||
|
|
||||||
|
cat > "$ALERT_FILE" << EOF
|
||||||
|
# Test Alert - ${CURRENT_DATE}
|
||||||
|
|
||||||
|
## Alert Details
|
||||||
|
|
||||||
|
- **Run ID**: ${RUN_ID}
|
||||||
|
- **Date**: ${CURRENT_DATE}
|
||||||
|
- **Success Rate**: ${success_rate}% (below threshold of ${SUCCESS_THRESHOLD}%)
|
||||||
|
- **Failed Tests**: ${failed_tests}
|
||||||
|
|
||||||
|
## Recommended Actions
|
||||||
|
|
||||||
|
1. Run the auto-recovery script: \`./bin/auto-recovery.sh\`
|
||||||
|
2. Check recent code changes that might have affected tests
|
||||||
|
3. Verify selector stability with \`./bin/verify-selectors.sh\`
|
||||||
|
4. Review the full report: \`${REPORT_FILE}\`
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
- Fix failing tests before proceeding with deployment
|
||||||
|
- Update selectors if necessary
|
||||||
|
- Run tests again to verify fixes
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo -e "${RED}Alert generated: ${ALERT_FILE}${NC}"
|
||||||
|
echo -e "Would send notification email/Slack message in a production environment"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to generate recommendations
|
||||||
|
generate_recommendations() {
|
||||||
|
echo -e "\n${YELLOW}Generating recommendations...${NC}"
|
||||||
|
|
||||||
|
# Analyze test execution times
|
||||||
|
if [ -n "$AVERAGE_DURATION" ] && [ $(echo "$AVERAGE_DURATION > 10" | bc) -eq 1 ]; then
|
||||||
|
echo -e "${YELLOW}Performance Recommendation: Tests are taking longer than 10 seconds on average.${NC}"
|
||||||
|
echo -e "- Consider optimizing test execution"
|
||||||
|
echo -e "- Review the slowest tests identified above"
|
||||||
|
echo -e "- Use more efficient selectors"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Analyze failure patterns
|
||||||
|
if [ $FAILED_TESTS -gt 0 ]; then
|
||||||
|
echo -e "${YELLOW}Stability Recommendation: ${FAILED_TESTS} tests are failing.${NC}"
|
||||||
|
echo -e "- Run the auto-recovery script: ./bin/auto-recovery.sh"
|
||||||
|
echo -e "- Check selector stability with: ./bin/verify-selectors.sh"
|
||||||
|
echo -e "- Review the common failure patterns above"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check for missing test data
|
||||||
|
if ! [ -f "tests/e2e/data/test-users.ts" ] || ! [ -f "tests/e2e/data/test-events.ts" ]; then
|
||||||
|
echo -e "${YELLOW}Test Data Recommendation: Missing test data files.${NC}"
|
||||||
|
echo -e "- Create or restore test data files"
|
||||||
|
echo -e "- Run test data generation scripts"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Main execution
|
||||||
|
echo -e "\n${GREEN}=== Test Monitoring Dashboard - ${CURRENT_DATE} ===${NC}"
|
||||||
|
|
||||||
|
# Analyze test results
|
||||||
|
analyze_test_results
|
||||||
|
ANALYSIS_STATUS=$?
|
||||||
|
|
||||||
|
# Generate historical trends
|
||||||
|
generate_trends
|
||||||
|
|
||||||
|
# Generate recommendations
|
||||||
|
generate_recommendations
|
||||||
|
|
||||||
|
# Summary
|
||||||
|
echo -e "\n${GREEN}=== Monitoring Summary ===${NC}"
|
||||||
|
if [ $ANALYSIS_STATUS -eq 0 ]; then
|
||||||
|
echo -e "${GREEN}✓ Tests are performing above threshold (${SUCCESS_THRESHOLD}%)${NC}"
|
||||||
|
echo -e "Continue monitoring for performance trends"
|
||||||
|
else
|
||||||
|
echo -e "${RED}✗ Tests are performing below threshold (${SUCCESS_THRESHOLD}%)${NC}"
|
||||||
|
echo -e "Review recommendations and take action before deployment"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate ASCII chart for visualization
|
||||||
|
if [ "$STORE_RESULTS" = true ]; then
|
||||||
|
echo -e "\nRun test-report-generator.js to create visual charts and reports"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit $ANALYSIS_STATUS
|
||||||
Loading…
Reference in a new issue