From 433aa79007bbaa3749e7a220effcefa8045c0632 Mon Sep 17 00:00:00 2001 From: myrmidex Date: Sun, 9 Aug 2026 15:22:02 +0200 Subject: [PATCH] 119 - Store article thumbnail in image_url during validation --- app/Services/Article/ValidationService.php | 1 + ..._01_01_000017_widen_articles_image_url.php | 22 ++++++++ tests/Unit/Services/ValidationServiceTest.php | 53 ++++++++++++++++++- 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 database/migrations/2024_01_01_000017_widen_articles_image_url.php diff --git a/app/Services/Article/ValidationService.php b/app/Services/Article/ValidationService.php index 431417bc..b79359c3 100644 --- a/app/Services/Article/ValidationService.php +++ b/app/Services/Article/ValidationService.php @@ -28,6 +28,7 @@ public function validate(Article $article): Article $updateData['title'] = $articleData['title'] ?? $article->title; $updateData['description'] = $articleData['description'] ?? $article->description; $updateData['content'] = $articleData['full_article'] ?? null; + $updateData['image_url'] = ($articleData['thumbnail'] ?? null) ?: $article->image_url; } if (! isset($articleData['full_article']) || empty($articleData['full_article'])) { diff --git a/database/migrations/2024_01_01_000017_widen_articles_image_url.php b/database/migrations/2024_01_01_000017_widen_articles_image_url.php new file mode 100644 index 00000000..8f294508 --- /dev/null +++ b/database/migrations/2024_01_01_000017_widen_articles_image_url.php @@ -0,0 +1,22 @@ +text('image_url')->nullable()->change(); + }); + } + + public function down(): void + { + Schema::table('articles', function (Blueprint $table) { + $table->string('image_url')->nullable()->change(); + }); + } +}; diff --git a/tests/Unit/Services/ValidationServiceTest.php b/tests/Unit/Services/ValidationServiceTest.php index 5133193c..d9f31af8 100644 --- a/tests/Unit/Services/ValidationServiceTest.php +++ b/tests/Unit/Services/ValidationServiceTest.php @@ -38,7 +38,7 @@ protected function tearDown(): void parent::tearDown(); } - private function mockFetchReturning(Article $article, ?string $content, ?string $title = 'Test Title', ?string $description = 'Test description'): void + private function mockFetchReturning(Article $article, ?string $content, ?string $title = 'Test Title', ?string $description = 'Test description', ?string $thumbnail = null): void { $data = []; if ($title) { @@ -50,6 +50,9 @@ private function mockFetchReturning(Article $article, ?string $content, ?string if ($content) { $data['full_article'] = $content; } + if ($thumbnail) { + $data['thumbnail'] = $thumbnail; + } $this->articleFetcher ->shouldReceive('fetchArticleData') @@ -379,4 +382,52 @@ public function test_validate_only_uses_active_keywords(): void $routeArticle = RouteArticle::where('article_id', $article->id)->first(); $this->assertEquals(ApprovalStatusEnum::PENDING, $routeArticle->approval_status); } + + public function test_validate_stores_thumbnail_in_image_url(): void + { + $feed = Feed::factory()->create(); + Route::factory()->active()->create(['feed_id' => $feed->id]); + + $article = Article::factory()->create([ + 'feed_id' => $feed->id, + 'image_url' => null, + ]); + $this->mockFetchReturning($article, 'Content about Belgium', thumbnail: 'https://example.com/thumb.jpg'); + + $this->validationService->validate($article); + + $this->assertEquals('https://example.com/thumb.jpg', $article->fresh()->image_url); + } + + public function test_validate_stores_thumbnail_when_full_article_is_missing(): void + { + $feed = Feed::factory()->create(); + Route::factory()->active()->create(['feed_id' => $feed->id]); + + $article = Article::factory()->create([ + 'feed_id' => $feed->id, + 'image_url' => null, + ]); + $this->mockFetchReturning($article, null, thumbnail: 'https://example.com/thumb.jpg'); + + $this->validationService->validate($article); + + $this->assertEquals('https://example.com/thumb.jpg', $article->fresh()->image_url); + } + + public function test_validate_leaves_image_url_null_when_parser_returns_no_thumbnail(): void + { + $feed = Feed::factory()->create(); + Route::factory()->active()->create(['feed_id' => $feed->id]); + + $article = Article::factory()->create([ + 'feed_id' => $feed->id, + 'image_url' => null, + ]); + $this->mockFetchReturning($article, 'Content about Belgium'); + + $this->validationService->validate($article); + + $this->assertNull($article->fresh()->image_url); + } }