Files
devplacepy/tests/unit/services/community/discoverer.py
T
retoor 6f80a820da
DevPlace CI / test (push) Failing after 3m13s
Zo doen wijdat in oost
2026-10-16 07:20:44 +02:00

134 lines
5.9 KiB
Python

# retoor <retoor@molodetz.nl>
from tests.conftest import run_async
from devplacepy.services.community.discoverer import CommunityDiscoverer
from devplacepy.services.community.spec import STATUS_FAILED, STATUS_LOGIN, STATUS_READY
from tests.unit.services.community.fakes import (
FakeFetcher,
club_community,
html_community,
json_community,
rss_community,
spa_community,
)
def discover(routes: dict, query: str, credentials: dict | None = None):
fetcher = FakeFetcher(routes)
return run_async(CommunityDiscoverer(fetcher, credentials=credentials).discover(query)), fetcher
def test_json_api_community_is_learned():
result, _ = discover(json_community(), "https://forum.test/api/posts")
assert result.status == STATUS_READY, result.error
feed = result.schema["feeds"][0]
assert feed["type"] == "json_api"
assert feed["list_path"] == "$.items"
assert feed["post"]["fields"]["id"] == ["$.id"]
assert feed["post"]["fields"]["content"][0] == "$.content_html"
assert feed["post"]["fields"]["created_at"] == ["$.created_at"]
assert feed["author"]["fields"]["username"] == ["$.author.username"]
assert feed["author"]["fields"]["id"] == ["$.author.id"]
assert feed["pagination"] == {"style": "page", "param": "page", "start": 1}
assert feed["comments"]["mode"] == "inline"
assert feed["comments"]["fields"]["content"] == ["$.body"]
assert feed["comments"]["author"]["fields"]["username"] == ["$.user.username"]
records = result.sample["records"]
assert len(records["posts"]) == 8
assert len(records["comments"]) == 6
assert {user["username"] for user in records["users"]} >= {"writer0", "writer1", "replier0"}
def test_rss_community_is_learned_from_advertised_feed():
result, _ = discover(rss_community(), "https://blog.test/")
assert result.status == STATUS_READY, result.error
feed = result.schema["feeds"][0]
assert feed["type"] == "rss"
assert feed["post"]["fields"]["created_at"] == ["$.pubDate"]
assert result.sample["records"]["users"][0]["username"] == "Alice"
assert result.sample["records"]["posts"][0]["content"].startswith("Full body of entry")
assert feed["comments"]["mode"] == "page"
assert feed["comments"]["item_selector"] == "div.comment"
assert feed["post"]["detail"]["content"] == ["article"]
comments = result.sample["records"]["comments"]
assert len(comments) == 9
assert sum(1 for comment in comments if comment.get("parent_uid")) == 3
def test_html_list_community_is_learned():
result, _ = discover(html_community(), "https://board.test/")
assert result.status == STATUS_READY, result.error
feed = result.schema["feeds"][0]
assert feed["type"] == "html_list"
assert feed["item_selector"] == "article.post"
assert len(result.sample["records"]["posts"]) == 6
assert result.sample["records"]["posts"][0]["title"].startswith("Thread 1")
assert feed["comments"]["mode"] == "page"
assert feed["comments"]["fields"]["id"] == ["::attr(id)"]
assert feed["comments"]["author"]["fields"]["username"] == [".author"]
assert len(result.sample["records"]["comments"]) == 9
def test_unreachable_community_fails_with_reason():
result, _ = discover({}, "https://nothing.test/")
assert result.status == STATUS_FAILED
assert result.error
def test_javascript_only_site_is_rendered():
result, _ = discover(spa_community(), "https://spa.test/")
assert result.status == STATUS_READY, result.error
feed = result.schema["feeds"][0]
assert feed["render"] is True
assert len(result.sample["records"]["posts"]) == 6
def test_login_wall_without_credentials_is_flagged_not_failed():
state = {}
result, _ = discover(club_community(state), "https://club.test/")
assert result.status == STATUS_LOGIN
assert result.schema["login"]["mode"] == "form"
assert result.schema["login"]["username_field"] == "user"
assert result.schema["login_required"] is True
def test_login_wall_with_credentials_is_learned_behind_the_wall():
state = {}
result, fetcher = discover(club_community(state), "https://club.test/", {"username": "bob", "password": "pw"})
assert result.status == STATUS_READY, result.error
assert result.schema["login_required"] is True
assert result.schema["feeds"][0]["type"] == "rss"
assert fetcher.posts[0] == ("https://club.test/login", {"csrf": "t1", "user": "bob", "pass": "pw"})
def test_wrong_credentials_fail_loudly():
result, _ = discover(club_community({}), "https://club.test/", {"username": "bob", "password": "nope"})
assert result.status == STATUS_FAILED
assert "rejected the stored credentials" in result.error
def test_feeds_listing_the_same_posts_are_learned_once_and_comment_feeds_are_skipped():
routes = rss_community()
routes["https://blog.test/"] = (
'<html><head><link rel="alternate" type="application/rss+xml" href="/feed.xml">'
'<link rel="alternate" type="application/rss+xml" href="/comments.xml"></head>'
'<body><a href="/latest">Latest posts</a></body></html>'
)
routes["https://blog.test/comments.xml"] = routes["https://blog.test/feed.xml"]
items = "".join(
f'<article class="post"><h2><a href="/p/{n}">Entry {n} on testing</a></h2><span class="author">Alice</span>'
f"<p>Body of entry {n} with enough text to count as content.</p></article>"
for n in range(1, 7)
)
routes["https://blog.test/latest"] = f"<html><body><main>{items}</main></body></html>"
result, fetcher = discover(routes, "https://blog.test/")
assert result.status == STATUS_READY, result.error
assert [feed["type"] for feed in result.schema["feeds"]] == ["rss"]
assert not any("comments.xml" in request for request in fetcher.requests)
def test_generic_probe_paths_are_skipped_when_a_feed_is_advertised():
_, fetcher = discover(rss_community(), "https://blog.test/")
assert not any(request.endswith("/api/posts") or request.endswith("/rss.xml") for request in fetcher.requests)