2026-05-31 16:01:05 +00:00
from __future__ import annotations
2026-06-04 15:20:49 +00:00
def test_structured_block_has_render_default_for_body ( ) - > None :
from paperforge . worker . ocr_blocks import build_structured_blocks
raw_blocks = [
{
" paper_id " : " KEY001 " ,
" page " : 1 ,
" block_id " : " p1_b1 " ,
" raw_label " : " text " ,
" raw_order " : 0 ,
" bbox " : [ 100 , 200 , 900 , 300 ] ,
" text " : " This is a body paragraph with enough text to be meaningful and avoid the short-text threshold. " ,
" page_width " : 1200 ,
" page_height " : 1600 ,
}
]
rows = build_structured_blocks ( raw_blocks )
assert rows [ 0 ] [ " role " ] == " body_paragraph "
assert rows [ 0 ] [ " render_default " ] is True
assert rows [ 0 ] [ " index_default " ] is True
def test_structured_block_marks_noise_as_not_renderable ( ) - > None :
from paperforge . worker . ocr_blocks import build_structured_blocks
raw_blocks = [
{
" paper_id " : " KEY001 " ,
" page " : 1 ,
" block_id " : " p1_b1 " ,
" raw_label " : " header " ,
" raw_order " : 0 ,
" bbox " : [ 1 , 2 , 100 , 20 ] ,
" text " : " Running head: SOME JOURNAL " ,
" page_width " : 1200 ,
" page_height " : 1600 ,
}
]
rows = build_structured_blocks ( raw_blocks )
assert rows [ 0 ] [ " role " ] in { " noise " , " page_header " }
assert rows [ 0 ] [ " render_default " ] is False
2026-05-31 16:01:05 +00:00
def test_heading_role_is_not_figure_text ( ) - > None :
from paperforge . worker . ocr_roles import assign_block_role
block = {
" block_label " : " paragraph_title " ,
" block_content " : " 5.1 Bone " ,
" block_bbox " : [ 606 , 732 , 709 , 759 ] ,
}
role = assign_block_role ( block , page_blocks = [ ] , page_width = 1191 , page_height = 1684 )
assert role . role in { " section_heading " , " subsection_heading " }
def test_figure_caption_role_beats_body_paragraph ( ) - > None :
from paperforge . worker . ocr_roles import assign_block_role
block = {
" block_label " : " text " ,
" block_content " : " Figure 4 RT-qPCR results. Temporal changes in messenger RNA... " ,
" block_bbox " : [ 373 , 1101 , 1143 , 1258 ] ,
}
role = assign_block_role ( block , page_blocks = [ ] , page_width = 1200 , page_height = 1600 )
assert role . role == " figure_caption "
def test_paragraph_title_is_heading_prior ( ) - > None :
from paperforge . worker . ocr_roles import assign_block_role
block = {
" block_label " : " paragraph_title " ,
" block_content " : " 5 In vitro PEMF studies " ,
" block_bbox " : [ 94 , 1328 , 387 , 1356 ] ,
}
role = assign_block_role ( block , page_blocks = [ ] , page_width = 1191 , page_height = 1684 )
assert role . role in { " section_heading " , " subsection_heading " }
assert role . confidence > = 0.7
def test_figure_title_is_caption_prior ( ) - > None :
from paperforge . worker . ocr_roles import assign_block_role
block = {
" block_label " : " figure_title " ,
" block_content " : " Figure 2. Representative pathology records. " ,
" block_bbox " : [ 300 , 1180 , 980 , 1250 ] ,
}
role = assign_block_role ( block , page_blocks = [ ] , page_width = 1200 , page_height = 1600 )
assert role . role == " figure_caption "
assert role . confidence > = 0.8
def test_unknown_structural_for_unrecognized ( ) - > None :
from paperforge . worker . ocr_roles import assign_block_role
block = {
" block_label " : " text " ,
" block_content " : " xyz " ,
" block_bbox " : [ 100 , 100 , 200 , 120 ] ,
}
role = assign_block_role ( block , page_blocks = [ ] , page_width = 1200 , page_height = 1600 )
assert role . role in { " body_paragraph " , " unknown_structural " }
assert role . confidence < 0.8
2026-06-05 05:31:50 +00:00
def test_stabilize_role_classifies_paper_title ( ) - > None :
from paperforge . worker . ocr_roles import assign_block_role
assignment = assign_block_role (
2026-06-05 14:47:13 +00:00
block = {
" block_label " : " paragraph_title " ,
" block_content " : " Test Paper About Science " ,
" page " : 1 ,
" block_bbox " : [ 100 , 50 , 900 , 100 ] ,
} ,
2026-06-05 05:31:50 +00:00
page_blocks = [ ] ,
2026-06-05 14:47:13 +00:00
page_height = 1000 ,
2026-06-05 05:31:50 +00:00
)
assert assignment . role == " paper_title "
def test_stabilize_abstract_heading_is_not_body ( ) - > None :
from paperforge . worker . ocr_roles import assign_block_role
assignment = assign_block_role (
block = { " block_label " : " paragraph_title " , " block_content " : " Abstract " } ,
page_blocks = [ ] ,
)
assert assignment . role == " abstract_heading "
def test_stabilize_frontmatter_noise_not_section_heading ( ) - > None :
from paperforge . worker . ocr_roles import assign_block_role
for noise in ( " OPEN ACCESS " , " CITATION " , " COPYRIGHT " , " KEYWORDS " , " EDITED BY " , " REVIEWED BY " ) :
assignment = assign_block_role (
block = { " block_label " : " paragraph_title " , " block_content " : noise } ,
page_blocks = [ ] ,
)
assert assignment . role not in ( " section_heading " , " subsection_heading " ) , f " { noise } should not be a heading "
2026-06-05 14:47:13 +00:00
def test_backmatter_heading_not_paper_title ( ) - > None :
from paperforge . worker . ocr_roles import assign_block_role
for text in [ " Generative AI statement " , " Acknowledgments " , " Funding " , " Conflict of interest " ] :
block = {
" block_label " : " paragraph_title " ,
" block_content " : text ,
" page " : 1 ,
" block_bbox " : [ 100 , 50 , 500 , 80 ] ,
}
assignment = assign_block_role ( block , page_blocks = [ ] , page_height = 1000 )
assert assignment . role != " paper_title " , f " ' { text } ' should not be paper_title "
def test_backmatter_heading_gets_backmatter_role ( ) - > None :
from paperforge . worker . ocr_roles import assign_block_role
backmatter_phrases = [
" Author contributions " ,
" Funding " ,
" Acknowledgments " ,
" Conflict of interest " ,
" Generative AI statement " ,
]
for text in backmatter_phrases :
block = {
" block_label " : " paragraph_title " ,
" block_content " : text ,
" page " : 20 ,
" block_bbox " : [ 100 , 600 , 500 , 630 ] ,
}
assignment = assign_block_role ( block , page_blocks = [ ] , page_height = 1000 )
assert assignment . role . startswith ( " backmatter_ " ) , f " ' { text } ' should get backmatter_ role, got { assignment . role } "
def test_references_heading_gets_reference_role ( ) - > None :
from paperforge . worker . ocr_roles import assign_block_role
assignment = assign_block_role (
block = { " block_label " : " paragraph_title " , " block_content " : " References " } ,
page_blocks = [ ] ,
)
assert assignment . role == " reference_heading " , (
f " paragraph_title ' References ' should be reference_heading, got { assignment . role } "
)
assignment_text = assign_block_role (
block = { " block_label " : " text " , " block_content " : " References " } ,
page_blocks = [ ] ,
)
assert assignment_text . role == " reference_heading " , (
f " text ' References ' should be reference_heading, got { assignment_text . role } "
)
def test_body_with_noise_phrase_below_backmatter_heading ( ) - > None :
""" Text block with ' supplementary material ' under backmatter heading -> backmatter_body, not frontmatter_noise. """
from paperforge . worker . ocr_roles import assign_block_role
page_blocks = [
{
" block_label " : " paragraph_title " ,
" block_content " : " Supplementary material " ,
" block_bbox " : [ 604 , 536 , 909 , 567 ] ,
" page " : 22 ,
} ,
{
" block_label " : " text " ,
" block_content " : " The Supplementary Material for this article can be found online. " ,
" block_bbox " : [ 604 , 590 , 1096 , 662 ] ,
" page " : 22 ,
} ,
]
assignment = assign_block_role (
page_blocks [ 1 ] ,
page_blocks = page_blocks ,
page_width = 1191 ,
)
assert assignment . role == " body_paragraph " , (
f " Role layer should stay conservative and leave tail ownership to render, got { assignment . role } "
)
def test_style_aware_unnumbered_heading_detection ( ) - > None :
""" Unnumbered headings with distinct visual style are detected as headings.
The current assign_block_role ignores span_metadata ( size , flags ) ,
relying only on block_label and text patterns . Two text blocks with
heading - like style ( different sizes , bold ) should both be detected as
headings , and a truly ordinary body block should not be promoted .
"""
from paperforge . worker . ocr_roles import assign_block_role
big_heading = {
" block_label " : " text " ,
" block_content " : " Clinical Outcomes " ,
" span_metadata " : { " size " : 16 , " flags " : " bold " } ,
" block_bbox " : [ 96 , 300 , 500 , 330 ] ,
" page " : 5 ,
}
sub_heading = {
" block_label " : " text " ,
" block_content " : " Histological Analysis " ,
" span_metadata " : { " size " : 14 , " flags " : " bold " } ,
" block_bbox " : [ 96 , 450 , 500 , 480 ] ,
" page " : 5 ,
}
body_block = {
" block_label " : " text " ,
" block_content " : " Immunohistochemical staining revealed significant differences between the treatment and control groups across all time points examined. " ,
" span_metadata " : { " size " : 10 , " flags " : " normal " } ,
" block_bbox " : [ 96 , 500 , 1090 , 620 ] ,
" page " : 5 ,
}
page_blocks = [ big_heading , sub_heading , body_block ]
big_role = assign_block_role (
big_heading ,
page_blocks = page_blocks ,
page_height = 1000 ,
)
sub_role = assign_block_role (
sub_heading ,
page_blocks = page_blocks ,
page_height = 1000 ,
)
body_role = assign_block_role (
body_block ,
page_blocks = page_blocks ,
page_height = 1000 ,
)
assert big_role . role in { " section_heading " , " backmatter_heading " } , (
f " Big heading should be detected as heading, got { big_role . role } "
)
assert sub_role . role in { " section_heading " , " backmatter_heading " } , (
f " Sub heading should be detected as heading, got { sub_role . role } "
)
assert body_role . role not in { " section_heading " , " backmatter_heading " , " subsection_heading " } , (
f " Body should not be promoted to heading, got { body_role . role } "
)
def test_backmatter_body_cross_column_ownership ( ) - > None :
""" Body in right column attaches to nearest right-column heading, not left-column one. """
from paperforge . worker . ocr_roles import assign_block_role
page_blocks = [
{
" block_label " : " paragraph_title " ,
" block_content " : " Conflict of interest " ,
" block_bbox " : [ 94 , 536 , 338 , 565 ] ,
" page " : 22 ,
} ,
{
" block_label " : " paragraph_title " ,
" block_content " : " Supplementary material " ,
" block_bbox " : [ 604 , 536 , 909 , 567 ] ,
" page " : 22 ,
} ,
{
" block_label " : " text " ,
" block_content " : " The Supplementary Material for this article can be found online. " ,
" block_bbox " : [ 604 , 590 , 1096 , 662 ] ,
" page " : 22 ,
} ,
]
assignment = assign_block_role (
page_blocks [ 2 ] ,
page_blocks = page_blocks ,
page_width = 1191 ,
)
assert assignment . role == " body_paragraph " , (
f " Role layer should stay conservative and leave tail ownership to render, got { assignment . role } "
)