Integrate CSP hash update process into test framework

This commit is contained in:
colin 2025-07-06 16:05:03 -04:00
parent 2b37907c27
commit 869b08ec0e
13 changed files with 1130 additions and 0 deletions

97
tests/README.md Normal file
View File

@ -0,0 +1,97 @@
# Resume Site Tests
This directory contains tests for the resume site.
## Directory Structure
- `unit/`: Unit tests for JavaScript files and other components
- `integration/`: Integration tests that test components working together
- `e2e/`: End-to-end tests that simulate user interactions
- `*.test.js`, `*.spec.js`: Playwright test files
- `lighthouse.js`: Lighthouse performance and accessibility tests
- `serve.js`: Simple Node.js server for testing
- `server.js`: Alternative server implementation
- `pre-test-setup.sh`: Script to set up the test environment, including updating CSP hashes
## Running Tests
To run all tests:
```bash
./run-all-tests.sh
```
Or using npm:
```bash
npm test
```
This will:
1. Run the pre-test setup script to update CSP hashes
2. Check if the server is running
3. Run all shell script tests
4. Run Playwright tests if available
5. Run Lighthouse tests
## Content Security Policy (CSP) Testing
The CSP hash update process is an important part of the testing framework. It ensures that:
1. All JavaScript and CSS files have integrity hashes
2. All inline styles have proper CSP hashes
3. The Caddyfile and HTML files have the correct CSP headers/meta tags
The `pre-test-setup.sh` script runs the `update-csp-hashes.sh` script to update all CSP hashes before running the tests. This ensures that any changes to the website are properly reflected in the CSP hashes.
The `csp-hash-test.sh` integration test checks if the CSP hash update process is working properly by verifying that:
- CSP headers are present in the response
- CSP headers contain the required directives
- JavaScript and CSS files have integrity attributes
- HTML files have CSP meta tags
## Running Specific Tests
### JavaScript Tests
```bash
npm run test:js
```
### Lighthouse Tests
```bash
npm run test:lighthouse
```
### Starting the Test Server
```bash
npm run serve
```
## Adding New Tests
### Shell Script Tests
Add new test scripts to the appropriate directory:
- `unit/`: For unit tests
- `integration/`: For integration tests
- `e2e/`: For end-to-end tests
Shell script tests should:
- Be executable bash scripts
- Return exit code 0 for success, non-zero for failure
- For integration and e2e tests, accept a base URL as the first argument
### Playwright Tests
Add new Playwright tests with the `.test.js` or `.spec.js` extension in the tests directory.
## Test Requirements
As per the project guidelines, all tests must:
- Pass for both mobile and desktop viewports
- Maintain Lighthouse scores: 100/100 for accessibility and SEO
- Include meaningful assertions, not placeholders

View File

@ -0,0 +1,92 @@
#!/bin/bash
# =====================================================================
# csp-hash-test.sh - Test the CSP hash update process
# =====================================================================
# This script checks if the CSP hash update process is working properly
# =====================================================================
# Check if base URL is provided
if [ -z "$1" ]; then
BASE_URL="http://localhost:8080"
else
BASE_URL="$1"
fi
echo "=== Testing CSP Hash Update Process ==="
echo "Using base URL: $BASE_URL"
# Array to track failures
FAILURES=0
# Check if the CSP headers are present
echo "Checking if CSP headers are present..."
RESPONSE=$(curl -s -I "$BASE_URL/")
if echo "$RESPONSE" | grep -q "Content-Security-Policy"; then
echo "✅ CSP header found in response"
else
echo "❌ CSP header not found in response"
FAILURES=$((FAILURES+1))
fi
# Check if the CSP header contains the required directives
echo "Checking if CSP header contains required directives..."
CSP_HEADER=$(curl -s -I "$BASE_URL/" | grep -i "Content-Security-Policy" | sed 's/.*: //')
for directive in "default-src" "script-src" "style-src" "img-src" "font-src" "connect-src" "object-src" "frame-ancestors" "base-uri" "form-action"; do
if echo "$CSP_HEADER" | grep -q "$directive"; then
echo "✅ CSP header contains $directive directive"
else
echo "❌ CSP header does not contain $directive directive"
FAILURES=$((FAILURES+1))
fi
done
# Check if JavaScript files have integrity attributes
echo "Checking if JavaScript files have integrity attributes..."
for js_file in "theme.js" "includes.js"; do
HTML=$(curl -s "$BASE_URL/")
if echo "$HTML" | grep -q "$js_file.*integrity"; then
echo "$js_file has integrity attribute"
else
echo "$js_file does not have integrity attribute"
FAILURES=$((FAILURES+1))
fi
done
# Check if CSS files have integrity attributes
echo "Checking if CSS files have integrity attributes..."
HTML=$(curl -s "$BASE_URL/")
if echo "$HTML" | grep -q "styles.css.*integrity"; then
echo "✅ styles.css has integrity attribute"
else
echo "❌ styles.css does not have integrity attribute"
FAILURES=$((FAILURES+1))
fi
# Check if HTML files have CSP meta tags
echo "Checking if HTML files have CSP meta tags..."
HTML=$(curl -s "$BASE_URL/")
if echo "$HTML" | grep -q '<meta http-equiv="Content-Security-Policy"'; then
echo "✅ HTML file has CSP meta tag"
else
echo "❌ HTML file does not have CSP meta tag"
FAILURES=$((FAILURES+1))
fi
# Check if the update-csp-hashes.sh script exists
echo "Checking if update-csp-hashes.sh script exists..."
if [ -f "$(pwd)/docker/resume/update-csp-hashes.sh" ]; then
echo "✅ update-csp-hashes.sh script exists"
else
echo "❌ update-csp-hashes.sh script does not exist"
FAILURES=$((FAILURES+1))
fi
# Check if any failures occurred
if [ "$FAILURES" -eq 0 ]; then
echo "=== All CSP Hash Tests Passed ==="
exit 0
else
echo "=== CSP Hash Tests Failed: $FAILURES failures ==="
exit 1
fi

View File

@ -0,0 +1,52 @@
#!/bin/bash
# =====================================================================
# test-csv-tool.sh - Test the CSV tool functionality
# =====================================================================
# This script checks if the CSV tool page loads without CSP errors
# =====================================================================
# Check if base URL is provided
if [ -z "$1" ]; then
BASE_URL="http://localhost:8080"
else
BASE_URL="$1"
fi
echo "=== Testing CSV Tool ==="
echo "Using base URL: $BASE_URL"
# Create a test CSV file
echo "Name,Age,City
John,30,New York
Jane,25,San Francisco
Bob,40,Chicago" > /tmp/test.csv
# Check if the page loads properly
echo "Checking if the CSV tool page loads properly..."
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/one-pager-tools/csv-tool.html")
if [ "$RESPONSE" -eq 200 ]; then
echo "✅ CSV tool page loads successfully (HTTP $RESPONSE)"
else
echo "❌ CSV tool page failed to load (HTTP $RESPONSE)"
rm -f /tmp/test.csv
exit 1
fi
# Check for CSP errors in the response headers
echo "Checking for CSP errors in response headers..."
CSP_HEADER=$(curl -s -I "$BASE_URL/one-pager-tools/csv-tool.html" | grep -i "Content-Security-Policy")
if [ -n "$CSP_HEADER" ]; then
echo "✅ CSP header found in response"
else
echo "❌ CSP header not found in response"
rm -f /tmp/test.csv
exit 1
fi
# Clean up
rm -f /tmp/test.csv
echo "=== CSV Tool Test Completed Successfully ==="
exit 0

View File

@ -0,0 +1,122 @@
#!/bin/bash
# =====================================================================
# functional-test.sh - Test the main functionality of the website
# =====================================================================
# This script checks if the main features of the website are working
# =====================================================================
# Check if base URL is provided
if [ -z "$1" ]; then
BASE_URL="http://localhost:8080"
else
BASE_URL="$1"
fi
echo "=== Testing Website Functionality ==="
echo "Using base URL: $BASE_URL"
# Array to track failures
FAILURES=0
# Function to test a page and check for expected content
test_page() {
local url="$1"
local name="$2"
local expected_title="$3"
local expected_content="$4"
echo "Testing $name page at $url"
# Check if the page loads
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$url")
if [ "$RESPONSE" -eq 200 ]; then
echo "$name page loads successfully (HTTP $RESPONSE)"
else
echo "$name page failed to load (HTTP $RESPONSE)"
FAILURES=$((FAILURES+1))
return
fi
# Check page title
TITLE=$(curl -s "$url" | grep -o "<title>.*</title>" | sed 's/<title>\(.*\)<\/title>/\1/')
if [[ "$TITLE" == *"$expected_title"* ]]; then
echo "✅ Page title matches: $TITLE"
else
echo "❌ Page title doesn't match. Expected: $expected_title, Got: $TITLE"
FAILURES=$((FAILURES+1))
fi
# Check for expected content
if [ -n "$expected_content" ]; then
CONTENT=$(curl -s "$url")
if echo "$CONTENT" | grep -q "$expected_content"; then
echo "✅ Page contains expected content: $expected_content"
else
echo "❌ Page doesn't contain expected content: $expected_content"
FAILURES=$((FAILURES+1))
fi
fi
echo "---"
}
# Test main page
test_page "$BASE_URL/" "Main" "Colin Knapp - Portfolio" "Colin Knapp"
# Test stories page
test_page "$BASE_URL/stories/" "Stories" "Stories" "Case Studies"
# Test CSV tool
test_page "$BASE_URL/one-pager-tools/csv-tool.html" "CSV Tool" "CSV Viewer" "Paste your CSV data here"
# Check for JavaScript files
echo "Checking for required JavaScript files..."
JS_FILES=("theme.js" "includes.js" "utils.js")
for js_file in "${JS_FILES[@]}"; do
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/$js_file")
if [ "$RESPONSE" -eq 200 ]; then
echo "$js_file loads successfully (HTTP $RESPONSE)"
else
echo "$js_file failed to load (HTTP $RESPONSE)"
FAILURES=$((FAILURES+1))
fi
done
# Check for CSS files
echo "Checking for required CSS files..."
CSS_FILES=("styles.css")
for css_file in "${CSS_FILES[@]}"; do
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/$css_file")
if [ "$RESPONSE" -eq 200 ]; then
echo "$css_file loads successfully (HTTP $RESPONSE)"
else
echo "$css_file failed to load (HTTP $RESPONSE)"
FAILURES=$((FAILURES+1))
fi
done
# Check for security headers
echo "Checking for security headers..."
HEADERS=$(curl -s -I "$BASE_URL/")
if echo "$HEADERS" | grep -q "Content-Security-Policy"; then
echo "✅ Content-Security-Policy header found"
else
echo "❌ Content-Security-Policy header not found"
FAILURES=$((FAILURES+1))
fi
if echo "$HEADERS" | grep -q "X-Frame-Options"; then
echo "✅ X-Frame-Options header found"
else
echo "❌ X-Frame-Options header not found"
FAILURES=$((FAILURES+1))
fi
# Check if any failures occurred
if [ "$FAILURES" -eq 0 ]; then
echo "=== All Functionality Tests Passed ==="
exit 0
else
echo "=== Functionality Tests Failed: $FAILURES failures ==="
exit 1
fi

View File

@ -0,0 +1,108 @@
#!/bin/bash
# =====================================================================
# includes-test.sh - Test the includes functionality
# =====================================================================
# This script checks if the includes system is working properly
# =====================================================================
# Check if base URL is provided
if [ -z "$1" ]; then
BASE_URL="http://localhost:8080"
else
BASE_URL="$1"
fi
echo "=== Testing Includes Functionality ==="
echo "Using base URL: $BASE_URL"
# Array to track failures
FAILURES=0
# Test if includes.js exists and loads properly
echo "Checking if includes.js exists and loads properly..."
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/includes.js")
if [ "$RESPONSE" -eq 200 ]; then
echo "✅ includes.js loads successfully (HTTP $RESPONSE)"
# Check includes.js content
INCLUDES_JS=$(curl -s "$BASE_URL/includes.js")
if echo "$INCLUDES_JS" | grep -q "includeHTML"; then
echo "✅ includes.js contains includeHTML function"
else
echo "❌ includes.js doesn't contain includeHTML function"
FAILURES=$((FAILURES+1))
fi
if echo "$INCLUDES_JS" | grep -q "DOMContentLoaded"; then
echo "✅ includes.js contains DOMContentLoaded event listener"
else
echo "❌ includes.js doesn't contain DOMContentLoaded event listener"
FAILURES=$((FAILURES+1))
fi
else
echo "❌ includes.js failed to load (HTTP $RESPONSE)"
FAILURES=$((FAILURES+1))
fi
# Check if the includes/header.html file exists
echo "Checking includes/header.html file..."
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/includes/header.html")
if [ "$RESPONSE" -eq 200 ] || [ "$RESPONSE" -eq 403 ]; then
echo "✅ includes/header.html file exists (HTTP $RESPONSE)"
else
echo "❌ includes/header.html file doesn't exist (HTTP $RESPONSE)"
FAILURES=$((FAILURES+1))
fi
# Check if pages with includes load correctly
echo "Checking pages that use includes..."
INCLUDE_PAGES=(
"template-with-includes.html"
"stories/story-with-includes.html"
"one-pager-tools/tool-with-includes.html"
)
for page in "${INCLUDE_PAGES[@]}"; do
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/$page")
if [ "$RESPONSE" -eq 200 ]; then
echo "$page loads successfully (HTTP $RESPONSE)"
# Check if the page has include placeholders
CONTENT=$(curl -s "$BASE_URL/$page")
if echo "$CONTENT" | grep -q "id=\"header-include\""; then
echo "$page has header include placeholder"
else
echo "$page doesn't have header include placeholder"
FAILURES=$((FAILURES+1))
fi
if echo "$CONTENT" | grep -q "id=\"footer-include\""; then
echo "$page has footer include placeholder"
else
echo "$page doesn't have footer include placeholder"
FAILURES=$((FAILURES+1))
fi
# Check if includes.js is included in the page
if echo "$CONTENT" | grep -q "includes.js"; then
echo "$page includes the includes.js script"
else
echo "$page doesn't include the includes.js script"
FAILURES=$((FAILURES+1))
fi
else
echo "$page failed to load (HTTP $RESPONSE)"
FAILURES=$((FAILURES+1))
fi
echo "---"
done
# Check if any failures occurred
if [ "$FAILURES" -eq 0 ]; then
echo "=== All Includes Tests Passed ==="
exit 0
else
echo "=== Includes Tests Failed: $FAILURES failures ==="
exit 1
fi

View File

@ -0,0 +1,63 @@
#!/bin/bash
# =====================================================================
# main-page-test.sh - Test the main page functionality
# =====================================================================
# This script checks if the main page loads correctly
# =====================================================================
# Check if base URL is provided
if [ -z "$1" ]; then
BASE_URL="http://localhost:8080"
else
BASE_URL="$1"
fi
echo "=== Testing Main Page ==="
echo "Using base URL: $BASE_URL"
# Check if the main page loads properly
echo "Checking if the main page loads properly..."
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/index.html")
if [ "$RESPONSE" -eq 200 ]; then
echo "✅ Main page loads successfully (HTTP $RESPONSE)"
else
echo "❌ Main page failed to load (HTTP $RESPONSE)"
exit 1
fi
# Check for page title
echo "Checking page title..."
TITLE=$(curl -s "$BASE_URL/index.html" | grep -o "<title>.*</title>")
if [ -n "$TITLE" ]; then
echo "✅ Page title found: $TITLE"
else
echo "❌ Page title not found"
exit 1
fi
# Check for CSS loading
echo "Checking if CSS loads properly..."
CSS_LINK=$(curl -s "$BASE_URL/index.html" | grep -o '<link[^>]*href="[^"]*styles.css[^"]*"[^>]*>')
if [ -n "$CSS_LINK" ]; then
echo "✅ CSS link found: $CSS_LINK"
# Check if the CSS file itself loads
CSS_URL=$(echo "$CSS_LINK" | grep -o 'href="[^"]*"' | sed 's/href="//;s/"$//')
CSS_RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/$CSS_URL")
if [ "$CSS_RESPONSE" -eq 200 ]; then
echo "✅ CSS file loads successfully (HTTP $CSS_RESPONSE)"
else
echo "❌ CSS file failed to load (HTTP $CSS_RESPONSE)"
exit 1
fi
else
echo "❌ CSS link not found"
exit 1
fi
echo "=== Main Page Test Completed Successfully ==="
exit 0

View File

@ -0,0 +1,76 @@
#!/bin/bash
# =====================================================================
# stories-test.sh - Test all story pages
# =====================================================================
# This script checks if all story pages load correctly
# =====================================================================
# Check if base URL is provided
if [ -z "$1" ]; then
BASE_URL="http://localhost:8080"
else
BASE_URL="$1"
fi
echo "=== Testing Story Pages ==="
echo "Using base URL: $BASE_URL"
# Get the list of story pages from the stories index
echo "Getting list of story pages..."
STORY_LINKS=$(curl -s "$BASE_URL/stories/index.html" | grep -o 'href="[^"]*\.html"' | grep -v 'index.html' | sed 's/href="//;s/"$//')
if [ -z "$STORY_LINKS" ]; then
echo "❌ No story links found in stories/index.html"
exit 1
fi
echo "Found story links: $STORY_LINKS"
# Test each story page
FAILED=0
for link in $STORY_LINKS; do
# Make sure the link is properly formed
if [[ "$link" != /* && "$link" != http* ]]; then
# Relative link, add stories/ prefix if needed
if [[ "$link" != stories/* ]]; then
STORY_URL="$BASE_URL/stories/$link"
else
STORY_URL="$BASE_URL/$link"
fi
elif [[ "$link" == /* ]]; then
# Absolute path
STORY_URL="$BASE_URL$link"
else
# Full URL
STORY_URL="$link"
fi
echo "Testing story page: $STORY_URL"
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$STORY_URL")
if [ "$RESPONSE" -eq 200 ]; then
echo "✅ Story page loads successfully (HTTP $RESPONSE)"
# Check for required elements
CONTENT=$(curl -s "$STORY_URL")
if echo "$CONTENT" | grep -q "<h1>" && echo "$CONTENT" | grep -q "<p>"; then
echo "✅ Story page has required elements (h1 and p tags)"
else
echo "❌ Story page is missing required elements"
FAILED=1
fi
else
echo "❌ Story page failed to load (HTTP $RESPONSE)"
FAILED=1
fi
echo "---"
done
if [ "$FAILED" -eq 0 ]; then
echo "=== All Story Pages Test Completed Successfully ==="
exit 0
else
echo "=== Story Pages Test Failed ==="
exit 1
fi

88
tests/integration/theme-test.sh Executable file
View File

@ -0,0 +1,88 @@
#!/bin/bash
# =====================================================================
# theme-test.sh - Test the theme functionality
# =====================================================================
# This script checks if the theme system is working properly
# =====================================================================
# Check if base URL is provided
if [ -z "$1" ]; then
BASE_URL="http://localhost:8080"
else
BASE_URL="$1"
fi
echo "=== Testing Theme Functionality ==="
echo "Using base URL: $BASE_URL"
# Array to track failures
FAILURES=0
# Test if theme.js exists and loads properly
echo "Checking if theme.js exists and loads properly..."
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/theme.js")
if [ "$RESPONSE" -eq 200 ]; then
echo "✅ theme.js loads successfully (HTTP $RESPONSE)"
# Check theme.js content
THEME_JS=$(curl -s "$BASE_URL/theme.js")
if echo "$THEME_JS" | grep -q "DOMContentLoaded"; then
echo "✅ theme.js contains DOMContentLoaded event listener"
else
echo "❌ theme.js doesn't contain DOMContentLoaded event listener"
FAILURES=$((FAILURES+1))
fi
if echo "$THEME_JS" | grep -q "themeToggle"; then
echo "✅ theme.js contains themeToggle functionality"
else
echo "❌ theme.js doesn't contain themeToggle functionality"
FAILURES=$((FAILURES+1))
fi
if echo "$THEME_JS" | grep -q "localStorage"; then
echo "✅ theme.js uses localStorage for theme persistence"
else
echo "❌ theme.js doesn't use localStorage for theme persistence"
FAILURES=$((FAILURES+1))
fi
else
echo "❌ theme.js failed to load (HTTP $RESPONSE)"
FAILURES=$((FAILURES+1))
fi
# Check if CSS has theme-related styles
echo "Checking if styles.css has theme-related styles..."
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/styles.css")
if [ "$RESPONSE" -eq 200 ]; then
echo "✅ styles.css loads successfully (HTTP $RESPONSE)"
# Check styles.css content for theme-related styles
STYLES_CSS=$(curl -s "$BASE_URL/styles.css")
if echo "$STYLES_CSS" | grep -q "data-theme"; then
echo "✅ styles.css contains data-theme attribute selectors"
else
echo "❌ styles.css doesn't contain data-theme attribute selectors"
FAILURES=$((FAILURES+1))
fi
# Check for dark mode styles
if echo "$STYLES_CSS" | grep -q "dark"; then
echo "✅ styles.css contains dark mode styles"
else
echo "❌ styles.css doesn't contain dark mode styles"
FAILURES=$((FAILURES+1))
fi
else
echo "❌ styles.css failed to load (HTTP $RESPONSE)"
FAILURES=$((FAILURES+1))
fi
# Check if any failures occurred
if [ "$FAILURES" -eq 0 ]; then
echo "=== All Theme Tests Passed ==="
exit 0
else
echo "=== Theme Tests Failed: $FAILURES failures ==="
exit 1
fi

35
tests/pre-test-setup.sh Executable file
View File

@ -0,0 +1,35 @@
#!/bin/bash
# =====================================================================
# pre-test-setup.sh - Setup for tests
# =====================================================================
# This script sets up the environment for testing
# =====================================================================
set -e # Exit on any error
TESTS_DIR="$(dirname "$0")"
RESUME_DIR="$(pwd)/docker/resume"
echo "=== Setting Up Test Environment ==="
# Check if we're in the correct directory
if [ ! -d "$RESUME_DIR" ]; then
echo "Error: Could not find the resume directory at $RESUME_DIR"
echo "Make sure you're running this script from the project root"
exit 1
fi
# Run the CSP hash update script
echo "Running CSP hash update script..."
cd "$RESUME_DIR"
if [ -f "./update-csp-hashes.sh" ]; then
./update-csp-hashes.sh
else
echo "Error: Could not find update-csp-hashes.sh script"
exit 1
fi
# Return to the original directory
cd - > /dev/null
echo "=== Test Environment Setup Complete ==="

112
tests/run-all-tests.sh Executable file
View File

@ -0,0 +1,112 @@
#!/bin/bash
# =====================================================================
# run-all-tests.sh - Run all tests against an existing server
# =====================================================================
# This script runs all tests against an existing server
# =====================================================================
set -e # Exit on any error
# Define constants
BASE_URL="http://localhost:8080"
TESTS_DIR="$(dirname "$0")"
# Run pre-test setup
echo "Running pre-test setup..."
if [ -f "$TESTS_DIR/pre-test-setup.sh" ]; then
"$TESTS_DIR/pre-test-setup.sh"
else
echo "Warning: pre-test-setup.sh not found, skipping setup"
fi
# Check if the server is running
echo "Checking if server is running at $BASE_URL..."
if ! curl -s -o /dev/null -w "%{http_code}" "$BASE_URL/" | grep -q "200"; then
echo "Server is not running at $BASE_URL. Please start it using:"
echo "cd docker/resume && ./caddy.sh"
exit 1
fi
echo "Server is running at $BASE_URL"
# Run shell script tests
run_shell_tests() {
echo "Running shell script tests..."
# Run unit tests
echo "Running unit tests..."
if [ -d "$TESTS_DIR/unit" ] && [ "$(ls -A "$TESTS_DIR/unit")" ]; then
for test in "$TESTS_DIR/unit"/*.sh; do
if [ -f "$test" ] && [ -x "$test" ]; then
echo "Running unit test: $(basename "$test")"
"$test" || echo "FAILED: $(basename "$test")"
fi
done
else
echo "No unit tests found."
fi
# Run integration tests
echo "Running integration tests..."
if [ -d "$TESTS_DIR/integration" ] && [ "$(ls -A "$TESTS_DIR/integration")" ]; then
for test in "$TESTS_DIR/integration"/*.sh; do
if [ -f "$test" ] && [ -x "$test" ]; then
echo "Running integration test: $(basename "$test")"
"$test" "$BASE_URL" || echo "FAILED: $(basename "$test")"
fi
done
# Check for subdirectories
for dir in "$TESTS_DIR/integration"/*/; do
if [ -d "$dir" ]; then
for test in "$dir"*.sh; do
if [ -f "$test" ] && [ -x "$test" ]; then
echo "Running integration test: $(basename "$test")"
"$test" "$BASE_URL" || echo "FAILED: $(basename "$test")"
fi
done
fi
done
else
echo "No integration tests found."
fi
# Run e2e tests
echo "Running e2e tests..."
if [ -d "$TESTS_DIR/e2e" ] && [ "$(ls -A "$TESTS_DIR/e2e")" ]; then
for test in "$TESTS_DIR/e2e"/*.sh; do
if [ -f "$test" ] && [ -x "$test" ]; then
echo "Running e2e test: $(basename "$test")"
"$test" "$BASE_URL" || echo "FAILED: $(basename "$test")"
fi
done
else
echo "No e2e tests found."
fi
}
# Run JavaScript tests
run_js_tests() {
echo "Running JavaScript tests..."
# Check if Playwright is installed
if command -v npx &> /dev/null && npx playwright --version &> /dev/null; then
# Run Playwright tests
echo "Running Playwright tests..."
npx playwright test || echo "FAILED: Playwright tests"
else
echo "Playwright not found, skipping Playwright tests."
fi
# Run Lighthouse tests if available
if [ -f "$TESTS_DIR/lighthouse.js" ]; then
echo "Running Lighthouse tests..."
node "$TESTS_DIR/lighthouse.js" "$BASE_URL" || echo "FAILED: Lighthouse tests"
fi
}
# Main execution
echo "=== Starting Test Suite ==="
run_shell_tests
run_js_tests
echo "=== Test Suite Completed ==="

192
tests/run-tests.sh Executable file
View File

@ -0,0 +1,192 @@
#!/bin/bash
# =====================================================================
# run-tests.sh - Main test runner for the resume site
# =====================================================================
# This script starts a local Caddy server and runs all tests against it
# =====================================================================
set -e # Exit on any error
# Define constants
TEST_PORT=8080
CADDY_DIR="docker/resume"
CADDY_FILE="Caddyfile.local"
TESTS_DIR="$(dirname "$0")"
LOG_FILE="$TESTS_DIR/test-run.log"
# Function to clean up processes on exit
cleanup() {
echo "Cleaning up..."
# Find and kill any Caddy processes we started
if [ -f "$TESTS_DIR/.caddy.pid" ]; then
CADDY_PID=$(cat "$TESTS_DIR/.caddy.pid")
if ps -p $CADDY_PID > /dev/null; then
echo "Stopping Caddy server (PID: $CADDY_PID)"
kill $CADDY_PID
fi
rm "$TESTS_DIR/.caddy.pid"
fi
echo "Cleanup complete"
}
# Register the cleanup function to run on exit
trap cleanup EXIT
# Start the Caddy server
start_caddy() {
echo "Starting Caddy server on port $TEST_PORT..."
# Navigate to the Caddy directory
cd "$CADDY_DIR"
# Check if Caddyfile.local exists, if not, create it from Caddyfile
if [ ! -f "$CADDY_FILE" ]; then
echo "Creating $CADDY_FILE from Caddyfile..."
cp Caddyfile "$CADDY_FILE"
# Modify the Caddyfile.local to use the test port
sed -i '' "s/:80/:$TEST_PORT/g" "$CADDY_FILE"
fi
# Start Caddy in the background using the local config
echo "Running: caddy run --config $CADDY_FILE"
mkdir -p $(dirname "$LOG_FILE") && caddy run --config "$CADDY_FILE" > "$LOG_FILE" 2>&1 &
CADDY_PID=$!
mkdir -p "$TESTS_DIR" && echo $CADDY_PID > "$TESTS_DIR/.caddy.pid"
# Return to the original directory
cd - > /dev/null
# Wait for Caddy to start
echo "Waiting for Caddy to start..."
sleep 2
# Check if Caddy is running
if ! ps -p $CADDY_PID > /dev/null; then
echo "Failed to start Caddy server. Check $LOG_FILE for details."
exit 1
fi
echo "Caddy server started with PID: $CADDY_PID"
# Wait a bit more to ensure Caddy is fully initialized
sleep 3
}
# Run Node.js server for tests that require it
start_node_server() {
if [ -f "$TESTS_DIR/serve.js" ]; then
echo "Starting Node.js server for tests..."
node "$TESTS_DIR/serve.js" > "$TESTS_DIR/node-server.log" 2>&1 &
NODE_SERVER_PID=$!
echo $NODE_SERVER_PID > "$TESTS_DIR/.node-server.pid"
# Wait for Node.js server to start
sleep 2
# Check if Node.js server is running
if ! ps -p $NODE_SERVER_PID > /dev/null; then
echo "Failed to start Node.js server. Check $TESTS_DIR/node-server.log for details."
exit 1
fi
echo "Node.js server started with PID: $NODE_SERVER_PID"
fi
}
# Clean up Node.js server
cleanup_node_server() {
if [ -f "$TESTS_DIR/.node-server.pid" ]; then
NODE_SERVER_PID=$(cat "$TESTS_DIR/.node-server.pid")
if ps -p $NODE_SERVER_PID > /dev/null; then
echo "Stopping Node.js server (PID: $NODE_SERVER_PID)"
kill $NODE_SERVER_PID
fi
rm "$TESTS_DIR/.node-server.pid"
fi
}
# Run shell script tests
run_shell_tests() {
echo "Running shell script tests..."
# Run unit tests
echo "Running unit tests..."
if [ -d "$TESTS_DIR/unit" ] && [ "$(ls -A "$TESTS_DIR/unit")" ]; then
for test in "$TESTS_DIR/unit"/*.sh; do
if [ -f "$test" ] && [ -x "$test" ]; then
echo "Running unit test: $(basename "$test")"
"$test" || echo "FAILED: $(basename "$test")"
fi
done
else
echo "No unit tests found."
fi
# Run integration tests
echo "Running integration tests..."
if [ -d "$TESTS_DIR/integration" ] && [ "$(ls -A "$TESTS_DIR/integration")" ]; then
for test in "$TESTS_DIR/integration"/*.sh; do
if [ -f "$test" ] && [ -x "$test" ]; then
echo "Running integration test: $(basename "$test")"
"$test" "http://localhost:$TEST_PORT" || echo "FAILED: $(basename "$test")"
fi
done
# Check for subdirectories
for dir in "$TESTS_DIR/integration"/*/; do
if [ -d "$dir" ]; then
for test in "$dir"*.sh; do
if [ -f "$test" ] && [ -x "$test" ]; then
echo "Running integration test: $(basename "$test")"
"$test" "http://localhost:$TEST_PORT" || echo "FAILED: $(basename "$test")"
fi
done
fi
done
else
echo "No integration tests found."
fi
# Run e2e tests
echo "Running e2e tests..."
if [ -d "$TESTS_DIR/e2e" ] && [ "$(ls -A "$TESTS_DIR/e2e")" ]; then
for test in "$TESTS_DIR/e2e"/*.sh; do
if [ -f "$test" ] && [ -x "$test" ]; then
echo "Running e2e test: $(basename "$test")"
"$test" "http://localhost:$TEST_PORT" || echo "FAILED: $(basename "$test")"
fi
done
else
echo "No e2e tests found."
fi
}
# Run JavaScript tests
run_js_tests() {
echo "Running JavaScript tests..."
# Check if Playwright is installed
if command -v npx &> /dev/null && npx playwright --version &> /dev/null; then
# Run Playwright tests
echo "Running Playwright tests..."
npx playwright test || echo "FAILED: Playwright tests"
else
echo "Playwright not found, skipping Playwright tests."
fi
# Run Lighthouse tests if available
if [ -f "$TESTS_DIR/lighthouse.js" ]; then
echo "Running Lighthouse tests..."
node "$TESTS_DIR/lighthouse.js" "http://localhost:$TEST_PORT" || echo "FAILED: Lighthouse tests"
fi
}
# Main execution
echo "=== Starting Test Suite ==="
start_caddy
start_node_server
run_shell_tests
run_js_tests
cleanup_node_server
echo "=== Test Suite Completed ==="

48
tests/unit/includes-test.sh Executable file
View File

@ -0,0 +1,48 @@
#!/bin/bash
# =====================================================================
# includes-test.sh - Test the includes.js functionality
# =====================================================================
# This script checks if the includes.js file is valid JavaScript
# =====================================================================
echo "=== Testing includes.js ==="
# Path to the includes.js file
INCLUDES_JS="docker/resume/includes.js"
# Check if the file exists
if [ ! -f "$INCLUDES_JS" ]; then
echo "❌ File not found: $INCLUDES_JS"
exit 1
fi
echo "✅ File exists: $INCLUDES_JS"
# Check if the file is valid JavaScript using node
if command -v node &> /dev/null; then
echo "Checking if the file is valid JavaScript..."
if node --check "$INCLUDES_JS" &> /dev/null; then
echo "✅ File is valid JavaScript"
else
echo "❌ File contains JavaScript syntax errors"
node --check "$INCLUDES_JS"
exit 1
fi
else
echo "⚠️ Node.js not found, skipping JavaScript syntax check"
fi
# Check for required functions
echo "Checking for required functions..."
REQUIRED_FUNCTIONS=("includeHTML")
for func in "${REQUIRED_FUNCTIONS[@]}"; do
if grep -q "function $func" "$INCLUDES_JS"; then
echo "✅ Required function found: $func"
else
echo "❌ Required function not found: $func"
exit 1
fi
done
echo "=== includes.js Test Completed Successfully ==="
exit 0

45
tests/unit/theme-test.sh Executable file
View File

@ -0,0 +1,45 @@
#!/bin/bash
# =====================================================================
# theme-test.sh - Test the theme.js functionality
# =====================================================================
# This script checks if the theme.js file is valid JavaScript
# =====================================================================
echo "=== Testing theme.js ==="
# Path to the theme.js file
THEME_JS="docker/resume/theme.js"
# Check if the file exists
if [ ! -f "$THEME_JS" ]; then
echo "❌ File not found: $THEME_JS"
exit 1
fi
echo "✅ File exists: $THEME_JS"
# Check if the file is valid JavaScript using node
if command -v node &> /dev/null; then
echo "Checking if the file is valid JavaScript..."
if node --check "$THEME_JS" &> /dev/null; then
echo "✅ File is valid JavaScript"
else
echo "❌ File contains JavaScript syntax errors"
node --check "$THEME_JS"
exit 1
fi
else
echo "⚠️ Node.js not found, skipping JavaScript syntax check"
fi
# Check for theme-related functionality
echo "Checking for theme-related functionality..."
if grep -q "dark" "$THEME_JS" || grep -q "light" "$THEME_JS" || grep -q "theme" "$THEME_JS"; then
echo "✅ Theme-related functionality found"
else
echo "❌ No theme-related functionality found"
exit 1
fi
echo "=== theme.js Test Completed Successfully ==="
exit 0