mirror of
https://github.com/Textualize/textual.git
synced 2025-10-17 02:38:12 +03:00
Merge pull request #595 from Textualize/user-css-over-widget-css
User CSS should always take precedence over Widget CSS
This commit is contained in:
@@ -5,15 +5,16 @@ import pytest
|
||||
|
||||
from textual.color import Color
|
||||
from textual.css._help_renderables import HelpText
|
||||
from textual.css.stylesheet import Stylesheet, StylesheetParseError
|
||||
from textual.css.stylesheet import Stylesheet, StylesheetParseError, CssSource
|
||||
from textual.css.tokenizer import TokenizeError
|
||||
from textual.dom import DOMNode
|
||||
from textual.geometry import Spacing
|
||||
from textual.widget import Widget
|
||||
|
||||
|
||||
def _make_stylesheet(css: str) -> Stylesheet:
|
||||
def _make_user_stylesheet(css: str) -> Stylesheet:
|
||||
stylesheet = Stylesheet()
|
||||
stylesheet.source["test.css"] = css
|
||||
stylesheet.source["test.css"] = CssSource(css, is_defaults=False)
|
||||
stylesheet.parse()
|
||||
return stylesheet
|
||||
|
||||
@@ -21,7 +22,7 @@ def _make_stylesheet(css: str) -> Stylesheet:
|
||||
def test_stylesheet_apply_highest_specificity_wins():
|
||||
"""#ids have higher specificity than .classes"""
|
||||
css = "#id {color: red;} .class {color: blue;}"
|
||||
stylesheet = _make_stylesheet(css)
|
||||
stylesheet = _make_user_stylesheet(css)
|
||||
node = DOMNode(classes="class", id="id")
|
||||
stylesheet.apply(node)
|
||||
|
||||
@@ -30,7 +31,7 @@ def test_stylesheet_apply_highest_specificity_wins():
|
||||
|
||||
def test_stylesheet_apply_doesnt_override_defaults():
|
||||
css = "#id {color: red;}"
|
||||
stylesheet = _make_stylesheet(css)
|
||||
stylesheet = _make_user_stylesheet(css)
|
||||
node = DOMNode(id="id")
|
||||
stylesheet.apply(node)
|
||||
|
||||
@@ -42,7 +43,7 @@ def test_stylesheet_apply_highest_specificity_wins_multiple_classes():
|
||||
"""When we use two selectors containing only classes, then the selector
|
||||
`.b.c` has greater specificity than the selector `.a`"""
|
||||
css = ".b.c {background: blue;} .a {background: red; color: lime;}"
|
||||
stylesheet = _make_stylesheet(css)
|
||||
stylesheet = _make_user_stylesheet(css)
|
||||
node = DOMNode(classes="a b c")
|
||||
stylesheet.apply(node)
|
||||
|
||||
@@ -55,7 +56,7 @@ def test_stylesheet_many_classes_dont_overrule_id():
|
||||
a selector containing multiple classes cannot take priority over even a
|
||||
single class."""
|
||||
css = "#id {color: red;} .a.b.c.d {color: blue;}"
|
||||
stylesheet = _make_stylesheet(css)
|
||||
stylesheet = _make_user_stylesheet(css)
|
||||
node = DOMNode(classes="a b c d", id="id")
|
||||
stylesheet.apply(node)
|
||||
|
||||
@@ -64,7 +65,7 @@ def test_stylesheet_many_classes_dont_overrule_id():
|
||||
|
||||
def test_stylesheet_last_rule_wins_when_same_rule_twice_in_one_ruleset():
|
||||
css = "#id {color: red; color: blue;}"
|
||||
stylesheet = _make_stylesheet(css)
|
||||
stylesheet = _make_user_stylesheet(css)
|
||||
node = DOMNode(id="id")
|
||||
stylesheet.apply(node)
|
||||
|
||||
@@ -73,7 +74,7 @@ def test_stylesheet_last_rule_wins_when_same_rule_twice_in_one_ruleset():
|
||||
|
||||
def test_stylesheet_rulesets_merged_for_duplicate_selectors():
|
||||
css = "#id {color: red; background: lime;} #id {color:blue;}"
|
||||
stylesheet = _make_stylesheet(css)
|
||||
stylesheet = _make_user_stylesheet(css)
|
||||
node = DOMNode(id="id")
|
||||
stylesheet.apply(node)
|
||||
|
||||
@@ -85,7 +86,7 @@ def test_stylesheet_apply_takes_final_rule_in_specificity_clash():
|
||||
""".a and .b both contain background and have same specificity, so .b wins
|
||||
since it was declared last - the background should be blue."""
|
||||
css = ".a {background: red; color: lime;} .b {background: blue;}"
|
||||
stylesheet = _make_stylesheet(css)
|
||||
stylesheet = _make_user_stylesheet(css)
|
||||
node = DOMNode(classes="a b", id="c")
|
||||
stylesheet.apply(node)
|
||||
|
||||
@@ -96,11 +97,32 @@ def test_stylesheet_apply_takes_final_rule_in_specificity_clash():
|
||||
def test_stylesheet_apply_empty_rulesets():
|
||||
"""Ensure that we don't crash when working with empty rulesets"""
|
||||
css = ".a {} .b {}"
|
||||
stylesheet = _make_stylesheet(css)
|
||||
stylesheet = _make_user_stylesheet(css)
|
||||
node = DOMNode(classes="a b")
|
||||
stylesheet.apply(node)
|
||||
|
||||
|
||||
def test_stylesheet_apply_user_css_over_widget_css():
|
||||
user_css = ".a {color: red; tint: yellow;}"
|
||||
|
||||
class MyWidget(Widget):
|
||||
CSS = ".a {color: blue !important; background: lime;}"
|
||||
|
||||
node = MyWidget()
|
||||
node.add_class("a")
|
||||
|
||||
stylesheet = _make_user_stylesheet(user_css)
|
||||
stylesheet.add_source(MyWidget.CSS, "widget.py:MyWidget", is_default_css=True)
|
||||
stylesheet.apply(node)
|
||||
|
||||
# The node is red because user CSS overrides Widget.CSS
|
||||
assert node.styles.color == Color(255, 0, 0)
|
||||
# The background colour defined in the Widget still applies, since user CSS doesn't override it
|
||||
assert node.styles.background == Color(0, 255, 0)
|
||||
# As expected, the tint colour is yellow, since there's no competition between user or widget CSS
|
||||
assert node.styles.tint == Color(255, 255, 0)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"css_value,expectation,expected_color",
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user