"""
Regression tests for inline content inside block containers (spec S1).
Inline tags are registered to ignore_handler because they are meant to be
consumed by extract_text_content. Only
and
- ever called it, so
every other container - div, li, td, th, blockquote - iterated its children as
blocks, and inline tags returned None. Their text was silently discarded, and
bare text nodes each became a separate paragraph.
"""
import pytest
from pyWebLayout.abstract.block import (
HList,
Paragraph,
Quote,
Table,
)
from pyWebLayout.abstract.inline import LinkedWord, Word
from pyWebLayout.io.readers.html_extraction import parse_html_string
def words_of(block):
return [w.text for w in getattr(block, 'words', [])]
def all_words(blocks):
out = []
for block in blocks:
out.extend(words_of(block))
return out
def cell_blocks(table):
for _, row in table.all_rows():
for cell in row.cells():
yield list(cell.blocks())
EXPECTED = ["hello", "world", "again"]
class TestInlineContentIsKept:
"""The same markup must survive in every container."""
def test_paragraph_control(self):
"""
already worked - this is the reference behaviour."""
blocks = parse_html_string("
hello world again
")
assert all_words(blocks) == EXPECTED
def test_div(self):
blocks = parse_html_string("hello world again
")
assert all_words(blocks) == EXPECTED
def test_list_item(self):
blocks = parse_html_string("")
hlist = next(b for b in blocks if isinstance(b, HList))
item = list(hlist.items())[0]
assert all_words(item.blocks()) == EXPECTED
def test_table_cell(self):
blocks = parse_html_string(
"")
table = next(b for b in blocks if isinstance(b, Table))
assert all_words(next(cell_blocks(table))) == EXPECTED
def test_table_header_cell(self):
blocks = parse_html_string(
"")
table = next(b for b in blocks if isinstance(b, Table))
assert all_words(next(cell_blocks(table))) == EXPECTED
def test_blockquote(self):
blocks = parse_html_string("hello world again
")
quote = next(b for b in blocks if isinstance(b, Quote))
assert all_words(quote.blocks()) == EXPECTED
class TestInlineRunsCoalesce:
"""A run of inline content is one paragraph, not one per text node."""
def test_div_yields_a_single_paragraph(self):
blocks = parse_html_string("a b c
")
paragraphs = [b for b in blocks if isinstance(b, Paragraph)]
assert len(paragraphs) == 1, f"expected one paragraph, got {len(blocks)} blocks"
assert words_of(paragraphs[0]) == ["a", "b", "c"]
def test_cell_yields_a_single_paragraph(self):
blocks = parse_html_string("")
table = next(b for b in blocks if isinstance(b, Table))
cell = next(cell_blocks(table))
assert len(cell) == 1
assert words_of(cell[0]) == ["a", "b", "c"]
def test_block_child_splits_the_run(self):
"""Inline runs either side of a block child stay separate, in order."""
blocks = parse_html_string(
"")
table = next(b for b in blocks if isinstance(b, Table))
cell = next(cell_blocks(table))
assert [words_of(b) for b in cell] == [["before"], ["middle"], ["after"]]
def test_line_break_splits_the_run(self):
blocks = parse_html_string("first
second
")
paragraphs = [b for b in blocks if isinstance(b, Paragraph)]
assert [words_of(p) for p in paragraphs] == [["first"], ["second"]]
def test_whitespace_between_blocks_makes_no_paragraph(self):
blocks = parse_html_string("")
assert [words_of(b) for b in blocks] == [["one"], ["two"]]
class TestLinksSurvive:
""" must produce LinkedWord wherever it appears."""
def test_link_in_cell(self):
blocks = parse_html_string(
'')
table = next(b for b in blocks if isinstance(b, Table))
cell = next(cell_blocks(table))
found = [w for b in cell for w in getattr(b, 'words', [])]
assert [w.text for w in found] == ["link", "text"]
linked = [w for w in found if isinstance(w, LinkedWord)]
assert len(linked) == 1
assert linked[0].location == "http://x"
def test_link_in_div(self):
blocks = parse_html_string('')
found = [w for b in blocks for w in getattr(b, 'words', [])]
assert [w.text for w in found] == ["see", "Section", "2", "now"]
assert all(isinstance(w, LinkedWord) for w in found[1:3])
def test_link_in_list_item(self):
blocks = parse_html_string('')
hlist = next(b for b in blocks if isinstance(b, HList))
item = hlist._items[0]
found = [w for b in item.blocks() for w in getattr(b, 'words', [])]
assert [w.text for w in found] == ["click", "here"]
assert isinstance(found[0], LinkedWord)
class TestNestedContainers:
def test_div_in_div(self):
blocks = parse_html_string("")
assert [words_of(b) for b in blocks] == [["outer"], ["inner"], ["tail"]]
def test_block_children_still_pass_through(self):
blocks = parse_html_string("")
assert len(blocks) == 2
assert words_of(blocks[0]) == ["Title"]
assert words_of(blocks[1]) == ["Body"]
def test_cell_containing_a_list(self):
blocks = parse_html_string(
"")
table = next(b for b in blocks if isinstance(b, Table))
cell = next(cell_blocks(table))
assert isinstance(cell[0], Paragraph)
assert words_of(cell[0]) == ["intro"]
assert isinstance(cell[1], HList)
class TestComments:
def test_comment_text_is_not_content(self):
blocks = parse_html_string("realtext
")
assert all_words(blocks) == ["real", "text"]