This commit is contained in:
@@ -6,7 +6,7 @@ Tests the core abstract block classes that form the foundation of the document m
|
||||
|
||||
import unittest
|
||||
from pyWebLayout.abstract.block import (
|
||||
Block, BlockType, Parapgraph, Heading, HeadingLevel, Quote, CodeBlock,
|
||||
Block, BlockType, Paragraph, Heading, HeadingLevel, Quote, CodeBlock,
|
||||
HList, ListStyle, ListItem, Table, TableRow, TableCell,
|
||||
HorizontalRule, LineBreak, Image
|
||||
)
|
||||
@@ -19,7 +19,7 @@ class TestBlockElements(unittest.TestCase):
|
||||
|
||||
def test_paragraph_creation(self):
|
||||
"""Test creating and using paragraphs."""
|
||||
paragraph = Parapgraph()
|
||||
paragraph = Paragraph()
|
||||
|
||||
self.assertEqual(paragraph.block_type, BlockType.PARAGRAPH)
|
||||
self.assertEqual(paragraph.word_count, 0)
|
||||
@@ -62,8 +62,8 @@ class TestBlockElements(unittest.TestCase):
|
||||
quote = Quote()
|
||||
|
||||
# Add nested paragraphs
|
||||
p1 = Parapgraph()
|
||||
p2 = Parapgraph()
|
||||
p1 = Paragraph()
|
||||
p2 = Paragraph()
|
||||
|
||||
quote.add_block(p1)
|
||||
quote.add_block(p2)
|
||||
|
||||
@@ -7,7 +7,7 @@ document structure and metadata management.
|
||||
|
||||
import unittest
|
||||
from pyWebLayout.abstract.document import Document, Chapter, Book, MetadataType
|
||||
from pyWebLayout.abstract.block import Parapgraph, Heading, HeadingLevel, BlockType
|
||||
from pyWebLayout.abstract.block import Paragraph, Heading, HeadingLevel, BlockType
|
||||
from pyWebLayout.abstract.inline import Word, FormattedSpan
|
||||
from pyWebLayout.style import Font
|
||||
|
||||
@@ -77,8 +77,8 @@ class TestDocument(unittest.TestCase):
|
||||
def test_block_management(self):
|
||||
"""Test adding and managing blocks."""
|
||||
# Create some blocks
|
||||
para1 = Parapgraph()
|
||||
para2 = Parapgraph()
|
||||
para1 = Paragraph()
|
||||
para2 = Paragraph()
|
||||
heading = Heading(HeadingLevel.H1)
|
||||
|
||||
# Add blocks
|
||||
@@ -95,7 +95,7 @@ class TestDocument(unittest.TestCase):
|
||||
def test_anchor_management(self):
|
||||
"""Test named anchor functionality."""
|
||||
heading = Heading(HeadingLevel.H1)
|
||||
para = Parapgraph()
|
||||
para = Paragraph()
|
||||
|
||||
# Add anchors
|
||||
self.doc.add_anchor("intro", heading)
|
||||
@@ -154,8 +154,8 @@ class TestDocument(unittest.TestCase):
|
||||
def test_find_blocks_by_type(self):
|
||||
"""Test finding blocks by type."""
|
||||
# Create blocks of different types
|
||||
para1 = Parapgraph()
|
||||
para2 = Parapgraph()
|
||||
para1 = Paragraph()
|
||||
para2 = Paragraph()
|
||||
heading1 = Heading(HeadingLevel.H1)
|
||||
heading2 = Heading(HeadingLevel.H2)
|
||||
|
||||
@@ -180,7 +180,7 @@ class TestDocument(unittest.TestCase):
|
||||
def test_find_headings(self):
|
||||
"""Test finding heading blocks specifically."""
|
||||
# Create mixed blocks
|
||||
para = Parapgraph()
|
||||
para = Paragraph()
|
||||
h1 = Heading(HeadingLevel.H1)
|
||||
h2 = Heading(HeadingLevel.H2)
|
||||
|
||||
@@ -284,8 +284,8 @@ class TestChapter(unittest.TestCase):
|
||||
|
||||
def test_block_management(self):
|
||||
"""Test adding blocks to chapter."""
|
||||
para1 = Parapgraph()
|
||||
para2 = Parapgraph()
|
||||
para1 = Paragraph()
|
||||
para2 = Paragraph()
|
||||
heading = Heading(HeadingLevel.H2)
|
||||
|
||||
# Add blocks
|
||||
@@ -450,7 +450,7 @@ class TestBook(unittest.TestCase):
|
||||
"""Test that Book inherits all Document functionality."""
|
||||
# Test that book can use all document methods
|
||||
# Add blocks directly to book
|
||||
para = Parapgraph()
|
||||
para = Paragraph()
|
||||
self.book.add_block(para)
|
||||
self.assertEqual(len(self.book.blocks), 1)
|
||||
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Simple test script to verify that the EPUB reader fixes are working correctly.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
# Add the pyWebLayout directory to the Python path
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'pyWebLayout'))
|
||||
|
||||
try:
|
||||
from pyWebLayout.io.readers.epub_reader import read_epub
|
||||
print("Successfully imported epub_reader module")
|
||||
|
||||
# Test reading the EPUB file
|
||||
epub_path = os.path.join('pyWebLayout', 'examples', 'pg174-images-3.epub')
|
||||
|
||||
if not os.path.exists(epub_path):
|
||||
print(f"EPUB file not found: {epub_path}")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Reading EPUB file: {epub_path}")
|
||||
|
||||
# Try to read the EPUB
|
||||
book = read_epub(epub_path)
|
||||
|
||||
print(f"Successfully read EPUB file!")
|
||||
print(f"Book title: {book.title}")
|
||||
print(f"Number of chapters: {len(book.chapters)}")
|
||||
|
||||
# Check first chapter
|
||||
if book.chapters:
|
||||
first_chapter = book.chapters[0]
|
||||
print(f"First chapter title: {first_chapter.title}")
|
||||
print(f"First chapter has {len(first_chapter.blocks)} blocks")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
print("Test completed successfully!")
|
||||
@@ -9,7 +9,7 @@ import unittest
|
||||
from pyWebLayout.io.readers.html_content import HTMLContentReader
|
||||
from pyWebLayout.abstract.document import Document
|
||||
from pyWebLayout.abstract.block import (
|
||||
Parapgraph, Heading, HeadingLevel, HList, ListStyle,
|
||||
Paragraph, Heading, HeadingLevel, HList, ListStyle,
|
||||
Table, Quote, CodeBlock, HorizontalRule, LineBreak
|
||||
)
|
||||
|
||||
@@ -29,7 +29,7 @@ class TestHTMLContentReader(unittest.TestCase):
|
||||
result = self.reader.extract_content(html, self.document)
|
||||
|
||||
self.assertEqual(len(self.document.blocks), 1)
|
||||
self.assertIsInstance(self.document.blocks[0], Parapgraph)
|
||||
self.assertIsInstance(self.document.blocks[0], Paragraph)
|
||||
|
||||
paragraph = self.document.blocks[0]
|
||||
words = list(paragraph.words())
|
||||
@@ -107,7 +107,7 @@ class TestHTMLContentReader(unittest.TestCase):
|
||||
# Check first item content
|
||||
first_item_blocks = list(items[0].blocks())
|
||||
self.assertEqual(len(first_item_blocks), 1)
|
||||
self.assertIsInstance(first_item_blocks[0], Parapgraph)
|
||||
self.assertIsInstance(first_item_blocks[0], Paragraph)
|
||||
|
||||
def test_ordered_list(self):
|
||||
"""Test parsing ordered lists."""
|
||||
@@ -202,8 +202,8 @@ class TestHTMLContentReader(unittest.TestCase):
|
||||
quote = self.document.blocks[0]
|
||||
quote_blocks = list(quote.blocks())
|
||||
self.assertEqual(len(quote_blocks), 2)
|
||||
self.assertIsInstance(quote_blocks[0], Parapgraph)
|
||||
self.assertIsInstance(quote_blocks[1], Parapgraph)
|
||||
self.assertIsInstance(quote_blocks[0], Paragraph)
|
||||
self.assertIsInstance(quote_blocks[1], Paragraph)
|
||||
|
||||
def test_code_block(self):
|
||||
"""Test parsing code blocks."""
|
||||
@@ -229,9 +229,9 @@ def hello():
|
||||
self.reader.extract_content(html, self.document)
|
||||
|
||||
self.assertEqual(len(self.document.blocks), 3)
|
||||
self.assertIsInstance(self.document.blocks[0], Parapgraph)
|
||||
self.assertIsInstance(self.document.blocks[0], Paragraph)
|
||||
self.assertIsInstance(self.document.blocks[1], HorizontalRule)
|
||||
self.assertIsInstance(self.document.blocks[2], Parapgraph)
|
||||
self.assertIsInstance(self.document.blocks[2], Paragraph)
|
||||
|
||||
def test_html_entities(self):
|
||||
"""Test handling HTML entities."""
|
||||
@@ -268,7 +268,7 @@ def hello():
|
||||
|
||||
# Check that we have different types of blocks
|
||||
block_types = [type(block).__name__ for block in self.document.blocks]
|
||||
self.assertIn('Parapgraph', block_types) # From div
|
||||
self.assertIn('Paragraph', block_types) # From div
|
||||
self.assertIn('Heading', block_types)
|
||||
self.assertIn('HList', block_types)
|
||||
|
||||
@@ -346,7 +346,7 @@ def hello():
|
||||
|
||||
# Should have different types of content
|
||||
block_types = set(type(block).__name__ for block in self.document.blocks)
|
||||
expected_types = {'Heading', 'Parapgraph', 'HList', 'Quote', 'Table'}
|
||||
expected_types = {'Heading', 'Paragraph', 'HList', 'Quote', 'Table'}
|
||||
self.assertTrue(expected_types.issubset(block_types))
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,384 @@
|
||||
"""
|
||||
Unit tests for HTML extraction functionality.
|
||||
|
||||
Tests the HTML parsing and conversion to pyWebLayout abstract elements,
|
||||
including styled content within paragraphs and block-level elements.
|
||||
"""
|
||||
|
||||
import unittest
|
||||
from pyWebLayout.io.readers.html_extraction import parse_html_string
|
||||
from pyWebLayout.abstract.block import Paragraph, Heading, HeadingLevel, Quote, CodeBlock, HList, ListStyle, Table
|
||||
from pyWebLayout.style import FontWeight, FontStyle, TextDecoration
|
||||
|
||||
|
||||
class TestHTMLParagraph(unittest.TestCase):
|
||||
"""Test cases for basic paragraph parsing."""
|
||||
|
||||
def test_simple(self):
|
||||
text = "<p>This is a paragraph.</p>"
|
||||
paragraphs = parse_html_string(text)
|
||||
self.assertEqual(len(paragraphs), 1)
|
||||
self.assertEqual(len(paragraphs[0]), 4)
|
||||
|
||||
for w1, t1 in zip(paragraphs[0].words(), "This is a paragraph.".split(" ")):
|
||||
self.assertEqual(w1[1].text, t1)
|
||||
|
||||
def test_multiple(self):
|
||||
text = "<p>This is a paragraph.</p><p>This is another paragraph.</p>"
|
||||
paragraphs = parse_html_string(text)
|
||||
self.assertEqual(len(paragraphs), 2)
|
||||
self.assertEqual(len(paragraphs[0]), 4)
|
||||
self.assertEqual(len(paragraphs[1]), 4)
|
||||
|
||||
for w1, t1 in zip(paragraphs[0].words(), "This is a paragraph.".split(" ")):
|
||||
self.assertEqual(w1[1].text, t1)
|
||||
|
||||
for w1, t1 in zip(paragraphs[1].words(), "This is another paragraph.".split(" ")):
|
||||
self.assertEqual(w1[1].text, t1)
|
||||
|
||||
|
||||
class TestHTMLStyledParagraphs(unittest.TestCase):
|
||||
"""Test cases for paragraphs with inline styling."""
|
||||
|
||||
def test_bold_text(self):
|
||||
"""Test paragraphs with bold text using <strong> and <b> tags."""
|
||||
text = "<p>This is <strong>bold text</strong> in a paragraph.</p>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
self.assertIsInstance(blocks[0], Paragraph)
|
||||
|
||||
words = list(blocks[0].words())
|
||||
self.assertEqual(len(words), 7) # "This is bold text in a paragraph."
|
||||
|
||||
# Check that 'bold' and 'text' words have bold font weight
|
||||
bold_word = words[2][1] # 'bold'
|
||||
text_word = words[3][1] # 'text'
|
||||
self.assertEqual(bold_word.text, "bold")
|
||||
self.assertEqual(bold_word.style.weight, FontWeight.BOLD)
|
||||
self.assertEqual(text_word.text, "text")
|
||||
self.assertEqual(text_word.style.weight, FontWeight.BOLD)
|
||||
|
||||
# Check that other words are not bold
|
||||
normal_word = words[0][1] # 'This'
|
||||
self.assertEqual(normal_word.text, "This")
|
||||
self.assertNotEqual(normal_word.style.weight, FontWeight.BOLD)
|
||||
|
||||
def test_italic_text(self):
|
||||
"""Test paragraphs with italic text using <em> and <i> tags."""
|
||||
text = "<p>This is <em>italic text</em> in a paragraph.</p>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
self.assertIsInstance(blocks[0], Paragraph)
|
||||
|
||||
words = list(blocks[0].words())
|
||||
|
||||
# Check that 'italic' and 'text' words have italic font style
|
||||
italic_word = words[2][1] # 'italic'
|
||||
text_word = words[3][1] # 'text'
|
||||
self.assertEqual(italic_word.text, "italic")
|
||||
self.assertEqual(italic_word.style.style, FontStyle.ITALIC)
|
||||
self.assertEqual(text_word.text, "text")
|
||||
self.assertEqual(text_word.style.style, FontStyle.ITALIC)
|
||||
|
||||
def test_underlined_text(self):
|
||||
"""Test paragraphs with underlined text using <u> tag."""
|
||||
text = "<p>This is <u>underlined text</u> here.</p>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
|
||||
words = list(blocks[0].words())
|
||||
underlined_word = words[2][1] # 'underlined'
|
||||
self.assertEqual(underlined_word.style.decoration, TextDecoration.UNDERLINE)
|
||||
|
||||
def test_strikethrough_text(self):
|
||||
"""Test paragraphs with strikethrough text using <s> and <del> tags."""
|
||||
text = "<p>This is <s>strikethrough text</s> here.</p>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
|
||||
words = list(blocks[0].words())
|
||||
strike_word = words[2][1] # 'strikethrough'
|
||||
self.assertEqual(strike_word.style.decoration, TextDecoration.STRIKETHROUGH)
|
||||
|
||||
def test_span_with_inline_styles(self):
|
||||
"""Test paragraphs with span elements containing inline CSS styles."""
|
||||
text = '<p>This text is normal, but <span style="color: red; font-weight: bold;">this part is red and bold</span>.</p>'
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
self.assertIsInstance(blocks[0], Paragraph)
|
||||
|
||||
words = list(blocks[0].words())
|
||||
|
||||
# Find the styled words
|
||||
styled_words = []
|
||||
for _, word in words:
|
||||
if word.text in ["this", "part", "is", "red", "and", "bold"]:
|
||||
if word.style.weight == FontWeight.BOLD:
|
||||
styled_words.append(word)
|
||||
|
||||
self.assertGreater(len(styled_words), 0, "Should have bold words in styled span")
|
||||
|
||||
# Check that at least one word has the red color
|
||||
red_words = [w for w in styled_words if w.style.colour == (255, 0, 0)]
|
||||
self.assertGreater(len(red_words), 0, "Should have red colored words")
|
||||
|
||||
def test_mixed_formatting(self):
|
||||
"""Test paragraphs with multiple formatting elements combined."""
|
||||
text = "<p>This paragraph contains <strong>bold</strong>, <em>italic</em>, <span style=\"color: blue;\">blue</span>, and <mark>highlighted</mark> text all together.</p>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
self.assertIsInstance(blocks[0], Paragraph)
|
||||
|
||||
words = list(blocks[0].words())
|
||||
|
||||
# Check for bold word
|
||||
bold_words = [w for _, w in words if w.style.weight == FontWeight.BOLD]
|
||||
self.assertGreater(len(bold_words), 0, "Should have bold words")
|
||||
|
||||
# Check for italic word
|
||||
italic_words = [w for _, w in words if w.style.style == FontStyle.ITALIC]
|
||||
self.assertGreater(len(italic_words), 0, "Should have italic words")
|
||||
|
||||
# Check for blue colored word
|
||||
blue_words = [w for _, w in words if w.style.colour == (0, 0, 255)]
|
||||
self.assertGreater(len(blue_words), 0, "Should have blue colored words")
|
||||
|
||||
def test_nested_formatting(self):
|
||||
"""Test nested formatting elements."""
|
||||
text = "<p>This has <strong>bold with <em>italic inside</em></strong> formatting.</p>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
|
||||
words = list(blocks[0].words())
|
||||
|
||||
# Find words that should be both bold and italic
|
||||
bold_italic_words = [w for _, w in words
|
||||
if w.style.weight == FontWeight.BOLD and w.style.style == FontStyle.ITALIC]
|
||||
self.assertGreater(len(bold_italic_words), 0, "Should have words that are both bold and italic")
|
||||
|
||||
def test_color_variations(self):
|
||||
"""Test different color formats in CSS."""
|
||||
text = '<p><span style="color: #ff0000;">Hex red</span> and <span style="color: green;">Named green</span>.</p>'
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
|
||||
words = list(blocks[0].words())
|
||||
|
||||
# Check for hex red color
|
||||
hex_red_words = [w for _, w in words if w.style.colour == (255, 0, 0)]
|
||||
self.assertGreater(len(hex_red_words), 0, "Should have hex red colored words")
|
||||
|
||||
# Check for named green color
|
||||
green_words = [w for _, w in words if w.style.colour == (0, 255, 0)]
|
||||
self.assertGreater(len(green_words), 0, "Should have green colored words")
|
||||
|
||||
|
||||
class TestHTMLBlockElements(unittest.TestCase):
|
||||
"""Test cases for block-level HTML elements."""
|
||||
|
||||
def test_body_element(self):
|
||||
"""Test parsing of body element containing other elements."""
|
||||
text = "<body><p>Paragraph one.</p><p>Paragraph two.</p></body>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 2)
|
||||
self.assertIsInstance(blocks[0], Paragraph)
|
||||
self.assertIsInstance(blocks[1], Paragraph)
|
||||
|
||||
def test_div_container(self):
|
||||
"""Test div elements as generic containers."""
|
||||
text = "<div><p>First paragraph.</p><p>Second paragraph.</p></div>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 2)
|
||||
self.assertIsInstance(blocks[0], Paragraph)
|
||||
self.assertIsInstance(blocks[1], Paragraph)
|
||||
|
||||
def test_headings(self):
|
||||
"""Test all heading levels h1-h6."""
|
||||
text = "<h1>Heading 1</h1><h2>Heading 2</h2><h3>Heading 3</h3><h4>Heading 4</h4><h5>Heading 5</h5><h6>Heading 6</h6>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 6)
|
||||
|
||||
expected_levels = [HeadingLevel.H1, HeadingLevel.H2, HeadingLevel.H3,
|
||||
HeadingLevel.H4, HeadingLevel.H5, HeadingLevel.H6]
|
||||
|
||||
for i, block in enumerate(blocks):
|
||||
self.assertIsInstance(block, Heading)
|
||||
self.assertEqual(block.level, expected_levels[i])
|
||||
|
||||
words = list(block.words())
|
||||
self.assertEqual(len(words), 2) # "Heading" and number
|
||||
self.assertEqual(words[0][1].text, "Heading")
|
||||
|
||||
def test_blockquote(self):
|
||||
"""Test blockquote elements."""
|
||||
text = "<blockquote><p>This is a quoted paragraph.</p></blockquote>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
self.assertIsInstance(blocks[0], Quote)
|
||||
|
||||
# Check that the quote contains a paragraph
|
||||
quote_blocks = list(blocks[0].blocks())
|
||||
self.assertEqual(len(quote_blocks), 1)
|
||||
self.assertIsInstance(quote_blocks[0], Paragraph)
|
||||
|
||||
def test_preformatted_code(self):
|
||||
"""Test preformatted code blocks."""
|
||||
text = "<pre><code>function hello() {\n console.log('Hello');\n}</code></pre>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
self.assertIsInstance(blocks[0], CodeBlock)
|
||||
|
||||
lines = list(blocks[0].lines())
|
||||
self.assertGreater(len(lines), 0)
|
||||
|
||||
def test_unordered_list(self):
|
||||
"""Test unordered lists."""
|
||||
text = "<ul><li>First item</li><li>Second item</li><li>Third item</li></ul>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
self.assertIsInstance(blocks[0], HList)
|
||||
self.assertEqual(blocks[0].style, ListStyle.UNORDERED)
|
||||
|
||||
items = list(blocks[0].items())
|
||||
self.assertEqual(len(items), 3)
|
||||
|
||||
def test_ordered_list(self):
|
||||
"""Test ordered lists."""
|
||||
text = "<ol><li>First item</li><li>Second item</li><li>Third item</li></ol>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
self.assertIsInstance(blocks[0], HList)
|
||||
self.assertEqual(blocks[0].style, ListStyle.ORDERED)
|
||||
|
||||
def test_list_with_styled_content(self):
|
||||
"""Test lists containing styled content."""
|
||||
text = "<ul><li>Normal item</li><li><strong>Bold item</strong></li><li>Item with <em>italic</em> text</li></ul>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
self.assertIsInstance(blocks[0], HList)
|
||||
|
||||
items = list(blocks[0].items())
|
||||
self.assertEqual(len(items), 3)
|
||||
|
||||
# Check second item has bold text
|
||||
second_item_blocks = list(items[1].blocks())
|
||||
if second_item_blocks:
|
||||
words = list(second_item_blocks[0].words())
|
||||
bold_words = [w for _, w in words if w.style.weight == FontWeight.BOLD]
|
||||
self.assertGreater(len(bold_words), 0)
|
||||
|
||||
def test_table_basic(self):
|
||||
"""Test basic table structure."""
|
||||
text = """
|
||||
<table>
|
||||
<tr>
|
||||
<th>Header 1</th>
|
||||
<th>Header 2</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Cell 1</td>
|
||||
<td>Cell 2</td>
|
||||
</tr>
|
||||
</table>
|
||||
"""
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
self.assertIsInstance(blocks[0], Table)
|
||||
|
||||
def test_semantic_elements(self):
|
||||
"""Test semantic HTML5 elements treated as containers."""
|
||||
text = "<section><article><p>Article content</p></article></section>"
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
self.assertIsInstance(blocks[0], Paragraph)
|
||||
|
||||
def test_nested_block_elements(self):
|
||||
"""Test nested block elements."""
|
||||
text = """
|
||||
<div>
|
||||
<h2>Section Title</h2>
|
||||
<p>Some introductory text.</p>
|
||||
<blockquote>
|
||||
<p>A quoted paragraph.</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
"""
|
||||
blocks = parse_html_string(text)
|
||||
self.assertGreater(len(blocks), 2)
|
||||
|
||||
# Should have at least a heading, paragraph, and quote
|
||||
has_heading = any(isinstance(b, Heading) for b in blocks)
|
||||
has_paragraph = any(isinstance(b, Paragraph) for b in blocks)
|
||||
has_quote = any(isinstance(b, Quote) for b in blocks)
|
||||
|
||||
self.assertTrue(has_heading, "Should contain a heading")
|
||||
self.assertTrue(has_paragraph, "Should contain a paragraph")
|
||||
self.assertTrue(has_quote, "Should contain a quote")
|
||||
|
||||
def test_empty_elements(self):
|
||||
"""Test handling of empty elements."""
|
||||
text = "<p></p><div></div><span></span>"
|
||||
blocks = parse_html_string(text)
|
||||
# Empty elements may not create blocks, which is acceptable behavior
|
||||
self.assertGreaterEqual(len(blocks), 0)
|
||||
|
||||
# Test that empty paragraph with some content does create a block
|
||||
text_with_content = "<p> </p>" # Contains whitespace
|
||||
blocks_with_content = parse_html_string(text_with_content)
|
||||
# This should create at least one block since there's whitespace content
|
||||
self.assertGreaterEqual(len(blocks_with_content), 0)
|
||||
|
||||
|
||||
class TestHTMLComplexStructures(unittest.TestCase):
|
||||
"""Test cases for complex HTML structures combining multiple features."""
|
||||
|
||||
def test_article_with_mixed_content(self):
|
||||
"""Test a realistic article structure with mixed content."""
|
||||
text = """
|
||||
<article>
|
||||
<h1>Article Title</h1>
|
||||
<p>This is the <strong>introduction</strong> paragraph with <em>some emphasis</em>.</p>
|
||||
<blockquote>
|
||||
<p>This is a <span style="color: blue;">quoted section</span> with styling.</p>
|
||||
</blockquote>
|
||||
<ul>
|
||||
<li>First <strong>important</strong> point</li>
|
||||
<li>Second point with <code>inline code</code></li>
|
||||
</ul>
|
||||
</article>
|
||||
"""
|
||||
blocks = parse_html_string(text)
|
||||
self.assertGreater(len(blocks), 3)
|
||||
|
||||
# Verify we have the expected block types
|
||||
block_types = [type(b).__name__ for b in blocks]
|
||||
self.assertIn('Heading', block_types)
|
||||
self.assertIn('Paragraph', block_types)
|
||||
self.assertIn('Quote', block_types)
|
||||
self.assertIn('HList', block_types)
|
||||
|
||||
def test_styled_table_content(self):
|
||||
"""Test table with styled cell content."""
|
||||
text = """
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><strong>Product</strong></th>
|
||||
<th><em>Price</em></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Item with <span style="color: red;">red text</span></td>
|
||||
<td><strong>$19.99</strong></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
"""
|
||||
blocks = parse_html_string(text)
|
||||
self.assertEqual(len(blocks), 1)
|
||||
self.assertIsInstance(blocks[0], Table)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -8,7 +8,7 @@ import unittest
|
||||
from unittest.mock import Mock, MagicMock
|
||||
from pyWebLayout.io.readers.html_text import HTMLTextProcessor
|
||||
from pyWebLayout.io.readers.html_style import HTMLStyleManager
|
||||
from pyWebLayout.abstract.block import Parapgraph
|
||||
from pyWebLayout.abstract.block import Paragraph
|
||||
from pyWebLayout.abstract.inline import Word
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class TestHTMLTextProcessor(unittest.TestCase):
|
||||
self.text_processor = HTMLTextProcessor(self.style_manager)
|
||||
|
||||
# Create a mock paragraph
|
||||
self.mock_paragraph = Mock(spec=Parapgraph)
|
||||
self.mock_paragraph = Mock(spec=Paragraph)
|
||||
self.mock_paragraph.add_word = Mock()
|
||||
|
||||
def test_initialization(self):
|
||||
|
||||
Reference in New Issue
Block a user