From fc24db16276f33ab28e01b862859017831fff0fa Mon Sep 17 00:00:00 2001 From: Will McGugan Date: Wed, 20 Sep 2023 17:19:36 +0100 Subject: [PATCH] snapshot tests --- docs/guide/CSS.md | 2 + docs/guide/widgets.md | 7 + src/textual/dom.py | 1 + .../__snapshots__/test_snapshots.ambr | 314 ++++++++++++++++++ .../snapshot_apps/scoped_css.py | 34 ++ .../snapshot_apps/unscoped_css.py | 35 ++ tests/snapshot_tests/test_snapshots.py | 8 + 7 files changed, 401 insertions(+) create mode 100644 tests/snapshot_tests/snapshot_apps/scoped_css.py create mode 100644 tests/snapshot_tests/snapshot_apps/unscoped_css.py diff --git a/docs/guide/CSS.md b/docs/guide/CSS.md index 0d38a616cb..63cef3558b 100644 --- a/docs/guide/CSS.md +++ b/docs/guide/CSS.md @@ -325,6 +325,8 @@ Here are some other pseudo classes: - `:enabled` Matches widgets which are in an enabled state. - `:focus` Matches widgets which have input focus. - `:focus-within` Matches widgets with a focused a child widget. +- `:dark` Matches widgets in dark mode (where `App.dark == True`). +- `:light` Matches widgets in dark mode (where `App.dark == False`). ## Combinators diff --git a/docs/guide/widgets.md b/docs/guide/widgets.md index 26d382169a..2e0a8926e1 100644 --- a/docs/guide/widgets.md +++ b/docs/guide/widgets.md @@ -103,6 +103,13 @@ Here's the Hello example again, this time the widget has embedded default CSS: ```{.textual path="docs/examples/guide/widgets/hello04.py"} ``` +#### Scoped CSS + +Default CSS is *scoped* by default. +All this means is that CSS defined in `DEFAULT_CSS` will effect the widget and potentially its children only. +This is to prevent you from inadvertently breaking an unrelated widget. + +You can disabled scoped CSS by setting the class var `SCOPED_CSS` to `False`. #### Default specificity diff --git a/src/textual/dom.py b/src/textual/dom.py index ddb2037453..d63308ad5c 100644 --- a/src/textual/dom.py +++ b/src/textual/dom.py @@ -134,6 +134,7 @@ class DOMNode(MessagePump): # Indicates if the CSS should be automatically scoped SCOPED_CSS: ClassVar[bool] = True + """Should default css be limited to the widget type?""" # True if this node inherits the CSS from the base class. _inherit_css: ClassVar[bool] = True diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr index 543f624d23..969ee7ffb4 100644 --- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr +++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr @@ -26011,6 +26011,163 @@ ''' # --- +# name: test_scoped_css + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MyApp + + + + + + + + + + ────────────────────────────────────────────────────────────────────────────── + ─── + foo + ─── + ─── + bar + ─── + ────────────────────────────────────────────────────────────────────────────── + ────────────────────────────────────────────────────────────────────────────── + ─── + foo + ─── + ─── + bar + ─── + ────────────────────────────────────────────────────────────────────────────── + I should not be styled + + + + + + + + + + + + ''' +# --- # name: test_screen_switch ''' @@ -30850,6 +31007,163 @@ ''' # --- +# name: test_unscoped_css + ''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + MyApp + + + + + + + + + + ────────────────────────────────────────────────────────────────────────────── + ─── + foo + ─── + ─── + bar + ─── + ────────────────────────────────────────────────────────────────────────────── + ────────────────────────────────────────────────────────────────────────────── + ─── + foo + ─── + ─── + bar + ─── + ────────────────────────────────────────────────────────────────────────────── + ─────────────────── + This will be styled + ─────────────────── + + + + + + + + + + ''' +# --- # name: test_vertical_layout ''' diff --git a/tests/snapshot_tests/snapshot_apps/scoped_css.py b/tests/snapshot_tests/snapshot_apps/scoped_css.py new file mode 100644 index 0000000000..3ee46c108f --- /dev/null +++ b/tests/snapshot_tests/snapshot_apps/scoped_css.py @@ -0,0 +1,34 @@ +from textual.app import App, ComposeResult +from textual.widget import Widget +from textual.widgets import Label + + +class MyWidget(Widget): + DEFAULT_CSS = """ + MyWidget { + height: auto; + border: magenta; + } + Label { + border: solid green; + } + """ + + def compose(self) -> ComposeResult: + yield Label("foo") + yield Label("bar") + + def on_mount(self) -> None: + self.log(self.app.stylesheet.css) + + +class MyApp(App): + def compose(self) -> ComposeResult: + yield MyWidget() + yield MyWidget() + yield Label("I should not be styled") + + +if __name__ == "__main__": + app = MyApp() + app.run() diff --git a/tests/snapshot_tests/snapshot_apps/unscoped_css.py b/tests/snapshot_tests/snapshot_apps/unscoped_css.py new file mode 100644 index 0000000000..f0cecbadff --- /dev/null +++ b/tests/snapshot_tests/snapshot_apps/unscoped_css.py @@ -0,0 +1,35 @@ +from textual.app import App, ComposeResult +from textual.widget import Widget +from textual.widgets import Label + + +class MyWidget(Widget): + SCOPED_CSS = False + DEFAULT_CSS = """ + MyWidget { + height: auto; + border: magenta; + } + Label { + border: solid green; + } + """ + + def compose(self) -> ComposeResult: + yield Label("foo") + yield Label("bar") + + def on_mount(self) -> None: + self.log(self.app.stylesheet.css) + + +class MyApp(App): + def compose(self) -> ComposeResult: + yield MyWidget() + yield MyWidget() + yield Label("This will be styled") + + +if __name__ == "__main__": + app = MyApp() + app.run() diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py index f8d8a67b83..f0f478515e 100644 --- a/tests/snapshot_tests/test_snapshots.py +++ b/tests/snapshot_tests/test_snapshots.py @@ -710,3 +710,11 @@ def test_auto_grid(snap_compare) -> None: def test_auto_grid_default_height(snap_compare) -> None: assert snap_compare(SNAPSHOT_APPS_DIR / "auto_grid_default_height.py", press=["g"]) + + +def test_scoped_css(snap_compare) -> None: + assert snap_compare(SNAPSHOT_APPS_DIR / "scoped_css.py") + + +def test_unscoped_css(snap_compare) -> None: + assert snap_compare(SNAPSHOT_APPS_DIR / "unscoped_css.py")