Beispiel #1
0
 def test_mount_and_dismount(self):
     component = MockComponent(0)
     app = engine.RenderEngine(component)
     render_results = app._request_rerender([component])
     render_results.run()
     component.did_mount.assert_called_once()
     component.did_render.assert_called_once()
Beispiel #2
0
    def test_one_child_rerender(self):
        class TestCompInner(component.Component):

            @component.register_props
            def __init__(self, val):
                self.count = 0

            def render(self):
                self.count += 1
                return base_components.Label(self.props.val)

        class TestCompOuter(component.Component):
            def render(self):
                return base_components.View()(TestCompInner(self.value))

        test_comp = TestCompOuter()
        test_comp.value = 2
        app = engine.RenderEngine(test_comp)
        render_result = app._request_rerender([test_comp])
        inner_comp = app._component_tree[app._component_tree[test_comp]][0]
        self.assertEqual(inner_comp.count, 1)
        self.assertEqual(inner_comp.props.val, 2)

        test_comp.value = 4
        render_result = app._request_rerender([test_comp])
        inner_comp = app._component_tree[app._component_tree[test_comp]][0]
        self.assertEqual(inner_comp.count, 2)
        self.assertEqual(inner_comp.props.val, 4)
Beispiel #3
0
    def test_state_changes(self):
        component = _TestComponentOuter()
        app = engine.RenderEngine(component)
        render_result = app._request_rerender([component])
        qt_tree = render_result.trees[0]
        qt_commands = render_result.commands

        component.state_a = "AChanged"
        render_result = app._request_rerender([component])
        new_qt_tree = render_result.trees[0]
        qt_commands = render_result.commands
        # TODO: Make it so that only the label (0, 0) needs to update!
        expected_commands = [(qt_tree._dereference([0, 0]).component.underlying.setText, "AChanged")]
        self.assertEqual(qt_commands, expected_commands)

        component.state_b = "BChanged"
        render_result = app._request_rerender([component])
        qt_commands = render_result.commands
        expected_commands = [(qt_tree._dereference([1, 0]).component.underlying.setText, "BChanged")]
        self.assertEqual(qt_commands, expected_commands)

        component.state_c = "CChanged"
        render_result = app._request_rerender([component])
        new_qt_tree = render_result.trees[0]
        qt_commands = render_result.commands
        expected_commands = [(qt_tree._dereference([2]).component.underlying.setText, "CChanged")]
        self.assertEqual(qt_commands, expected_commands)
Beispiel #4
0
    def test_keyed_list_add(self):
        component = _TestComponentOuterList(True, True)
        app = engine.RenderEngine(component)
        render_result = app._request_rerender([component])
        qt_tree = render_result.trees[0]
        qt_commands = render_result.commands

        component.state = ["A", "B", "D", "C"]
        render_result = app._request_rerender([component])
        _new_qt_tree = render_result.trees[0]
        qt_commands = render_result.commands

        def new_V(*args):
            view = _new_qt_tree._dereference(args)
            return [(view.component._add_child, i, child.component.underlying)
                    for (i, child) in enumerate(view.children)]

        self.assertEqual(
            _new_qt_tree._dereference([2, 0]).component.props.text, "D")

        def new_C(*args):
            return _commands_for_address(_new_qt_tree, args)

        expected_commands = (new_C(2, 0) + new_C(2, 1) + new_V(2) + new_C(2) +
                             [(qt_tree.component._add_child, 2,
                               _new_qt_tree.children[2].component.underlying)])

        self.assertEqual(qt_commands, expected_commands)
Beispiel #5
0
    def test_basic_render(self):
        component = _TestComponentOuter()
        app = engine.RenderEngine(component)
        render_result = app._request_rerender([component])
        qt_tree = render_result.trees[0]
        qt_commands = render_result.commands

        def C(*args):
            return _commands_for_address(qt_tree, args)

        def V(*args):
            view = qt_tree._dereference(args)
            return [(view.component._add_child, i, child.component.underlying)
                    for (i, child) in enumerate(view.children)]

        expected_commands = C(0, 0) + C(0, 1) + V(0) + C(0) + C(1, 0) + C(
            1, 1) + V(1) + C(1) + C(2) + V() + C()
        self.assertEqual(qt_commands, expected_commands)

        # After everything rendered, a rerender shouldn't involve any commands
        # TODO: make sure this is actually true!
        render_result = app._request_rerender([component])
        qt_tree = render_result.trees[0]
        qt_commands = render_result.commands
        self.assertEqual(qt_commands, [])
Beispiel #6
0
    def test_render_exception(self):
        class TestCompInner1(component.Component):

            @component.register_props
            def __init__(self, val):
                self.count = 0
                self.success_count = 0

            def render(self):
                self.count += 1
                self.success_count += 1
                return base_components.Label(self.props.val)

        class TestCompInner2(component.Component):

            @component.register_props
            def __init__(self, val):
                self.count = 0
                self.success_count = 0

            def render(self):
                self.count += 1
                assert self.props.val == 8
                self.success_count += 1
                return base_components.Label(self.props.val)

        class TestCompOuter(component.Component):
            def render(self):
                return base_components.View()(
                    TestCompInner1(self.value * 2),
                    TestCompInner2(self.value * 4),
                )

        test_comp = TestCompOuter()
        test_comp.value = 2
        app = engine.RenderEngine(test_comp)
        render_result = app._request_rerender([test_comp])
        inner_comp1, inner_comp2 = app._component_tree[app._component_tree[test_comp]]
        self.assertEqual(inner_comp1.count, 1)
        self.assertEqual(inner_comp1.props.val, 4)
        self.assertEqual(inner_comp2.count, 1)
        self.assertEqual(inner_comp2.props.val, 8)

        test_comp.value = 3
        try:
            render_result = app._request_rerender([test_comp])
        except AssertionError:
            pass
        inner_comp1, inner_comp2 = app._component_tree[app._component_tree[test_comp]]
        self.assertEqual(inner_comp1.props.val, 4)
        self.assertEqual(inner_comp2.count, 2)
        self.assertEqual(inner_comp2.success_count, 1)
        self.assertEqual(inner_comp2.props.val, 8)
Beispiel #7
0
    def test_reference(self):
        class TestComp(component.Component):
            def __init__(self):
                super().__init__()
                self.render_count = 0
                self.ref1 = component.Reference()
                self.ref2 = component.Reference()

            def render(self):
                self.render_count += 1
                if self.render_count == 1:
                    return base_components.Label("Test").register_ref(
                        self.ref1)
                else:
                    return base_components.Label("Test").register_ref(
                        self.ref2)

        class TestCompWrapper(component.Component):
            def __init__(self):
                super().__init__()
                self.render_count = 0

            def render(self):
                self.render_count += 1
                if self.render_count == 3:
                    # We do this to force the dismount of TestComp
                    return base_components.Label("Test")
                else:
                    return TestComp()

        root = TestCompWrapper()
        render_engine = engine.RenderEngine(root)
        render_engine._request_rerender([root])
        sub_comp = render_engine._component_tree[root]
        label_comp = render_engine._component_tree[sub_comp]
        self.assertEqual(sub_comp.ref1(), label_comp)
        self.assertEqual(sub_comp.ref2(), None)

        # Rerender so that ref2 should also point to label
        render_engine._request_rerender([root])
        new_sub_comp = render_engine._component_tree[root]
        new_label = render_engine._component_tree[new_sub_comp]
        self.assertEqual(new_sub_comp, sub_comp)
        self.assertEqual(new_label, label_comp)
        self.assertEqual(sub_comp.ref1(), label_comp)
        self.assertEqual(sub_comp.ref2(), label_comp)

        # Rerender to test dismount behavior
        render_engine._request_rerender([root])
        new_sub_comp = render_engine._component_tree[root]
        assert sub_comp not in render_engine._component_tree
        self.assertEqual(sub_comp.ref1(), None)
        self.assertEqual(sub_comp.ref2(), None)
Beispiel #8
0
    def test_keyed_list_nochange(self):
        component = _TestComponentOuterList(True, False)
        app = engine.RenderEngine(component)
        render_result = app._request_rerender([component])
        qt_tree = render_result.trees[0]
        qt_commands = render_result.commands

        component.state = ["C", "B", "A"]
        render_result = app._request_rerender([component])
        _new_qt_tree = render_result.trees[0]
        qt_commands = render_result.commands

        expected_commands = [(qt_tree._dereference([0, 0]).component.underlying.setText, "C"), (qt_tree._dereference([2, 0]).component.underlying.setText, "A")]
        self.assertEqual(qt_commands, expected_commands)
Beispiel #9
0
    def test_refresh_child_error(self):
        class OldInnerClass(component.Component):

            @component.register_props
            def __init__(self, val):
                self.count = 0
                self.will_unmount = unittest.mock.MagicMock()

            def render(self):
                self.count += 1
                return base_components.Label(self.props.val)

        class NewInnerClass(component.Component):

            @component.register_props
            def __init__(self, val):
                self.count = 0

            def render(self):
                self.count += 1
                assert False
                return base_components.Label(self.props.val * 2)

        class OuterClass(component.Component):

            @component.register_props
            def __init__(self):
                self.count = 0

            def render(self):
                self.count += 1
                return base_components.View()(
                    OldInnerClass(5)
                )

        outer_comp = OuterClass()
        app = engine.RenderEngine(outer_comp)
        app._request_rerender([outer_comp])
        old_inner_comp = app._component_tree[app._component_tree[outer_comp]][0]
        assert isinstance(old_inner_comp, OldInnerClass)

        try:
            app._refresh_by_class([(OldInnerClass, NewInnerClass)])
        except AssertionError:
            pass
        inner_comp = app._component_tree[app._component_tree[outer_comp]][0]
        old_inner_comp.will_unmount.assert_not_called()
        assert isinstance(inner_comp, OldInnerClass)
        self.assertEqual(inner_comp.props.val, 5)
Beispiel #10
0
    def test_keyed_list_delete_child(self):
        component = _TestComponentOuterList(True, True)
        app = engine.RenderEngine(component)
        render_result = app._request_rerender([component])
        qt_tree = render_result.trees[0]
        old_child = qt_tree.children[2].component
        qt_commands = render_result.commands

        component.state = ["A", "B"]
        render_result = app._request_rerender([component])
        _new_qt_tree = render_result.trees[0]
        qt_commands = render_result.commands

        expected_commands = [(qt_tree.component._delete_child, 2, old_child)]

        self.assertEqual(qt_commands, expected_commands)
Beispiel #11
0
    def test_keyed_list_reshuffle(self):
        component = _TestComponentOuterList(True, True)
        app = engine.RenderEngine(component)
        render_result = app._request_rerender([component])
        qt_tree = render_result.trees[0]
        qt_commands = render_result.commands
        old_child0 = qt_tree.children[0].component
        old_child2 = qt_tree.children[2].component

        component.state = ["C", "B", "A"]
        render_result = app._request_rerender([component])
        _new_qt_tree = render_result.trees[0]
        qt_commands = render_result.commands

        expected_commands = (
                             [(qt_tree.component._add_child, 0, qt_tree.children[2].component.underlying)]
                             + [(qt_tree.component._add_child, 1, qt_tree.children[1].component.underlying)])

        self.assertEqual(qt_commands, expected_commands)
Beispiel #12
0
 def _test_comp(self, comp, children=None):
     children = children or []
     render_engine = engine.RenderEngine(comp)
     res = render_engine._request_rerender([comp])
     res.run()
Beispiel #13
0
 def __init__(self, component):
     self._root = component
     self._render_engine = engine.RenderEngine(self._root, self)
     self.render_count = 0