|
2 | 2 |
|
3 | 3 | import pytest |
4 | 4 |
|
5 | | -from textual.app import App, ComposeResult |
| 5 | +from textual.app import App |
6 | 6 | from textual.reactive import reactive, var |
7 | | -from textual.widget import Widget |
8 | 7 |
|
9 | 8 | OLD_VALUE = 5_000 |
10 | 9 | NEW_VALUE = 1_000_000 |
@@ -81,14 +80,16 @@ async def watch_count(self, old_value: int, new_value: int) -> None: |
81 | 80 | try: |
82 | 81 | await asyncio.wait_for(app.watcher_called_event.wait(), timeout=0.05) |
83 | 82 | except TimeoutError: |
84 | | - pytest.fail("Async watcher wasn't called within timeout when reactive init = True") |
| 83 | + pytest.fail( |
| 84 | + "Async watcher wasn't called within timeout when reactive init = True") |
85 | 85 |
|
86 | 86 | assert app.count == OLD_VALUE |
87 | 87 | assert app.watcher_old_value == OLD_VALUE |
88 | 88 | assert app.watcher_new_value == OLD_VALUE # The value wasn't changed |
89 | 89 |
|
90 | 90 |
|
91 | | -@pytest.mark.xfail(reason="Reactive watcher is incorrectly always called the first time it is set, even if value is same [issue#1230]") |
| 91 | +@pytest.mark.xfail( |
| 92 | + reason="Reactive watcher is incorrectly always called the first time it is set, even if value is same [issue#1230]") |
92 | 93 | async def test_watch_init_false_always_update_false(): |
93 | 94 | class WatcherInitFalse(App): |
94 | 95 | count = reactive(0, init=False) |
@@ -173,20 +174,45 @@ def watch_value(self, new_value): |
173 | 174 | assert app.watcher_called_with == OLD_VALUE |
174 | 175 |
|
175 | 176 |
|
176 | | -@pytest.mark.xfail(reason="Validator methods not running when init=True [issue#1220]") |
177 | 177 | async def test_validate_init_true(): |
178 | 178 | """When init is True for a reactive attribute, Textual should call the validator |
179 | 179 | AND the watch method when the app starts.""" |
| 180 | + validator_call_count = 0 |
180 | 181 |
|
181 | 182 | class ValidatorInitTrue(App): |
182 | 183 | count = var(5, init=True) |
183 | 184 |
|
184 | 185 | def validate_count(self, value: int) -> int: |
| 186 | + nonlocal validator_call_count |
| 187 | + validator_call_count += 1 |
185 | 188 | return value + 1 |
186 | 189 |
|
187 | 190 | app = ValidatorInitTrue() |
188 | 191 | async with app.run_test(): |
| 192 | + app.count = 5 |
189 | 193 | assert app.count == 6 # Validator should run, so value should be 5+1=6 |
| 194 | + assert validator_call_count == 1 |
| 195 | + |
| 196 | + |
| 197 | +async def test_validate_init_true_set_before_dom_ready(): |
| 198 | + """When init is True for a reactive attribute, Textual should call the validator |
| 199 | + AND the watch method when the app starts.""" |
| 200 | + validator_call_count = 0 |
| 201 | + |
| 202 | + class ValidatorInitTrue(App): |
| 203 | + count = var(5, init=True) |
| 204 | + |
| 205 | + def validate_count(self, value: int) -> int: |
| 206 | + nonlocal validator_call_count |
| 207 | + validator_call_count += 1 |
| 208 | + return value + 1 |
| 209 | + |
| 210 | + app = ValidatorInitTrue() |
| 211 | + app.count = 5 |
| 212 | + async with app.run_test(): |
| 213 | + assert app.count == 6 # Validator should run, so value should be 5+1=6 |
| 214 | + assert validator_call_count == 1 |
| 215 | + |
190 | 216 |
|
191 | 217 |
|
192 | 218 | @pytest.mark.xfail(reason="Compute methods not called when init=True [issue#1227]") |
|
0 commit comments