pyWebLayout/tests/test_abstract_document.py
Duncan Tourolle c0c366e9f4
Some checks failed
Python CI / test (push) Failing after 1m35s
Additional changes.
2025-06-06 20:54:33 +02:00

469 lines
17 KiB
Python

"""
Unit tests for abstract document elements.
Tests the Document, Chapter, Book, and MetadataType classes that handle
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.inline import Word, FormattedSpan
from pyWebLayout.style import Font
class TestMetadataType(unittest.TestCase):
"""Test cases for MetadataType enum."""
def test_metadata_types(self):
"""Test that all expected metadata types exist."""
expected_types = [
'TITLE', 'AUTHOR', 'DESCRIPTION', 'KEYWORDS', 'LANGUAGE',
'PUBLICATION_DATE', 'MODIFIED_DATE', 'PUBLISHER', 'IDENTIFIER',
'COVER_IMAGE', 'CUSTOM'
]
for type_name in expected_types:
self.assertTrue(hasattr(MetadataType, type_name))
# Test custom type has expected value
self.assertEqual(MetadataType.CUSTOM.value, 100)
class TestDocument(unittest.TestCase):
"""Test cases for Document class."""
def setUp(self):
"""Set up test fixtures."""
self.doc = Document("Test Document", "en-US")
self.font = Font()
def test_document_creation(self):
"""Test document creation with basic parameters."""
self.assertEqual(self.doc.get_title(), "Test Document")
self.assertEqual(self.doc.get_metadata(MetadataType.LANGUAGE), "en-US")
self.assertEqual(len(self.doc.blocks), 0)
def test_document_creation_minimal(self):
"""Test document creation with minimal parameters."""
doc = Document()
self.assertIsNone(doc.get_title())
self.assertEqual(doc.get_metadata(MetadataType.LANGUAGE), "en-US")
def test_metadata_management(self):
"""Test setting and getting metadata."""
# Set various metadata types
self.doc.set_metadata(MetadataType.AUTHOR, "John Doe")
self.doc.set_metadata(MetadataType.DESCRIPTION, "A test document")
self.doc.set_metadata(MetadataType.KEYWORDS, ["test", "document"])
# Test retrieval
self.assertEqual(self.doc.get_metadata(MetadataType.AUTHOR), "John Doe")
self.assertEqual(self.doc.get_metadata(MetadataType.DESCRIPTION), "A test document")
self.assertEqual(self.doc.get_metadata(MetadataType.KEYWORDS), ["test", "document"])
# Test non-existent metadata
self.assertIsNone(self.doc.get_metadata(MetadataType.PUBLISHER))
def test_title_convenience_methods(self):
"""Test title getter and setter convenience methods."""
# Test setting title
self.doc.set_title("New Title")
self.assertEqual(self.doc.get_title(), "New Title")
# Test that it's also in metadata
self.assertEqual(self.doc.get_metadata(MetadataType.TITLE), "New Title")
def test_block_management(self):
"""Test adding and managing blocks."""
# Create some blocks
para1 = Parapgraph()
para2 = Parapgraph()
heading = Heading(HeadingLevel.H1)
# Add blocks
self.doc.add_block(para1)
self.doc.add_block(heading)
self.doc.add_block(para2)
# Test blocks list
self.assertEqual(len(self.doc.blocks), 3)
self.assertEqual(self.doc.blocks[0], para1)
self.assertEqual(self.doc.blocks[1], heading)
self.assertEqual(self.doc.blocks[2], para2)
def test_anchor_management(self):
"""Test named anchor functionality."""
heading = Heading(HeadingLevel.H1)
para = Parapgraph()
# Add anchors
self.doc.add_anchor("intro", heading)
self.doc.add_anchor("content", para)
# Test retrieval
self.assertEqual(self.doc.get_anchor("intro"), heading)
self.assertEqual(self.doc.get_anchor("content"), para)
self.assertIsNone(self.doc.get_anchor("nonexistent"))
def test_resource_management(self):
"""Test document resource management."""
# Add various resources
self.doc.add_resource("image1", {"type": "image", "path": "test.jpg"})
self.doc.add_resource("style1", {"type": "css", "content": "body {}"})
# Test retrieval
image = self.doc.get_resource("image1")
self.assertEqual(image["type"], "image")
self.assertEqual(image["path"], "test.jpg")
style = self.doc.get_resource("style1")
self.assertEqual(style["type"], "css")
# Test non-existent resource
self.assertIsNone(self.doc.get_resource("nonexistent"))
def test_stylesheet_management(self):
"""Test stylesheet addition."""
# Add stylesheets
css1 = {"href": "style.css", "type": "text/css"}
css2 = {"href": "theme.css", "type": "text/css"}
self.doc.add_stylesheet(css1)
self.doc.add_stylesheet(css2)
# Test that stylesheets are stored
self.assertEqual(len(self.doc._stylesheets), 2)
self.assertEqual(self.doc._stylesheets[0], css1)
self.assertEqual(self.doc._stylesheets[1], css2)
def test_script_management(self):
"""Test script addition."""
# Add scripts
script1 = "console.log('Hello');"
script2 = "document.ready(function(){});"
self.doc.add_script(script1)
self.doc.add_script(script2)
# Test that scripts are stored
self.assertEqual(len(self.doc._scripts), 2)
self.assertEqual(self.doc._scripts[0], script1)
self.assertEqual(self.doc._scripts[1], script2)
def test_find_blocks_by_type(self):
"""Test finding blocks by type."""
# Create blocks of different types
para1 = Parapgraph()
para2 = Parapgraph()
heading1 = Heading(HeadingLevel.H1)
heading2 = Heading(HeadingLevel.H2)
# Add blocks to document
self.doc.add_block(para1)
self.doc.add_block(heading1)
self.doc.add_block(para2)
self.doc.add_block(heading2)
# Test finding paragraphs
paragraphs = self.doc.find_blocks_by_type(BlockType.PARAGRAPH)
self.assertEqual(len(paragraphs), 2)
self.assertIn(para1, paragraphs)
self.assertIn(para2, paragraphs)
# Test finding headings
headings = self.doc.find_blocks_by_type(BlockType.HEADING)
self.assertEqual(len(headings), 2)
self.assertIn(heading1, headings)
self.assertIn(heading2, headings)
def test_find_headings(self):
"""Test finding heading blocks specifically."""
# Create mixed blocks
para = Parapgraph()
h1 = Heading(HeadingLevel.H1)
h2 = Heading(HeadingLevel.H2)
# Add words to headings for title extraction
word1 = Word("Chapter", self.font)
word2 = Word("One", self.font)
h1.add_word(word1)
h1.add_word(word2)
word3 = Word("Section", self.font)
h2.add_word(word3)
self.doc.add_block(para)
self.doc.add_block(h1)
self.doc.add_block(h2)
# Test finding headings
headings = self.doc.find_headings()
self.assertEqual(len(headings), 2)
self.assertIn(h1, headings)
self.assertIn(h2, headings)
self.assertNotIn(para, headings)
def test_generate_table_of_contents(self):
"""Test table of contents generation."""
# Create headings with content
h1 = Heading(HeadingLevel.H1)
h2 = Heading(HeadingLevel.H2)
h3 = Heading(HeadingLevel.H3)
# Add words to headings
h1.add_word(Word("Introduction", self.font))
h2.add_word(Word("Getting", self.font))
h2.add_word(Word("Started", self.font))
h3.add_word(Word("Installation", self.font))
self.doc.add_block(h1)
self.doc.add_block(h2)
self.doc.add_block(h3)
# Generate TOC
toc = self.doc.generate_table_of_contents()
# Test TOC structure
self.assertEqual(len(toc), 3)
# Test first entry
level, title, block = toc[0]
self.assertEqual(level, 1) # H1
self.assertEqual(title, "Introduction")
self.assertEqual(block, h1)
# Test second entry
level, title, block = toc[1]
self.assertEqual(level, 2) # H2
self.assertEqual(title, "Getting Started")
self.assertEqual(block, h2)
# Test third entry
level, title, block = toc[2]
self.assertEqual(level, 3) # H3
self.assertEqual(title, "Installation")
self.assertEqual(block, h3)
class TestChapter(unittest.TestCase):
"""Test cases for Chapter class."""
def setUp(self):
"""Set up test fixtures."""
self.chapter = Chapter("Test Chapter", 1)
def test_chapter_creation(self):
"""Test chapter creation."""
self.assertEqual(self.chapter.title, "Test Chapter")
self.assertEqual(self.chapter.level, 1)
self.assertEqual(len(self.chapter.blocks), 0)
def test_chapter_creation_minimal(self):
"""Test chapter creation with minimal parameters."""
chapter = Chapter()
self.assertIsNone(chapter.title)
self.assertEqual(chapter.level, 1)
def test_title_property(self):
"""Test title property getter and setter."""
# Test setter
self.chapter.title = "New Chapter Title"
self.assertEqual(self.chapter.title, "New Chapter Title")
# Test setting to None
self.chapter.title = None
self.assertIsNone(self.chapter.title)
def test_level_property(self):
"""Test level property."""
self.assertEqual(self.chapter.level, 1)
# Level should be read-only (no setter test)
# This is by design based on the class definition
def test_block_management(self):
"""Test adding blocks to chapter."""
para1 = Parapgraph()
para2 = Parapgraph()
heading = Heading(HeadingLevel.H2)
# Add blocks
self.chapter.add_block(para1)
self.chapter.add_block(heading)
self.chapter.add_block(para2)
# Test blocks list
self.assertEqual(len(self.chapter.blocks), 3)
self.assertEqual(self.chapter.blocks[0], para1)
self.assertEqual(self.chapter.blocks[1], heading)
self.assertEqual(self.chapter.blocks[2], para2)
def test_metadata_management(self):
"""Test chapter metadata."""
# Set metadata
self.chapter.set_metadata("author", "Jane Doe")
self.chapter.set_metadata("word_count", 1500)
self.chapter.set_metadata("tags", ["intro", "basics"])
# Test retrieval
self.assertEqual(self.chapter.get_metadata("author"), "Jane Doe")
self.assertEqual(self.chapter.get_metadata("word_count"), 1500)
self.assertEqual(self.chapter.get_metadata("tags"), ["intro", "basics"])
# Test non-existent metadata
self.assertIsNone(self.chapter.get_metadata("nonexistent"))
class TestBook(unittest.TestCase):
"""Test cases for Book class."""
def setUp(self):
"""Set up test fixtures."""
self.book = Book("Test Book", "Author Name", "en-US")
def test_book_creation(self):
"""Test book creation with all parameters."""
self.assertEqual(self.book.get_title(), "Test Book")
self.assertEqual(self.book.get_author(), "Author Name")
self.assertEqual(self.book.get_metadata(MetadataType.LANGUAGE), "en-US")
self.assertEqual(len(self.book.chapters), 0)
def test_book_creation_minimal(self):
"""Test book creation with minimal parameters."""
book = Book()
self.assertIsNone(book.get_title())
self.assertIsNone(book.get_author())
self.assertEqual(book.get_metadata(MetadataType.LANGUAGE), "en-US")
def test_book_creation_partial(self):
"""Test book creation with partial parameters."""
book = Book(title="Just Title")
self.assertEqual(book.get_title(), "Just Title")
self.assertIsNone(book.get_author())
def test_author_convenience_methods(self):
"""Test author getter and setter convenience methods."""
# Test setting author
self.book.set_author("New Author")
self.assertEqual(self.book.get_author(), "New Author")
# Test that it's also in metadata
self.assertEqual(self.book.get_metadata(MetadataType.AUTHOR), "New Author")
def test_chapter_management(self):
"""Test adding and managing chapters."""
# Create chapters
ch1 = Chapter("Introduction", 1)
ch2 = Chapter("Getting Started", 1)
ch3 = Chapter("Advanced Topics", 1)
# Add chapters
self.book.add_chapter(ch1)
self.book.add_chapter(ch2)
self.book.add_chapter(ch3)
# Test chapters list
self.assertEqual(len(self.book.chapters), 3)
self.assertEqual(self.book.chapters[0], ch1)
self.assertEqual(self.book.chapters[1], ch2)
self.assertEqual(self.book.chapters[2], ch3)
def test_create_chapter(self):
"""Test creating chapters through the book."""
# Create chapter with title and level
ch1 = self.book.create_chapter("Chapter 1", 1)
self.assertEqual(ch1.title, "Chapter 1")
self.assertEqual(ch1.level, 1)
self.assertEqual(len(self.book.chapters), 1)
self.assertEqual(self.book.chapters[0], ch1)
# Create chapter with minimal parameters
ch2 = self.book.create_chapter()
self.assertIsNone(ch2.title)
self.assertEqual(ch2.level, 1)
self.assertEqual(len(self.book.chapters), 2)
def test_generate_book_toc(self):
"""Test table of contents generation for book."""
# Create chapters with different levels
ch1 = Chapter("Introduction", 1)
ch2 = Chapter("Getting Started", 1)
ch3 = Chapter("Basic Concepts", 2)
ch4 = Chapter("Advanced Topics", 1)
ch5 = Chapter("Best Practices", 2)
# Add chapters to book
self.book.add_chapter(ch1)
self.book.add_chapter(ch2)
self.book.add_chapter(ch3)
self.book.add_chapter(ch4)
self.book.add_chapter(ch5)
# Generate TOC
toc = self.book.generate_table_of_contents()
# Test TOC structure
self.assertEqual(len(toc), 5)
# Test entries
expected = [
(1, "Introduction", ch1),
(1, "Getting Started", ch2),
(2, "Basic Concepts", ch3),
(1, "Advanced Topics", ch4),
(2, "Best Practices", ch5)
]
for i, (exp_level, exp_title, exp_chapter) in enumerate(expected):
level, title, chapter = toc[i]
self.assertEqual(level, exp_level)
self.assertEqual(title, exp_title)
self.assertEqual(chapter, exp_chapter)
def test_generate_book_toc_with_untitled_chapters(self):
"""Test TOC generation with chapters that have no title."""
# Create chapters, some without titles
ch1 = Chapter("Introduction", 1)
ch2 = Chapter(None, 1) # No title
ch3 = Chapter("Conclusion", 1)
self.book.add_chapter(ch1)
self.book.add_chapter(ch2)
self.book.add_chapter(ch3)
# Generate TOC
toc = self.book.generate_table_of_contents()
# Should only include chapters with titles
self.assertEqual(len(toc), 2)
level, title, chapter = toc[0]
self.assertEqual(title, "Introduction")
self.assertEqual(chapter, ch1)
level, title, chapter = toc[1]
self.assertEqual(title, "Conclusion")
self.assertEqual(chapter, ch3)
def test_book_inherits_document_features(self):
"""Test that Book inherits all Document functionality."""
# Test that book can use all document methods
# Add blocks directly to book
para = Parapgraph()
self.book.add_block(para)
self.assertEqual(len(self.book.blocks), 1)
# Test metadata
self.book.set_metadata(MetadataType.PUBLISHER, "Test Publisher")
self.assertEqual(self.book.get_metadata(MetadataType.PUBLISHER), "Test Publisher")
# Test anchors
heading = Heading(HeadingLevel.H1)
self.book.add_anchor("preface", heading)
self.assertEqual(self.book.get_anchor("preface"), heading)
if __name__ == '__main__':
unittest.main()