""" Test A: Basic App Import and Route Tests ========================================= Tests module imports and all GET routes without requiring Oracle. Run: python test_app_basic.py Expected results: - All 17 module imports: PASS - HTML routes (/ /missing-skus /mappings /sync): PASS (templates exist) - /health: PASS (returns Oracle=error, sqlite=ok) - /api/sync/status, /api/sync/history, /api/validate/missing-skus: PASS (SQLite-only) - /api/mappings, /api/mappings/export-csv, /api/articles/search: FAIL (require Oracle pool) These are KNOWN FAILURES when Oracle is unavailable - documented as bugs requiring guards. """ import os import sys import tempfile # --- Set env vars BEFORE any app import --- _tmpdir = tempfile.mkdtemp() _sqlite_path = os.path.join(_tmpdir, "test_import.db") os.environ["FORCE_THIN_MODE"] = "true" os.environ["SQLITE_DB_PATH"] = _sqlite_path os.environ["ORACLE_DSN"] = "dummy" os.environ["ORACLE_USER"] = "dummy" os.environ["ORACLE_PASSWORD"] = "dummy" # Add api/ to path so we can import app _api_dir = os.path.dirname(os.path.abspath(__file__)) if _api_dir not in sys.path: sys.path.insert(0, _api_dir) # ------------------------------------------------------- # Section 1: Module Import Checks # ------------------------------------------------------- MODULES = [ "app.config", "app.database", "app.main", "app.routers.health", "app.routers.dashboard", "app.routers.mappings", "app.routers.sync", "app.routers.validation", "app.routers.articles", "app.services.sqlite_service", "app.services.scheduler_service", "app.services.mapping_service", "app.services.article_service", "app.services.validation_service", "app.services.import_service", "app.services.sync_service", "app.services.order_reader", ] passed = 0 failed = 0 results = [] print("\n=== Test A: GoMag Import Manager Basic Tests ===\n") print("--- Section 1: Module Imports ---\n") for mod in MODULES: try: __import__(mod) print(f" [PASS] import {mod}") passed += 1 results.append((f"import:{mod}", True, None, False)) except Exception as e: print(f" [FAIL] import {mod} -> {e}") failed += 1 results.append((f"import:{mod}", False, str(e), False)) # ------------------------------------------------------- # Section 2: Route Tests via TestClient # ------------------------------------------------------- print("\n--- Section 2: GET Route Tests ---\n") # Routes: (description, path, expected_ok_codes, known_oracle_failure) # known_oracle_failure=True means the route needs Oracle pool and will 500 without it. # These are flagged as bugs, not test infrastructure failures. GET_ROUTES = [ ("GET /health", "/health", [200], False), ("GET / (dashboard HTML)", "/", [200, 500], False), ("GET /missing-skus (HTML)", "/missing-skus", [200, 500], False), ("GET /mappings (HTML)", "/mappings", [200, 500], False), ("GET /sync (HTML)", "/sync", [200, 500], False), ("GET /api/mappings", "/api/mappings", [200, 503], True), ("GET /api/mappings/export-csv", "/api/mappings/export-csv", [200, 503], True), ("GET /api/mappings/csv-template", "/api/mappings/csv-template", [200], False), ("GET /api/sync/status", "/api/sync/status", [200], False), ("GET /api/sync/history", "/api/sync/history", [200], False), ("GET /api/sync/schedule", "/api/sync/schedule", [200], False), ("GET /api/validate/missing-skus", "/api/validate/missing-skus", [200], False), ("GET /api/validate/missing-skus?page=1", "/api/validate/missing-skus?page=1&per_page=10", [200], False), ("GET /logs (HTML)", "/logs", [200, 500], False), ("GET /api/sync/run/nonexistent/log", "/api/sync/run/nonexistent/log", [200, 404], False), ("GET /api/articles/search?q=ab", "/api/articles/search?q=ab", [200, 503], True), ] try: from fastapi.testclient import TestClient from app.main import app # Use context manager so lifespan (startup/shutdown) runs properly. # Without 'with', init_sqlite() never fires and SQLite-only routes return 500. with TestClient(app, raise_server_exceptions=False) as client: for name, path, expected, is_oracle_route in GET_ROUTES: try: resp = client.get(path) if resp.status_code in expected: print(f" [PASS] {name} -> HTTP {resp.status_code}") passed += 1 results.append((name, True, None, is_oracle_route)) else: body_snippet = resp.text[:300].replace("\n", " ") print(f" [FAIL] {name} -> HTTP {resp.status_code} (expected {expected})") print(f" Body: {body_snippet}") failed += 1 results.append((name, False, f"HTTP {resp.status_code}", is_oracle_route)) except Exception as e: print(f" [FAIL] {name} -> Exception: {e}") failed += 1 results.append((name, False, str(e), is_oracle_route)) except ImportError as e: print(f" [FAIL] Cannot create TestClient: {e}") print(" Make sure 'httpx' is installed: pip install httpx") for name, path, _, _ in GET_ROUTES: failed += 1 results.append((name, False, "TestClient unavailable", False)) # ------------------------------------------------------- # Summary # ------------------------------------------------------- total = passed + failed print(f"\n=== Summary: {passed}/{total} tests passed ===") if failed > 0: print("\nFailed tests:") for name, ok, err, _ in results: if not ok: print(f" - {name}: {err}") sys.exit(0 if failed == 0 else 1)