| 21 | |
| 22 | |
| 23 | async def test_data_binding(): |
| 24 | app = DataBindApp() |
| 25 | async with app.run_test() as pilot: |
| 26 | |
| 27 | # Check default |
| 28 | assert app.bar == "Bar" |
| 29 | |
| 30 | label1 = app.query_one("#label1", FooLabel) |
| 31 | label2 = app.query_one("#label2", FooLabel) |
| 32 | |
| 33 | # These are bound, so should have the same value as the App.foo |
| 34 | assert label1.foo == "Bar" |
| 35 | # Not yet bound, so should have its own default |
| 36 | assert label2.foo == "Foo" |
| 37 | |
| 38 | # Changing this reactive, should also change the bound widgets |
| 39 | app.bar = "Baz" |
| 40 | |
| 41 | # Sanity check |
| 42 | assert app.bar == "Baz" |
| 43 | |
| 44 | # Should also have updated bound labels |
| 45 | assert label1.foo == "Baz" |
| 46 | assert label2.foo == "Foo" |
| 47 | |
| 48 | with pytest.raises(ReactiveError): |
| 49 | # This should be an error because FooLabel.foo is not defined on the app |
| 50 | label2.data_bind(foo=FooLabel.foo) |
| 51 | |
| 52 | # Bind data outside of compose |
| 53 | label2.data_bind(foo=DataBindApp.bar) |
| 54 | await pilot.pause() |
| 55 | # Confirm new binding has propagated |
| 56 | assert label2.foo == "Baz" |
| 57 | |
| 58 | # Set reactive and check propagation |
| 59 | app.bar = "Egg" |
| 60 | assert label1.foo == "Egg" |
| 61 | assert label2.foo == "Egg" |
| 62 | |
| 63 | # Test nothing goes awry when removing widget with bound data |
| 64 | await label1.remove() |
| 65 | |
| 66 | # Try one last time |
| 67 | app.bar = "Spam" |
| 68 | |
| 69 | # Confirm remaining widgets still propagate |
| 70 | assert label2.foo == "Spam" |
| 71 | |
| 72 | |
| 73 | async def test_data_binding_missing_reactive(): |