| """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) |
| |
| 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 |
|
|
| |
| 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(): |
| |
| 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 |
|
|