auto flake and corrections

This commit is contained in:
2025-11-08 23:46:15 +01:00
parent 1ea870eef5
commit 781a9b6c08
81 changed files with 4646 additions and 3718 deletions
+128 -128
View File
@@ -12,9 +12,9 @@ import threading
import time
from PIL import Image as PILImage
from pyWebLayout.abstract.block import (
Block, BlockType, Paragraph, Heading, HeadingLevel, Quote, CodeBlock,
HList, ListStyle, ListItem, Table, TableRow, TableCell,
HorizontalRule, Image
BlockType, Paragraph, Heading, HeadingLevel, Quote, CodeBlock, HList,
ListStyle, ListItem, Table, TableRow, TableCell, HorizontalRule,
Image
)
from pyWebLayout.abstract.inline import Word, LineBreak
from pyWebLayout.style import Font
@@ -29,256 +29,256 @@ except ImportError:
class TestBlockElements(unittest.TestCase):
"""Test cases for basic block elements."""
def test_paragraph_creation(self):
"""Test creating and using paragraphs."""
paragraph = Paragraph()
self.assertEqual(paragraph.block_type, BlockType.PARAGRAPH)
self.assertEqual(paragraph.word_count, 0)
self.assertIsNone(paragraph.parent)
# Add words
font = Font()
word1 = Word("Hello", font)
word2 = Word("World", font)
paragraph.add_word(word1)
paragraph.add_word(word2)
self.assertEqual(paragraph.word_count, 2)
# Test word iteration
words = list(paragraph.words_iter())
self.assertEqual(len(words), 2)
self.assertEqual(words[0][1].text, "Hello")
self.assertEqual(words[1][1].text, "World")
def test_heading_levels(self):
"""Test heading creation with different levels."""
h1 = Heading(HeadingLevel.H1)
h3 = Heading(HeadingLevel.H3)
h6 = Heading(HeadingLevel.H6)
self.assertEqual(h1.level, HeadingLevel.H1)
self.assertEqual(h3.level, HeadingLevel.H3)
self.assertEqual(h6.level, HeadingLevel.H6)
self.assertEqual(h1.block_type, BlockType.HEADING)
# Test level modification
h1.level = HeadingLevel.H2
self.assertEqual(h1.level, HeadingLevel.H2)
def test_quote_nesting(self):
"""Test blockquote with nested content."""
quote = Quote()
# Add nested paragraphs
p1 = Paragraph()
p2 = Paragraph()
quote.add_block(p1)
quote.add_block(p2)
self.assertEqual(p1.parent, quote)
self.assertEqual(p2.parent, quote)
# Test block iteration
blocks = list(quote.blocks())
self.assertEqual(len(blocks), 2)
self.assertEqual(blocks[0], p1)
self.assertEqual(blocks[1], p2)
def test_code_block(self):
"""Test code block functionality."""
code = CodeBlock("python")
self.assertEqual(code.language, "python")
self.assertEqual(code.line_count, 0)
# Add code lines
code.add_line("def hello():")
code.add_line(" print('Hello!')")
self.assertEqual(code.line_count, 2)
# Test line iteration
lines = list(code.lines())
self.assertEqual(len(lines), 2)
self.assertEqual(lines[0][1], "def hello():")
self.assertEqual(lines[1][1], " print('Hello!')")
# Test language modification
code.language = "javascript"
self.assertEqual(code.language, "javascript")
def test_list_creation(self):
"""Test list creation and item management."""
# Unordered list
ul = HList(ListStyle.UNORDERED)
self.assertEqual(ul.style, ListStyle.UNORDERED)
self.assertEqual(ul.item_count, 0)
# Add list items
item1 = ListItem()
item2 = ListItem()
ul.add_item(item1)
ul.add_item(item2)
self.assertEqual(ul.item_count, 2)
self.assertEqual(item1.parent, ul)
self.assertEqual(item2.parent, ul)
# Test item iteration
items = list(ul.items())
self.assertEqual(len(items), 2)
# Test list style change
ul.style = ListStyle.ORDERED
self.assertEqual(ul.style, ListStyle.ORDERED)
def test_definition_list(self):
"""Test definition list with terms."""
dl = HList(ListStyle.DEFINITION)
# Add definition items with terms
dt1 = ListItem(term="Python")
dt2 = ListItem(term="JavaScript")
dl.add_item(dt1)
dl.add_item(dt2)
self.assertEqual(dt1.term, "Python")
self.assertEqual(dt2.term, "JavaScript")
# Test term modification
dt1.term = "Python 3"
self.assertEqual(dt1.term, "Python 3")
def test_table_structure(self):
"""Test table, row, and cell structure."""
table = Table(caption="Test Table")
self.assertEqual(table.caption, "Test Table")
self.assertEqual(table.row_count["total"], 0)
# Create rows and cells
header_row = TableRow()
data_row = TableRow()
# Header cells
h1 = TableCell(is_header=True)
h2 = TableCell(is_header=True)
header_row.add_cell(h1)
header_row.add_cell(h2)
# Data cells
d1 = TableCell(is_header=False)
d2 = TableCell(is_header=False, colspan=2)
data_row.add_cell(d1)
data_row.add_cell(d2)
# Add rows to table
table.add_row(header_row, "header")
table.add_row(data_row, "body")
# Test structure
self.assertEqual(table.row_count["header"], 1)
self.assertEqual(table.row_count["body"], 1)
self.assertEqual(table.row_count["total"], 2)
# Test cell properties
self.assertTrue(h1.is_header)
self.assertFalse(d1.is_header)
self.assertEqual(d2.colspan, 2)
self.assertEqual(d2.rowspan, 1) # Default
# Test row cell count
self.assertEqual(header_row.cell_count, 2)
self.assertEqual(data_row.cell_count, 2)
def test_table_sections(self):
"""Test table header, body, and footer sections."""
table = Table()
# Add rows to different sections
header = TableRow()
body1 = TableRow()
body2 = TableRow()
footer = TableRow()
table.add_row(header, "header")
table.add_row(body1, "body")
table.add_row(body2, "body")
table.add_row(footer, "footer")
# Test section iteration
header_rows = list(table.header_rows())
body_rows = list(table.body_rows())
footer_rows = list(table.footer_rows())
self.assertEqual(len(header_rows), 1)
self.assertEqual(len(body_rows), 2)
self.assertEqual(len(footer_rows), 1)
# Test all_rows iteration
all_rows = list(table.all_rows())
self.assertEqual(len(all_rows), 4)
# Check section labels
sections = [section for section, row in all_rows]
self.assertEqual(sections, ["header", "body", "body", "footer"])
def test_image_loading(self):
"""Test image element properties."""
# Test with basic properties
img = Image("test.jpg", "Test image", 100, 200)
self.assertEqual(img.source, "test.jpg")
self.assertEqual(img.alt_text, "Test image")
self.assertEqual(img.width, 100)
self.assertEqual(img.height, 200)
# Test property modification
img.source = "new.png"
img.alt_text = "New image"
img.width = 150
img.height = 300
self.assertEqual(img.source, "new.png")
self.assertEqual(img.alt_text, "New image")
self.assertEqual(img.width, 150)
self.assertEqual(img.height, 300)
# Test dimensions tuple
self.assertEqual(img.get_dimensions(), (150, 300))
def test_aspect_ratio_calculation(self):
"""Test image aspect ratio calculations."""
# Test with specified dimensions
img = Image("test.jpg", width=400, height=200)
self.assertEqual(img.get_aspect_ratio(), 2.0) # 400/200
# Test with only one dimension
img2 = Image("test.jpg", width=300)
self.assertIsNone(img2.get_aspect_ratio()) # No height specified
# Test scaled dimensions
scaled = img.calculate_scaled_dimensions(max_width=200, max_height=150)
# Should scale down proportionally
self.assertEqual(scaled[0], 200) # Width limited by max_width
self.assertEqual(scaled[1], 100) # Height scaled proportionally
def test_simple_elements(self):
"""Test simple block elements."""
hr = HorizontalRule()
br = LineBreak()
self.assertEqual(hr.block_type, BlockType.HORIZONTAL_RULE)
self.assertEqual(br.block_type, BlockType.LINE_BREAK)
# These elements have no additional properties
self.assertIsNone(hr.parent)
self.assertIsNone(br.parent)
@@ -286,29 +286,29 @@ class TestBlockElements(unittest.TestCase):
class TestImagePIL(unittest.TestCase):
"""Test cases for Image class with PIL functionality."""
@classmethod
def setUpClass(cls):
"""Set up temporary directory and test images."""
cls.temp_dir = tempfile.mkdtemp()
cls.sample_image_path = "tests/data/sample_image.jpg"
# Create test images in different formats
cls._create_test_images()
# Start Flask server for URL testing if Flask is available
if FLASK_AVAILABLE:
cls._start_flask_server()
@classmethod
def tearDownClass(cls):
"""Clean up temporary directory and stop Flask server."""
shutil.rmtree(cls.temp_dir, ignore_errors=True)
if FLASK_AVAILABLE and hasattr(cls, 'flask_thread'):
cls.flask_server_running = False
cls.flask_thread.join(timeout=2)
@classmethod
def _create_test_images(cls):
"""Create test images in different formats."""
@@ -316,17 +316,17 @@ class TestImagePIL(unittest.TestCase):
if os.path.exists(cls.sample_image_path):
with PILImage.open(cls.sample_image_path) as img:
cls.original_size = img.size
# Save in different formats
cls.jpg_path = os.path.join(cls.temp_dir, "test.jpg")
cls.png_path = os.path.join(cls.temp_dir, "test.png")
cls.bmp_path = os.path.join(cls.temp_dir, "test.bmp")
cls.gif_path = os.path.join(cls.temp_dir, "test.gif")
img.save(cls.jpg_path, "JPEG")
img.save(cls.png_path, "PNG")
img.save(cls.bmp_path, "BMP")
# Convert to RGB for GIF (GIF doesn't support transparency from RGBA)
rgb_img = img.convert("RGB")
rgb_img.save(cls.gif_path, "GIF")
@@ -334,17 +334,17 @@ class TestImagePIL(unittest.TestCase):
# Create a simple test image if sample doesn't exist
cls.original_size = (100, 100)
test_img = PILImage.new("RGB", cls.original_size, (255, 0, 0))
cls.jpg_path = os.path.join(cls.temp_dir, "test.jpg")
cls.png_path = os.path.join(cls.temp_dir, "test.png")
cls.bmp_path = os.path.join(cls.temp_dir, "test.bmp")
cls.gif_path = os.path.join(cls.temp_dir, "test.gif")
test_img.save(cls.jpg_path, "JPEG")
test_img.save(cls.png_path, "PNG")
test_img.save(cls.bmp_path, "BMP")
test_img.save(cls.gif_path, "GIF")
@classmethod
def _start_flask_server(cls):
"""Start a Flask server for URL testing."""
@@ -365,7 +365,7 @@ class TestImagePIL(unittest.TestCase):
def run_flask():
cls.flask_app.run(host='127.0.0.1', port=cls.flask_port, debug=False,
use_reloader=False, threaded=True)
use_reloader=False, threaded=True)
cls.flask_thread = threading.Thread(target=run_flask, daemon=True)
cls.flask_thread.start()
@@ -384,120 +384,120 @@ class TestImagePIL(unittest.TestCase):
pass
time.sleep(wait_interval)
elapsed += wait_interval
def test_image_url_detection(self):
"""Test URL detection functionality."""
img = Image()
# Test URL detection
self.assertTrue(img._is_url("http://example.com/image.jpg"))
self.assertTrue(img._is_url("https://example.com/image.png"))
self.assertTrue(img._is_url("ftp://example.com/image.gif"))
# Test non-URL detection
self.assertFalse(img._is_url("image.jpg"))
self.assertFalse(img._is_url("/path/to/image.png"))
self.assertFalse(img._is_url("../relative/path.gif"))
self.assertFalse(img._is_url(""))
def test_load_local_image_jpg(self):
"""Test loading local JPG image."""
img = Image(self.jpg_path)
file_path, pil_img = img.load_image_data()
self.assertIsNotNone(pil_img)
self.assertEqual(file_path, self.jpg_path)
self.assertEqual(pil_img.size, self.original_size)
self.assertEqual(img.width, self.original_size[0])
self.assertEqual(img.height, self.original_size[1])
def test_load_local_image_png(self):
"""Test loading local PNG image."""
img = Image(self.png_path)
file_path, pil_img = img.load_image_data()
self.assertIsNotNone(pil_img)
self.assertEqual(file_path, self.png_path)
self.assertEqual(pil_img.size, self.original_size)
def test_load_local_image_bmp(self):
"""Test loading local BMP image."""
img = Image(self.bmp_path)
file_path, pil_img = img.load_image_data()
self.assertIsNotNone(pil_img)
self.assertEqual(file_path, self.bmp_path)
self.assertEqual(pil_img.size, self.original_size)
def test_load_local_image_gif(self):
"""Test loading local GIF image."""
img = Image(self.gif_path)
file_path, pil_img = img.load_image_data()
self.assertIsNotNone(pil_img)
self.assertEqual(file_path, self.gif_path)
self.assertEqual(pil_img.size, self.original_size)
def test_load_nonexistent_image(self):
"""Test loading non-existent image."""
img = Image("nonexistent.jpg")
file_path, pil_img = img.load_image_data()
self.assertIsNone(pil_img)
self.assertIsNone(file_path)
def test_load_empty_source(self):
"""Test loading with empty source."""
img = Image("")
file_path, pil_img = img.load_image_data()
self.assertIsNone(pil_img)
self.assertIsNone(file_path)
def test_auto_update_dimensions(self):
"""Test automatic dimension updating."""
img = Image(self.jpg_path, width=50, height=50) # Wrong initial dimensions
# Test with auto-update enabled (default)
file_path, pil_img = img.load_image_data(auto_update_dimensions=True)
self.assertEqual(img.width, self.original_size[0])
self.assertEqual(img.height, self.original_size[1])
def test_no_auto_update_dimensions(self):
"""Test loading without automatic dimension updating."""
original_width, original_height = 50, 50
img = Image(self.jpg_path, width=original_width, height=original_height)
# Test with auto-update disabled
file_path, pil_img = img.load_image_data(auto_update_dimensions=False)
self.assertEqual(img.width, original_width) # Should remain unchanged
self.assertEqual(img.height, original_height) # Should remain unchanged
def test_get_image_info(self):
"""Test getting detailed image information."""
img = Image(self.jpg_path)
info = img.get_image_info()
self.assertIsInstance(info, dict)
self.assertIn('format', info)
self.assertIn('mode', info)
self.assertIn('size', info)
self.assertIn('width', info)
self.assertIn('height', info)
self.assertEqual(info['size'], self.original_size)
self.assertEqual(info['width'], self.original_size[0])
self.assertEqual(info['height'], self.original_size[1])
def test_get_image_info_different_formats(self):
"""Test getting image info for different formats."""
formats_and_paths = [
@@ -506,80 +506,80 @@ class TestImagePIL(unittest.TestCase):
('BMP', self.bmp_path),
('GIF', self.gif_path),
]
for expected_format, path in formats_and_paths:
with self.subTest(format=expected_format):
img = Image(path)
info = img.get_image_info()
self.assertEqual(info['format'], expected_format)
self.assertEqual(info['size'], self.original_size)
def test_get_image_info_nonexistent(self):
"""Test getting image info for non-existent image."""
img = Image("nonexistent.jpg")
info = img.get_image_info()
self.assertEqual(info, {})
@unittest.skipUnless(FLASK_AVAILABLE, "Flask not available for URL testing")
def test_load_image_from_url(self):
"""Test loading image from URL."""
url = f"http://127.0.0.1:{self.flask_port}/test.jpg"
img = Image(url)
file_path, pil_img = img.load_image_data()
self.assertIsNotNone(pil_img)
self.assertIsNotNone(file_path)
self.assertTrue(file_path.endswith('.tmp')) # Should be a temp file
self.assertEqual(pil_img.size, self.original_size)
# Check that dimensions were updated
self.assertEqual(img.width, self.original_size[0])
self.assertEqual(img.height, self.original_size[1])
@unittest.skipUnless(FLASK_AVAILABLE, "Flask not available for URL testing")
def test_get_image_info_from_url(self):
"""Test getting image info from URL."""
url = f"http://127.0.0.1:{self.flask_port}/test.jpg"
img = Image(url)
info = img.get_image_info()
self.assertIsInstance(info, dict)
self.assertEqual(info['format'], 'JPEG')
self.assertEqual(info['size'], self.original_size)
def test_load_invalid_url(self):
"""Test loading from invalid URL."""
img = Image("http://nonexistent.domain/image.jpg")
file_path, pil_img = img.load_image_data()
self.assertIsNone(pil_img)
self.assertIsNone(file_path)
def test_multiple_loads_cleanup(self):
"""Test that multiple loads don't leave temp files."""
img = Image(self.jpg_path)
# Load multiple times
for _ in range(3):
file_path, pil_img = img.load_image_data()
self.assertIsNotNone(pil_img)
def test_original_sample_image(self):
"""Test loading the original sample image if it exists."""
if os.path.exists(self.sample_image_path):
img = Image(self.sample_image_path)
file_path, pil_img = img.load_image_data()
self.assertIsNotNone(pil_img)
self.assertEqual(file_path, self.sample_image_path)
# Test that we can get image info
info = img.get_image_info()
self.assertIsInstance(info, dict)
+131 -122
View File
@@ -8,13 +8,13 @@ document structure and metadata management.
import unittest
from pyWebLayout.abstract.document import Document, Chapter, Book, MetadataType
from pyWebLayout.abstract.block import Paragraph, Heading, HeadingLevel, BlockType
from pyWebLayout.abstract.inline import Word, FormattedSpan
from pyWebLayout.abstract.inline import Word
from pyWebLayout.style import Font, FontWeight, FontStyle, TextDecoration
class TestMetadataType(unittest.TestCase):
"""Test cases for MetadataType enum."""
def test_metadata_types(self):
"""Test that all expected metadata types exist."""
expected_types = [
@@ -22,135 +22,141 @@ class TestMetadataType(unittest.TestCase):
'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"])
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 = Paragraph()
para2 = Paragraph()
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 = Paragraph()
# 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
@@ -158,87 +164,87 @@ class TestDocument(unittest.TestCase):
para2 = Paragraph()
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 = Paragraph()
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
@@ -248,127 +254,127 @@ class TestDocument(unittest.TestCase):
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 = Paragraph()
para2 = Paragraph()
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
@@ -377,13 +383,13 @@ class TestBook(unittest.TestCase):
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
@@ -392,20 +398,20 @@ class TestBook(unittest.TestCase):
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),
@@ -414,38 +420,38 @@ class TestBook(unittest.TestCase):
(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
@@ -453,11 +459,14 @@ class TestBook(unittest.TestCase):
para = Paragraph()
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")
self.assertEqual(
self.book.get_metadata(
MetadataType.PUBLISHER),
"Test Publisher")
# Test anchors
heading = Heading(HeadingLevel.H1)
self.book.add_anchor("preface", heading)
@@ -466,11 +475,11 @@ class TestBook(unittest.TestCase):
class TestDocumentFontRegistry(unittest.TestCase):
"""Test cases for Document font registry functionality."""
def setUp(self):
"""Set up test fixtures."""
self.doc = Document("Test Document", "en-US")
def test_get_or_create_font_creates_new_font(self):
"""Test that get_or_create_font creates a new font when none exists."""
font = self.doc.get_or_create_font(
@@ -478,14 +487,14 @@ class TestDocumentFontRegistry(unittest.TestCase):
colour=(255, 0, 0),
weight=FontWeight.BOLD
)
self.assertEqual(font.font_size, 14)
self.assertEqual(font.colour, (255, 0, 0))
self.assertEqual(font.weight, FontWeight.BOLD)
# Check that font is stored in registry
self.assertEqual(len(self.doc._fonts), 1)
def test_get_or_create_font_reuses_existing_font(self):
"""Test that get_or_create_font reuses existing fonts."""
# Create first font
@@ -494,20 +503,20 @@ class TestDocumentFontRegistry(unittest.TestCase):
colour=(255, 0, 0),
weight=FontWeight.BOLD
)
# Create second font with same properties
font2 = self.doc.get_or_create_font(
font_size=14,
colour=(255, 0, 0),
weight=FontWeight.BOLD
)
# Should return the same font object
self.assertIs(font1, font2)
# Should only have one font in registry
self.assertEqual(len(self.doc._fonts), 1)
def test_get_or_create_font_creates_different_fonts(self):
"""Test that different font properties create different fonts."""
# Create first font
@@ -516,28 +525,28 @@ class TestDocumentFontRegistry(unittest.TestCase):
colour=(255, 0, 0),
weight=FontWeight.BOLD
)
# Create font with different size
font2 = self.doc.get_or_create_font(
font_size=16,
colour=(255, 0, 0),
weight=FontWeight.BOLD
)
# Create font with different color
font3 = self.doc.get_or_create_font(
font_size=14,
colour=(0, 255, 0),
weight=FontWeight.BOLD
)
# Create font with different weight
font4 = self.doc.get_or_create_font(
font_size=14,
colour=(255, 0, 0),
weight=FontWeight.NORMAL
)
# All should be different objects
self.assertIsNot(font1, font2)
self.assertIsNot(font1, font3)
@@ -545,10 +554,10 @@ class TestDocumentFontRegistry(unittest.TestCase):
self.assertIsNot(font2, font3)
self.assertIsNot(font2, font4)
self.assertIsNot(font3, font4)
# Should have four fonts in registry
self.assertEqual(len(self.doc._fonts), 4)
def test_get_or_create_font_with_all_parameters(self):
"""Test get_or_create_font with all parameters."""
font = self.doc.get_or_create_font(
@@ -562,7 +571,7 @@ class TestDocumentFontRegistry(unittest.TestCase):
language="fr_FR",
min_hyphenation_width=80
)
self.assertEqual(font._font_path, "path/to/font.ttf")
self.assertEqual(font.font_size, 18)
self.assertEqual(font.colour, (128, 64, 192))
@@ -572,11 +581,11 @@ class TestDocumentFontRegistry(unittest.TestCase):
self.assertEqual(font.background, (255, 255, 255, 128))
self.assertEqual(font.language, "fr_FR")
self.assertEqual(font.min_hyphenation_width, 80)
def test_get_or_create_font_with_defaults(self):
"""Test get_or_create_font with default values."""
font = self.doc.get_or_create_font()
# Should create font with default values
self.assertIsNotNone(font)
self.assertEqual(font.font_size, 16) # Default font size
@@ -588,12 +597,12 @@ class TestDocumentFontRegistry(unittest.TestCase):
class TestChapterFontRegistry(unittest.TestCase):
"""Test cases for Chapter font registry functionality."""
def setUp(self):
"""Set up test fixtures."""
self.doc = Document("Test Document", "en-US")
self.chapter = Chapter("Test Chapter", 1, parent=self.doc)
def test_chapter_uses_parent_font_registry(self):
"""Test that chapter uses parent document's font registry."""
# Create font through chapter - should delegate to parent
@@ -602,52 +611,52 @@ class TestChapterFontRegistry(unittest.TestCase):
colour=(255, 0, 0),
weight=FontWeight.BOLD
)
# Create same font through document - should return same object
font2 = self.doc.get_or_create_font(
font_size=14,
colour=(255, 0, 0),
weight=FontWeight.BOLD
)
# Should be the same font object
self.assertIs(font1, font2)
# Should be stored in document's registry, not chapter's
self.assertEqual(len(self.doc._fonts), 1)
self.assertEqual(len(self.chapter._fonts), 0)
def test_chapter_without_parent_manages_own_fonts(self):
"""Test that chapter without parent manages its own fonts."""
# Create chapter without parent
standalone_chapter = Chapter("Standalone Chapter", 1)
# Create font through chapter
font1 = standalone_chapter.get_or_create_font(
font_size=14,
colour=(255, 0, 0),
weight=FontWeight.BOLD
)
# Create same font again - should reuse
font2 = standalone_chapter.get_or_create_font(
font_size=14,
colour=(255, 0, 0),
weight=FontWeight.BOLD
)
# Should be the same font object
self.assertIs(font1, font2)
# Should be stored in chapter's own registry
self.assertEqual(len(standalone_chapter._fonts), 1)
def test_chapter_parent_assignment(self):
"""Test that chapter parent assignment works correctly."""
# Create chapter with parent
chapter_with_parent = Chapter("Chapter with Parent", 1, parent=self.doc)
self.assertEqual(chapter_with_parent._parent, self.doc)
# Create chapter without parent
chapter_without_parent = Chapter("Chapter without Parent", 1)
self.assertIsNone(chapter_without_parent._parent)
@@ -655,11 +664,11 @@ class TestChapterFontRegistry(unittest.TestCase):
class TestBookFontRegistry(unittest.TestCase):
"""Test cases for Book font registry functionality."""
def setUp(self):
"""Set up test fixtures."""
self.book = Book("Test Book", "Author Name", "en-US")
def test_book_inherits_document_font_registry(self):
"""Test that Book inherits Document's font registry functionality."""
# Create font through book
@@ -668,17 +677,17 @@ class TestBookFontRegistry(unittest.TestCase):
colour=(255, 0, 0),
weight=FontWeight.BOLD
)
# Create same font again - should reuse
font2 = self.book.get_or_create_font(
font_size=14,
colour=(255, 0, 0),
weight=FontWeight.BOLD
)
# Should be the same font object
self.assertIs(font1, font2)
# Should have one font in registry
self.assertEqual(len(self.book._fonts), 1)
+105 -105
View File
@@ -6,7 +6,7 @@ interactive functionality and user interface elements.
"""
import unittest
from unittest.mock import Mock, patch
from unittest.mock import Mock
from pyWebLayout.abstract.functional import (
Link, LinkType, Button, Form, FormField, FormFieldType
)
@@ -14,14 +14,14 @@ from pyWebLayout.abstract.functional import (
class TestLinkType(unittest.TestCase):
"""Test cases for LinkType enum."""
def test_link_types(self):
"""Test that all expected link types exist."""
expected_types = ['INTERNAL', 'EXTERNAL', 'API', 'FUNCTION']
for type_name in expected_types:
self.assertTrue(hasattr(LinkType, type_name))
# Test specific values
self.assertEqual(LinkType.INTERNAL.value, 1)
self.assertEqual(LinkType.EXTERNAL.value, 2)
@@ -31,21 +31,21 @@ class TestLinkType(unittest.TestCase):
class TestLink(unittest.TestCase):
"""Test cases for Link class."""
def setUp(self):
"""Set up test fixtures."""
self.mock_callback = Mock(return_value="callback_result")
def test_link_creation_minimal(self):
"""Test link creation with minimal parameters."""
link = Link("test-location")
self.assertEqual(link.location, "test-location")
self.assertEqual(link.link_type, LinkType.INTERNAL) # Default
self.assertEqual(link.params, {})
self.assertIsNone(link.title)
self.assertIsNone(link._callback)
def test_link_creation_full(self):
"""Test link creation with all parameters."""
params = {"param1": "value1", "param2": "value2"}
@@ -56,29 +56,29 @@ class TestLink(unittest.TestCase):
params=params,
title="Example Link"
)
self.assertEqual(link.location, "https://example.com")
self.assertEqual(link.link_type, LinkType.EXTERNAL)
self.assertEqual(link.params, params)
self.assertEqual(link.title, "Example Link")
self.assertEqual(link._callback, self.mock_callback)
def test_internal_link_execution(self):
"""Test executing internal links."""
link = Link("#section1", LinkType.INTERNAL)
result = link.execute()
# Internal links should return the location
self.assertEqual(result, "#section1")
def test_external_link_execution(self):
"""Test executing external links."""
link = Link("https://example.com", LinkType.EXTERNAL)
result = link.execute()
# External links should return the location
self.assertEqual(result, "https://example.com")
def test_api_link_execution(self):
"""Test executing API links with callback."""
params = {"action": "save", "id": 123}
@@ -92,9 +92,10 @@ class TestLink(unittest.TestCase):
result = link.execute()
# Should call callback with location, point (None when not provided), and params
self.mock_callback.assert_called_once_with("/api/save", None, action="save", id=123)
self.mock_callback.assert_called_once_with(
"/api/save", None, action="save", id=123)
self.assertEqual(result, "callback_result")
def test_function_link_execution(self):
"""Test executing function links with callback."""
params = {"data": "test"}
@@ -110,23 +111,23 @@ class TestLink(unittest.TestCase):
# Should call callback with location, point (None when not provided), and params
self.mock_callback.assert_called_once_with("save_document", None, data="test")
self.assertEqual(result, "callback_result")
def test_api_link_without_callback(self):
"""Test API link without callback returns location."""
link = Link("/api/endpoint", LinkType.API)
result = link.execute()
# Without callback, should return location
self.assertEqual(result, "/api/endpoint")
def test_function_link_without_callback(self):
"""Test function link without callback returns location."""
link = Link("function_name", LinkType.FUNCTION)
result = link.execute()
# Without callback, should return location
self.assertEqual(result, "function_name")
def test_link_properties(self):
"""Test link property access."""
params = {"key": "value"}
@@ -136,7 +137,7 @@ class TestLink(unittest.TestCase):
params=params,
title="Test Title"
)
# Test all property getters
self.assertEqual(link.location, "test")
self.assertEqual(link.link_type, LinkType.API)
@@ -146,20 +147,20 @@ class TestLink(unittest.TestCase):
class TestButton(unittest.TestCase):
"""Test cases for Button class."""
def setUp(self):
"""Set up test fixtures."""
self.mock_callback = Mock(return_value="button_clicked")
def test_button_creation_minimal(self):
"""Test button creation with minimal parameters."""
button = Button("Click Me", self.mock_callback)
self.assertEqual(button.label, "Click Me")
self.assertEqual(button._callback, self.mock_callback)
self.assertEqual(button.params, {})
self.assertTrue(button.enabled)
def test_button_creation_full(self):
"""Test button creation with all parameters."""
params = {"action": "submit", "form_id": "test_form"}
@@ -169,37 +170,37 @@ class TestButton(unittest.TestCase):
params=params,
enabled=False
)
self.assertEqual(button.label, "Submit")
self.assertEqual(button._callback, self.mock_callback)
self.assertEqual(button.params, params)
self.assertFalse(button.enabled)
def test_button_label_property(self):
"""Test button label getter and setter."""
button = Button("Original", self.mock_callback)
# Test getter
self.assertEqual(button.label, "Original")
# Test setter
button.label = "New Label"
self.assertEqual(button.label, "New Label")
def test_button_enabled_property(self):
"""Test button enabled getter and setter."""
button = Button("Test", self.mock_callback, enabled=True)
# Test initial state
self.assertTrue(button.enabled)
# Test setter
button.enabled = False
self.assertFalse(button.enabled)
button.enabled = True
self.assertTrue(button.enabled)
def test_button_execute_enabled(self):
"""Test executing enabled button."""
params = {"data": "test_data"}
@@ -210,40 +211,40 @@ class TestButton(unittest.TestCase):
# Should call callback with point (None when not provided) and params
self.mock_callback.assert_called_once_with(None, data="test_data")
self.assertEqual(result, "button_clicked")
def test_button_execute_disabled(self):
"""Test executing disabled button."""
button = Button("Test", self.mock_callback, enabled=False)
result = button.execute()
# Should not call callback and return None
self.mock_callback.assert_not_called()
self.assertIsNone(result)
def test_button_execute_no_callback(self):
"""Test executing button without callback."""
button = Button("Test", None, enabled=True)
result = button.execute()
# Should return None
self.assertIsNone(result)
class TestFormFieldType(unittest.TestCase):
"""Test cases for FormFieldType enum."""
def test_form_field_types(self):
"""Test that all expected form field types exist."""
expected_types = [
'TEXT', 'PASSWORD', 'CHECKBOX', 'RADIO', 'SELECT', 'TEXTAREA',
'NUMBER', 'DATE', 'TIME', 'EMAIL', 'URL', 'COLOR', 'RANGE', 'HIDDEN'
]
for type_name in expected_types:
self.assertTrue(hasattr(FormFieldType, type_name))
# Test some specific values
self.assertEqual(FormFieldType.TEXT.value, 1)
self.assertEqual(FormFieldType.PASSWORD.value, 2)
@@ -252,11 +253,11 @@ class TestFormFieldType(unittest.TestCase):
class TestFormField(unittest.TestCase):
"""Test cases for FormField class."""
def test_form_field_creation_minimal(self):
"""Test form field creation with minimal parameters."""
field = FormField("username", FormFieldType.TEXT)
self.assertEqual(field.name, "username")
self.assertEqual(field.field_type, FormFieldType.TEXT)
self.assertEqual(field.label, "username") # Default to name
@@ -264,7 +265,7 @@ class TestFormField(unittest.TestCase):
self.assertFalse(field.required)
self.assertEqual(field.options, [])
self.assertIsNone(field.form)
def test_form_field_creation_full(self):
"""Test form field creation with all parameters."""
options = [("value1", "Label 1"), ("value2", "Label 2")]
@@ -276,37 +277,37 @@ class TestFormField(unittest.TestCase):
required=True,
options=options
)
self.assertEqual(field.name, "country")
self.assertEqual(field.field_type, FormFieldType.SELECT)
self.assertEqual(field.label, "Country")
self.assertEqual(field.value, "value1")
self.assertTrue(field.required)
self.assertEqual(field.options, options)
def test_form_field_value_property(self):
"""Test form field value getter and setter."""
field = FormField("test", FormFieldType.TEXT, value="initial")
# Test getter
self.assertEqual(field.value, "initial")
# Test setter
field.value = "new_value"
self.assertEqual(field.value, "new_value")
def test_form_field_form_property(self):
"""Test form field form getter and setter."""
field = FormField("test", FormFieldType.TEXT)
mock_form = Mock()
# Initial state
self.assertIsNone(field.form)
# Test setter
field.form = mock_form
self.assertEqual(field.form, mock_form)
def test_form_field_properties(self):
"""Test all form field property getters."""
options = [("opt1", "Option 1")]
@@ -318,7 +319,7 @@ class TestFormField(unittest.TestCase):
required=True,
options=options
)
# Test all getters
self.assertEqual(field.name, "test_field")
self.assertEqual(field.field_type, FormFieldType.CHECKBOX)
@@ -330,20 +331,20 @@ class TestFormField(unittest.TestCase):
class TestForm(unittest.TestCase):
"""Test cases for Form class."""
def setUp(self):
"""Set up test fixtures."""
self.mock_callback = Mock(return_value="form_submitted")
def test_form_creation_minimal(self):
"""Test form creation with minimal parameters."""
form = Form("test_form")
self.assertEqual(form.form_id, "test_form")
self.assertIsNone(form.action)
self.assertIsNone(form._callback)
self.assertEqual(len(form._fields), 0)
def test_form_creation_full(self):
"""Test form creation with all parameters."""
form = Form(
@@ -351,145 +352,144 @@ class TestForm(unittest.TestCase):
action="/submit",
callback=self.mock_callback
)
self.assertEqual(form.form_id, "contact_form")
self.assertEqual(form.action, "/submit")
self.assertEqual(form._callback, self.mock_callback)
def test_form_field_management(self):
"""Test adding and retrieving form fields."""
form = Form("test_form")
# Create fields
field1 = FormField("username", FormFieldType.TEXT, value="john")
field2 = FormField("password", FormFieldType.PASSWORD, value="secret")
field3 = FormField("email", FormFieldType.EMAIL, value="john@example.com")
# Add fields
form.add_field(field1)
form.add_field(field2)
form.add_field(field3)
# Test that fields are stored correctly
self.assertEqual(len(form._fields), 3)
# Test field retrieval
self.assertEqual(form.get_field("username"), field1)
self.assertEqual(form.get_field("password"), field2)
self.assertEqual(form.get_field("email"), field3)
self.assertIsNone(form.get_field("nonexistent"))
# Test that fields have form reference
self.assertEqual(field1.form, form)
self.assertEqual(field2.form, form)
self.assertEqual(field3.form, form)
def test_form_get_values(self):
"""Test getting form values."""
form = Form("test_form")
# Add fields with values
form.add_field(FormField("name", FormFieldType.TEXT, value="John Doe"))
form.add_field(FormField("age", FormFieldType.NUMBER, value=30))
form.add_field(FormField("subscribe", FormFieldType.CHECKBOX, value=True))
# Get values
values = form.get_values()
expected = {
"name": "John Doe",
"age": 30,
"subscribe": True
}
self.assertEqual(values, expected)
def test_form_get_values_empty(self):
"""Test getting values from empty form."""
form = Form("empty_form")
values = form.get_values()
self.assertEqual(values, {})
def test_form_execute_with_callback(self):
"""Test executing form with callback."""
form = Form("test_form", callback=self.mock_callback)
# Add some fields
form.add_field(FormField("field1", FormFieldType.TEXT, value="value1"))
form.add_field(FormField("field2", FormFieldType.TEXT, value="value2"))
result = form.execute()
# Should call callback with form_id and values
expected_values = {"field1": "value1", "field2": "value2"}
self.mock_callback.assert_called_once_with("test_form", expected_values)
self.assertEqual(result, "form_submitted")
def test_form_execute_without_callback(self):
"""Test executing form without callback."""
form = Form("test_form")
# Add a field
form.add_field(FormField("test", FormFieldType.TEXT, value="test_value"))
result = form.execute()
# Should return the form values
expected = {"test": "test_value"}
self.assertEqual(result, expected)
def test_form_properties(self):
"""Test form property getters."""
form = Form("test_form", action="/submit")
self.assertEqual(form.form_id, "test_form")
self.assertEqual(form.action, "/submit")
class TestFormIntegration(unittest.TestCase):
"""Integration tests for form functionality."""
def test_complete_form_workflow(self):
"""Test a complete form creation and submission workflow."""
# Create form
form = Form("registration_form", action="/register")
# Add various field types
form.add_field(FormField(
"username", FormFieldType.TEXT,
"username", FormFieldType.TEXT,
label="Username", required=True, value="testuser"
))
form.add_field(FormField(
"password", FormFieldType.PASSWORD,
label="Password", required=True, value="secret123"
))
form.add_field(FormField(
"email", FormFieldType.EMAIL,
label="Email", required=True, value="test@example.com"
))
form.add_field(FormField(
"country", FormFieldType.SELECT,
label="Country", value="US",
options=[("US", "United States"), ("CA", "Canada"), ("UK", "United Kingdom")]
))
form.add_field(
FormField(
"country", FormFieldType.SELECT, label="Country", value="US", options=[
("US", "United States"), ("CA", "Canada"), ("UK", "United Kingdom")]))
form.add_field(FormField(
"newsletter", FormFieldType.CHECKBOX,
label="Subscribe to newsletter", value=True
))
# Test form state
self.assertEqual(len(form._fields), 5)
# Test individual field access
username_field = form.get_field("username")
self.assertEqual(username_field.value, "testuser")
self.assertTrue(username_field.required)
# Test getting all values
values = form.get_values()
expected = {
@@ -500,26 +500,26 @@ class TestFormIntegration(unittest.TestCase):
"newsletter": True
}
self.assertEqual(values, expected)
# Test form submission
result = form.execute()
self.assertEqual(result, expected)
def test_form_field_modification(self):
"""Test modifying form fields after creation."""
form = Form("test_form")
# Add field
field = FormField("test", FormFieldType.TEXT, value="initial")
form.add_field(field)
# Modify field value
field.value = "modified"
# Test that form reflects the change
values = form.get_values()
self.assertEqual(values["test"], "modified")
# Test getting the modified field
retrieved_field = form.get_field("test")
self.assertEqual(retrieved_field.value, "modified")
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -34,7 +34,9 @@ class TestChapterFontRegistry(FontRegistryTestMixin, unittest.TestCase):
return Chapter("Test Chapter", level=1)
class TestChapterFontRegistryParentDelegation(FontRegistryParentDelegationTestMixin, unittest.TestCase):
class TestChapterFontRegistryParentDelegation(
FontRegistryParentDelegationTestMixin,
unittest.TestCase):
"""Test FontRegistry parent delegation for Chapter - simplified with mixin."""
def create_parent(self):
+33 -33
View File
@@ -3,20 +3,20 @@ Unit tests for LinkedWord and LinkedImage classes.
"""
import unittest
from pyWebLayout.abstract.inline import Word, LinkedWord
from pyWebLayout.abstract.block import Image, LinkedImage
from pyWebLayout.abstract.inline import LinkedWord
from pyWebLayout.abstract.block import LinkedImage
from pyWebLayout.abstract.functional import LinkType
from pyWebLayout.style import Font
class TestLinkedWord(unittest.TestCase):
"""Test cases for LinkedWord class."""
def setUp(self):
"""Set up test fixtures."""
self.font = Font(font_size=16)
self.location = "https://example.com"
def test_linked_word_creation(self):
"""Test creating a LinkedWord."""
linked_word = LinkedWord(
@@ -25,12 +25,12 @@ class TestLinkedWord(unittest.TestCase):
location=self.location,
link_type=LinkType.EXTERNAL
)
self.assertEqual(linked_word.text, "example")
self.assertEqual(linked_word.location, self.location)
self.assertEqual(linked_word.link_type, LinkType.EXTERNAL)
self.assertIsNone(linked_word.link_callback)
def test_linked_word_inherits_from_word(self):
"""Test that LinkedWord inherits Word properties."""
linked_word = LinkedWord(
@@ -38,21 +38,21 @@ class TestLinkedWord(unittest.TestCase):
style=self.font,
location=self.location
)
# Should have Word properties
self.assertEqual(linked_word.text, "test")
self.assertEqual(linked_word.style, self.font)
self.assertIsNone(linked_word.previous)
self.assertIsNone(linked_word.next)
def test_linked_word_with_callback(self):
"""Test LinkedWord with a callback function."""
callback_called = []
def test_callback(location, **params):
callback_called.append((location, params))
return "navigated"
linked_word = LinkedWord(
text="click",
style=self.font,
@@ -61,15 +61,15 @@ class TestLinkedWord(unittest.TestCase):
callback=test_callback,
params={"source": "test"}
)
result = linked_word.execute_link()
linked_word.execute_link()
self.assertEqual(len(callback_called), 1)
self.assertEqual(callback_called[0][0], self.location)
self.assertIn("text", callback_called[0][1])
self.assertEqual(callback_called[0][1]["text"], "click")
self.assertEqual(callback_called[0][1]["source"], "test")
def test_linked_word_execute_external_link(self):
"""Test executing an external link returns the location."""
linked_word = LinkedWord(
@@ -78,10 +78,10 @@ class TestLinkedWord(unittest.TestCase):
location=self.location,
link_type=LinkType.EXTERNAL
)
result = linked_word.execute_link()
self.assertEqual(result, self.location)
def test_linked_word_with_title(self):
"""Test LinkedWord with title/tooltip."""
linked_word = LinkedWord(
@@ -90,9 +90,9 @@ class TestLinkedWord(unittest.TestCase):
location=self.location,
title="Click to visit example.com"
)
self.assertEqual(linked_word.link_title, "Click to visit example.com")
def test_linked_word_chain(self):
"""Test chaining multiple LinkedWords."""
word1 = LinkedWord(
@@ -100,14 +100,14 @@ class TestLinkedWord(unittest.TestCase):
style=self.font,
location=self.location
)
word2 = LinkedWord(
text="here",
style=self.font,
location=self.location,
previous=word1
)
# Check chain
self.assertEqual(word1.next, word2)
self.assertEqual(word2.previous, word1)
@@ -115,13 +115,13 @@ class TestLinkedWord(unittest.TestCase):
class TestLinkedImage(unittest.TestCase):
"""Test cases for LinkedImage class."""
def setUp(self):
"""Set up test fixtures."""
self.source = "logo.png"
self.alt_text = "Company Logo"
self.location = "https://example.com/home"
def test_linked_image_creation(self):
"""Test creating a LinkedImage."""
linked_image = LinkedImage(
@@ -132,14 +132,14 @@ class TestLinkedImage(unittest.TestCase):
height=50,
link_type=LinkType.EXTERNAL
)
self.assertEqual(linked_image.source, self.source)
self.assertEqual(linked_image.alt_text, self.alt_text)
self.assertEqual(linked_image.location, self.location)
self.assertEqual(linked_image.width, 100)
self.assertEqual(linked_image.height, 50)
self.assertEqual(linked_image.link_type, LinkType.EXTERNAL)
def test_linked_image_inherits_from_image(self):
"""Test that LinkedImage inherits Image properties."""
linked_image = LinkedImage(
@@ -147,20 +147,20 @@ class TestLinkedImage(unittest.TestCase):
alt_text=self.alt_text,
location=self.location
)
# Should have Image properties and methods
self.assertEqual(linked_image.source, self.source)
self.assertEqual(linked_image.alt_text, self.alt_text)
self.assertIsNotNone(linked_image.get_dimensions)
def test_linked_image_with_callback(self):
"""Test LinkedImage with a callback function."""
callback_called = []
def image_callback(location, **params):
callback_called.append((location, params))
return "image_clicked"
linked_image = LinkedImage(
source=self.source,
alt_text=self.alt_text,
@@ -168,15 +168,15 @@ class TestLinkedImage(unittest.TestCase):
link_type=LinkType.FUNCTION,
callback=image_callback
)
result = linked_image.execute_link()
linked_image.execute_link()
self.assertEqual(len(callback_called), 1)
self.assertEqual(callback_called[0][0], self.location)
self.assertIn("alt_text", callback_called[0][1])
self.assertEqual(callback_called[0][1]["alt_text"], self.alt_text)
self.assertIn("source", callback_called[0][1])
def test_linked_image_execute_internal_link(self):
"""Test executing an internal link returns the location."""
linked_image = LinkedImage(
@@ -185,7 +185,7 @@ class TestLinkedImage(unittest.TestCase):
location="#section2",
link_type=LinkType.INTERNAL
)
result = linked_image.execute_link()
self.assertEqual(result, "#section2")