1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
|
from __future__ import annotations
from typing import Any
import pytest
from parsel import Selector
from parsel.xpathfuncs import set_xpathfunc
def test_has_class_simple() -> None:
body = """
<p class="foo bar-baz">First</p>
<p class="foo">Second</p>
<p class="bar">Third</p>
<p>Fourth</p>
"""
sel = Selector(text=body)
assert [x.extract() for x in sel.xpath('//p[has-class("foo")]/text()')] == [
"First",
"Second",
]
assert [x.extract() for x in sel.xpath('//p[has-class("bar")]/text()')] == ["Third"]
assert [x.extract() for x in sel.xpath('//p[has-class("foo","bar")]/text()')] == []
assert [
x.extract() for x in sel.xpath('//p[has-class("foo","bar-baz")]/text()')
] == ["First"]
def test_has_class_error_no_args() -> None:
body = """
<p CLASS="foo">First</p>
"""
sel = Selector(text=body)
with pytest.raises(ValueError, match="has-class must have at least 1 argument"):
sel.xpath("has-class()")
def test_has_class_error_invalid_arg_type() -> None:
body = """
<p CLASS="foo">First</p>
"""
sel = Selector(text=body)
with pytest.raises(ValueError, match="has-class arguments must be strings"):
sel.xpath("has-class(.)")
def test_has_class_error_invalid_unicode() -> None:
body = """
<p CLASS="foo">First</p>
"""
sel = Selector(text=body)
with pytest.raises(ValueError, match="All strings must be XML compatible"):
sel.xpath('has-class("héllö")'.encode()) # type: ignore[arg-type]
def test_has_class_unicode() -> None:
body = """
<p CLASS="fóó">First</p>
"""
sel = Selector(text=body)
assert [x.extract() for x in sel.xpath('//p[has-class("fóó")]/text()')] == ["First"]
def test_has_class_uppercase() -> None:
body = """
<p CLASS="foo">First</p>
"""
sel = Selector(text=body)
assert [x.extract() for x in sel.xpath('//p[has-class("foo")]/text()')] == ["First"]
def test_has_class_newline() -> None:
body = """
<p CLASS="foo
bar">First</p>
"""
sel = Selector(text=body)
assert [x.extract() for x in sel.xpath('//p[has-class("foo")]/text()')] == ["First"]
def test_has_class_tab() -> None:
body = """
<p CLASS="foo\tbar">First</p>
"""
sel = Selector(text=body)
assert [x.extract() for x in sel.xpath('//p[has-class("foo")]/text()')] == ["First"]
def test_set_xpathfunc() -> None:
def myfunc(ctx: Any) -> None:
myfunc.call_count += 1 # type: ignore[attr-defined]
myfunc.call_count = 0 # type: ignore[attr-defined]
body = """
<p CLASS="foo">First</p>
"""
sel = Selector(text=body)
with pytest.raises(ValueError, match=r"Unregistered function(: myfunc)? in myfunc"):
sel.xpath("myfunc()")
set_xpathfunc("myfunc", myfunc)
sel.xpath("myfunc()")
assert myfunc.call_count == 1 # type: ignore[attr-defined]
set_xpathfunc("myfunc", None)
with pytest.raises(ValueError, match=r"Unregistered function(: myfunc)? in myfunc"):
sel.xpath("myfunc()")
|