61 lines
2.5 KiB
Python
61 lines
2.5 KiB
Python
# retoor <retoor@molodetz.nl>
|
|
|
|
import pytest
|
|
|
|
from devplacepy.services.community import extract
|
|
|
|
|
|
def test_select_walks_keys_indexes_and_wildcards():
|
|
data = {"a": [{"b": 1}, {"b": 2}], "c": {"d": "x"}}
|
|
assert extract.select(data, "$.a[*].b") == [1, 2]
|
|
assert extract.select(data, "$.a[1].b") == [2]
|
|
assert extract.select(data, "$.c.d") == ["x"]
|
|
assert extract.select(data, "$.missing") == []
|
|
|
|
|
|
@pytest.mark.parametrize("path", ["a.b", "$.a[", "$..", "$" + ".x" * 40])
|
|
def test_bad_paths_raise(path):
|
|
with pytest.raises(ValueError):
|
|
extract.parse_path(path)
|
|
|
|
|
|
def test_instants_accept_iso_rfc822_and_epochs():
|
|
assert extract.normalize_instant("2026-01-01T00:00:00Z") == "2026-01-01T00:00:00+00:00"
|
|
assert extract.normalize_instant("Tue, 14 Oct 2026 10:00:00 GMT") == "2026-10-14T10:00:00+00:00"
|
|
assert extract.normalize_instant(1700000000) == extract.normalize_instant(1700000000000)
|
|
assert extract.normalize_instant("garbage") is None
|
|
assert extract.normalize_instant("") is None
|
|
|
|
|
|
def test_atom_feed_is_parsed_with_links_and_authors():
|
|
atom = (
|
|
'<feed xmlns="http://www.w3.org/2005/Atom"><title>T</title><entry><title>E</title>'
|
|
'<link href="http://x/1" rel="alternate"/><author><name>Ann</name></author>'
|
|
"<updated>2026-01-02T00:00:00Z</updated></entry></feed>"
|
|
)
|
|
kind, _, items = extract.parse_feed(atom)
|
|
assert kind == "atom"
|
|
assert extract.text_at(items[0], "$.link.@href") == "http://x/1"
|
|
assert extract.text_at(items[0], "$.author.name") == "Ann"
|
|
|
|
|
|
def test_css_selectors_support_classes_ids_attributes_and_combinators():
|
|
root = extract.parse_html(
|
|
'<div id="m"><ul><li class="a b"><a href="/x" rel="next">One</a></li><li class="a">Two</li></ul></div>'
|
|
)
|
|
assert len(extract.select_nodes(root, "li.a")) == 2
|
|
assert len(extract.select_nodes(root, "li.a.b")) == 1
|
|
assert len(extract.select_nodes(root, "#m > ul > li")) == 2
|
|
assert len(extract.select_nodes(root, "div li")) == 2
|
|
assert extract.html_field(extract.select_nodes(root, "li.b")[0], "a[rel=next]::attr(href)") == "/x"
|
|
|
|
|
|
def test_strip_tags_keeps_paragraph_breaks_and_drops_scripts():
|
|
assert extract.strip_tags("<p>a</p><script>x()</script><p>b<br>c</p>") == "a\n\nb\n\nc"
|
|
assert extract.strip_tags("plain text") == "plain text"
|
|
|
|
|
|
def test_field_text_falls_through_alternates_and_now_token():
|
|
assert extract.field_text({"a": "", "b": "yes"}, ["$.a", "$.b"]) == "yes"
|
|
assert extract.field_text({}, [extract.NOW_TOKEN]).startswith("20")
|