diff --git a/.env.test b/.env.test
new file mode 100644
index 0000000..f758e34
--- /dev/null
+++ b/.env.test
@@ -0,0 +1,31 @@
+# Test Environment Configuration
+DATABASE_URL=postgresql://readur_test:readur_test@localhost:5433/readur_test
+JWT_SECRET=test-jwt-secret-key-not-for-production
+SERVER_ADDRESS=0.0.0.0:8001
+
+# File Storage & Upload (using temp directories)
+UPLOAD_PATH=/tmp/test_uploads
+ALLOWED_FILE_TYPES=pdf,png,jpg,jpeg,txt,doc,docx
+
+# Watch Folder Configuration
+WATCH_FOLDER=/tmp/test_watch
+WATCH_INTERVAL_SECONDS=5
+FILE_STABILITY_CHECK_MS=500
+MAX_FILE_AGE_HOURS=1
+
+# OCR & Processing Settings (reduced for tests)
+OCR_LANGUAGE=eng
+CONCURRENT_OCR_JOBS=2
+OCR_TIMEOUT_SECONDS=60
+MAX_FILE_SIZE_MB=10
+
+# Performance Settings (reduced for tests)
+MEMORY_LIMIT_MB=256
+CPU_PRIORITY=normal
+
+# Test-specific settings
+RUST_LOG=debug
+TEST_ENV=true
+
+# Frontend test configuration
+VITE_API_BASE_URL=http://localhost:8001
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index ff1ce92..da096c1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@ assets/
frontend/dist/
.claude/
uploads/
+test-results/
diff --git a/Makefile b/Makefile
index bc14a68..5bafd64 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-.PHONY: help test test-unit test-integration test-frontend test-e2e test-all test-watch test-clean test-logs test-shell dev-up dev-down dev-logs build clean
+.PHONY: help test test-unit test-integration test-frontend test-e2e test-all test-watch test-clean test-logs test-shell test-results test-html test-results-unit test-results-integration test-results-frontend test-results-clean dev-up dev-down dev-logs build clean
# Default target
help:
@@ -16,6 +16,12 @@ help:
@echo " make test-logs - View test container logs"
@echo " make test-shell - Open shell in test container"
@echo ""
+ @echo "Test Results Commands:"
+ @echo " make test-results - Show latest test summary"
+ @echo " make test-html - Open latest HTML test report"
+ @echo " make test-results-unit - Show latest unit test results"
+ @echo " make test-results-clean- Clean all saved test results"
+ @echo ""
@echo "Development Commands:"
@echo " make dev-up - Start development environment"
@echo " make dev-down - Stop development environment"
@@ -113,4 +119,23 @@ ci-test:
# Quick test for local development (runs faster subset)
quick-test:
@echo "Running quick test suite..."
- @./run-tests.sh unit
\ No newline at end of file
+ @./run-tests.sh unit
+
+# Test results viewing
+test-results:
+ @./view-test-results.sh summary
+
+test-html:
+ @./view-test-results.sh html
+
+test-results-unit:
+ @./view-test-results.sh unit
+
+test-results-integration:
+ @./view-test-results.sh integration
+
+test-results-frontend:
+ @./view-test-results.sh frontend
+
+test-results-clean:
+ @./view-test-results.sh clean
\ No newline at end of file
diff --git a/run-tests.sh b/run-tests.sh
index 618b971..8e2afeb 100755
--- a/run-tests.sh
+++ b/run-tests.sh
@@ -16,6 +16,8 @@ NC='\033[0m' # No Color
COMPOSE_FILE="docker-compose.test.yml"
COMPOSE_PROJECT_NAME="readur_test"
TEST_TIMEOUT=600 # 10 minutes timeout for all tests
+TEST_RESULTS_DIR="test-results"
+TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
# Function to print colored output
print_status() {
@@ -34,6 +36,22 @@ print_warning() {
echo -e "${YELLOW}[!]${NC} $1"
}
+# Function to strip ANSI color codes
+strip_ansi() {
+ sed 's/\x1b\[[0-9;]*m//g'
+}
+
+# Function to save output to file
+save_output() {
+ local test_type=$1
+ local output=$2
+ local status=$3
+ local output_file="${TEST_RESULTS_DIR}/${test_type}/${TIMESTAMP}_${test_type}_${status}.log"
+
+ echo "$output" | strip_ansi > "$output_file"
+ echo "Results saved to: $output_file"
+}
+
# Function to cleanup test environment
cleanup() {
print_status "Cleaning up test environment..."
@@ -161,12 +179,23 @@ main() {
run_unit_tests() {
print_status "Running unit tests..."
- # Run tests locally with test database URL
- if DATABASE_URL="postgresql://readur_test:readur_test@localhost:5433/readur_test" \
- cargo test --lib --no-fail-fast; then
+ # Run tests locally with test database URL and capture output
+ local output
+ local exit_code
+
+ output=$(DATABASE_URL="postgresql://readur_test:readur_test@localhost:5433/readur_test" \
+ cargo test --lib --no-fail-fast 2>&1)
+ exit_code=$?
+
+ # Display output in terminal
+ echo "$output"
+
+ if [ $exit_code -eq 0 ]; then
print_success "Unit tests passed"
+ save_output "unit" "$output" "passed"
else
print_error "Unit tests failed"
+ save_output "unit" "$output" "failed"
exit 1
fi
}
@@ -176,13 +205,24 @@ run_integration_tests() {
print_status "Running integration tests..."
# Run integration tests locally with test database URL and API URL
- if DATABASE_URL="postgresql://readur_test:readur_test@localhost:5433/readur_test" \
+ local output
+ local exit_code
+
+ output=$(DATABASE_URL="postgresql://readur_test:readur_test@localhost:5433/readur_test" \
TEST_DATABASE_URL="postgresql://readur_test:readur_test@localhost:5433/readur_test" \
API_URL="http://localhost:8001" \
- cargo test --test '*' --no-fail-fast; then
+ cargo test --test '*' --no-fail-fast 2>&1)
+ exit_code=$?
+
+ # Display output in terminal
+ echo "$output"
+
+ if [ $exit_code -eq 0 ]; then
print_success "Integration tests passed"
+ save_output "integration" "$output" "passed"
else
print_error "Integration tests failed"
+ save_output "integration" "$output" "failed"
exit 1
fi
}
@@ -192,11 +232,22 @@ run_frontend_tests() {
print_status "Running frontend tests..."
# Run frontend tests in a separate container
- if docker compose -f $COMPOSE_FILE -p $COMPOSE_PROJECT_NAME \
- --profile frontend-tests run --rm frontend_test; then
+ local output
+ local exit_code
+
+ output=$(docker compose -f $COMPOSE_FILE -p $COMPOSE_PROJECT_NAME \
+ --profile frontend-tests run --rm frontend_test 2>&1)
+ exit_code=$?
+
+ # Display output in terminal
+ echo "$output"
+
+ if [ $exit_code -eq 0 ]; then
print_success "Frontend tests passed"
+ save_output "frontend" "$output" "passed"
else
print_error "Frontend tests failed"
+ save_output "frontend" "$output" "failed"
exit 1
fi
}
@@ -207,16 +258,183 @@ run_e2e_tests() {
# TODO: Add E2E test implementation using Playwright or Cypress
}
+# Function to generate detailed test report
+generate_test_report() {
+ local report_file="${TEST_RESULTS_DIR}/reports/${TIMESTAMP}_test_report.html"
+
+ print_status "Generating test report..."
+
+ cat > "$report_file" << 'EOF'
+
+
+
+ Readur Test Results
+
+
+
+
+
+
+EOF
+
+ # Add timestamp
+ sed -i "s/TIMESTAMP_PLACEHOLDER/$(date)/" "$report_file"
+
+ # Add summary section
+ local total_tests=0
+ local passed_tests=0
+ local failed_tests=0
+
+ # Count test results from saved files
+ if ls "${TEST_RESULTS_DIR}"/unit/*_passed.log > /dev/null 2>&1; then
+ passed_tests=$((passed_tests + 1))
+ total_tests=$((total_tests + 1))
+ fi
+ if ls "${TEST_RESULTS_DIR}"/unit/*_failed.log > /dev/null 2>&1; then
+ failed_tests=$((failed_tests + 1))
+ total_tests=$((total_tests + 1))
+ fi
+ if ls "${TEST_RESULTS_DIR}"/integration/*_passed.log > /dev/null 2>&1; then
+ passed_tests=$((passed_tests + 1))
+ total_tests=$((total_tests + 1))
+ fi
+ if ls "${TEST_RESULTS_DIR}"/integration/*_failed.log > /dev/null 2>&1; then
+ failed_tests=$((failed_tests + 1))
+ total_tests=$((total_tests + 1))
+ fi
+ if ls "${TEST_RESULTS_DIR}"/frontend/*_passed.log > /dev/null 2>&1; then
+ passed_tests=$((passed_tests + 1))
+ total_tests=$((total_tests + 1))
+ fi
+ if ls "${TEST_RESULTS_DIR}"/frontend/*_failed.log > /dev/null 2>&1; then
+ failed_tests=$((failed_tests + 1))
+ total_tests=$((total_tests + 1))
+ fi
+
+ cat >> "$report_file" << EOF
+
+
+
Total Test Suites
+
$total_tests
+
+
+
Passed
+
$passed_tests
+
+
+
Failed
+
$failed_tests
+
+
+EOF
+
+ # Add test results sections
+ for test_type in unit integration frontend; do
+ for log_file in "${TEST_RESULTS_DIR}/${test_type}"/${TIMESTAMP}_*.log; do
+ if [ -f "$log_file" ]; then
+ local basename=$(basename "$log_file")
+ local status=""
+ if [[ "$basename" == *"_passed.log" ]]; then
+ status="passed"
+ elif [[ "$basename" == *"_failed.log" ]]; then
+ status="failed"
+ fi
+
+ cat >> "$report_file" << EOF
+
+
+ $(echo "${test_type^}" | sed 's/_/ /g') Tests
+ [$status]
+
+
+
+EOF
+ fi
+ done
+ done
+
+ cat >> "$report_file" << 'EOF'
+
+
+
+EOF
+
+ print_success "Test report generated: $report_file"
+
+ # Also create a simple text summary
+ local summary_file="${TEST_RESULTS_DIR}/reports/${TIMESTAMP}_summary.txt"
+ cat > "$summary_file" << EOF
+READUR TEST SUMMARY
+==================
+Test Run: $(date)
+Total Test Suites: $total_tests
+Passed: $passed_tests
+Failed: $failed_tests
+
+Individual Results:
+EOF
+
+ for test_type in unit integration frontend; do
+ for log_file in "${TEST_RESULTS_DIR}/${test_type}"/${TIMESTAMP}_*.log; do
+ if [ -f "$log_file" ]; then
+ local basename=$(basename "$log_file")
+ local status=""
+ if [[ "$basename" == *"_passed.log" ]]; then
+ status="โ PASSED"
+ elif [[ "$basename" == *"_failed.log" ]]; then
+ status="โ FAILED"
+ fi
+ echo "- ${test_type^} Tests: $status" >> "$summary_file"
+ fi
+ done
+ done
+
+ echo "" >> "$summary_file"
+ echo "Detailed logs available in: ${TEST_RESULTS_DIR}/" >> "$summary_file"
+ echo "HTML Report: $report_file" >> "$summary_file"
+
+ print_success "Summary saved: $summary_file"
+}
+
# Function to show test results summary
show_summary() {
print_status "Test Summary:"
- docker compose -f $COMPOSE_FILE -p $COMPOSE_PROJECT_NAME logs readur_test | \
- grep -E "(test result:|passed|failed)" | tail -20
+
+ # Show recent results
+ if [ -f "${TEST_RESULTS_DIR}/reports/${TIMESTAMP}_summary.txt" ]; then
+ cat "${TEST_RESULTS_DIR}/reports/${TIMESTAMP}_summary.txt"
+ else
+ echo "No summary file found"
+ fi
}
# Run main function
main
+# Generate test report
+generate_test_report
+
# Show summary
show_summary
diff --git a/view-test-results.sh b/view-test-results.sh
new file mode 100755
index 0000000..af03495
--- /dev/null
+++ b/view-test-results.sh
@@ -0,0 +1,155 @@
+#!/bin/bash
+
+# Script to view latest test results
+
+TEST_RESULTS_DIR="test-results"
+
+# Colors for output
+GREEN='\033[0;32m'
+BLUE='\033[0;34m'
+YELLOW='\033[1;33m'
+NC='\033[0m' # No Color
+
+print_header() {
+ echo -e "${BLUE}=== $1 ===${NC}"
+}
+
+print_success() {
+ echo -e "${GREEN}โ${NC} $1"
+}
+
+print_info() {
+ echo -e "${YELLOW}โน${NC} $1"
+}
+
+# Check if test results directory exists
+if [ ! -d "$TEST_RESULTS_DIR" ]; then
+ echo "No test results found. Run 'make test' first."
+ exit 1
+fi
+
+# Parse command line arguments
+ACTION="${1:-summary}"
+
+case $ACTION in
+ summary|s)
+ print_header "Latest Test Summary"
+ # Find the most recent summary file
+ LATEST_SUMMARY=$(ls -t "$TEST_RESULTS_DIR"/reports/*_summary.txt 2>/dev/null | head -1)
+ if [ -f "$LATEST_SUMMARY" ]; then
+ cat "$LATEST_SUMMARY"
+ else
+ echo "No test summary found."
+ fi
+ ;;
+
+ html|h)
+ print_header "Opening HTML Report"
+ # Find the most recent HTML report
+ LATEST_HTML=$(ls -t "$TEST_RESULTS_DIR"/reports/*_test_report.html 2>/dev/null | head -1)
+ if [ -f "$LATEST_HTML" ]; then
+ print_success "Opening $LATEST_HTML"
+ # Try to open with default browser
+ if command -v xdg-open >/dev/null 2>&1; then
+ xdg-open "$LATEST_HTML"
+ elif command -v open >/dev/null 2>&1; then
+ open "$LATEST_HTML"
+ else
+ print_info "Manual open required: $LATEST_HTML"
+ fi
+ else
+ echo "No HTML report found."
+ fi
+ ;;
+
+ logs|l)
+ print_header "Available Test Logs"
+ if [ -d "$TEST_RESULTS_DIR" ]; then
+ echo "Unit Tests:"
+ ls -la "$TEST_RESULTS_DIR"/unit/ 2>/dev/null || echo " No unit test logs"
+ echo ""
+ echo "Integration Tests:"
+ ls -la "$TEST_RESULTS_DIR"/integration/ 2>/dev/null || echo " No integration test logs"
+ echo ""
+ echo "Frontend Tests:"
+ ls -la "$TEST_RESULTS_DIR"/frontend/ 2>/dev/null || echo " No frontend test logs"
+ echo ""
+ echo "Reports:"
+ ls -la "$TEST_RESULTS_DIR"/reports/ 2>/dev/null || echo " No reports"
+ fi
+ ;;
+
+ unit|u)
+ print_header "Latest Unit Test Results"
+ LATEST_UNIT=$(ls -t "$TEST_RESULTS_DIR"/unit/*.log 2>/dev/null | head -1)
+ if [ -f "$LATEST_UNIT" ]; then
+ print_success "From: $LATEST_UNIT"
+ echo ""
+ cat "$LATEST_UNIT"
+ else
+ echo "No unit test results found."
+ fi
+ ;;
+
+ integration|i)
+ print_header "Latest Integration Test Results"
+ LATEST_INTEGRATION=$(ls -t "$TEST_RESULTS_DIR"/integration/*.log 2>/dev/null | head -1)
+ if [ -f "$LATEST_INTEGRATION" ]; then
+ print_success "From: $LATEST_INTEGRATION"
+ echo ""
+ cat "$LATEST_INTEGRATION"
+ else
+ echo "No integration test results found."
+ fi
+ ;;
+
+ frontend|f)
+ print_header "Latest Frontend Test Results"
+ LATEST_FRONTEND=$(ls -t "$TEST_RESULTS_DIR"/frontend/*.log 2>/dev/null | head -1)
+ if [ -f "$LATEST_FRONTEND" ]; then
+ print_success "From: $LATEST_FRONTEND"
+ echo ""
+ cat "$LATEST_FRONTEND"
+ else
+ echo "No frontend test results found."
+ fi
+ ;;
+
+ clean|c)
+ print_header "Cleaning Test Results"
+ read -p "Are you sure you want to delete all test results? (y/N): " -n 1 -r
+ echo
+ if [[ $REPLY =~ ^[Yy]$ ]]; then
+ rm -rf "$TEST_RESULTS_DIR"/*
+ print_success "Test results cleaned"
+ else
+ echo "Cancelled"
+ fi
+ ;;
+
+ help|--help|-h)
+ print_header "Test Results Viewer"
+ echo "Usage: $0 [command]"
+ echo ""
+ echo "Commands:"
+ echo " summary, s Show latest test summary (default)"
+ echo " html, h Open latest HTML report in browser"
+ echo " logs, l List all available test logs"
+ echo " unit, u Show latest unit test results"
+ echo " integration, i Show latest integration test results"
+ echo " frontend, f Show latest frontend test results"
+ echo " clean, c Clean all test results"
+ echo " help, -h Show this help"
+ echo ""
+ echo "Examples:"
+ echo " $0 # Show summary"
+ echo " $0 html # Open HTML report"
+ echo " $0 unit # Show unit test details"
+ ;;
+
+ *)
+ echo "Unknown command: $ACTION"
+ echo "Run '$0 help' for available commands."
+ exit 1
+ ;;
+esac
\ No newline at end of file