Http::response('Mock HTML content', 200) ]); } public function test_get_articles_from_feed_returns_collection(): void { $feed = Feed::factory()->create([ 'type' => 'rss', 'url' => 'https://example.com/feed.rss' ]); $result = ArticleFetcher::getArticlesFromFeed($feed); $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); } public function test_get_articles_from_rss_feed_returns_empty_collection(): void { $feed = Feed::factory()->create([ 'type' => 'rss', 'url' => 'https://example.com/feed.rss' ]); $result = ArticleFetcher::getArticlesFromFeed($feed); // RSS parsing is not implemented yet, should return empty collection $this->assertEmpty($result); } public function test_get_articles_from_website_feed_handles_no_parser(): void { $feed = Feed::factory()->create([ 'type' => 'website', 'url' => 'https://unsupported-site.com/' ]); $result = ArticleFetcher::getArticlesFromFeed($feed); // Should return empty collection when no parser is available $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); $this->assertEmpty($result); } public function test_get_articles_from_unsupported_feed_type(): void { $feed = Feed::factory()->create([ 'type' => 'website', // Use valid type but with unsupported URL 'url' => 'https://unsupported-feed-type.com/feed' ]); $result = ArticleFetcher::getArticlesFromFeed($feed); $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); $this->assertEmpty($result); } public function test_fetch_article_data_returns_array(): void { $article = Article::factory()->create([ 'url' => 'https://example.com/article' ]); $result = ArticleFetcher::fetchArticleData($article); $this->assertIsArray($result); // Will be empty array due to unsupported URL in test $this->assertEmpty($result); } public function test_fetch_article_data_handles_invalid_url(): void { $article = Article::factory()->create([ 'url' => 'invalid-url' ]); $result = ArticleFetcher::fetchArticleData($article); $this->assertIsArray($result); $this->assertEmpty($result); } public function test_get_articles_from_feed_with_null_feed_type(): void { // Create feed with valid type first, then manually set to invalid value $feed = Feed::factory()->create([ 'type' => 'website', 'url' => 'https://example.com/feed' ]); // Use reflection to set an invalid type that bypasses enum validation $reflection = new \ReflectionClass($feed); $property = $reflection->getProperty('attributes'); $property->setAccessible(true); $attributes = $property->getValue($feed); $attributes['type'] = 'invalid_type'; $property->setValue($feed, $attributes); $result = ArticleFetcher::getArticlesFromFeed($feed); $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); $this->assertEmpty($result); } public function test_get_articles_from_website_feed_with_supported_parser(): void { // Mock successful HTTP response with sample HTML Http::fake([ 'https://www.vrt.be/vrtnws/nl/' => Http::response('Sample VRT content', 200) ]); $feed = Feed::factory()->create([ 'type' => 'website', 'url' => 'https://www.vrt.be/vrtnws/nl/' ]); // Test actual behavior - VRT parser should be available $result = ArticleFetcher::getArticlesFromFeed($feed); $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); // VRT parser will process the mocked HTML response } public function test_get_articles_from_website_feed_handles_invalid_url(): void { // HTTP mock already set in setUp() to return mock HTML for all requests $feed = Feed::factory()->create([ 'type' => 'website', 'url' => 'https://invalid-domain-that-does-not-exist-12345.com/' ]); $result = ArticleFetcher::getArticlesFromFeed($feed); $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); $this->assertEmpty($result); } public function test_fetch_article_data_with_supported_parser(): void { // Mock successful HTTP response with sample HTML Http::fake([ 'https://www.vrt.be/vrtnws/nl/test-article' => Http::response('Sample article content', 200) ]); $article = Article::factory()->create([ 'url' => 'https://www.vrt.be/vrtnws/nl/test-article' ]); // Test actual behavior - VRT parser should be available $result = ArticleFetcher::fetchArticleData($article); $this->assertIsArray($result); // VRT parser will process the mocked HTML response } public function test_fetch_article_data_handles_unsupported_domain(): void { $article = Article::factory()->create([ 'url' => 'https://unsupported-domain.com/article' ]); $result = ArticleFetcher::fetchArticleData($article); $this->assertIsArray($result); $this->assertEmpty($result); } public function test_save_article_creates_new_article_when_not_exists(): void { $feed = Feed::factory()->create(); $url = 'https://example.com/unique-article'; // Ensure article doesn't exist $this->assertDatabaseMissing('articles', ['url' => $url]); // Use reflection to access private method for testing $reflection = new \ReflectionClass(ArticleFetcher::class); $saveArticleMethod = $reflection->getMethod('saveArticle'); $saveArticleMethod->setAccessible(true); $article = $saveArticleMethod->invoke(null, $url, $feed->id); $this->assertInstanceOf(Article::class, $article); $this->assertEquals($url, $article->url); $this->assertEquals($feed->id, $article->feed_id); $this->assertDatabaseHas('articles', ['url' => $url, 'feed_id' => $feed->id]); } public function test_save_article_returns_existing_article_when_exists(): void { $feed = Feed::factory()->create(); $existingArticle = Article::factory()->create([ 'url' => 'https://example.com/existing-article', 'feed_id' => $feed->id ]); // Use reflection to access private method for testing $reflection = new \ReflectionClass(ArticleFetcher::class); $saveArticleMethod = $reflection->getMethod('saveArticle'); $saveArticleMethod->setAccessible(true); $article = $saveArticleMethod->invoke(null, $existingArticle->url, $feed->id); $this->assertEquals($existingArticle->id, $article->id); $this->assertEquals($existingArticle->url, $article->url); // Ensure no duplicate was created $this->assertEquals(1, Article::where('url', $existingArticle->url)->count()); } public function test_save_article_without_feed_id(): void { $url = 'https://example.com/article-without-feed'; // Use reflection to access private method for testing $reflection = new \ReflectionClass(ArticleFetcher::class); $saveArticleMethod = $reflection->getMethod('saveArticle'); $saveArticleMethod->setAccessible(true); $article = $saveArticleMethod->invoke(null, $url, null); $this->assertInstanceOf(Article::class, $article); $this->assertEquals($url, $article->url); $this->assertNull($article->feed_id); $this->assertDatabaseHas('articles', ['url' => $url, 'feed_id' => null]); } protected function tearDown(): void { Mockery::close(); parent::tearDown(); } }