import XCTest @testable import RSSuper final class FeedParserTests: XCTestCase { func testParsesRSS20Feed() throws { let parser = FeedParser() let result = try parser.parse( data: Data(rssSample.utf8), sourceURL: "https://example.com/rss.xml" ) XCTAssertEqual(result.feedType, .rss) XCTAssertEqual(result.feed.title, "Example Podcast") XCTAssertEqual(result.feed.subtitle, "Weekly iOS and Swift updates") XCTAssertEqual(result.feed.items.count, 2) XCTAssertEqual(result.feed.ttl, 60) let firstItem = try XCTUnwrap(result.feed.items.first) XCTAssertEqual(firstItem.title, "Episode 1") XCTAssertEqual(firstItem.author, "Host Name") XCTAssertEqual(firstItem.guid, "episode-1") XCTAssertEqual(firstItem.categories, ["Swift"]) XCTAssertEqual(firstItem.enclosure?.url, "https://example.com/audio/ep1.mp3") XCTAssertEqual(firstItem.enclosure?.type, "audio/mpeg") XCTAssertEqual(firstItem.enclosure?.length, 12345) XCTAssertEqual(firstItem.content, "

Full content for episode 1.

") } func testParsesAtom10Feed() throws { let parser = FeedParser() let result = try parser.parse( data: Data(atomSample.utf8), sourceURL: "https://example.com/atom.xml" ) XCTAssertEqual(result.feedType, .atom) XCTAssertEqual(result.feed.title, "Example Atom Feed") XCTAssertEqual(result.feed.subtitle, "Recent engineering posts") XCTAssertEqual(result.feed.link, "https://example.com") XCTAssertEqual(result.feed.items.count, 2) let firstItem = try XCTUnwrap(result.feed.items.first) XCTAssertEqual(firstItem.guid, "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a") XCTAssertEqual(firstItem.link, "https://example.com/posts/1") XCTAssertEqual(firstItem.author, "Jane Author") XCTAssertEqual(firstItem.enclosure?.url, "https://example.com/audio/post1.mp3") XCTAssertEqual(firstItem.enclosure?.type, "audio/mpeg") XCTAssertEqual(firstItem.enclosure?.length, 2048) } func testHandlesITunesNamespace() throws { let parser = FeedParser() let result = try parser.parse( data: Data(rssWithITunesSample.utf8), sourceURL: "https://example.com/itunes.xml" ) XCTAssertEqual(result.feed.subtitle, "Podcast subtitle") XCTAssertEqual(result.feed.description, "Feed-level summary") let item = try XCTUnwrap(result.feed.items.first) XCTAssertEqual(item.author, "Podcast Author") XCTAssertEqual(item.description, "Item-level summary") } func testThrowsForMalformedXML() { let parser = FeedParser() XCTAssertThrowsError( try parser.parse( data: Data("Broken".utf8), sourceURL: "https://example.com/broken.xml" ) ) { error in XCTAssertEqual(error as? FeedParsingError, .malformedXML) } } func testParsesRealWorldStyleFeeds() throws { let parser = FeedParser() let rssResult = try parser.parse( data: Data(realWorldRSSSample.utf8), sourceURL: "https://feeds.example.com/news.xml" ) XCTAssertEqual(rssResult.feedType, .rss) XCTAssertGreaterThan(rssResult.feed.items.count, 0) let atomResult = try parser.parse( data: Data(realWorldAtomSample.utf8), sourceURL: "https://feeds.example.com/engineering.xml" ) XCTAssertEqual(atomResult.feedType, .atom) XCTAssertGreaterThan(atomResult.feed.items.count, 0) } } private let rssSample = """ <?xml version="1.0" encoding="UTF-8"?> <rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"> <channel> <title>Example Podcast https://example.com A sample RSS feed en-us Mon, 30 Mar 2026 10:00:00 +0000 RSSuper Test Suite 60 Weekly iOS and Swift updates Episode 1 https://example.com/episodes/1 episode-1 Mon, 30 Mar 2026 09:00:00 +0000 Swift Episode 1 summary Full content for episode 1.

]]>
Host Name
Episode 2 https://example.com/episodes/2 episode-2 Mon, 30 Mar 2026 08:00:00 +0000 Episode 2 summary
""" private let atomSample = """ Example Atom Feed Recent engineering posts 2026-03-30T10:00:00Z Atom Test Generator Post One urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a 2026-03-30T09:00:00Z 2026-03-30T08:59:00Z First post summary <p>First post full content</p> Jane Author Post Two urn:uuid:7a9b2f0d-65b2-44a7-a2ad-d3c3ff7dd003 2026-03-30T08:00:00Z Second post summary """ private let rssWithITunesSample = """ iTunes Feed Podcast subtitle Feed-level summary Episode Podcast Author Item-level summary """ private let realWorldRSSSample = """ Daily Tech News https://news.example.com Latest updates from the tech world Mon, 30 Mar 2026 12:00:00 +0000 Apple ships new SDK tools https://news.example.com/apple-sdk-tools news-1 Mon, 30 Mar 2026 11:00:00 +0000 Tooling improvements for mobile developers. """ private let realWorldAtomSample = """ Engineering Blog 2026-03-30T12:00:00Z Improving app startup performance tag:engineering.example.com,2026:post-1 2026-03-29T16:00:00Z 2026-03-29T15:00:00Z How we reduced cold-start by 25%. Detailed analysis of startup bottlenecks and fixes. Engineering Team """