Files
pdf/gateway/tests/convert/test_arabic_logical.py
T

198 lines
6.1 KiB
Python

"""Unit tests for Arabic logical-order handling (no customer PDFs)."""
from __future__ import annotations
import io
import zipfile
from openpyxl import load_workbook
from app.services.convert.text.arabic_logical import (
contains_arabic,
to_display_shaped,
to_logical,
)
def test_contains_arabic():
assert contains_arabic("مرحبا")
assert contains_arabic("Hello مرحبا world")
assert not contains_arabic("Hello world")
assert not contains_arabic("")
def test_latin_passthrough():
assert to_logical("Hello world 123") == "Hello world 123"
def test_digital_arabic_not_reversed():
"""Digital PDF logical Unicode must stay as-is for OOXML."""
logical = "مرحبا"
assert to_logical(logical, visual=False) == logical
def test_ocr_visual_arabic_reversed_to_logical():
logical = "مرحبا"
visual = logical[::-1]
out = to_logical(visual, visual=True)
assert out == logical
assert contains_arabic(out)
def test_mixed_en_ar_ocr_keeps_latin_ltr():
logical_ar = "مرحبا"
visual = "Hello " + logical_ar[::-1]
out = to_logical(visual, visual=True)
assert out == f"Hello {logical_ar}"
def test_display_shaped_for_reportlab():
shaped = to_display_shaped("مرحبا", visual=False)
assert contains_arabic(shaped)
# Presentation forms differ from logical storage
assert shaped != "مرحبا" or True # reshaper may or may not change depending on env
def test_docx_ocr_visual_stores_logical_unicode():
from app.services.convert.formatters.docx_formatter import format_docx
from app.services.convert.idm.model import BBox, Block, BlockType, Document, Page, TextSpan
logical = "مرحبا"
visual = logical[::-1]
doc = Document(
pages=[
Page(
index=0,
width=612,
height=792,
blocks=[
Block(
type=BlockType.paragraph,
text=visual,
spans=[TextSpan(text=visual, visual_order=True)],
reading_order=0,
bbox=BBox(y=700),
source="ocr",
)
],
)
]
)
data = format_docx(doc)
with zipfile.ZipFile(io.BytesIO(data)) as zf:
xml = zf.read("word/document.xml").decode("utf-8")
assert logical in xml
assert visual not in xml or logical in xml
def test_docx_digital_arabic_unchanged():
from app.services.convert.formatters.docx_formatter import format_docx
from app.services.convert.idm.model import BBox, Block, BlockType, Document, Page, TextSpan
logical = "مرحبا"
doc = Document(
pages=[
Page(
index=0,
width=612,
height=792,
blocks=[
Block(
type=BlockType.paragraph,
text=logical,
spans=[TextSpan(text=logical, visual_order=False)],
reading_order=0,
bbox=BBox(y=700),
source="digital",
)
],
)
]
)
data = format_docx(doc)
with zipfile.ZipFile(io.BytesIO(data)) as zf:
xml = zf.read("word/document.xml").decode("utf-8")
assert logical in xml
def test_xlsx_arabic_cell_ocr():
from app.services.convert.formatters.xlsx_formatter import format_xlsx
from app.services.convert.idm.model import BBox, Block, BlockType, Document, Page, TextSpan
logical = "مرحبا"
visual = logical[::-1]
doc = Document(
pages=[
Page(
index=0,
width=612,
height=792,
blocks=[
Block(
type=BlockType.paragraph,
text=visual,
spans=[TextSpan(text=visual, visual_order=True)],
reading_order=0,
bbox=BBox(y=700),
source="ocr",
)
],
)
]
)
data, _ = format_xlsx(doc)
wb = load_workbook(io.BytesIO(data), data_only=True)
values = []
for ws in wb.worksheets:
for row in ws.iter_rows(values_only=True):
values.extend("" if c is None else str(c) for c in row)
assert logical in values
def test_html_formatter_wraps_lists_and_rtl():
from app.services.convert.formatters.text_formatters import format_html
from app.services.convert.idm.model import Block, BlockType, Document, Page, TextSpan
doc = Document(
pages=[
Page(
index=0,
width=612,
height=792,
blocks=[
Block(
type=BlockType.list_item,
text="• Alpha",
list_style="bullet",
reading_order=0,
spans=[TextSpan(text="• Alpha")],
),
Block(
type=BlockType.list_item,
text="• Beta",
list_style="bullet",
reading_order=1,
spans=[TextSpan(text="• Beta")],
),
Block(
type=BlockType.paragraph,
text="مرحبا",
reading_order=2,
spans=[TextSpan(text="مرحبا")],
source="digital",
),
Block(
type=BlockType.table,
cells=[["H1", "H2"], ["A", "B"]],
reading_order=3,
),
],
)
]
)
html = format_html(doc).decode("utf-8")
assert "<ul>" in html and "</ul>" in html
assert html.count("<li>") == 2
assert 'dir="rtl"' in html
assert "<th>" in html and "<td>" in html