def test_selectors(): css = """ foo, bar {} """ selector, declarations = next(parse_style_sheet(css)) assert len(selector) == 2
def test_select_name(): css = "classitem {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector(Node("classitem")) assert not selector(Node("packageitem"))
def test_attribute_equal(): css = "classitem[subject=foo] {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector(Node("classitem", attributes={"subject": "foo"})) assert not selector(Node("classitem", attributes={"subject": "bar"}))
def test_empty_pseudo_selector_with_name(): css = "node:empty {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector(Node("node")) assert not selector(Node("node", children=[Node("child")])) assert specificity == (0, 1, 1)
def test_attribute_contains(): css = "classitem[subject*=foo] {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector(Node("classitem", attributes={"subject": "foo"})) assert selector(Node("classitem", attributes={"subject": "be foo-ish"})) assert not selector(Node("classitem", attributes={"subject": "fobic"}))
def test_attribute_ends_with(): css = "classitem[subject$=foo] {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector(Node("classitem", attributes={"subject": "foo"})) assert selector(Node("classitem", attributes={"subject": "manicfoo"})) assert not selector(Node("classitem", attributes={"subject": "fooless"}))
def test_attribute_starts_with_dash(): css = "classitem[subject|=foo] {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector(Node("classitem", attributes={"subject": "foo"})) assert selector(Node("classitem", attributes={"subject": "foo-mania"})) assert not selector(Node("classitem", attributes={"subject": "foomania"}))
def test_has_pseudo_selector_with_combinator_is_not_supported(): # NB. This is according to the CSS spec, but our parser is not # able to deal with this. This test is just here to illustrate. css = "classitem:has(> nested) {}" error, payload = next(parse_style_sheet(css)) assert error == "error"
def test_attributes(): css = "classitem[subject] {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector(Node("classitem", attributes={"subject": "val"})) assert not selector(Node("classitem")) assert not selector(Node("classitem", attributes={"subject": None}))
def test_invalid_css_syntax_in_declarations(): css = """ foo { foo : bar : baz } """ rules = list(parse_style_sheet(css)) _, decls = rules[0] assert len(rules) == 1 assert len(decls) == 0
def test_hovered_pseudo_selector(state): css = f":{state} {{}}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector(Node("node", state=(state, ))) assert selector(Node("node", state=(state, "other-state"))) assert not selector(Node("node", state=()))
def test_invalid_css_syntax(): css = """ foo/bar ; """ rules = list(parse_style_sheet(css)) selector, _ = rules[0] assert len(rules) == 1 assert selector == "error"
def test_multiple_rules(): css = """ * {} item {} """ rules = list(parse_style_sheet(css)) assert len(rules) == 2
def test_invalid_selector(): css = """ foo/bar {} good {} """ rules = list(parse_style_sheet(css)) selector, _ = rules[0] assert len(rules) == 2 assert selector == "error"
def test_has_and_is_selector(): css = "node:has(:is(:hover)) {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector( Node( "node", children=[Node("foo", children=[Node("bar", state=("hover", ))])], ))
def test_not_pseudo_selector(): css = "classitem:not(:hover) {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector(Node("classitem")) assert selector(Node("classitem", state=("active"))) assert specificity == (0, 1, 1) assert not selector(Node("classitem", state=("hover", ))) assert not selector(Node("classitem", state=("hover", "active")))
def test_has_pseudo_selector(): css = "classitem:has(nested) {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector(Node("classitem", children=[Node("nested")])) assert specificity == (0, 0, 2) assert selector( Node("classitem", children=[Node("middle", children=[Node("nested")])])) assert not selector(Node("classitem"))
def test_select_parent_combinator(): css = "classitem > nested {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector(Node("nested", parent=Node("classitem"))) assert not selector( Node( "nested", parent=Node("other", parent=Node("classitem")), )) assert not selector(Node("nested")) assert not selector(Node("classitem"))
def test_attributes_with_dots(): css = "classitem[subject.members] {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector(Node("classitem", attributes={"subject.members": "foo"}))
def first_decl_block(css): _, value = next(parse_style_sheet(css)) return value
def test_empty_css(): css = "" rules = list(parse_style_sheet(css)) assert rules == []
def test_attributes_are_lower_case(): css = "ClassItem[MixedCase] {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector(Node("classitem", attributes={"mixedcase": "foo"}))
def test_select_all(): css = "* {}" (selector, specificity), payload = next(parse_style_sheet(css)) assert selector("any")