641 lines
25 KiB
Python
641 lines
25 KiB
Python
"""
|
|
Unit tests for pyWebLayout.concrete.functional module.
|
|
Tests the RenderableLink, RenderableButton, RenderableForm, and RenderableFormField classes.
|
|
"""
|
|
|
|
import unittest
|
|
import numpy as np
|
|
from PIL import Image
|
|
from unittest.mock import Mock, patch, MagicMock
|
|
|
|
from pyWebLayout.concrete.functional import (
|
|
RenderableLink, RenderableButton, RenderableForm, RenderableFormField
|
|
)
|
|
from pyWebLayout.abstract.functional import (
|
|
Link, Button, Form, FormField, LinkType, FormFieldType
|
|
)
|
|
from pyWebLayout.style import Font, FontWeight, FontStyle, TextDecoration
|
|
from pyWebLayout.style.layout import Alignment
|
|
|
|
|
|
class TestRenderableLink(unittest.TestCase):
|
|
"""Test cases for the RenderableLink class"""
|
|
|
|
def setUp(self):
|
|
"""Set up test fixtures"""
|
|
self.font = Font(
|
|
font_path=None, # Use default font
|
|
font_size=12,
|
|
colour=(0, 0, 0)
|
|
)
|
|
self.callback = Mock()
|
|
|
|
# Create different types of links
|
|
self.internal_link = Link("chapter1", LinkType.INTERNAL, self.callback)
|
|
self.external_link = Link("https://example.com", LinkType.EXTERNAL, self.callback)
|
|
self.api_link = Link("/api/settings", LinkType.API, self.callback)
|
|
self.function_link = Link("toggle_theme", LinkType.FUNCTION, self.callback)
|
|
|
|
def test_renderable_link_initialization_internal(self):
|
|
"""Test initialization of internal link"""
|
|
link_text = "Go to Chapter 1"
|
|
renderable = RenderableLink(self.internal_link, link_text, self.font)
|
|
|
|
self.assertEqual(renderable._link, self.internal_link)
|
|
self.assertEqual(renderable._text_obj.text, link_text)
|
|
self.assertFalse(renderable._hovered)
|
|
self.assertEqual(renderable._callback, self.internal_link.execute)
|
|
|
|
# Check that the font has underline decoration and blue color
|
|
self.assertEqual(renderable._text_obj.style.decoration, TextDecoration.UNDERLINE)
|
|
self.assertEqual(renderable._text_obj.style.colour, (0, 0, 200))
|
|
|
|
def test_renderable_link_initialization_external(self):
|
|
"""Test initialization of external link"""
|
|
link_text = "Visit Example"
|
|
renderable = RenderableLink(self.external_link, link_text, self.font)
|
|
|
|
self.assertEqual(renderable._link, self.external_link)
|
|
# External links should have darker blue color
|
|
self.assertEqual(renderable._text_obj.style.colour, (0, 0, 180))
|
|
|
|
def test_renderable_link_initialization_api(self):
|
|
"""Test initialization of API link"""
|
|
link_text = "Settings"
|
|
renderable = RenderableLink(self.api_link, link_text, self.font)
|
|
|
|
self.assertEqual(renderable._link, self.api_link)
|
|
# API links should have red color
|
|
self.assertEqual(renderable._text_obj.style.colour, (150, 0, 0))
|
|
|
|
def test_renderable_link_initialization_function(self):
|
|
"""Test initialization of function link"""
|
|
link_text = "Toggle Theme"
|
|
renderable = RenderableLink(self.function_link, link_text, self.font)
|
|
|
|
self.assertEqual(renderable._link, self.function_link)
|
|
# Function links should have green color
|
|
self.assertEqual(renderable._text_obj.style.colour, (0, 120, 0))
|
|
|
|
def test_renderable_link_with_custom_params(self):
|
|
"""Test link initialization with custom parameters"""
|
|
link_text = "Custom Link"
|
|
custom_origin = (10, 20)
|
|
custom_size = (100, 30)
|
|
custom_callback = Mock()
|
|
|
|
renderable = RenderableLink(
|
|
self.internal_link, link_text, self.font,
|
|
origin=custom_origin, size=custom_size, callback=custom_callback
|
|
)
|
|
|
|
np.testing.assert_array_equal(renderable._origin, np.array(custom_origin))
|
|
np.testing.assert_array_equal(renderable._size, np.array(custom_size))
|
|
self.assertEqual(renderable._callback, custom_callback)
|
|
|
|
def test_link_property(self):
|
|
"""Test link property accessor"""
|
|
link_text = "Test Link"
|
|
renderable = RenderableLink(self.internal_link, link_text, self.font)
|
|
|
|
self.assertEqual(renderable.link, self.internal_link)
|
|
|
|
def test_set_hovered(self):
|
|
"""Test setting hover state"""
|
|
link_text = "Hover Test"
|
|
renderable = RenderableLink(self.internal_link, link_text, self.font)
|
|
|
|
self.assertFalse(renderable._hovered)
|
|
|
|
renderable.set_hovered(True)
|
|
self.assertTrue(renderable._hovered)
|
|
|
|
renderable.set_hovered(False)
|
|
self.assertFalse(renderable._hovered)
|
|
|
|
@patch('PIL.ImageDraw.Draw')
|
|
def test_render_normal_state(self, mock_draw_class):
|
|
"""Test rendering in normal state"""
|
|
mock_draw = Mock()
|
|
mock_draw_class.return_value = mock_draw
|
|
|
|
link_text = "Test Link"
|
|
renderable = RenderableLink(self.internal_link, link_text, self.font)
|
|
|
|
with patch.object(renderable._text_obj, 'render') as mock_text_render:
|
|
mock_text_render.return_value = Image.new('RGBA', (80, 16), (255, 255, 255, 255))
|
|
result = renderable.render()
|
|
|
|
self.assertIsInstance(result, Image.Image)
|
|
mock_text_render.assert_called_once()
|
|
# Should not draw highlight when not hovered
|
|
mock_draw.rectangle.assert_not_called()
|
|
|
|
@patch('PIL.ImageDraw.Draw')
|
|
def test_render_hovered_state(self, mock_draw_class):
|
|
"""Test rendering in hovered state"""
|
|
mock_draw = Mock()
|
|
mock_draw_class.return_value = mock_draw
|
|
|
|
link_text = "Test Link"
|
|
renderable = RenderableLink(self.internal_link, link_text, self.font)
|
|
renderable.set_hovered(True)
|
|
|
|
with patch.object(renderable._text_obj, 'render') as mock_text_render:
|
|
mock_text_render.return_value = Image.new('RGBA', (80, 16), (255, 255, 255, 255))
|
|
result = renderable.render()
|
|
|
|
self.assertIsInstance(result, Image.Image)
|
|
mock_text_render.assert_called_once()
|
|
# Should draw highlight when hovered
|
|
mock_draw.rectangle.assert_called_once()
|
|
|
|
def test_in_object(self):
|
|
"""Test in_object method"""
|
|
link_text = "Test Link"
|
|
renderable = RenderableLink(self.internal_link, link_text, self.font, origin=(10, 20))
|
|
|
|
# Point inside link
|
|
self.assertTrue(renderable.in_object((15, 25)))
|
|
|
|
# Point outside link
|
|
self.assertFalse(renderable.in_object((200, 200)))
|
|
|
|
|
|
class TestRenderableButton(unittest.TestCase):
|
|
"""Test cases for the RenderableButton class"""
|
|
|
|
def setUp(self):
|
|
"""Set up test fixtures"""
|
|
self.font = Font(
|
|
font_path=None, # Use default font
|
|
font_size=12,
|
|
colour=(255, 255, 255)
|
|
)
|
|
self.callback = Mock()
|
|
self.button = Button("Click Me", self.callback)
|
|
|
|
def test_renderable_button_initialization(self):
|
|
"""Test basic button initialization"""
|
|
renderable = RenderableButton(self.button, self.font)
|
|
|
|
self.assertEqual(renderable._button, self.button)
|
|
self.assertEqual(renderable._text_obj.text, "Click Me")
|
|
self.assertFalse(renderable._pressed)
|
|
self.assertFalse(renderable._hovered)
|
|
self.assertEqual(renderable._callback, self.button.execute)
|
|
self.assertEqual(renderable._border_radius, 4)
|
|
|
|
def test_renderable_button_with_custom_params(self):
|
|
"""Test button initialization with custom parameters"""
|
|
custom_padding = (8, 12, 8, 12)
|
|
custom_radius = 8
|
|
custom_origin = (50, 60)
|
|
custom_size = (120, 40)
|
|
|
|
renderable = RenderableButton(
|
|
self.button, self.font,
|
|
padding=custom_padding,
|
|
border_radius=custom_radius,
|
|
origin=custom_origin,
|
|
size=custom_size
|
|
)
|
|
|
|
self.assertEqual(renderable._padding, custom_padding)
|
|
self.assertEqual(renderable._border_radius, custom_radius)
|
|
np.testing.assert_array_equal(renderable._origin, np.array(custom_origin))
|
|
np.testing.assert_array_equal(renderable._size, np.array(custom_size))
|
|
|
|
def test_button_property(self):
|
|
"""Test button property accessor"""
|
|
renderable = RenderableButton(self.button, self.font)
|
|
|
|
self.assertEqual(renderable.button, self.button)
|
|
|
|
def test_set_pressed(self):
|
|
"""Test setting pressed state"""
|
|
renderable = RenderableButton(self.button, self.font)
|
|
|
|
self.assertFalse(renderable._pressed)
|
|
|
|
renderable.set_pressed(True)
|
|
self.assertTrue(renderable._pressed)
|
|
|
|
renderable.set_pressed(False)
|
|
self.assertFalse(renderable._pressed)
|
|
|
|
def test_set_hovered(self):
|
|
"""Test setting hover state"""
|
|
renderable = RenderableButton(self.button, self.font)
|
|
|
|
self.assertFalse(renderable._hovered)
|
|
|
|
renderable.set_hovered(True)
|
|
self.assertTrue(renderable._hovered)
|
|
|
|
renderable.set_hovered(False)
|
|
self.assertFalse(renderable._hovered)
|
|
|
|
@patch('PIL.ImageDraw.Draw')
|
|
def test_render_normal_state(self, mock_draw_class):
|
|
"""Test rendering in normal state"""
|
|
mock_draw = Mock()
|
|
mock_draw_class.return_value = mock_draw
|
|
|
|
renderable = RenderableButton(self.button, self.font)
|
|
|
|
with patch.object(renderable._text_obj, 'render') as mock_text_render:
|
|
mock_text_render.return_value = Image.new('RGBA', (60, 16), (255, 255, 255, 255))
|
|
result = renderable.render()
|
|
|
|
self.assertIsInstance(result, Image.Image)
|
|
mock_draw.rounded_rectangle.assert_called_once()
|
|
mock_text_render.assert_called_once()
|
|
|
|
@patch('PIL.ImageDraw.Draw')
|
|
def test_render_disabled_state(self, mock_draw_class):
|
|
"""Test rendering disabled button"""
|
|
mock_draw = Mock()
|
|
mock_draw_class.return_value = mock_draw
|
|
|
|
disabled_button = Button("Disabled", self.callback, enabled=False)
|
|
renderable = RenderableButton(disabled_button, self.font)
|
|
|
|
with patch.object(renderable._text_obj, 'render') as mock_text_render:
|
|
mock_text_render.return_value = Image.new('RGBA', (60, 16), (255, 255, 255, 255))
|
|
result = renderable.render()
|
|
|
|
self.assertIsInstance(result, Image.Image)
|
|
mock_draw.rounded_rectangle.assert_called_once()
|
|
|
|
@patch('PIL.ImageDraw.Draw')
|
|
def test_render_pressed_state(self, mock_draw_class):
|
|
"""Test rendering pressed button"""
|
|
mock_draw = Mock()
|
|
mock_draw_class.return_value = mock_draw
|
|
|
|
renderable = RenderableButton(self.button, self.font)
|
|
renderable.set_pressed(True)
|
|
|
|
with patch.object(renderable._text_obj, 'render') as mock_text_render:
|
|
mock_text_render.return_value = Image.new('RGBA', (60, 16), (255, 255, 255, 255))
|
|
result = renderable.render()
|
|
|
|
self.assertIsInstance(result, Image.Image)
|
|
mock_draw.rounded_rectangle.assert_called_once()
|
|
|
|
@patch('PIL.ImageDraw.Draw')
|
|
def test_render_hovered_state(self, mock_draw_class):
|
|
"""Test rendering hovered button"""
|
|
mock_draw = Mock()
|
|
mock_draw_class.return_value = mock_draw
|
|
|
|
renderable = RenderableButton(self.button, self.font)
|
|
renderable.set_hovered(True)
|
|
|
|
with patch.object(renderable._text_obj, 'render') as mock_text_render:
|
|
mock_text_render.return_value = Image.new('RGBA', (60, 16), (255, 255, 255, 255))
|
|
result = renderable.render()
|
|
|
|
self.assertIsInstance(result, Image.Image)
|
|
mock_draw.rounded_rectangle.assert_called_once()
|
|
|
|
def test_in_object(self):
|
|
"""Test in_object method"""
|
|
renderable = RenderableButton(self.button, self.font, origin=(10, 20))
|
|
|
|
# Point inside button
|
|
self.assertTrue(renderable.in_object((15, 25)))
|
|
|
|
# Point outside button
|
|
self.assertFalse(renderable.in_object((200, 200)))
|
|
|
|
|
|
class TestRenderableFormField(unittest.TestCase):
|
|
"""Test cases for the RenderableFormField class"""
|
|
|
|
def setUp(self):
|
|
"""Set up test fixtures"""
|
|
self.font = Font(
|
|
font_path=None, # Use default font
|
|
font_size=12,
|
|
colour=(0, 0, 0)
|
|
)
|
|
|
|
# Create different types of form fields
|
|
self.text_field = FormField("username", FormFieldType.TEXT, "Username")
|
|
self.password_field = FormField("password", FormFieldType.PASSWORD, "Password")
|
|
self.textarea_field = FormField("description", FormFieldType.TEXTAREA, "Description")
|
|
self.select_field = FormField("country", FormFieldType.SELECT, "Country")
|
|
|
|
def test_renderable_form_field_initialization_text(self):
|
|
"""Test initialization of text field"""
|
|
renderable = RenderableFormField(self.text_field, self.font)
|
|
|
|
self.assertEqual(renderable._field, self.text_field)
|
|
self.assertEqual(renderable._label_text.text, "Username")
|
|
self.assertFalse(renderable._focused)
|
|
|
|
def test_renderable_form_field_initialization_textarea(self):
|
|
"""Test initialization of textarea field"""
|
|
renderable = RenderableFormField(self.textarea_field, self.font)
|
|
|
|
self.assertEqual(renderable._field, self.textarea_field)
|
|
# Textarea should have larger default height
|
|
self.assertGreater(renderable._size[1], 50)
|
|
|
|
def test_renderable_form_field_with_custom_params(self):
|
|
"""Test field initialization with custom parameters"""
|
|
custom_padding = (8, 15, 8, 15)
|
|
custom_origin = (25, 35)
|
|
custom_size = (200, 60)
|
|
|
|
renderable = RenderableFormField(
|
|
self.text_field, self.font,
|
|
padding=custom_padding,
|
|
origin=custom_origin,
|
|
size=custom_size
|
|
)
|
|
|
|
self.assertEqual(renderable._padding, custom_padding)
|
|
np.testing.assert_array_equal(renderable._origin, np.array(custom_origin))
|
|
np.testing.assert_array_equal(renderable._size, np.array(custom_size))
|
|
|
|
def test_set_focused(self):
|
|
"""Test setting focus state"""
|
|
renderable = RenderableFormField(self.text_field, self.font)
|
|
|
|
self.assertFalse(renderable._focused)
|
|
|
|
renderable.set_focused(True)
|
|
self.assertTrue(renderable._focused)
|
|
|
|
renderable.set_focused(False)
|
|
self.assertFalse(renderable._focused)
|
|
|
|
@patch('PIL.ImageDraw.Draw')
|
|
def test_render_text_field(self, mock_draw_class):
|
|
"""Test rendering text field"""
|
|
mock_draw = Mock()
|
|
mock_draw_class.return_value = mock_draw
|
|
|
|
renderable = RenderableFormField(self.text_field, self.font)
|
|
|
|
with patch.object(renderable._label_text, 'render') as mock_label_render:
|
|
mock_label_render.return_value = Image.new('RGBA', (60, 16), (255, 255, 255, 255))
|
|
result = renderable.render()
|
|
|
|
self.assertIsInstance(result, Image.Image)
|
|
mock_label_render.assert_called_once()
|
|
mock_draw.rectangle.assert_called_once() # Field background
|
|
|
|
|
|
""" TODO: Fix test
|
|
@patch('PIL.ImageDraw.Draw')
|
|
def test_render_field_with_value(self, mock_draw_class):
|
|
"""Test rendering field with value"""
|
|
mock_draw = Mock()
|
|
mock_draw_class.return_value = mock_draw
|
|
|
|
self.text_field.value = "john_doe"
|
|
renderable = RenderableFormField(self.text_field, self.font)
|
|
|
|
with patch.object(renderable._label_text, 'render') as mock_label_render:
|
|
mock_label_render.return_value = Image.new('RGBA', (60, 16), (255, 255, 255, 255))
|
|
with patch('pyWebLayout.concrete.text.Text') as mock_text_class:
|
|
mock_text_obj = Mock()
|
|
mock_text_obj.render.return_value = Image.new('RGBA', (60, 16), (255, 255, 255, 255))
|
|
mock_text_class.return_value = mock_text_obj
|
|
|
|
result = renderable.render()
|
|
|
|
self.assertIsInstance(result, Image.Image)
|
|
mock_label_render.assert_called_once()
|
|
mock_text_class.assert_called() # Value text should be created
|
|
"""
|
|
|
|
@patch('PIL.ImageDraw.Draw')
|
|
def test_render_password_field(self, mock_draw_class):
|
|
"""Test rendering password field with masked value"""
|
|
mock_draw = Mock()
|
|
mock_draw_class.return_value = mock_draw
|
|
|
|
self.password_field.value = "secret123"
|
|
renderable = RenderableFormField(self.password_field, self.font)
|
|
|
|
with patch.object(renderable._label_text, 'render') as mock_label_render:
|
|
mock_label_render.return_value = Image.new('RGBA', (60, 16), (255, 255, 255, 255))
|
|
with patch('pyWebLayout.concrete.text.Text') as mock_text_class:
|
|
mock_text_obj = Mock()
|
|
mock_text_obj.render.return_value = Image.new('RGBA', (60, 16), (255, 255, 255, 255))
|
|
mock_text_class.return_value = mock_text_obj
|
|
|
|
result = renderable.render()
|
|
|
|
self.assertIsInstance(result, Image.Image)
|
|
# Check that Text was called with masked characters
|
|
if mock_text_class.call_args:
|
|
self.assertEqual(args[0], "•" * len("secret123"))
|
|
|
|
@patch('PIL.ImageDraw.Draw')
|
|
def test_render_focused_field(self, mock_draw_class):
|
|
"""Test rendering focused field"""
|
|
mock_draw = Mock()
|
|
mock_draw_class.return_value = mock_draw
|
|
|
|
renderable = RenderableFormField(self.text_field, self.font)
|
|
renderable.set_focused(True)
|
|
|
|
with patch.object(renderable._label_text, 'render') as mock_label_render:
|
|
mock_label_render.return_value = Image.new('RGBA', (60, 16), (255, 255, 255, 255))
|
|
result = renderable.render()
|
|
|
|
self.assertIsInstance(result, Image.Image)
|
|
mock_draw.rectangle.assert_called_once()
|
|
|
|
def test_handle_click_inside_field(self):
|
|
"""Test clicking inside field area"""
|
|
renderable = RenderableFormField(self.text_field, self.font)
|
|
|
|
# Click inside field area (below label)
|
|
field_area_point = (15, 30) # Should be in field area
|
|
result = renderable.handle_click(field_area_point)
|
|
|
|
# Should return True and set focused
|
|
self.assertTrue(result)
|
|
self.assertTrue(renderable._focused)
|
|
|
|
def test_handle_click_outside_field(self):
|
|
"""Test clicking outside field area"""
|
|
renderable = RenderableFormField(self.text_field, self.font)
|
|
|
|
# Click outside field area
|
|
outside_point = (200, 200)
|
|
result = renderable.handle_click(outside_point)
|
|
|
|
# Should return False and not set focused
|
|
self.assertFalse(result)
|
|
self.assertFalse(renderable._focused)
|
|
|
|
def test_in_object(self):
|
|
"""Test in_object method"""
|
|
renderable = RenderableFormField(self.text_field, self.font, origin=(10, 20))
|
|
|
|
# Point inside field
|
|
self.assertTrue(renderable.in_object((15, 25)))
|
|
|
|
# Point outside field
|
|
self.assertFalse(renderable.in_object((200, 200)))
|
|
|
|
|
|
class TestRenderableForm(unittest.TestCase):
|
|
"""Test cases for the RenderableForm class"""
|
|
|
|
def setUp(self):
|
|
"""Set up test fixtures"""
|
|
self.font = Font(
|
|
font_path=None, # Use default font
|
|
font_size=12,
|
|
colour=(0, 0, 0)
|
|
)
|
|
self.callback = Mock()
|
|
self.form = Form("test_form", "/submit", self.callback)
|
|
|
|
# Add some fields to the form
|
|
self.username_field = FormField("username", FormFieldType.TEXT, "Username")
|
|
self.password_field = FormField("password", FormFieldType.PASSWORD, "Password")
|
|
self.form.add_field(self.username_field)
|
|
self.form.add_field(self.password_field)
|
|
|
|
def test_renderable_form_initialization(self):
|
|
"""Test basic form initialization"""
|
|
renderable = RenderableForm(self.form, self.font)
|
|
|
|
self.assertEqual(renderable._form, self.form)
|
|
self.assertEqual(renderable._font, self.font)
|
|
self.assertEqual(len(renderable._renderable_fields), 2)
|
|
self.assertIsNotNone(renderable._submit_button)
|
|
self.assertEqual(renderable._callback, self.form.execute)
|
|
|
|
def test_renderable_form_with_custom_params(self):
|
|
"""Test form initialization with custom parameters"""
|
|
custom_spacing = 15
|
|
custom_origin = (20, 30)
|
|
custom_size = (400, 350)
|
|
|
|
renderable = RenderableForm(
|
|
self.form, self.font,
|
|
spacing=custom_spacing,
|
|
origin=custom_origin,
|
|
size=custom_size
|
|
)
|
|
|
|
self.assertEqual(renderable._spacing, custom_spacing)
|
|
np.testing.assert_array_equal(renderable._origin, np.array(custom_origin))
|
|
np.testing.assert_array_equal(renderable._size, np.array(custom_size))
|
|
|
|
def test_create_form_elements(self):
|
|
"""Test creation of form elements"""
|
|
renderable = RenderableForm(self.form, self.font)
|
|
|
|
# Should create renderable fields for each form field
|
|
self.assertEqual(len(renderable._renderable_fields), 2)
|
|
self.assertIsInstance(renderable._renderable_fields[0], RenderableFormField)
|
|
self.assertIsInstance(renderable._renderable_fields[1], RenderableFormField)
|
|
|
|
# Should create submit button
|
|
self.assertIsNotNone(renderable._submit_button)
|
|
self.assertIsInstance(renderable._submit_button, RenderableButton)
|
|
|
|
def test_calculate_size(self):
|
|
"""Test automatic size calculation"""
|
|
# Create form without explicit size
|
|
renderable = RenderableForm(self.form, self.font)
|
|
|
|
# Size should be calculated based on fields and button
|
|
self.assertGreater(renderable._size[0], 0)
|
|
self.assertGreater(renderable._size[1], 0)
|
|
|
|
def test_layout(self):
|
|
"""Test form layout"""
|
|
renderable = RenderableForm(self.form, self.font)
|
|
renderable.layout()
|
|
|
|
# All fields should have origins set
|
|
for field in renderable._renderable_fields:
|
|
self.assertIsNotNone(field._origin)
|
|
self.assertGreater(field._origin[1], 0) # Should have positive Y position
|
|
|
|
# Submit button should have origin set
|
|
self.assertIsNotNone(renderable._submit_button._origin)
|
|
|
|
def test_render(self):
|
|
"""Test form rendering"""
|
|
renderable = RenderableForm(self.form, self.font)
|
|
|
|
# Mock field and button rendering
|
|
for field in renderable._renderable_fields:
|
|
field.render = Mock(return_value=Image.new('RGBA', (150, 40), (255, 255, 255, 255)))
|
|
|
|
renderable._submit_button.render = Mock(return_value=Image.new('RGBA', (80, 30), (100, 150, 200, 255)))
|
|
|
|
result = renderable.render()
|
|
|
|
self.assertIsInstance(result, Image.Image)
|
|
|
|
# All fields should have been rendered
|
|
for field in renderable._renderable_fields:
|
|
field.render.assert_called_once()
|
|
|
|
# Submit button should have been rendered
|
|
renderable._submit_button.render.assert_called_once()
|
|
|
|
def test_handle_click_submit_button(self):
|
|
"""Test clicking submit button"""
|
|
renderable = RenderableForm(self.form, self.font)
|
|
|
|
# Mock submit button's in_object method
|
|
renderable._submit_button.in_object = Mock(return_value=True)
|
|
renderable._submit_button._callback = Mock(return_value="submitted")
|
|
|
|
result = renderable.handle_click((50, 100))
|
|
|
|
self.assertEqual(result, "submitted")
|
|
renderable._submit_button.in_object.assert_called_once()
|
|
renderable._submit_button._callback.assert_called_once()
|
|
|
|
def test_handle_click_form_field(self):
|
|
"""Test clicking form field"""
|
|
renderable = RenderableForm(self.form, self.font)
|
|
|
|
# Mock submit button's in_object to return False
|
|
renderable._submit_button.in_object = Mock(return_value=False)
|
|
|
|
# Mock first field's in_object and handle_click
|
|
renderable._renderable_fields[0].in_object = Mock(return_value=True)
|
|
renderable._renderable_fields[0].handle_click = Mock(return_value=True)
|
|
|
|
click_point = (30, 40)
|
|
result = renderable.handle_click(click_point)
|
|
|
|
self.assertTrue(result)
|
|
renderable._renderable_fields[0].in_object.assert_called_once()
|
|
renderable._renderable_fields[0].handle_click.assert_called_once()
|
|
|
|
def test_handle_click_outside_elements(self):
|
|
"""Test clicking outside all elements"""
|
|
renderable = RenderableForm(self.form, self.font)
|
|
|
|
# Mock all elements to return False for in_object
|
|
renderable._submit_button.in_object = Mock(return_value=False)
|
|
for field in renderable._renderable_fields:
|
|
field.in_object = Mock(return_value=False)
|
|
|
|
result = renderable.handle_click((1000, 1000))
|
|
|
|
self.assertIsNone(result)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|