pyWebLayout/tests/test_callback_registry.py
Duncan Tourolle 39622c7dd7
All checks were successful
Python CI / test (push) Successful in 6m46s
integration of functional elements
2025-11-08 10:17:01 +01:00

213 lines
7.7 KiB
Python

"""
Unit tests for the CallbackRegistry system.
"""
import unittest
from unittest.mock import Mock
from pyWebLayout.core.callback_registry import CallbackRegistry
from pyWebLayout.core.base import Interactable
from pyWebLayout.concrete.functional import LinkText, ButtonText, FormFieldText
from pyWebLayout.abstract.functional import Link, Button, FormField, LinkType, FormFieldType
from pyWebLayout.style import Font
class TestCallbackRegistry(unittest.TestCase):
"""Test cases for CallbackRegistry class."""
def setUp(self):
"""Set up test fixtures."""
self.registry = CallbackRegistry()
self.font = Font(font_size=12, colour=(0, 0, 0))
self.mock_draw = Mock()
def test_registry_initialization(self):
"""Test that registry initializes empty."""
self.assertEqual(self.registry.count(), 0)
self.assertEqual(len(self.registry.get_all_ids()), 0)
self.assertEqual(len(self.registry.get_all_types()), 0)
def test_register_with_html_id(self):
"""Test registering an interactable with HTML id."""
link = Link("https://example.com", LinkType.EXTERNAL, html_id="my-link")
link_text = LinkText(link, "Example", self.font, self.mock_draw)
registered_id = self.registry.register(link_text, html_id="my-link")
self.assertEqual(registered_id, "my-link")
self.assertEqual(self.registry.count(), 1)
self.assertIn("my-link", self.registry)
def test_register_without_html_id(self):
"""Test registering an interactable without HTML id (auto-generated)."""
button = Button("Click Me", callback=None)
button_text = ButtonText(button, self.font, self.mock_draw)
registered_id = self.registry.register(button_text)
# Should generate auto id like "auto_button_0"
self.assertTrue(registered_id.startswith("auto_button_"))
self.assertEqual(self.registry.count(), 1)
def test_get_by_id(self):
"""Test retrieving an interactable by id."""
link = Link("test", html_id="test-link")
link_text = LinkText(link, "Test", self.font, self.mock_draw)
self.registry.register(link_text, html_id="test-link")
retrieved = self.registry.get_by_id("test-link")
self.assertEqual(retrieved, link_text)
def test_get_by_id_not_found(self):
"""Test retrieving non-existent id returns None."""
result = self.registry.get_by_id("nonexistent")
self.assertIsNone(result)
def test_get_by_type(self):
"""Test retrieving all interactables of a type."""
# Register multiple buttons
button1 = Button("Button 1", callback=None)
button2 = Button("Button 2", callback=None)
button_text1 = ButtonText(button1, self.font, self.mock_draw)
button_text2 = ButtonText(button2, self.font, self.mock_draw)
self.registry.register(button_text1, html_id="btn1")
self.registry.register(button_text2, html_id="btn2")
# Also register a link
link = Link("test")
link_text = LinkText(link, "Test", self.font, self.mock_draw)
self.registry.register(link_text, html_id="link1")
buttons = self.registry.get_by_type("button")
links = self.registry.get_by_type("link")
self.assertEqual(len(buttons), 2)
self.assertIn(button_text1, buttons)
self.assertIn(button_text2, buttons)
self.assertEqual(len(links), 1)
self.assertIn(link_text, links)
def test_set_callback(self):
"""Test setting a callback by id."""
button = Button("Test", callback=None)
button_text = ButtonText(button, self.font, self.mock_draw)
self.registry.register(button_text, html_id="test-btn")
def my_callback(point):
return "clicked"
success = self.registry.set_callback("test-btn", my_callback)
self.assertTrue(success)
self.assertEqual(button_text._callback, my_callback)
def test_set_callback_not_found(self):
"""Test setting callback for non-existent id returns False."""
result = self.registry.set_callback("nonexistent", lambda: None)
self.assertFalse(result)
def test_set_callbacks_by_type(self):
"""Test setting callbacks for all objects of a type."""
# Register multiple buttons
button1 = Button("Button 1", callback=None)
button2 = Button("Button 2", callback=None)
button_text1 = ButtonText(button1, self.font, self.mock_draw)
button_text2 = ButtonText(button2, self.font, self.mock_draw)
self.registry.register(button_text1)
self.registry.register(button_text2)
def click_handler(point):
return "clicked"
count = self.registry.set_callbacks_by_type("button", click_handler)
self.assertEqual(count, 2)
self.assertEqual(button_text1._callback, click_handler)
self.assertEqual(button_text2._callback, click_handler)
def test_unregister(self):
"""Test unregistering an interactable."""
button = Button("Test", callback=None)
button_text = ButtonText(button, self.font, self.mock_draw)
self.registry.register(button_text, html_id="test-btn")
self.assertEqual(self.registry.count(), 1)
success = self.registry.unregister("test-btn")
self.assertTrue(success)
self.assertEqual(self.registry.count(), 0)
self.assertNotIn("test-btn", self.registry)
def test_clear(self):
"""Test clearing all registrations."""
button = Button("Test", callback=None)
button_text = ButtonText(button, self.font, self.mock_draw)
link = Link("test")
link_text = LinkText(link, "Test", self.font, self.mock_draw)
self.registry.register(button_text)
self.registry.register(link_text)
self.assertEqual(self.registry.count(), 2)
self.registry.clear()
self.assertEqual(self.registry.count(), 0)
self.assertEqual(len(self.registry.get_all_types()), 0)
def test_count_by_type(self):
"""Test counting objects by type."""
# Register 2 buttons and 1 link
for i in range(2):
button = Button(f"Button {i}", callback=None)
button_text = ButtonText(button, self.font, self.mock_draw)
self.registry.register(button_text)
link = Link("test")
link_text = LinkText(link, "Test", self.font, self.mock_draw)
self.registry.register(link_text)
self.assertEqual(self.registry.count_by_type("button"), 2)
self.assertEqual(self.registry.count_by_type("link"), 1)
self.assertEqual(self.registry.count_by_type("form_field"), 0)
def test_contains_operator(self):
"""Test 'in' operator for checking if id exists."""
button = Button("Test", callback=None)
button_text = ButtonText(button, self.font, self.mock_draw)
self.registry.register(button_text, html_id="test-btn")
self.assertIn("test-btn", self.registry)
self.assertNotIn("nonexistent", self.registry)
def test_len_operator(self):
"""Test len() operator."""
self.assertEqual(len(self.registry), 0)
button = Button("Test", callback=None)
button_text = ButtonText(button, self.font, self.mock_draw)
self.registry.register(button_text)
self.assertEqual(len(self.registry), 1)
def test_repr(self):
"""Test string representation."""
button = Button("Test", callback=None)
button_text = ButtonText(button, self.font, self.mock_draw)
self.registry.register(button_text)
repr_str = repr(self.registry)
self.assertIn("CallbackRegistry", repr_str)
self.assertIn("total=1", repr_str)
self.assertIn("button", repr_str)
if __name__ == '__main__':
unittest.main()