sampleRss = <<<'XML' The Guardian - International https://www.theguardian.com/international First Article Title https://www.theguardian.com/world/2026/mar/08/first-article First article description Sun, 08 Mar 2026 12:00:00 GMT Second Article Title https://www.theguardian.com/world/2026/mar/08/second-article Second article description Sun, 08 Mar 2026 11:00:00 GMT XML; } public function test_get_articles_from_rss_feed_returns_collection(): void { Http::fake(['*' => Http::response($this->sampleRss, 200)]); $feed = Feed::factory()->create([ 'type' => 'rss', 'provider' => 'guardian', 'url' => 'https://www.theguardian.com/international/rss', ]); $fetcher = $this->createArticleFetcher(); $result = $fetcher->getArticlesFromFeed($feed); $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); } public function test_get_articles_from_rss_feed_creates_articles(): void { Http::fake(['*' => Http::response($this->sampleRss, 200)]); $feed = Feed::factory()->create([ 'type' => 'rss', 'provider' => 'guardian', 'url' => 'https://www.theguardian.com/international/rss', ]); $fetcher = $this->createArticleFetcher(); $result = $fetcher->getArticlesFromFeed($feed); $this->assertCount(2, $result); $this->assertDatabaseHas('articles', [ 'url' => 'https://www.theguardian.com/world/2026/mar/08/first-article', 'feed_id' => $feed->id, ]); $this->assertDatabaseHas('articles', [ 'url' => 'https://www.theguardian.com/world/2026/mar/08/second-article', 'feed_id' => $feed->id, ]); } public function test_get_articles_from_rss_feed_does_not_duplicate_existing(): void { Http::fake(['*' => Http::response($this->sampleRss, 200)]); $feed = Feed::factory()->create([ 'type' => 'rss', 'provider' => 'guardian', 'url' => 'https://www.theguardian.com/international/rss', ]); Article::factory()->create([ 'url' => 'https://www.theguardian.com/world/2026/mar/08/first-article', 'feed_id' => $feed->id, ]); $fetcher = $this->createArticleFetcher(); $result = $fetcher->getArticlesFromFeed($feed); $this->assertCount(2, $result); $this->assertEquals(1, Article::where('url', 'https://www.theguardian.com/world/2026/mar/08/first-article')->count()); } public function test_get_articles_from_rss_feed_handles_invalid_xml(): void { Http::fake(['*' => Http::response('this is not xml', 200)]); $feed = Feed::factory()->create([ 'type' => 'rss', 'provider' => 'guardian', 'url' => 'https://www.theguardian.com/international/rss', ]); $fetcher = $this->createArticleFetcher(); $result = $fetcher->getArticlesFromFeed($feed); $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); $this->assertEmpty($result); } public function test_get_articles_from_rss_feed_handles_empty_channel(): void { Http::fake([ '*' => Http::response('Empty', 200), ]); $feed = Feed::factory()->create([ 'type' => 'rss', 'provider' => 'guardian', 'url' => 'https://www.theguardian.com/international/rss', ]); $fetcher = $this->createArticleFetcher(); $result = $fetcher->getArticlesFromFeed($feed); $this->assertEmpty($result); } public function test_get_articles_from_rss_feed_handles_http_failure(): void { Http::fake(['*' => Http::response('Server Error', 500)]); $feed = Feed::factory()->create([ 'type' => 'rss', 'provider' => 'guardian', 'url' => 'https://www.theguardian.com/international/rss', ]); $fetcher = $this->createArticleFetcher(); $result = $fetcher->getArticlesFromFeed($feed); $this->assertEmpty($result); } public function test_get_articles_from_belga_rss_feed_creates_articles(): void { $belgaRss = <<<'XML' Belga News Agency https://www.belganewsagency.eu Belgium announces new climate plan https://www.belganewsagency.eu/belgium-announces-new-climate-plan Belgium has unveiled a comprehensive climate strategy. Sun, 08 Mar 2026 10:00:00 GMT EU summit concludes in Brussels https://www.belganewsagency.eu/eu-summit-concludes-in-brussels European leaders reached agreement on key issues. Sun, 08 Mar 2026 09:00:00 GMT XML; Http::fake(['*' => Http::response($belgaRss, 200)]); $feed = Feed::factory()->create([ 'type' => 'rss', 'provider' => 'belga', 'url' => 'https://www.belganewsagency.eu/feed', ]); $fetcher = $this->createArticleFetcher(); $result = $fetcher->getArticlesFromFeed($feed); $this->assertCount(2, $result); $this->assertDatabaseHas('articles', [ 'url' => 'https://www.belganewsagency.eu/belgium-announces-new-climate-plan', 'feed_id' => $feed->id, ]); $this->assertDatabaseHas('articles', [ 'url' => 'https://www.belganewsagency.eu/eu-summit-concludes-in-brussels', 'feed_id' => $feed->id, ]); } protected function tearDown(): void { Mockery::close(); parent::tearDown(); } }