File size: 2,910 Bytes
52739ad | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | """Tests for the upload & parse flow (Session 2).
Covers the happy path (raw text) and, per the acceptance criteria, the
parse-failure paths: non-PDF files, broken PDFs, password-protected PDFs,
empty input, and oversize input.
"""
import io
import pytest
from fastapi.testclient import TestClient
from pypdf import PdfWriter
from app.main import MAX_UPLOAD_BYTES, app
client = TestClient(app)
def _encrypted_pdf_bytes(password: str = "secret") -> bytes:
"""Build a small, password-protected PDF in memory."""
writer = PdfWriter()
writer.add_blank_page(width=200, height=200)
# RC4 avoids a hard dependency on the `cryptography` package in CI.
writer.encrypt(user_password=password, algorithm="RC4-128")
buffer = io.BytesIO()
writer.write(buffer)
return buffer.getvalue()
def test_create_document_from_text():
body = "DocuAsk turns a document into a searchable index. " * 40
response = client.post("/documents", data={"text": body})
assert response.status_code == 201
payload = response.json()
assert payload["status"] == "ready"
assert payload["num_chunks"] >= 1
assert payload["num_chars"] == len(body)
assert payload["filename"] is None
# The returned id resolves to a stored document.
fetched = client.get(f"/documents/{payload['document_id']}")
assert fetched.status_code == 200
assert fetched.json()["document_id"] == payload["document_id"]
def test_empty_text_is_rejected():
response = client.post("/documents", data={"text": " "})
assert response.status_code == 400
assert "detail" in response.json()
def test_missing_input_is_rejected():
response = client.post("/documents")
assert response.status_code == 400
def test_non_pdf_file_is_rejected():
response = client.post(
"/documents",
files={"file": ("notes.png", b"\x89PNG\r\n", "image/png")},
)
assert response.status_code == 415
assert "PDF" in response.json()["detail"]
def test_broken_pdf_is_rejected():
# A .pdf name but garbage bytes — pypdf cannot read it.
response = client.post(
"/documents",
files={"file": ("broken.pdf", b"this is definitely not a pdf", "application/pdf")},
)
assert response.status_code == 400
assert "PDF" in response.json()["detail"]
def test_encrypted_pdf_is_rejected():
response = client.post(
"/documents",
files={"file": ("secret.pdf", _encrypted_pdf_bytes(), "application/pdf")},
)
assert response.status_code == 400
assert "password" in response.json()["detail"].lower()
def test_oversize_text_is_rejected():
huge = "a" * (MAX_UPLOAD_BYTES + 1)
response = client.post("/documents", data={"text": huge})
assert response.status_code == 413
def test_unknown_document_returns_404():
response = client.get("/documents/does-not-exist")
assert response.status_code == 404
|