"""Tests for chunk PDF file serving endpoint. Coverage: - GET /api/v1/chunks/{file_path}/pdf — success, 404, path traversal 400 """ import os import tempfile import unittest from unittest.mock import patch from fastapi.testclient import TestClient from app.main import app class TestChunkServing(unittest.TestCase): """Test GET /api/v1/chunks/{file_path}/pdf endpoint.""" def setUp(self): self.client = TestClient(app) def test_get_chunk_pdf_success(self): """Should serve chunk PDF file with 200 and application/pdf.""" with tempfile.TemporaryDirectory() as tmp_dir: test_file = os.path.join(tmp_dir, "test_page_1.pdf") with open(test_file, "wb") as f: f.write(b"%PDF-1.4 fake content") with patch("app.core.config.get_settings") as mock_settings: mock_settings.return_value.document_chunk_path = tmp_dir response = self.client.get("/api/v1/chunks/test_page_1.pdf/pdf") self.assertEqual(response.status_code, 200) self.assertIn("application/pdf", response.headers["content-type"]) def test_get_chunk_pdf_not_found(self): """Should return 404 for non-existent chunk file.""" with patch("app.core.config.get_settings") as mock_settings: mock_settings.return_value.document_chunk_path = "/tmp/nonexistent_chunk_dir" response = self.client.get("/api/v1/chunks/nonexistent.pdf/pdf") self.assertEqual(response.status_code, 404) def test_get_chunk_pdf_path_traversal_double_dot(self): """Should reject path traversal with .. (404 due to Starlette normalization).""" with patch("app.core.config.get_settings") as mock_settings: mock_settings.return_value.document_chunk_path = "/tmp/fake_chunk_dir" response = self.client.get("/api/v1/chunks/../etc/passwd/pdf") self.assertIn(response.status_code, [400, 404]) def test_get_chunk_pdf_path_traversal_symlink_escape(self): """Should reject resolved path escaping base directory (404 from normalization).""" with tempfile.TemporaryDirectory() as tmp_dir: with patch("app.core.config.get_settings") as mock_settings: mock_settings.return_value.document_chunk_path = tmp_dir response = self.client.get("/api/v1/chunks/../../etc/passwd/pdf") self.assertIn(response.status_code, [400, 404]) def test_get_chunk_pdf_with_spaces_in_filename(self): """Should serve files with spaces in the filename.""" with tempfile.TemporaryDirectory() as tmp_dir: test_file = os.path.join(tmp_dir, "NEC4 ACC_page_3.pdf") with open(test_file, "wb") as f: f.write(b"%PDF-1.4 fake content") with patch("app.core.config.get_settings") as mock_settings: mock_settings.return_value.document_chunk_path = tmp_dir response = self.client.get("/api/v1/chunks/NEC4 ACC_page_3.pdf/pdf") self.assertEqual(response.status_code, 200) self.assertIn("application/pdf", response.headers["content-type"])