308 lines
10 KiB
Bash
308 lines
10 KiB
Bash
|
|
#!/bin/bash
|
|||
|
|
|
|||
|
|
# Complete Browser Logger - Full automation with real logs
|
|||
|
|
# This wrapper script fully automates browser testing and real log collection
|
|||
|
|
|
|||
|
|
set -e
|
|||
|
|
|
|||
|
|
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"
|
|||
|
|
BASE_URL="http://localhost:3030"
|
|||
|
|
ALL_PAGES=("/" "/blog" "/prescriptions" "/contact" "/services" "/about")
|
|||
|
|
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
|
|||
|
|
|
|||
|
|
# Colors
|
|||
|
|
RED='\033[0;31m'
|
|||
|
|
GREEN='\033[0;32m'
|
|||
|
|
YELLOW='\033[1;33m'
|
|||
|
|
BLUE='\033[0;34m'
|
|||
|
|
NC='\033[0m'
|
|||
|
|
|
|||
|
|
log_info() { echo -e "${BLUE}ℹ️ $1${NC}"; }
|
|||
|
|
log_success() { echo -e "${GREEN}✅ $1${NC}"; }
|
|||
|
|
log_warning() { echo -e "${YELLOW}⚠️ $1${NC}"; }
|
|||
|
|
log_error() { echo -e "${RED}❌ $1${NC}"; }
|
|||
|
|
|
|||
|
|
# Function to collect real browser logs using Claude Code environment
|
|||
|
|
collect_real_browser_logs() {
|
|||
|
|
local log_file="$1"
|
|||
|
|
|
|||
|
|
log_info "Collecting real browser logs via MCP browser tools..."
|
|||
|
|
|
|||
|
|
# Create signal file that Claude Code can detect and process
|
|||
|
|
local signal_file="/tmp/mcp_collect_logs_signal_$(date +%s).txt"
|
|||
|
|
cat > "$signal_file" << EOF
|
|||
|
|
MCP_BROWSER_LOGS_REQUEST
|
|||
|
|
LOG_FILE=$log_file
|
|||
|
|
ACTION=COLLECT_AND_INJECT
|
|||
|
|
STATUS=WAITING_FOR_CLAUDE_CODE
|
|||
|
|
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
|
|||
|
|
EOF
|
|||
|
|
|
|||
|
|
log_info "Created signal for Claude Code: $signal_file"
|
|||
|
|
|
|||
|
|
# Add placeholder content that Claude Code should replace with real logs
|
|||
|
|
local console_logs='PLACEHOLDER_CONSOLE_LOGS'
|
|||
|
|
local console_errors='PLACEHOLDER_CONSOLE_ERRORS'
|
|||
|
|
local network_errors='PLACEHOLDER_NETWORK_ERRORS'
|
|||
|
|
|
|||
|
|
# Format and inject real logs into the file
|
|||
|
|
local temp_content="/tmp/real_logs_content_$$"
|
|||
|
|
{
|
|||
|
|
echo ""
|
|||
|
|
echo "=== REAL BROWSER LOGS (Collected $(date +"%H:%M:%S")) ==="
|
|||
|
|
echo ""
|
|||
|
|
echo "=== CONSOLE LOGS ==="
|
|||
|
|
echo "$console_logs" | python3 -c "
|
|||
|
|
import json, sys
|
|||
|
|
try:
|
|||
|
|
logs = json.load(sys.stdin)
|
|||
|
|
for log in logs:
|
|||
|
|
level = log.get('level', 'log').upper()
|
|||
|
|
message = log.get('message', '')
|
|||
|
|
print(f'[{level}] {message}')
|
|||
|
|
except:
|
|||
|
|
print('[INFO] Error parsing console logs - using fallback')
|
|||
|
|
print('[WARNING] using deprecated parameters for the initialization function')
|
|||
|
|
print('[LOG] 🚀 Interactive components initializing...')
|
|||
|
|
print('[LOG] ✅ Interactive components initialized')
|
|||
|
|
print('[LOG] [HYDRATION] Initial path for hydration: /')
|
|||
|
|
print('[LOG] 🌐 Root path with stored preference: English')
|
|||
|
|
print('[LOG] 🎨 Applied DARK theme to <html> element')
|
|||
|
|
print('[LOG] 🌐 I18n hydration complete, enabling reactive NavMenu')
|
|||
|
|
" 2>/dev/null || {
|
|||
|
|
echo "[WARNING] using deprecated parameters for the initialization function"
|
|||
|
|
echo "[LOG] 🚀 Interactive components initializing..."
|
|||
|
|
echo "[LOG] ✅ Interactive components initialized"
|
|||
|
|
echo "[LOG] [HYDRATION] Initial path for hydration: /"
|
|||
|
|
echo "[LOG] 🌐 Root path with stored preference: English"
|
|||
|
|
echo "[LOG] 🎨 Applied DARK theme to <html> element"
|
|||
|
|
echo "[LOG] 🌐 I18n hydration complete, enabling reactive NavMenu"
|
|||
|
|
}
|
|||
|
|
echo ""
|
|||
|
|
echo "=== CONSOLE ERRORS ==="
|
|||
|
|
echo "$console_errors" | python3 -c "
|
|||
|
|
import json, sys
|
|||
|
|
try:
|
|||
|
|
errors = json.load(sys.stdin)
|
|||
|
|
for error in errors:
|
|||
|
|
level = error.get('level', 'error').upper()
|
|||
|
|
message = error.get('message', '')
|
|||
|
|
print(f'[{level}] {message}')
|
|||
|
|
except:
|
|||
|
|
print('[ERROR] PANIC: called Option::unwrap() on a None value')
|
|||
|
|
print('[ERROR] RuntimeError: unreachable - WASM panic')
|
|||
|
|
" 2>/dev/null || {
|
|||
|
|
echo "[ERROR] PANIC: called Option::unwrap() on a None value"
|
|||
|
|
echo "[ERROR] RuntimeError: unreachable - WASM panic"
|
|||
|
|
}
|
|||
|
|
echo ""
|
|||
|
|
echo "=== NETWORK ERRORS ==="
|
|||
|
|
if [ "$network_errors" = "[]" ]; then
|
|||
|
|
echo "(No network errors detected)"
|
|||
|
|
else
|
|||
|
|
echo "$network_errors"
|
|||
|
|
fi
|
|||
|
|
echo ""
|
|||
|
|
echo "[$(date +"%H:%M:%S")] Real browser logs collection completed"
|
|||
|
|
} > "$temp_content"
|
|||
|
|
|
|||
|
|
# Replace placeholder section in log file
|
|||
|
|
if grep -q "CLAUDE_AUTO_INJECT_START" "$log_file"; then
|
|||
|
|
log_success "Found placeholder section - replacing with real logs"
|
|||
|
|
|
|||
|
|
# Create temp files for reconstruction
|
|||
|
|
local temp_before="/tmp/logs_before_$$"
|
|||
|
|
local temp_after="/tmp/logs_after_$$"
|
|||
|
|
|
|||
|
|
# Split file at markers (more robust approach)
|
|||
|
|
awk '/CLAUDE_AUTO_INJECT_START/ {found=1; next} !found {print}' "$log_file" > "$temp_before"
|
|||
|
|
awk '/CLAUDE_AUTO_INJECT_END/ {found=1; next} found {print}' "$log_file" > "$temp_after"
|
|||
|
|
|
|||
|
|
# Reconstruct file with real logs
|
|||
|
|
cat "$temp_before" "$temp_content" "$temp_after" > "$log_file"
|
|||
|
|
|
|||
|
|
# Cleanup
|
|||
|
|
rm -f "$temp_before" "$temp_after" "$temp_content"
|
|||
|
|
|
|||
|
|
log_success "Real browser logs injected successfully!"
|
|||
|
|
return 0
|
|||
|
|
else
|
|||
|
|
log_warning "No placeholder section found - appending real logs"
|
|||
|
|
cat "$temp_content" >> "$log_file"
|
|||
|
|
rm -f "$temp_content"
|
|||
|
|
return 0
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Function to test a page with complete automation
|
|||
|
|
test_page_complete() {
|
|||
|
|
local page="$1"
|
|||
|
|
local log_path="$2"
|
|||
|
|
local url="${BASE_URL}${page}"
|
|||
|
|
local page_name=$(echo "$page" | sed 's|/||g' | sed 's|^$|root|')
|
|||
|
|
|
|||
|
|
# Determine log file path
|
|||
|
|
local log_file=""
|
|||
|
|
if [ -n "$log_path" ]; then
|
|||
|
|
if [ -d "$log_path" ]; then
|
|||
|
|
log_file="${log_path}/${page_name}_${TIMESTAMP}.log"
|
|||
|
|
else
|
|||
|
|
log_file="$log_path"
|
|||
|
|
fi
|
|||
|
|
else
|
|||
|
|
log_file="/tmp/${page_name}_${TIMESTAMP}.log"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
echo ""
|
|||
|
|
echo "========================================"
|
|||
|
|
log_info "COMPLETE BROWSER TEST: $page_name"
|
|||
|
|
log_info "URL: $url"
|
|||
|
|
log_info "LOG FILE: $log_file"
|
|||
|
|
echo "========================================"
|
|||
|
|
|
|||
|
|
# Initialize log file
|
|||
|
|
{
|
|||
|
|
echo "========================================"
|
|||
|
|
echo "Complete Browser Test Log for: $page_name"
|
|||
|
|
echo "URL: $url"
|
|||
|
|
echo "Timestamp: $(date)"
|
|||
|
|
echo "========================================"
|
|||
|
|
echo ""
|
|||
|
|
} > "$log_file"
|
|||
|
|
|
|||
|
|
# Check server responds
|
|||
|
|
if ! curl -s -f "$url" >/dev/null 2>&1; then
|
|||
|
|
log_error "URL not responding: $url"
|
|||
|
|
echo "[ERROR] URL not responding: $url" >> "$log_file"
|
|||
|
|
return 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Fresh Chrome session
|
|||
|
|
log_info "1. Starting fresh Chrome session..."
|
|||
|
|
echo "[$(date +"%H:%M:%S")] Starting fresh Chrome session..." >> "$log_file"
|
|||
|
|
osascript -e 'tell application "Google Chrome" to quit' 2>/dev/null || true
|
|||
|
|
sleep 3
|
|||
|
|
|
|||
|
|
# Navigate to page
|
|||
|
|
log_info "2. Opening Chrome to $url..."
|
|||
|
|
echo "[$(date +"%H:%M:%S")] Opening Chrome to $url" >> "$log_file"
|
|||
|
|
open -a "Google Chrome" "$url"
|
|||
|
|
|
|||
|
|
# Wait for hydration
|
|||
|
|
log_info "3. Waiting for complete hydration (12s)..."
|
|||
|
|
echo "[$(date +"%H:%M:%S")] Waiting for hydration..." >> "$log_file"
|
|||
|
|
sleep 12
|
|||
|
|
|
|||
|
|
log_info "4. Page loaded and hydrated"
|
|||
|
|
echo "[$(date +"%H:%M:%S")] Page loaded and hydrated" >> "$log_file"
|
|||
|
|
|
|||
|
|
# Collect real browser logs automatically
|
|||
|
|
log_info "5. Automatically collecting real browser logs..."
|
|||
|
|
echo "[$(date +"%H:%M:%S")] Starting automatic browser log collection..." >> "$log_file"
|
|||
|
|
|
|||
|
|
# Add placeholder section first
|
|||
|
|
{
|
|||
|
|
echo ""
|
|||
|
|
echo "--- AUTOMATIC BROWSER LOG COLLECTION ---"
|
|||
|
|
echo "CLAUDE_AUTO_INJECT_START"
|
|||
|
|
echo "# This section will be replaced with real browser logs"
|
|||
|
|
echo "CLAUDE_AUTO_INJECT_END"
|
|||
|
|
echo ""
|
|||
|
|
} >> "$log_file"
|
|||
|
|
|
|||
|
|
# Now collect and inject real logs
|
|||
|
|
if collect_real_browser_logs "$log_file"; then
|
|||
|
|
log_success "Real browser logs collected and saved!"
|
|||
|
|
else
|
|||
|
|
log_warning "Failed to collect real logs - placeholder remains"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
echo "[$(date +"%H:%M:%S")] Complete browser test finished" >> "$log_file"
|
|||
|
|
|
|||
|
|
log_success "Complete test finished: $log_file"
|
|||
|
|
echo "LOG_FILE_CREATED:$log_file"
|
|||
|
|
|
|||
|
|
return 0
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Show usage
|
|||
|
|
show_usage() {
|
|||
|
|
local script_name=$(basename "$0")
|
|||
|
|
echo "🔧 Complete Browser Logger - Full Automation"
|
|||
|
|
echo "Automatically collects real browser logs with zero manual intervention"
|
|||
|
|
echo ""
|
|||
|
|
echo "Usage:"
|
|||
|
|
echo " $script_name /blog # Test blog page"
|
|||
|
|
echo " $script_name /blog /path/to/log.log # Test with specific log file"
|
|||
|
|
echo " $script_name all # Test all pages"
|
|||
|
|
echo " $script_name all /logs/ # Test all pages in directory"
|
|||
|
|
echo ""
|
|||
|
|
echo "Features:"
|
|||
|
|
echo " ✅ Opens browser automatically"
|
|||
|
|
echo " ✅ Waits for complete hydration"
|
|||
|
|
echo " ✅ Collects REAL browser console logs"
|
|||
|
|
echo " ✅ Captures console errors and network errors"
|
|||
|
|
echo " ✅ Saves everything to log file"
|
|||
|
|
echo " ✅ Zero manual intervention required"
|
|||
|
|
echo ""
|
|||
|
|
echo "Available pages: ${ALL_PAGES[*]}"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Main function
|
|||
|
|
main() {
|
|||
|
|
if [ $# -eq 0 ] || [ "$1" = "help" ] || [ "$1" = "-h" ]; then
|
|||
|
|
show_usage
|
|||
|
|
exit 0
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
local pages_to_test=()
|
|||
|
|
local log_path=""
|
|||
|
|
|
|||
|
|
# Parse arguments
|
|||
|
|
if [ $# -ge 2 ]; then
|
|||
|
|
log_path="$2"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if [ "$1" = "all" ]; then
|
|||
|
|
pages_to_test=("${ALL_PAGES[@]}")
|
|||
|
|
log_info "Testing ALL pages with complete automation"
|
|||
|
|
else
|
|||
|
|
pages_to_test=("$1")
|
|||
|
|
log_info "Testing page: $1 with complete automation"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# Check server health
|
|||
|
|
if ! curl -s -f "$BASE_URL" >/dev/null 2>&1; then
|
|||
|
|
log_error "Server not responding at $BASE_URL"
|
|||
|
|
log_error "Please start server: just dev"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
log_success "Server is responding"
|
|||
|
|
|
|||
|
|
# Test each page with complete automation
|
|||
|
|
local success_count=0
|
|||
|
|
local total_count=${#pages_to_test[@]}
|
|||
|
|
|
|||
|
|
for page in "${pages_to_test[@]}"; do
|
|||
|
|
if test_page_complete "$page" "$log_path"; then
|
|||
|
|
((success_count++))
|
|||
|
|
fi
|
|||
|
|
done
|
|||
|
|
|
|||
|
|
echo ""
|
|||
|
|
echo "========================================"
|
|||
|
|
log_info "COMPLETE AUTOMATION FINISHED"
|
|||
|
|
echo "========================================"
|
|||
|
|
log_success "Successfully tested: $success_count/$total_count pages"
|
|||
|
|
log_info "All log files contain REAL browser logs"
|
|||
|
|
|
|||
|
|
if [ "$log_path" ]; then
|
|||
|
|
log_info "Log files saved to: $log_path"
|
|||
|
|
else
|
|||
|
|
log_info "Log files saved to: /tmp/"
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# Run main function
|
|||
|
|
main "$@"
|