PDF-accessibility-saas/tests/test_api.py
Vadym Samoilenko 5a00ec88d7 Phase 1: De-Oliver rebrand — remove Azure AD, GCP, Oliver branding
- Delete PHP API layer (api.php, auth.php) — replaced by FastAPI in Phase 2
- Delete MSAL/Azure AD JS files (app.js, app-history.js, api.js)
- Delete GCP Cloud Build/Deploy infra (cloudbuild.yaml, deploy.sh, Dockerfiles)
- Delete Oliver-specific docs (OLIVER_CUSTOMIZATION.md, DAVE_QUICK_SETUP.md, etc.)
- Replace Oliver yellow #FFC407 with Aimpress indigo #6366F1 across CSS + reports
- Replace Oliver Solutions footer in report_generator.py with Aimpress
- Switch font from Montserrat to Inter in CSS
- Replace GCS optical-pdf-images bucket with STORAGE_BUCKET env var
- Rewrite README.md for Aimpress SaaS product

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-19 14:41:27 +01:00

187 lines
5.8 KiB
Python

"""
Integration tests for API (api.php)
"""
import pytest
import subprocess
import time
import requests
from pathlib import Path
@pytest.fixture(scope="module")
def php_server():
"""Start PHP development server for testing"""
# Start PHP server on a test port
port = 8888
env = {**subprocess.os.environ, 'DEV_MODE': 'true'}
process = subprocess.Popen(
["php", "-S", f"localhost:{port}"],
cwd=Path(__file__).parent.parent,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
env=env
)
# Wait for server to start
time.sleep(2)
# Check if server is running
try:
requests.get(f"http://localhost:{port}/", timeout=5)
except requests.RequestException:
process.terminate()
pytest.skip("Could not start PHP server")
yield f"http://localhost:{port}"
# Cleanup
process.terminate()
time.sleep(1)
class TestAPIAuthentication:
"""Test API authentication"""
def test_api_rejects_no_auth(self, php_server):
"""Test that API handles requests without authentication"""
response = requests.get(f"{php_server}/api.php")
# In dev mode (DEV_MODE=true), auth is bypassed so we get 400 (invalid action)
# In production mode, we would get 401
assert response.status_code in [400, 401]
data = response.json()
assert data['success'] is False
assert 'error' in data
def test_api_accepts_valid_key(self, php_server):
"""Test that API accepts requests with valid dev key"""
headers = {'X-API-Key': 'dev_key_12345'}
response = requests.get(f"{php_server}/api.php", headers=headers)
# Should return 200 and different error (invalid action, not auth error)
assert response.status_code != 401
data = response.json()
# Should get past authentication
if 'error' in data:
assert 'Unauthorized' not in data['error']
assert 'API key' not in data['error']
def test_api_accepts_bearer_token(self, php_server):
"""Test that API accepts Bearer token authentication"""
headers = {'Authorization': 'Bearer dev_key_12345'}
response = requests.get(f"{php_server}/api.php", headers=headers)
# Should get past authentication
assert response.status_code != 401
class TestAuthModule:
"""Test authentication module directly"""
def test_auth_key_generation(self, php_server):
"""Test API key generation endpoint"""
response = requests.get(f"{php_server}/auth.php?generate")
assert response.status_code == 200
text = response.text
# Should contain a generated key
assert len(text) > 50 # Keys are 64 chars hex
assert 'API Key' in text or 'New' in text
def test_auth_test_endpoint(self, php_server):
"""Test authentication test endpoint"""
headers = {'X-API-Key': 'dev_key_12345'}
response = requests.get(f"{php_server}/auth.php?test", headers=headers)
assert response.status_code == 200
text = response.text
# Should indicate successful authentication
assert '' in text or 'successful' in text.lower()
class TestAPIEndpoints:
"""Test API endpoint structure"""
def test_api_returns_json(self, php_server):
"""Test that API returns JSON"""
headers = {'X-API-Key': 'dev_key_12345'}
response = requests.get(f"{php_server}/api.php", headers=headers)
assert response.headers.get('Content-Type') == 'application/json'
# Should be valid JSON
try:
data = response.json()
assert isinstance(data, dict)
except ValueError:
pytest.fail("API did not return valid JSON")
def test_cors_headers_present(self, php_server):
"""Test that CORS headers are present"""
headers = {'X-API-Key': 'dev_key_12345'}
response = requests.get(f"{php_server}/api.php", headers=headers)
assert 'Access-Control-Allow-Origin' in response.headers
# CORS now returns specific origin or localhost in dev mode
origin = response.headers['Access-Control-Allow-Origin']
assert origin in ['*', 'http://localhost:8888', 'http://localhost:8000', 'null']
def test_api_handles_options(self, php_server):
"""Test that API handles OPTIONS preflight requests"""
response = requests.options(f"{php_server}/api.php")
# OPTIONS should not require authentication
assert response.status_code == 200 or response.status_code == 204
class TestHelperModules:
"""Test helper modules"""
def test_logger_config_import(self):
"""Test logger_config module"""
from logger_config import setup_logger
logger = setup_logger("test", "test_api.log")
assert logger is not None
# Test logging
logger.info("Test message from API tests")
def test_retry_helper_import(self):
"""Test retry_helper module"""
from retry_helper import retry_with_backoff, safe_execute
assert callable(retry_with_backoff)
assert callable(safe_execute)
def test_retry_decorator_works(self):
"""Test that retry decorator functions"""
from retry_helper import retry_with_backoff
@retry_with_backoff(max_retries=2, initial_delay=0.1)
def always_succeeds():
return "success"
result = always_succeeds()
assert result == "success"
@pytest.mark.skipif(
not Path("Test_files/sample_good.pdf").exists(),
reason="Sample PDF not available"
)
class TestAPIWithFile:
"""Test API with actual file upload (if samples available)"""
def test_api_file_structure_exists(self):
"""Test that test files exist"""
assert Path("Test_files").exists()
assert Path("Test_files").is_dir()
if __name__ == "__main__":
pytest.main([__file__, "-v"])