fedi-feed-router/tests/Unit/Services/ArticleFetcherRssTest.php
myrmidex 6784af2ff6
Some checks failed
CI / ci (push) Failing after 4m31s
25 - Fix all PHPStan errors and add mockery extension
2026-03-08 14:18:28 +01:00

164 lines
5.1 KiB
PHP

<?php
namespace Tests\Unit\Services;
use App\Models\Article;
use App\Models\Feed;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Http;
use Mockery;
use Tests\TestCase;
use Tests\Traits\CreatesArticleFetcher;
class ArticleFetcherRssTest extends TestCase
{
use CreatesArticleFetcher, RefreshDatabase;
private string $sampleRss;
protected function setUp(): void
{
parent::setUp();
$this->sampleRss = <<<'XML'
<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title>The Guardian - International</title>
<link>https://www.theguardian.com/international</link>
<item>
<title>First Article Title</title>
<link>https://www.theguardian.com/world/2026/mar/08/first-article</link>
<description>First article description</description>
<pubDate>Sun, 08 Mar 2026 12:00:00 GMT</pubDate>
</item>
<item>
<title>Second Article Title</title>
<link>https://www.theguardian.com/world/2026/mar/08/second-article</link>
<description>Second article description</description>
<pubDate>Sun, 08 Mar 2026 11:00:00 GMT</pubDate>
</item>
</channel>
</rss>
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('<?xml version="1.0"?><rss><channel><title>Empty</title></channel></rss>', 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);
}
protected function tearDown(): void
{
Mockery::close();
parent::tearDown();
}
}