def test_container_rendering(self): parent = Core(container=Core()) child = Core(parent=parent) render_result = parent._render() for view_id in (parent.id, parent.container.id, child.id): assert view_id in render_result
def test_style_fill(self): class TestCore(Core): pass TestCore.text_color = Core._css_color_prop('text_color', 'color') TestCore.background_color = Core._css_color_prop( 'background_color', 'background-color') class SomeStyle(Style): background_color = theme.background class OtherTheme(Theme): background = Color('indigo') Style.current_theme = OtherTheme TestCore.style = SomeStyle view = TestCore() view.text_color = 'black' assert 'color' in view._css_properties assert len(view._css_properties) == 1 css_properties = view._set_position_and_fill_from_theme() assert 'background-color' in css_properties assert len(css_properties) == 2 assert css_properties['background-color'] == Color('indigo').css
def test_container_hierarchy(self): parent = Core(container=Core()) child = Core(parent=parent) assert child.parent == parent assert child._parent == parent.container assert parent.children == (child, ) assert parent._children == [parent.container]
def test_properties__color(self): Core.text_color = Core._css_color_prop('text_color', 'color') view = Core() view.text_color = 'cyan' assert view.text_color.name == 'cyan' assert view._css_properties['color'] == 'rgba(0,255,255,255)'
def test_properties__bool(self): Core.bold = Core._css_bool_prop('bold', 'font-weight', 'bold') view = Core() view.bold = True assert view._css_properties['font-weight'] == 'bold' view.bold = False assert view._css_properties['font-weight'] is None
def test_event_generator(self): view = Core() assert view._animation_id is None @view def on_click(data): data.value = 1 yield data.value = 2 # First click update = view._process_event('click', view) assert view.value == 1 assert len(Events._animation_generators) == 1 # Return after animation complete animation_id = next(iter(Events._animation_generators.keys())) view._process_event_loop(animation_id) assert view.value == 2 assert len(Events._animation_generators) == 0 # Restart view._process_event('click', view) assert view.value == 1 animation_id = next(iter(Events._animation_generators.keys())) view._process_event_loop(animation_id) assert view.value == 2
def test_identity(self, is_view_id): view1 = Core() view2 = Core() class NotView: id = 'foobar' assert NotView().id != is_view_id assert view1.id == is_view_id assert view2.id == is_view_id assert view1.id != view2.id assert Core.get_view(view2.id) == view2
def test_animated_css_properties(self): view = Core() with animation(): view._set_css_property( 'corner_radius', '50%', 'border-radius', '50%', ) with animation( duration=2.0, ease='ease-func', direction='alternate', iterations='forever', start_delay=1, end_delay=2, ): view._set_css_property( 'alpha', 0.5, 'opacity', '50%', ) view._animation_id = 'abc123' rendered = view._render_props() assert rendered == { 'style': 'border-radius:50%;opacity:50%', 'ui4style': 'border-radius:50%:0.3s;opacity:50%:2.0s,ease-func,alternate,1s,2s,inf', }
def test_properties__mapping(self): Core.scrollable = Core._css_mapping_prop('scrollable', 'overflow', { True: 'auto', 'horizontal': 'auto hidden', 'vertical': 'hidden auto', }) view = Core() view.scrollable = True assert view._css_properties['overflow'] == 'auto' view.scrollable = False assert view._css_properties['overflow'] == None
def test_properties__generic(self): Core.corner_radius = Core._css_plain_prop('corner_radius', 'border-radius') view = Core() view.corner_radius = '25%' assert view._properties['corner_radius'] == '25%' assert view._css_properties['border-radius'] == '25%' assert view.corner_radius == '25%' view.corner_radius = 8 assert view._properties['corner_radius'] == 8 assert view._css_properties['border-radius'] == '8px' assert view.corner_radius == 8
def test_event_handler_decorator(self): view = Core() with pytest.raises(ValueError): @view def on_nonexistent_event(_): pass @view def on_click(_): pass assert inspect.isfunction( view.on_click) # noqa: Too clever for PyCharm assert view._render_events() == { 'hx-post': '/event', 'hx-trigger': 'click' }
def test_base_setter_and_render(self, anchor_view): view = anchor_view() assert view not in Core._get_dirties() view._set_css_property( 'text_color', (1, 1, 1, 1), 'color', 'rgba(255,255,255,255)', ) assert view in Core._get_dirties() view.left = 100 # Triggers position: absolute rendered = view._render_props() assert rendered == { 'style': 'color:rgba(255,255,255,255);position:absolute', }
class Select(View): _template = Template('<select id="$id" name="$id" class="$viewclass" ' '$rendered_attributes $oob hx-swap="none">' '$options</select>') def __init__(self, options=None, **kwargs): super().__init__(**kwargs) self.options = options or [] options = Core._prop('options') def _render_options(self): """
def test_event_handler_option_decorator(self): view = Core() @view @delay def on_click(_): pass @view @delay def on_change(_): pass assert view._render_events( )['hx-trigger'] == 'change delay:0.5s,click delay:0.5s' view.remove_event('change') assert view._render_events()['hx-trigger'] == 'click delay:0.5s'
def test_hierarchy(self): view1 = Core() view2 = Core(parent=view1) assert view2 in view1.children view3 = Core() with pytest.raises(AttributeError): view1.children.append(view3) view2.parent = view3 assert view2 not in view1.children view4 = Core(children=[view1, view2]) assert view1 in view4.children assert view2 in view4.children assert not view3.children
def clean_state(): Core._clean_state()
def test_renderer_registration(self): view = Core() assert len(view._renderers) == 3
def test_get_roots(self): view1 = Core() view2 = Core(parent=view1) view3 = Core(parent=view2) view4 = Core(parent=view1) assert Core._get_roots() == set() view4._mark_dirty() assert Core._get_roots() == {view4} view3._mark_dirty() assert Core._get_roots() == {view3, view4} view2._mark_dirty() assert Core._get_roots() == {view2, view4} view1._mark_dirty() assert Core._get_roots() == {view1}
class View(Core): style = BaseStyle # Layout properties left = Core._anchorprop('left') x = left right = Core._anchorprop('right') top = Core._anchorprop('top') y = top bottom = Core._anchorprop('bottom') width = Core._anchorprop('width') height = Core._anchorprop('height') center_x = Core._anchorprop('centerX') center_y = Core._anchorprop('centerY') # Composite properties center = Core._anchorprops('center_x', 'center_y') position = Core._anchorprops('left', 'top') size = Core._anchorprops('width', 'height') frame = Core._anchorprops('left', 'top', 'width', 'height') # Dock to parent top_left = Core._anchordock('top_left') top_right = Core._anchordock('top_right') bottom_left = Core._anchordock('bottom_left') bottom_right = Core._anchordock('bottom_right') top_center = Core._anchordock('top_center') bottom_center = Core._anchordock('bottom_center') left_center = Core._anchordock('left_center') right_center = Core._anchordock('right_center') sides = Core._anchordock('sides') top_and_bottom = Core._anchordock('top_and_bottom') all = Core._anchordock('all') # Dock to sibling above = Core._anchordock('above') below = Core._anchordock('below') left_of = Core._anchordock('left_of') right_of = Core._anchordock('right_of') # Dock to content fit_width = Core._anchordock('fit_width') fit_height = Core._anchordock('fit_height') # Appearance properties align = Core._css_plain_prop('align', 'text-align') alpha = Core._css_plain_prop('alpha', 'opacity') background_color = Core._css_color_prop('background_color', 'background-color') border_color = Core._css_color_prop('border_color', 'border-color') border_style = Core._css_plain_prop('border_style', 'border-style') border_width = Core._css_plain_prop('border_width', 'border-width') corner_radius = Core._css_plain_prop('corner_radius', 'border-radius') margin = Core._css_plain_prop('margin', 'margin') padding = Core._css_plain_prop('padding', 'padding') scrollable = Core._css_mapping_prop('scrollable', 'overflow', { True: 'auto', 'horizontal': 'auto hidden', 'vertical': 'hidden auto', }) shadow = Core._css_plain_prop('shadow', 'box-shadow') z = Core._css_plain_prop('z', 'z-index') # Text properties text = Core._prop('text') bold = Core._css_bool_prop('bold', 'font-weight', 'bold') font = Core._css_plain_prop('font', 'font-family') text_color = Core._css_color_prop('text_color', 'color') font_size = Core._css_plain_prop('font_size', 'font-size')