File: test_data_bind.py

package info (click to toggle)
textual 2.1.2-1.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 55,080 kB
  • sloc: python: 85,423; lisp: 1,669; makefile: 101
file content (86 lines) | stat: -rw-r--r-- 2,350 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
import pytest

from textual.app import App, ComposeResult
from textual.reactive import ReactiveError, reactive
from textual.widgets import Label


class FooLabel(Label):
    foo = reactive("Foo")

    def render(self) -> str:
        return self.foo


class DataBindApp(App):
    bar = reactive("Bar")

    def compose(self) -> ComposeResult:
        yield FooLabel(id="label1").data_bind(foo=DataBindApp.bar)
        yield FooLabel(id="label2")  # Not bound


async def test_data_binding():
    app = DataBindApp()
    async with app.run_test() as pilot:

        # Check default
        assert app.bar == "Bar"

        label1 = app.query_one("#label1", FooLabel)
        label2 = app.query_one("#label2", FooLabel)

        # These are bound, so should have the same value as the App.foo
        assert label1.foo == "Bar"
        # Not yet bound, so should have its own default
        assert label2.foo == "Foo"

        # Changing this reactive, should also change the bound widgets
        app.bar = "Baz"

        # Sanity check
        assert app.bar == "Baz"

        # Should also have updated bound labels
        assert label1.foo == "Baz"
        assert label2.foo == "Foo"

        with pytest.raises(ReactiveError):
            # This should be an error because FooLabel.foo is not defined on the app
            label2.data_bind(foo=FooLabel.foo)

        # Bind data outside of compose
        label2.data_bind(foo=DataBindApp.bar)
        await pilot.pause()
        # Confirm new binding has propagated
        assert label2.foo == "Baz"

        # Set reactive and check propagation
        app.bar = "Egg"
        assert label1.foo == "Egg"
        assert label2.foo == "Egg"

        # Test nothing goes awry when removing widget with bound data
        await label1.remove()

        # Try one last time
        app.bar = "Spam"

        # Confirm remaining widgets still propagate
        assert label2.foo == "Spam"


async def test_data_binding_missing_reactive():

    class DataBindErrorApp(App):
        foo = reactive("Bar")

        def compose(self) -> ComposeResult:
            yield FooLabel(id="label1").data_bind(
                nofoo=DataBindErrorApp.foo
            )  # Missing reactive

    app = DataBindErrorApp()
    with pytest.raises(ReactiveError):
        async with app.run_test():
            pass