Skip to content

Commit

Permalink
snapshot test
Browse files Browse the repository at this point in the history
  • Loading branch information
willmcgugan committed Oct 19, 2024
1 parent 9cf56a9 commit 9e0b047
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 3 deletions.
3 changes: 2 additions & 1 deletion src/textual/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -3153,7 +3153,8 @@ def _register(
self._register_child(parent, widget, before, after)
if widget._nodes:
self._register(widget, *widget._nodes, cache=cache)
apply_stylesheet(widget, cache=cache)
for widget in widget_list:
apply_stylesheet(widget, cache=cache)

if not self._running:
# If the app is not running, prevent awaiting of the widget tasks
Expand Down
4 changes: 4 additions & 0 deletions src/textual/css/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@
"inline",
"light",
"nocolor",
"first-of-type",
"last-of-type",
"odd",
"even",
}
VALID_OVERLAY: Final = {"none", "screen"}
VALID_CONSTRAIN: Final = {"inflect", "inside", "none"}
Expand Down
4 changes: 3 additions & 1 deletion src/textual/css/stylesheet.py
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,6 @@ def _check_rule(
"last-of_type",
"odd",
"even",
"focus-within",
}

def apply(
Expand Down Expand Up @@ -484,6 +483,9 @@ def apply(

node._has_hover_style = "hover" in all_pseudo_classes
node._has_focus_within = "focus-within" in all_pseudo_classes
node._has_order_style = not all_pseudo_classes.isdisjoint(
{"first-of-type", "last-of-type", "odd", "even"}
)

cache_key: tuple | None = None

Expand Down
2 changes: 2 additions & 0 deletions src/textual/dom.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,8 @@ def __init__(
)
self._has_hover_style: bool = False
self._has_focus_within: bool = False
self._has_order_style: bool = False
"""The node has an ordered dependent pseudo-style (`:odd`, `:even`, `:first-of-type`, `:last-of-type`)"""
self._reactive_connect: (
dict[str, tuple[MessagePump, Reactive[object] | object]] | None
) = None
Expand Down
10 changes: 9 additions & 1 deletion src/textual/widget.py
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ def last_of_type(self) -> bool:
if parent._nodes._updates == self._last_of_type[0]:
return self._last_of_type[1]
widget_type = type(self)
for node in reversed(parent.children):
for node in reversed(parent._nodes):
if isinstance(node, widget_type):
self._last_of_type = (parent._nodes._updates, node is self)
return self._last_of_type[1]
Expand Down Expand Up @@ -1166,8 +1166,16 @@ def mount(
parent, *widgets, before=insert_before, after=insert_after
)

def update_styles(children: Iterable[DOMNode]) -> None:
"""Update order related CSS"""
for child in children:
if child._has_order_style:
child._update_styles()

self.call_later(update_styles, list(self.children))
await_mount = AwaitMount(self, mounted)
self.call_next(await_mount)

return await_mount

def mount_all(
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions tests/snapshot_tests/test_snapshots.py
Original file line number Diff line number Diff line change
Expand Up @@ -2374,3 +2374,34 @@ def compose(self) -> ComposeResult:
yield Label("A margin of 4, should be 4 cells around the text")

assert snap_compare(FRApp())


def test_pseudo_classes(snap_compare):
"""Test pseudo classes added in https://github.com/Textualize/textual/pull/5139
You should see 6 bars, with alternating green and red backgrounds.
The first bar should have a red border.
The last bar should have a green border.
"""

class PSApp(App):
CSS = """
Label { width: 1fr; height: 1fr; }
Label:first-of-type { border:heavy red; }
Label:last-of-type { border:heavy green; }
Label:odd {background: $success 20%; }
Label:even {background: $error 20%; }
"""

def compose(self) -> ComposeResult:
for item_number in range(5):
yield Label(f"Item {item_number+1}")

def on_mount(self) -> None:
# Mounting a new widget should updated previous widgets, as the last of type has changed
self.mount(Label("HELLO"))

assert snap_compare(PSApp())

0 comments on commit 9e0b047

Please sign in to comment.