Files
yusufkaraaslan--skill_seekers/tests/test_phase2_golden_rss.py
T
wehub-resource-sync 2cab53bc94
Test Vector Database Adaptors / Test MCP Vector DB Tools (push) Has been cancelled
Tests / Code Quality (Ruff & Mypy) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (macos-latest, 3.11) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (macos-latest, 3.12) (push) Has been cancelled
Tests / Tests (push) Has been cancelled
Docker Publish / Build and Push Docker Images (map[description:Skill Seekers CLI - Convert documentation to AI skills dockerfile:Dockerfile name:skill-seekers]) (push) Has been cancelled
Docker Publish / Build and Push Docker Images (map[description:Skill Seekers MCP Server - 25 tools for AI assistants dockerfile:Dockerfile.mcp name:skill-seekers-mcp]) (push) Has been cancelled
Docker Publish / Test Docker Images (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (ubuntu-latest, 3.10) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (ubuntu-latest, 3.11) (push) Has been cancelled
Tests / Fast Unit Tests (parallel) (ubuntu-latest, 3.12) (push) Has been cancelled
Tests / Serial / Integration / E2E Tests (push) Has been cancelled
Tests / MCP Server Tests (push) Has been cancelled
Test Vector Database Adaptors / Test chroma Adaptor (push) Has been cancelled
Test Vector Database Adaptors / Test faiss Adaptor (push) Has been cancelled
Test Vector Database Adaptors / Test qdrant Adaptor (push) Has been cancelled
Test Vector Database Adaptors / Test weaviate Adaptor (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:46:28 +08:00

160 lines
5.7 KiB
Python

"""Golden-output tests for the RSS scraper (Phase 2 port).
The golden trees under tests/golden/phase2/rss*/ were captured from the
PRE-DocumentSkillBuilder code; these tests prove the port is byte-identical.
RSS extracted_data is article-shaped (not section-shaped), so the fixtures
exercise the rss-specific build paths: tag categorization with normalized-key
dedup, the "uncategorized" bucket, the empty-sanitization "unnamed" fallback,
the empty-feed "all_articles" fallback, summary truncation (>200 chars),
inline content vs summary, full_text, feed description truncation (>300
chars), >50 tags overflow, author counts, date range, and followed_links
Yes/No statistics.
"""
import copy
from tests.phase2_golden_utils import assert_matches_golden, build_snapshot
LONG_SUMMARY = (
"This is a deliberately long summary that keeps going well past the two "
"hundred character truncation threshold used by the recent-articles block "
"of SKILL.md so that the shortened form with a trailing ellipsis is "
"exercised by the golden tree comparison here."
)
LONG_FEED_DESCRIPTION = (
"A feed description that is intentionally longer than the three hundred "
"character limit applied in the Feed Information block of SKILL.md. " * 4
)
ARTICLES = [
{
# Overlapping normalized category keys ("Dev Ops" and "dev-ops" both
# sanitize to "dev_ops") exercise the duplicate-article guard.
"id": "urn:article:1",
"title": "Continuous Delivery in Practice",
"link": "https://example.com/posts/cd-in-practice",
"summary": LONG_SUMMARY,
"content": "Inline feed content that differs from the summary text.",
"published": "Mon, 01 Jan 2024 10:00:00 GMT",
"published_iso": "2024-01-01T10:00:00",
"author": "Jane Doe",
"categories": ["Dev Ops", "dev-ops"],
},
{
# content == summary exercises the skipped "### Content" branch.
"id": "urn:article:2",
"title": "Typing Tips for Python",
"link": "https://example.com/posts/typing-tips",
"summary": "Short notes on gradual typing.",
"content": "Short notes on gradual typing.",
"published": "Fri, 15 Mar 2024 08:30:00 GMT",
"published_iso": "2024-03-15T08:30:00",
"author": "John Roe",
"categories": ["Python"],
},
{
# No categories -> "uncategorized" bucket; no link/published/author
# metadata lines; has scraped full_text.
"id": "urn:article:3",
"title": "An Uncategorized Note",
"link": "",
"summary": "A note without tags.",
"content": "",
"published": "",
"published_iso": "",
"author": "Jane Doe",
"categories": [],
"full_text": "# Scraped Heading\n\nFull article text fetched from the page.",
},
{
# Category of only symbols sanitizes to "" -> "unnamed" filename.
"id": "urn:article:4",
"title": "Symbols Only",
"link": "https://example.com/posts/symbols",
"summary": "",
"content": "",
"published": "Sat, 10 Feb 2024 12:00:00 GMT",
"published_iso": "2024-02-10T12:00:00",
"author": "",
"categories": ["★★★"],
},
]
# 55 tags exercise the ">50 ... and N more" overflow in the Tags section.
ALL_CATEGORIES = sorted(
{"Dev Ops", "dev-ops", "Python", "★★★"} | {f"tag{i:02d}" for i in range(51)}
)
def _extracted_data() -> dict:
return {
"source": "https://example.com/feed.xml",
"feed_type": "RSS 2.0",
"feed_metadata": {
"title": "Example Engineering Blog",
"description": LONG_FEED_DESCRIPTION,
"link": "https://example.com",
"language": "en-us",
"author": "Example Team",
"published": "Mon, 01 Jan 2024 10:00:00 GMT",
"generator": "ExampleCMS 2.0",
"image_url": "https://example.com/logo.png",
"rights": "© Example Inc.",
},
"total_articles": len(ARTICLES),
"followed_links": True,
"all_categories": ALL_CATEGORIES,
"articles": copy.deepcopy(ARTICLES),
}
def test_rss_build_matches_golden(tmp_path):
from skill_seekers.cli.rss_scraper import RssToSkillConverter
converter = RssToSkillConverter(
{
"name": "golden_rss",
"description": "Use when testing the rss golden build",
"feed_url": "https://example.com/feed.xml",
"output_dir": str(tmp_path / "skill"),
}
)
converter.extracted_data = _extracted_data()
assert_matches_golden(build_snapshot(converter), "rss")
def test_rss_empty_feed_matches_golden(tmp_path):
"""No articles -> the all_articles fallback category and 'No' statistics."""
from skill_seekers.cli.rss_scraper import RssToSkillConverter
converter = RssToSkillConverter(
{
"name": "golden_rss_empty",
"description": "Use when testing the empty rss golden build",
"feed_url": "https://example.com/atom.xml",
"output_dir": str(tmp_path / "skill"),
}
)
converter.extracted_data = {
"source": "https://example.com/atom.xml",
"feed_type": "Atom",
"feed_metadata": {
"title": "Quiet Feed",
"description": "A feed with no entries yet.",
"link": "https://example.com/quiet",
"language": "",
"author": "",
"published": "",
"generator": "",
"image_url": "",
"rights": "",
},
"total_articles": 0,
"followed_links": False,
"all_categories": [],
"articles": [],
}
assert_matches_golden(build_snapshot(converter), "rss_empty")