import io from types import SimpleNamespace import pytest from fastapi.testclient import TestClient from PIL import Image from server import _html_to_text from server import SuryaOCRServer def test_html_to_text_strips_tags_and_unescapes() -> None: assert _html_to_text("
Hello World
") == "Hello World" assert _html_to_text("Line onea
b
") == "a b" assert _html_to_text("Total: & $42") == "Total: & $42" def test_html_to_text_empty_for_markup_only() -> None: assert _html_to_text("") == "" assert _html_to_text("Hello World
", bbox=[10.0, 20.0, 200.0, 40.0], polygon=[[10, 20], [200, 20], [200, 40], [10, 40]], confidence=0.97, skipped=False, ), ] server = _make_server(blocks) client = TestClient(server._create_ocr_server()) response = client.post( "/ocr", files={"file": ("test.png", _png_bytes(), "image/png")}, data={"language": "en"}, ) assert response.status_code == 200 results = response.json()["results"] assert len(results) == 1 assert results[0]["text"] == "Hello World" assert results[0]["bbox"] == [10, 20, 200, 40] assert results[0]["confidence"] == pytest.approx(0.97) assert results[0]["polygon"] == [ [10.0, 20.0], [200.0, 20.0], [200.0, 40.0], [10.0, 40.0] ] def test_server_defaults_missing_confidence() -> None: blocks = [ SimpleNamespace( html="x
", bbox=[0.0, 0.0, 5.0, 5.0], polygon=[[0, 0], [5, 0], [5, 5], [0, 5]], confidence=None, skipped=False, ), ] server = _make_server(blocks) client = TestClient(server._create_ocr_server()) response = client.post( "/ocr", files={"file": ("t.png", _png_bytes(), "image/png")} ) assert response.json()["results"][0]["confidence"] == pytest.approx(1.0) def test_server_skips_empty_and_skipped_blocks() -> None: blocks = [ SimpleNamespace(html="", bbox=[0.0, 0.0, 5.0, 5.0], polygon=[[0, 0], [5, 0], [5, 5], [0, 5]], confidence=0.9, skipped=False), SimpleNamespace(html="image
", bbox=[0.0, 0.0, 5.0, 5.0], polygon=[[0, 0], [5, 0], [5, 5], [0, 5]], confidence=0.9, skipped=True), SimpleNamespace(html="keep
", bbox=[1.0, 1.0, 9.0, 9.0], polygon=[[1, 1], [9, 1], [9, 9], [1, 9]], confidence=0.9, skipped=False), ] server = _make_server(blocks) client = TestClient(server._create_ocr_server()) response = client.post( "/ocr", files={"file": ("t.png", _png_bytes(), "image/png")} ) results = response.json()["results"] assert len(results) == 1 assert results[0]["text"] == "keep" def test_server_derives_bbox_from_polygon_when_bbox_missing() -> None: blocks = [ SimpleNamespace(html="z
", bbox=None, polygon=[[3, 4], [30, 4], [30, 40], [3, 40]], confidence=0.8, skipped=False), ] server = _make_server(blocks) client = TestClient(server._create_ocr_server()) response = client.post( "/ocr", files={"file": ("t.png", _png_bytes(), "image/png")} ) assert response.json()["results"][0]["bbox"] == [3, 4, 30, 40] def test_server_keeps_zero_bbox_without_deriving_from_polygon() -> None: blocks = [ SimpleNamespace(html="q
", bbox=[0, 0, 0, 0], polygon=[[3, 4], [30, 4], [30, 40], [3, 40]], confidence=0.9, skipped=False), ] server = _make_server(blocks) client = TestClient(server._create_ocr_server()) response = client.post( "/ocr", files={"file": ("t.png", _png_bytes(), "image/png")} ) assert response.json()["results"][0]["bbox"] == [0, 0, 0, 0] def test_server_skips_whitespace_only_html() -> None: blocks = [ SimpleNamespace(html="", bbox=[1, 1, 9, 9], polygon=[[1, 1], [9, 1], [9, 9], [1, 9]], confidence=0.9, skipped=False), ] server = _make_server(blocks) client = TestClient(server._create_ocr_server()) response = client.post( "/ocr", files={"file": ("t.png", _png_bytes(), "image/png")} ) assert response.json()["results"] == []