2025-08-02 03:48:06 +02:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
namespace Tests\Unit\Services;
|
|
|
|
|
|
2025-08-15 02:50:42 +02:00
|
|
|
use App\Services\Article\ArticleFetcher;
|
2025-08-02 03:48:06 +02:00
|
|
|
use App\Services\Article\ValidationService;
|
2025-08-15 02:50:42 +02:00
|
|
|
use App\Services\Log\LogSaver;
|
2025-08-02 03:48:06 +02:00
|
|
|
use App\Models\Article;
|
|
|
|
|
use App\Models\Feed;
|
|
|
|
|
use Tests\TestCase;
|
2025-08-15 02:50:42 +02:00
|
|
|
use Tests\Traits\CreatesArticleFetcher;
|
2025-08-02 03:48:06 +02:00
|
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
2025-08-10 15:20:28 +02:00
|
|
|
use Illuminate\Support\Facades\Http;
|
2025-08-15 02:50:42 +02:00
|
|
|
use Mockery;
|
2025-08-02 03:48:06 +02:00
|
|
|
|
|
|
|
|
class ValidationServiceTest extends TestCase
|
|
|
|
|
{
|
2025-08-15 02:50:42 +02:00
|
|
|
use RefreshDatabase, CreatesArticleFetcher;
|
|
|
|
|
|
|
|
|
|
private ValidationService $validationService;
|
|
|
|
|
|
|
|
|
|
protected function setUp(): void
|
|
|
|
|
{
|
|
|
|
|
parent::setUp();
|
|
|
|
|
$articleFetcher = $this->createArticleFetcher();
|
|
|
|
|
$this->validationService = new ValidationService($articleFetcher);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected function tearDown(): void
|
|
|
|
|
{
|
|
|
|
|
Mockery::close();
|
|
|
|
|
parent::tearDown();
|
|
|
|
|
}
|
2025-08-02 03:48:06 +02:00
|
|
|
|
|
|
|
|
public function test_validate_returns_article_with_validation_status(): void
|
|
|
|
|
{
|
2025-08-10 15:20:28 +02:00
|
|
|
// Mock HTTP requests
|
|
|
|
|
Http::fake([
|
|
|
|
|
'https://example.com/article' => Http::response('<html><body>Test content with Belgium news</body></html>', 200)
|
|
|
|
|
]);
|
|
|
|
|
|
2025-08-02 03:48:06 +02:00
|
|
|
$feed = Feed::factory()->create();
|
|
|
|
|
$article = Article::factory()->create([
|
|
|
|
|
'feed_id' => $feed->id,
|
|
|
|
|
'url' => 'https://example.com/article',
|
2025-08-10 21:18:20 +02:00
|
|
|
'approval_status' => 'pending'
|
2025-08-02 03:48:06 +02:00
|
|
|
]);
|
|
|
|
|
|
2025-08-15 02:50:42 +02:00
|
|
|
$result = $this->validationService->validate($article);
|
2025-08-11 18:26:00 +02:00
|
|
|
|
2025-08-02 03:48:06 +02:00
|
|
|
$this->assertInstanceOf(Article::class, $result);
|
2025-08-10 21:18:20 +02:00
|
|
|
$this->assertContains($result->approval_status, ['pending', 'approved', 'rejected']);
|
2025-08-02 03:48:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_validate_marks_article_invalid_when_missing_data(): void
|
|
|
|
|
{
|
2025-08-10 15:20:28 +02:00
|
|
|
// Mock HTTP requests to return HTML without article content
|
|
|
|
|
Http::fake([
|
|
|
|
|
'https://invalid-url-without-parser.com/article' => Http::response('<html><body>Empty</body></html>', 200)
|
|
|
|
|
]);
|
|
|
|
|
|
2025-08-02 03:48:06 +02:00
|
|
|
$feed = Feed::factory()->create();
|
|
|
|
|
$article = Article::factory()->create([
|
|
|
|
|
'feed_id' => $feed->id,
|
|
|
|
|
'url' => 'https://invalid-url-without-parser.com/article',
|
2025-08-10 21:18:20 +02:00
|
|
|
'approval_status' => 'pending'
|
2025-08-02 03:48:06 +02:00
|
|
|
]);
|
|
|
|
|
|
2025-08-15 02:50:42 +02:00
|
|
|
$result = $this->validationService->validate($article);
|
2025-08-11 18:26:00 +02:00
|
|
|
|
2025-08-10 21:18:20 +02:00
|
|
|
$this->assertEquals('rejected', $result->approval_status);
|
2025-08-02 03:48:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_validate_with_supported_article_content(): void
|
|
|
|
|
{
|
2025-08-10 15:20:28 +02:00
|
|
|
// Mock HTTP requests
|
|
|
|
|
Http::fake([
|
|
|
|
|
'https://example.com/article' => Http::response('<html><body>Article content</body></html>', 200)
|
|
|
|
|
]);
|
|
|
|
|
|
2025-08-02 03:48:06 +02:00
|
|
|
$feed = Feed::factory()->create();
|
|
|
|
|
$article = Article::factory()->create([
|
|
|
|
|
'feed_id' => $feed->id,
|
|
|
|
|
'url' => 'https://example.com/article',
|
2025-08-10 21:18:20 +02:00
|
|
|
'approval_status' => 'pending'
|
2025-08-02 03:48:06 +02:00
|
|
|
]);
|
|
|
|
|
|
2025-08-15 02:50:42 +02:00
|
|
|
$result = $this->validationService->validate($article);
|
2025-08-11 18:26:00 +02:00
|
|
|
|
2025-08-10 21:18:20 +02:00
|
|
|
// Since we can't fetch real content in tests, it should be marked rejected
|
|
|
|
|
$this->assertEquals('rejected', $result->approval_status);
|
2025-08-02 03:48:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_validate_updates_article_in_database(): void
|
|
|
|
|
{
|
2025-08-10 15:20:28 +02:00
|
|
|
// Mock HTTP requests
|
|
|
|
|
Http::fake([
|
|
|
|
|
'https://example.com/article' => Http::response('<html><body>Article content</body></html>', 200)
|
|
|
|
|
]);
|
|
|
|
|
|
2025-08-02 03:48:06 +02:00
|
|
|
$feed = Feed::factory()->create();
|
|
|
|
|
$article = Article::factory()->create([
|
|
|
|
|
'feed_id' => $feed->id,
|
|
|
|
|
'url' => 'https://example.com/article',
|
2025-08-10 21:18:20 +02:00
|
|
|
'approval_status' => 'pending'
|
2025-08-02 03:48:06 +02:00
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$originalId = $article->id;
|
2025-08-11 18:26:00 +02:00
|
|
|
|
2025-08-15 02:50:42 +02:00
|
|
|
$this->validationService->validate($article);
|
2025-08-11 18:26:00 +02:00
|
|
|
|
2025-08-02 03:48:06 +02:00
|
|
|
// Check that the article was updated in the database
|
|
|
|
|
$updatedArticle = Article::find($originalId);
|
2025-08-10 21:18:20 +02:00
|
|
|
$this->assertContains($updatedArticle->approval_status, ['pending', 'approved', 'rejected']);
|
2025-08-02 03:48:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_validate_handles_article_with_existing_validation(): void
|
|
|
|
|
{
|
2025-08-10 15:20:28 +02:00
|
|
|
// Mock HTTP requests
|
|
|
|
|
Http::fake([
|
|
|
|
|
'https://example.com/article' => Http::response('<html><body>Article content</body></html>', 200)
|
|
|
|
|
]);
|
|
|
|
|
|
2025-08-02 03:48:06 +02:00
|
|
|
$feed = Feed::factory()->create();
|
|
|
|
|
$article = Article::factory()->create([
|
|
|
|
|
'feed_id' => $feed->id,
|
|
|
|
|
'url' => 'https://example.com/article',
|
2025-08-10 21:18:20 +02:00
|
|
|
'approval_status' => 'approved'
|
2025-08-02 03:48:06 +02:00
|
|
|
]);
|
|
|
|
|
|
2025-08-10 21:18:20 +02:00
|
|
|
$originalApprovalStatus = $article->approval_status;
|
2025-08-11 18:26:00 +02:00
|
|
|
|
2025-08-15 02:50:42 +02:00
|
|
|
$result = $this->validationService->validate($article);
|
2025-08-11 18:26:00 +02:00
|
|
|
|
2025-08-10 21:18:20 +02:00
|
|
|
// Should re-validate - status may change based on content validation
|
|
|
|
|
$this->assertContains($result->approval_status, ['pending', 'approved', 'rejected']);
|
2025-08-02 03:48:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public function test_validate_keyword_checking_logic(): void
|
|
|
|
|
{
|
2025-08-10 15:20:28 +02:00
|
|
|
// Mock HTTP requests with content that contains Belgian keywords
|
|
|
|
|
Http::fake([
|
|
|
|
|
'https://example.com/article-about-bart-de-wever' => Http::response(
|
|
|
|
|
'<html><body><article>Article about Bart De Wever and Belgian politics</article></body></html>',
|
|
|
|
|
200
|
|
|
|
|
)
|
|
|
|
|
]);
|
|
|
|
|
|
2025-08-02 03:48:06 +02:00
|
|
|
$feed = Feed::factory()->create();
|
2025-08-11 18:26:00 +02:00
|
|
|
|
2025-08-02 03:48:06 +02:00
|
|
|
// Create an article that would match the validation keywords if content was available
|
|
|
|
|
$article = Article::factory()->create([
|
|
|
|
|
'feed_id' => $feed->id,
|
|
|
|
|
'url' => 'https://example.com/article-about-bart-de-wever',
|
2025-08-10 21:18:20 +02:00
|
|
|
'approval_status' => 'pending'
|
2025-08-02 03:48:06 +02:00
|
|
|
]);
|
|
|
|
|
|
2025-08-15 02:50:42 +02:00
|
|
|
$result = $this->validationService->validate($article);
|
2025-08-11 18:26:00 +02:00
|
|
|
|
2025-08-02 03:48:06 +02:00
|
|
|
// The service looks for keywords in the full_article content
|
2025-08-10 21:18:20 +02:00
|
|
|
// Since we can't fetch real content, it will be marked rejected
|
|
|
|
|
$this->assertEquals('rejected', $result->approval_status);
|
2025-08-02 03:48:06 +02:00
|
|
|
}
|
2025-08-11 18:26:00 +02:00
|
|
|
}
|