From 9d7348423abfd0443aab9d3d889df86df1bdeb43 Mon Sep 17 00:00:00 2001 From: perf3ct Date: Tue, 17 Jun 2025 14:48:47 +0000 Subject: [PATCH] feat(tests): test suite almost done --- Makefile | 116 +++++++++++++++++++++ docker-compose.test.yml | 112 ++++++++++++++++++++ run-tests.sh | 223 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 451 insertions(+) create mode 100644 Makefile create mode 100644 docker-compose.test.yml create mode 100755 run-tests.sh diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bc14a68 --- /dev/null +++ b/Makefile @@ -0,0 +1,116 @@ +.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 + +# Default target +help: + @echo "Readur Development and Testing Commands" + @echo "======================================" + @echo "" + @echo "Testing Commands:" + @echo " make test - Run all tests in isolated environment" + @echo " make test-unit - Run unit tests only" + @echo " make test-integration - Run integration tests only" + @echo " make test-frontend - Run frontend tests only" + @echo " make test-e2e - Run E2E tests (when implemented)" + @echo " make test-watch - Run tests and keep containers running" + @echo " make test-clean - Clean up test environment" + @echo " make test-logs - View test container logs" + @echo " make test-shell - Open shell in test container" + @echo "" + @echo "Development Commands:" + @echo " make dev-up - Start development environment" + @echo " make dev-down - Stop development environment" + @echo " make dev-logs - View development logs" + @echo " make build - Build all Docker images" + @echo " make clean - Clean all Docker resources" + +# Testing targets +test: test-all + +test-all: + @./run-tests.sh all + +test-unit: + @./run-tests.sh unit + +test-integration: + @./run-tests.sh integration + +test-frontend: + @./run-tests.sh frontend + +test-e2e: + @./run-tests.sh e2e + +test-watch: + @./run-tests.sh all keep-running + +test-clean: + @echo "Cleaning test environment..." + @docker-compose -f docker-compose.test.yml -p readur_test down -v --remove-orphans 2>/dev/null || true + @docker rm -f readur_postgres_test readur_app_test readur_frontend_test 2>/dev/null || true + @docker network rm readur_test_network 2>/dev/null || true + @rm -rf /tmp/test_uploads /tmp/test_watch 2>/dev/null || true + +test-logs: + @docker-compose -f docker-compose.test.yml -p readur_test logs -f + +test-shell: + @docker-compose -f docker-compose.test.yml -p readur_test exec readur_test /bin/bash + +# Development targets +dev-up: + @echo "Starting development environment..." + @docker-compose up -d + +dev-down: + @echo "Stopping development environment..." + @docker-compose down + +dev-logs: + @docker-compose logs -f + +# Build targets +build: + @echo "Building all images..." + @docker-compose build + @docker-compose -f docker-compose.test.yml build + +# Clean targets +clean: + @echo "Cleaning all Docker resources..." + @docker-compose down -v --remove-orphans + @docker-compose -f docker-compose.test.yml -p readur_test down -v --remove-orphans + @docker system prune -f + +# Specific test scenarios +test-ocr: + @echo "Running OCR-specific tests..." + @docker-compose -f docker-compose.test.yml -p readur_test exec -T readur_test \ + cargo test ocr --no-fail-fast + +test-webdav: + @echo "Running WebDAV-specific tests..." + @docker-compose -f docker-compose.test.yml -p readur_test exec -T readur_test \ + cargo test webdav --no-fail-fast + +test-performance: + @echo "Running performance tests..." + @docker-compose -f docker-compose.test.yml -p readur_test exec -T readur_test \ + cargo test performance --no-fail-fast + +# Database operations +test-db-reset: + @echo "Resetting test database..." + @docker-compose -f docker-compose.test.yml -p readur_test exec -T postgres_test \ + psql -U readur_test -d postgres -c "DROP DATABASE IF EXISTS readur_test; CREATE DATABASE readur_test;" + @docker-compose -f docker-compose.test.yml -p readur_test exec -T readur_test \ + sqlx migrate run + +# CI/CD helpers +ci-test: + @./run-tests.sh all + +# 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 diff --git a/docker-compose.test.yml b/docker-compose.test.yml new file mode 100644 index 0000000..d388e6e --- /dev/null +++ b/docker-compose.test.yml @@ -0,0 +1,112 @@ +services: + postgres_test: + image: postgres:16-alpine + container_name: readur_postgres_test + environment: + POSTGRES_USER: readur_test + POSTGRES_PASSWORD: readur_test + POSTGRES_DB: readur_test + volumes: + # Using tmpfs for ephemeral test data + - type: tmpfs + target: /var/lib/postgresql/data + ports: + - "5433:5432" # Different port to avoid conflict + healthcheck: + test: ["CMD-SHELL", "pg_isready -U readur_test"] + interval: 5s + timeout: 3s + retries: 5 + networks: + - readur_test_network + + readur_test: + build: + context: . + dockerfile: Dockerfile + container_name: readur_app_test + environment: + # Database configuration + DATABASE_URL: postgresql://readur_test:readur_test@postgres_test/readur_test + + # Server configuration + SERVER_HOST: 0.0.0.0 + SERVER_PORT: 8001 # Different port from dev + + # Security + JWT_SECRET: test-jwt-secret-key + + # File paths (using temporary directories) + UPLOAD_PATH: /tmp/test_uploads + WATCH_FOLDER: /tmp/test_watch + + # OCR configuration + OCR_LANGUAGE: eng + CONCURRENT_OCR_JOBS: 2 # Lower for tests + OCR_TIMEOUT_SECONDS: 60 # Shorter timeout for tests + MAX_FILE_SIZE_MB: 10 # Smaller for tests + + # Performance (reduced for testing) + MEMORY_LIMIT_MB: 256 + CPU_PRIORITY: normal + + # File watching + ALLOWED_FILE_TYPES: pdf,txt,doc,docx,png,jpg,jpeg + WATCH_INTERVAL_SECONDS: 5 # Faster for tests + FILE_STABILITY_CHECK_MS: 500 + MAX_FILE_AGE_HOURS: 1 + + # Test-specific environment variables + RUST_LOG: debug + TEST_ENV: true + + ports: + - "8001:8001" # Different port from dev + + volumes: + # Using tmpfs for faster test execution + - type: tmpfs + target: /tmp/test_uploads + - type: tmpfs + target: /tmp/test_watch + # Mount migrations for SQLx + - ./migrations:/app/migrations:ro + + depends_on: + postgres_test: + condition: service_healthy + + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:8001/api/health"] + interval: 10s + timeout: 5s + retries: 3 + start_period: 30s + + networks: + - readur_test_network + + # Frontend test runner service + frontend_test: + image: node:18-alpine + container_name: readur_frontend_test + working_dir: /app + environment: + NODE_ENV: test + VITE_API_BASE_URL: http://readur_test:8001 + CI: true + volumes: + - ./frontend:/app:ro + - /app/node_modules # Prevent mounting host node_modules + command: ["sh", "-c", "npm ci && npm test -- --run --reporter=verbose"] + networks: + - readur_test_network + profiles: + - frontend-tests + +networks: + readur_test_network: + name: readur_test_network + driver: bridge + +# No persistent volumes - everything is ephemeral for tests \ No newline at end of file diff --git a/run-tests.sh b/run-tests.sh new file mode 100755 index 0000000..618b971 --- /dev/null +++ b/run-tests.sh @@ -0,0 +1,223 @@ +#!/bin/bash + +# Test runner script for Readur +# This script orchestrates all tests in an isolated environment + +set -e # Exit on error + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Configuration +COMPOSE_FILE="docker-compose.test.yml" +COMPOSE_PROJECT_NAME="readur_test" +TEST_TIMEOUT=600 # 10 minutes timeout for all tests + +# Function to print colored output +print_status() { + echo -e "${BLUE}[TEST]${NC} $1" +} + +print_success() { + echo -e "${GREEN}[✓]${NC} $1" +} + +print_error() { + echo -e "${RED}[✗]${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}[!]${NC} $1" +} + +# Function to cleanup test environment +cleanup() { + print_status "Cleaning up test environment..." + docker compose -f $COMPOSE_FILE -p $COMPOSE_PROJECT_NAME down -v --remove-orphans 2>/dev/null || true + + # Force remove any lingering containers with our test names + docker rm -f readur_postgres_test readur_app_test readur_frontend_test 2>/dev/null || true + + # Force remove the test network if it exists + docker network rm readur_test_network 2>/dev/null || true + + # Remove any test artifacts + rm -rf /tmp/test_uploads /tmp/test_watch 2>/dev/null || true +} + +# Function to wait for service to be healthy +wait_for_service() { + local service=$1 + local max_attempts=30 + local attempt=0 + + print_status "Waiting for $service to be healthy..." + + while [ $attempt -lt $max_attempts ]; do + if docker compose -f $COMPOSE_FILE -p $COMPOSE_PROJECT_NAME ps | grep -q "${service}.*healthy"; then + print_success "$service is healthy" + return 0 + fi + + attempt=$((attempt + 1)) + sleep 2 + done + + print_error "$service failed to become healthy after $max_attempts attempts" + return 1 +} + +# Parse command line arguments +TEST_TYPE="${1:-all}" +KEEP_RUNNING="${2:-false}" + +# Trap to ensure cleanup on exit +trap cleanup EXIT INT TERM + +# Main test execution +main() { + print_status "Starting Readur test suite (type: $TEST_TYPE)" + + # Force cleanup any existing test environment to avoid conflicts + print_status "Ensuring clean test environment..." + cleanup + + # Extra cleanup for stubborn resources + print_status "Removing any conflicting resources..." + docker ps -a | grep -E "readur_(postgres|app|frontend)_test" | awk '{print $1}' | xargs -r docker rm -f 2>/dev/null || true + docker network ls | grep "readur_test_network" | awk '{print $1}' | xargs -r docker network rm 2>/dev/null || true + + # Load test environment variables + if [ -f .env.test ]; then + print_status "Loading test environment variables..." + export $(grep -v '^#' .env.test | xargs) + fi + + # Build test images + print_status "Building test images..." + docker compose -f $COMPOSE_FILE -p $COMPOSE_PROJECT_NAME build + + # Start test infrastructure + print_status "Starting test infrastructure..." + docker compose -f $COMPOSE_FILE -p $COMPOSE_PROJECT_NAME up -d postgres_test + + # Wait for PostgreSQL to be ready + wait_for_service "postgres_test" + + # The application runs SQLx migrations automatically at startup + print_status "Application will run database migrations on startup..." + + # Start the application + print_status "Starting Readur test instance..." + docker compose -f $COMPOSE_FILE -p $COMPOSE_PROJECT_NAME up -d readur_test + + # Wait for application to be ready + wait_for_service "readur_test" + + # Execute tests based on type + case $TEST_TYPE in + unit) + run_unit_tests + ;; + integration) + run_integration_tests + ;; + frontend) + run_frontend_tests + ;; + e2e) + run_e2e_tests + ;; + all) + run_unit_tests + run_integration_tests + run_frontend_tests + ;; + *) + print_error "Invalid test type: $TEST_TYPE" + echo "Usage: $0 [unit|integration|frontend|e2e|all] [keep-running]" + exit 1 + ;; + esac + + # Keep containers running if requested (useful for debugging) + if [ "$KEEP_RUNNING" = "keep-running" ]; then + print_warning "Keeping test containers running. Press Ctrl+C to stop and cleanup." + print_status "Test services:" + echo " - PostgreSQL: localhost:5433" + echo " - Readur API: http://localhost:8001" + echo " - Logs: docker compose -f $COMPOSE_FILE -p $COMPOSE_PROJECT_NAME logs -f" + + # Wait for user to press Ctrl+C + read -r -d '' _