from __future__ import annotations import uuid import pytest from fastapi.testclient import TestClient from sqlalchemy.orm import Session from tests.conftest import ( create_test_document, create_test_fingerprint, create_test_page, create_test_template, create_test_text_block, create_test_user, get_auth_headers, ) class TestListTemplates: """Tests for listing templates.""" def test_list_templates_empty(self, client: TestClient, db: Session) -> None: user = create_test_user(db) db.flush() headers = get_auth_headers(user) response = client.get("/api/v1/templates", headers=headers) assert response.status_code == 200 data = response.json() assert "items" in data assert "total" in data assert "page" in data def test_list_templates_with_data(self, client: TestClient, db: Session) -> None: user = create_test_user(db) create_test_template(db, name="Template_A", created_by=user) create_test_template(db, name="Template_B", created_by=user) db.flush() headers = get_auth_headers(user) response = client.get("/api/v1/templates", headers=headers) assert response.status_code == 200 data = response.json() assert data["total"] >= 2 def test_list_templates_pagination(self, client: TestClient, db: Session) -> None: user = create_test_user(db) for i in range(5): create_test_template(db, name=f"PagTemplate_{i}", created_by=user) db.flush() headers = get_auth_headers(user) response = client.get("/api/v1/templates?page=1&page_size=2", headers=headers) assert response.status_code == 200 data = response.json() assert data["page"] == 1 assert data["page_size"] == 2 assert len(data["items"]) <= 2 class TestGetTemplate: """Tests for getting a template by ID.""" def test_get_template_success(self, client: TestClient, db: Session) -> None: user = create_test_user(db) template = create_test_template(db, name="GetMe", created_by=user) db.flush() headers = get_auth_headers(user) response = client.get(f"/api/v1/templates/{template.id}", headers=headers) assert response.status_code == 200 data = response.json() assert data["id"] == str(template.id) assert data["name"] == "GetMe" assert data["page_width"] == 612.0 assert data["page_height"] == 792.0 assert data["is_active"] is True def test_get_template_not_found(self, client: TestClient, db: Session) -> None: user = create_test_user(db) db.flush() headers = get_auth_headers(user) fake_id = uuid.uuid4() response = client.get(f"/api/v1/templates/{fake_id}", headers=headers) assert response.status_code == 404 def test_get_template_includes_components(self, client: TestClient, db: Session) -> None: user = create_test_user(db) template = create_test_template(db, name="ComponentTemplate", created_by=user) db.flush() headers = get_auth_headers(user) response = client.get(f"/api/v1/templates/{template.id}", headers=headers) assert response.status_code == 200 data = response.json() assert "cells" in data assert "regions" in data assert "table_formats" in data assert "watermarks" in data assert "image_regions" in data class TestDeleteTemplate: """Tests for template soft-deletion.""" def test_delete_template_success(self, client: TestClient, db: Session) -> None: user = create_test_user(db) template = create_test_template(db, name="DeleteMe", created_by=user) db.flush() headers = get_auth_headers(user) response = client.delete(f"/api/v1/templates/{template.id}", headers=headers) assert response.status_code == 200 data = response.json() assert "message" in data # Verify template is deactivated (soft-deleted), not hard-deleted get_response = client.get(f"/api/v1/templates/{template.id}", headers=headers) assert get_response.status_code == 200 assert get_response.json()["is_active"] is False def test_delete_template_not_found(self, client: TestClient, db: Session) -> None: user = create_test_user(db) db.flush() headers = get_auth_headers(user) fake_id = uuid.uuid4() response = client.delete(f"/api/v1/templates/{fake_id}", headers=headers) assert response.status_code == 404 class TestMatchTemplate: """Tests for document-to-template matching endpoint.""" def test_match_document_not_found(self, client: TestClient, db: Session) -> None: user = create_test_user(db) db.flush() headers = get_auth_headers(user) fake_doc_id = uuid.uuid4() response = client.post( "/api/v1/templates/match", json={"document_id": str(fake_doc_id), "min_confidence": 0.5, "max_results": 5}, headers=headers, ) assert response.status_code == 404 def test_match_document_not_completed(self, client: TestClient, db: Session) -> None: user = create_test_user(db) doc = create_test_document(db, user=user, status="pending") db.flush() headers = get_auth_headers(user) response = client.post( "/api/v1/templates/match", json={"document_id": str(doc.id), "min_confidence": 0.5, "max_results": 5}, headers=headers, ) assert response.status_code == 400 def test_match_completed_document_no_templates(self, client: TestClient, db: Session) -> None: user = create_test_user(db) doc = create_test_document(db, user=user, status="completed") page = create_test_page(db, doc) create_test_text_block(db, page, text="Content") db.flush() headers = get_auth_headers(user) response = client.post( "/api/v1/templates/match", json={"document_id": str(doc.id), "min_confidence": 0.0, "max_results": 5}, headers=headers, ) assert response.status_code == 200 data = response.json() assert isinstance(data, list) class TestRenderTemplate: """Tests for template rendering endpoint.""" def test_render_template_not_found(self, client: TestClient, db: Session) -> None: user = create_test_user(db) db.flush() headers = get_auth_headers(user) fake_id = uuid.uuid4() response = client.post( "/api/v1/templates/render", json={ "template_id": str(fake_id), "data": {}, }, headers=headers, ) assert response.status_code == 404 def test_render_inactive_template(self, client: TestClient, db: Session) -> None: user = create_test_user(db) template = create_test_template(db, name="InactiveRender", created_by=user) template.is_active = False db.flush() headers = get_auth_headers(user) response = client.post( "/api/v1/templates/render", json={ "template_id": str(template.id), "data": {}, }, headers=headers, ) assert response.status_code == 400 def test_render_template_success(self, client: TestClient, db: Session) -> None: user = create_test_user(db) template = create_test_template(db, name="RenderOK", created_by=user) db.flush() headers = get_auth_headers(user) response = client.post( "/api/v1/templates/render", json={ "template_id": str(template.id), "data": {"field_1": "Hello World"}, "output_filename": "test_render.pdf", }, headers=headers, ) assert response.status_code == 200 data = response.json() assert data["filename"] == "test_render.pdf" assert data["file_size"] > 0 assert data["page_count"] == template.page_count assert "output_path" in data assert "rendered_at" in data class TestDownloadRenderedPDF: """Tests for downloading rendered PDFs.""" def test_download_not_found(self, client: TestClient, db: Session) -> None: user = create_test_user(db) template = create_test_template(db, name="DLTemplate", created_by=user) db.flush() headers = get_auth_headers(user) response = client.get( f"/api/v1/templates/{template.id}/download?filename=nonexistent.pdf", headers=headers, ) assert response.status_code == 404