feat: add declarative site parser engine
This commit is contained in:
@@ -61,7 +61,7 @@ class EmptyBodySession(FakeSession):
|
||||
class SourceAdapterTests(unittest.IsolatedAsyncioTestCase):
|
||||
async def test_worker_response_is_normalized(self) -> None:
|
||||
client = SiteParserClient(FakeSession(), "http://worker", "token", "captcha", 30)
|
||||
items, state = await client.fetch({
|
||||
items, state, warning = await client.fetch({
|
||||
"url": "https://example.test/rss.xml",
|
||||
"settings_json": '{"format":"rss","access":"auto"}',
|
||||
"runtime_state_json": '{}',
|
||||
@@ -71,10 +71,11 @@ class SourceAdapterTests(unittest.IsolatedAsyncioTestCase):
|
||||
self.assertEqual(items[0].media[0].url, "https://example.test/1.jpg")
|
||||
self.assertEqual(state["browser_state"]["cookies"][0]["name"], "cf_clearance")
|
||||
self.assertEqual(state["browser_user_agent"], "Test Browser")
|
||||
self.assertIsNone(warning)
|
||||
|
||||
async def test_followed_page_does_not_repeat_title(self) -> None:
|
||||
client = SiteParserClient(FollowedPageSession(), "http://worker", "token", "captcha", 30)
|
||||
items, _ = await client.fetch({
|
||||
items, _, _ = await client.fetch({
|
||||
"url": "https://example.test/rss.xml",
|
||||
"settings_json": '{"format":"rss","follow_links":true,"content_selector":"article.full"}',
|
||||
"runtime_state_json": "{}",
|
||||
@@ -84,7 +85,7 @@ class SourceAdapterTests(unittest.IsolatedAsyncioTestCase):
|
||||
|
||||
async def test_title_is_not_counted_as_site_body(self) -> None:
|
||||
client = SiteParserClient(EmptyBodySession(), "http://worker", "token", "captcha", 30)
|
||||
items, _ = await client.fetch({
|
||||
items, _, _ = await client.fetch({
|
||||
"url": "https://example.test/rss.xml",
|
||||
"settings_json": '{"format":"rss"}',
|
||||
"runtime_state_json": "{}",
|
||||
@@ -104,6 +105,27 @@ class SourceAdapterTests(unittest.IsolatedAsyncioTestCase):
|
||||
with self.assertRaisesRegex(ValueError, "min_text_length"):
|
||||
validate_source_config("site", {"format": "rss", "min_text_length": "many"})
|
||||
|
||||
def test_versioned_site_config_is_validated(self) -> None:
|
||||
validate_source_config("site", {
|
||||
"version": 1,
|
||||
"discovery": {"type": "rss", "limit": 10},
|
||||
"detail": {
|
||||
"enabled": True,
|
||||
"root_selector": "article",
|
||||
"fields": {"text": {"selector": ".body", "extract": "text"}},
|
||||
},
|
||||
"access": {"type": "cloudflare"},
|
||||
"retry": {"attempts": 3, "delay_seconds": 5, "timeout_seconds": 90},
|
||||
"min_text_length": 50,
|
||||
})
|
||||
|
||||
def test_html_discovery_requires_item_selector(self) -> None:
|
||||
with self.assertRaisesRegex(ValueError, "item_selector"):
|
||||
validate_source_config("site", {
|
||||
"version": 1,
|
||||
"discovery": {"type": "html"},
|
||||
})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user