85 - Remove approval_status from Article, migrate to route_articles
This commit is contained in:
parent
d0985fc57d
commit
f3406b1713
15 changed files with 100 additions and 356 deletions
|
|
@ -40,40 +40,6 @@ public function index(Request $request): JsonResponse
|
|||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Approve an article
|
||||
*/
|
||||
public function approve(Article $article): JsonResponse
|
||||
{
|
||||
try {
|
||||
$article->approve('manual');
|
||||
|
||||
return $this->sendResponse(
|
||||
new ArticleResource($article->fresh(['feed', 'articlePublication'])),
|
||||
'Article approved and queued for publishing.'
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
return $this->sendError('Failed to approve article: '.$e->getMessage(), [], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reject an article
|
||||
*/
|
||||
public function reject(Article $article): JsonResponse
|
||||
{
|
||||
try {
|
||||
$article->reject('manual');
|
||||
|
||||
return $this->sendResponse(
|
||||
new ArticleResource($article->fresh(['feed', 'articlePublication'])),
|
||||
'Article rejected.'
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
return $this->sendError('Failed to reject article: '.$e->getMessage(), [], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually refresh articles from all active feeds
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -21,8 +21,6 @@ public function toArray(Request $request): array
|
|||
'url' => $this->url,
|
||||
'title' => $this->title,
|
||||
'description' => $this->description,
|
||||
'is_valid' => $this->is_valid,
|
||||
'approval_status' => $this->approval_status,
|
||||
'publish_status' => $this->publish_status,
|
||||
'validated_at' => $this->validated_at?->toISOString(),
|
||||
'is_published' => $this->relationLoaded('articlePublication') && $this->articlePublication !== null,
|
||||
|
|
|
|||
|
|
@ -32,11 +32,6 @@ public function handle(ArticleApproved $event): void
|
|||
return;
|
||||
}
|
||||
|
||||
// Skip if not approved (safety check)
|
||||
if (! $article->isApproved()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$article->update(['publish_status' => 'publishing']);
|
||||
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Events\ArticleApproved;
|
||||
use App\Events\NewArticleFetched;
|
||||
use Database\Factories\ArticleFactory;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
|
@ -23,14 +22,11 @@
|
|||
* @property string $url
|
||||
* @property string $title
|
||||
* @property string|null $description
|
||||
* @property string $approval_status
|
||||
* @property string $publish_status
|
||||
* @property bool|null $is_valid
|
||||
* @property Carbon|null $validated_at
|
||||
* @property Carbon $created_at
|
||||
* @property Carbon $updated_at
|
||||
* @property ArticlePublication|null $articlePublication
|
||||
* @property \Illuminate\Support\HigherOrderCollectionProxy|mixed $routeArticles
|
||||
*/
|
||||
class Article extends Model
|
||||
{
|
||||
|
|
@ -46,7 +42,6 @@ class Article extends Model
|
|||
'image_url',
|
||||
'published_at',
|
||||
'author',
|
||||
'approval_status',
|
||||
'validated_at',
|
||||
'publish_status',
|
||||
];
|
||||
|
|
@ -57,7 +52,6 @@ class Article extends Model
|
|||
public function casts(): array
|
||||
{
|
||||
return [
|
||||
'approval_status' => 'string',
|
||||
'publish_status' => 'string',
|
||||
'published_at' => 'datetime',
|
||||
'validated_at' => 'datetime',
|
||||
|
|
@ -66,58 +60,6 @@ public function casts(): array
|
|||
];
|
||||
}
|
||||
|
||||
public function isValid(): bool
|
||||
{
|
||||
return $this->validated_at !== null && ! $this->isRejected();
|
||||
}
|
||||
|
||||
public function isApproved(): bool
|
||||
{
|
||||
return $this->approval_status === 'approved';
|
||||
}
|
||||
|
||||
public function isPending(): bool
|
||||
{
|
||||
return $this->approval_status === 'pending';
|
||||
}
|
||||
|
||||
public function isRejected(): bool
|
||||
{
|
||||
return $this->approval_status === 'rejected';
|
||||
}
|
||||
|
||||
public function approve(?string $approvedBy = null): void
|
||||
{
|
||||
$this->update([
|
||||
'approval_status' => 'approved',
|
||||
]);
|
||||
|
||||
// Fire event to trigger publishing
|
||||
event(new ArticleApproved($this));
|
||||
}
|
||||
|
||||
public function reject(?string $rejectedBy = null): void
|
||||
{
|
||||
$this->update([
|
||||
'approval_status' => 'rejected',
|
||||
]);
|
||||
}
|
||||
|
||||
public function canBePublished(): bool
|
||||
{
|
||||
if (! $this->isValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If approval system is disabled, auto-approve valid articles
|
||||
if (! \App\Models\Setting::isPublishingApprovalsEnabled()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If approval system is enabled, only approved articles can be published
|
||||
return $this->isApproved();
|
||||
}
|
||||
|
||||
public function getIsPublishedAttribute(): bool
|
||||
{
|
||||
return $this->articlePublication()->exists();
|
||||
|
|
|
|||
|
|
@ -73,10 +73,6 @@ public function publishRouteArticle(RouteArticle $routeArticle, array $extracted
|
|||
*/
|
||||
public function publishToRoutedChannels(Article $article, array $extractedData): Collection
|
||||
{
|
||||
if (! $article->isValid()) {
|
||||
throw new PublishException($article, PlatformEnum::LEMMY, new RuntimeException('CANNOT_PUBLISH_INVALID_ARTICLE'));
|
||||
}
|
||||
|
||||
$feed = $article->feed;
|
||||
|
||||
$activeRoutes = Route::where('feed_id', $feed->id)
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ public function definition(): array
|
|||
'image_url' => $this->faker->optional()->imageUrl(),
|
||||
'published_at' => $this->faker->optional()->dateTimeBetween('-1 month', 'now'),
|
||||
'author' => $this->faker->optional()->name(),
|
||||
'approval_status' => $this->faker->randomElement(['pending', 'approved', 'rejected']),
|
||||
'publish_status' => 'unpublished',
|
||||
];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
// Migrate existing article approval_status to route_articles
|
||||
$validatedArticles = DB::table('articles')
|
||||
->whereIn('approval_status', ['approved', 'rejected'])
|
||||
->whereNotNull('validated_at')
|
||||
->get();
|
||||
|
||||
foreach ($validatedArticles as $article) {
|
||||
$routes = DB::table('routes')
|
||||
->where('feed_id', $article->feed_id)
|
||||
->where('is_active', true)
|
||||
->get();
|
||||
|
||||
foreach ($routes as $route) {
|
||||
$exists = DB::table('route_articles')
|
||||
->where('feed_id', $route->feed_id)
|
||||
->where('platform_channel_id', $route->platform_channel_id)
|
||||
->where('article_id', $article->id)
|
||||
->exists();
|
||||
|
||||
if ($exists) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DB::table('route_articles')->insert([
|
||||
'feed_id' => $route->feed_id,
|
||||
'platform_channel_id' => $route->platform_channel_id,
|
||||
'article_id' => $article->id,
|
||||
'approval_status' => $article->approval_status,
|
||||
'validated_at' => $article->validated_at,
|
||||
'created_at' => $article->created_at,
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove approval_status column from articles
|
||||
Schema::table('articles', function (Blueprint $table) {
|
||||
$table->dropIndex(['published_at', 'approval_status']);
|
||||
$table->dropColumn('approval_status');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('articles', function (Blueprint $table) {
|
||||
$table->enum('approval_status', ['pending', 'approved', 'rejected'])->default('pending')->after('feed_id');
|
||||
$table->index(['published_at', 'approval_status']);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
|
@ -47,8 +47,6 @@
|
|||
|
||||
// Articles
|
||||
Route::get('/articles', [ArticlesController::class, 'index'])->name('api.articles.index');
|
||||
Route::post('/articles/{article}/approve', [ArticlesController::class, 'approve'])->name('api.articles.approve');
|
||||
Route::post('/articles/{article}/reject', [ArticlesController::class, 'reject'])->name('api.articles.reject');
|
||||
Route::post('/articles/refresh', [ArticlesController::class, 'refresh'])->name('api.articles.refresh');
|
||||
|
||||
// Platform Accounts
|
||||
|
|
|
|||
|
|
@ -134,14 +134,12 @@ public function test_article_model_creates_successfully(): void
|
|||
'feed_id' => $feed->id,
|
||||
'title' => 'Test Article',
|
||||
'url' => 'https://example.com/article',
|
||||
'approval_status' => 'pending',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('articles', [
|
||||
'feed_id' => $feed->id,
|
||||
'title' => 'Test Article',
|
||||
'url' => 'https://example.com/article',
|
||||
'approval_status' => 'pending',
|
||||
]);
|
||||
|
||||
$this->assertEquals($feed->id, $article->feed->id);
|
||||
|
|
|
|||
|
|
@ -102,60 +102,6 @@ public function test_index_orders_articles_by_created_at_desc(): void
|
|||
$this->assertEquals('First Article', $articles[1]['title']);
|
||||
}
|
||||
|
||||
public function test_approve_article_successfully(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'pending',
|
||||
]);
|
||||
|
||||
$response = $this->postJson("/api/v1/articles/{$article->id}/approve");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJson([
|
||||
'success' => true,
|
||||
'message' => 'Article approved and queued for publishing.',
|
||||
]);
|
||||
|
||||
$article->refresh();
|
||||
$this->assertEquals('approved', $article->approval_status);
|
||||
}
|
||||
|
||||
public function test_approve_nonexistent_article_returns_404(): void
|
||||
{
|
||||
$response = $this->postJson('/api/v1/articles/999/approve');
|
||||
|
||||
$response->assertStatus(404);
|
||||
}
|
||||
|
||||
public function test_reject_article_successfully(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'pending',
|
||||
]);
|
||||
|
||||
$response = $this->postJson("/api/v1/articles/{$article->id}/reject");
|
||||
|
||||
$response->assertStatus(200)
|
||||
->assertJson([
|
||||
'success' => true,
|
||||
'message' => 'Article rejected.',
|
||||
]);
|
||||
|
||||
$article->refresh();
|
||||
$this->assertEquals('rejected', $article->approval_status);
|
||||
}
|
||||
|
||||
public function test_reject_nonexistent_article_returns_404(): void
|
||||
{
|
||||
$response = $this->postJson('/api/v1/articles/999/reject');
|
||||
|
||||
$response->assertStatus(404);
|
||||
}
|
||||
|
||||
public function test_index_includes_settings(): void
|
||||
{
|
||||
$response = $this->getJson('/api/v1/articles');
|
||||
|
|
|
|||
|
|
@ -188,7 +188,6 @@ public function test_validate_article_listener_processes_new_article(): void
|
|||
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'pending',
|
||||
]);
|
||||
|
||||
// Mock ArticleFetcher to return valid article data
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ public function test_exception_during_publishing_creates_error_notification(): v
|
|||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'approved',
|
||||
|
||||
'title' => 'Test Article',
|
||||
]);
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ public function test_no_publications_created_creates_warning_notification(): voi
|
|||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'approved',
|
||||
|
||||
'title' => 'Test Article',
|
||||
]);
|
||||
|
||||
|
|
@ -93,7 +93,7 @@ public function test_successful_publish_does_not_create_notification(): void
|
|||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'approved',
|
||||
|
||||
'title' => 'Test Article',
|
||||
]);
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ public function test_listener_validates_article_and_creates_route_articles(): vo
|
|||
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'pending',
|
||||
]);
|
||||
|
||||
$listener = $this->createListenerWithMockedFetcher('Article about Belgium');
|
||||
|
|
@ -91,7 +90,6 @@ public function test_listener_skips_articles_with_existing_publication(): void
|
|||
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'pending',
|
||||
]);
|
||||
|
||||
ArticlePublication::create([
|
||||
|
|
@ -120,7 +118,6 @@ public function test_listener_handles_validation_errors_gracefully(): void
|
|||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'pending',
|
||||
]);
|
||||
|
||||
$listener->handle(new NewArticleFetched($article));
|
||||
|
|
|
|||
|
|
@ -2,11 +2,9 @@
|
|||
|
||||
namespace Tests\Unit\Models;
|
||||
|
||||
use App\Events\ArticleApproved;
|
||||
use App\Events\NewArticleFetched;
|
||||
use App\Models\Article;
|
||||
use App\Models\Feed;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
|
|
@ -20,169 +18,9 @@ protected function setUp(): void
|
|||
{
|
||||
parent::setUp();
|
||||
|
||||
// Mock HTTP requests to prevent external calls
|
||||
Http::fake([
|
||||
'*' => Http::response('', 500),
|
||||
]);
|
||||
|
||||
// Don't fake events globally - let individual tests control this
|
||||
}
|
||||
|
||||
public function test_is_valid_returns_false_when_approval_status_is_pending(): void
|
||||
{
|
||||
$article = Article::factory()->make([
|
||||
'approval_status' => 'pending',
|
||||
]);
|
||||
|
||||
$this->assertFalse($article->isValid());
|
||||
}
|
||||
|
||||
public function test_is_valid_returns_false_when_approval_status_is_rejected(): void
|
||||
{
|
||||
$article = Article::factory()->make([
|
||||
'approval_status' => 'rejected',
|
||||
]);
|
||||
|
||||
$this->assertFalse($article->isValid());
|
||||
}
|
||||
|
||||
public function test_is_valid_returns_true_when_validated_and_not_rejected(): void
|
||||
{
|
||||
$article = Article::factory()->make([
|
||||
'approval_status' => 'approved',
|
||||
'validated_at' => now(),
|
||||
]);
|
||||
|
||||
$this->assertTrue($article->isValid());
|
||||
}
|
||||
|
||||
public function test_is_valid_returns_false_when_not_validated(): void
|
||||
{
|
||||
$article = Article::factory()->make([
|
||||
'approval_status' => 'approved',
|
||||
'validated_at' => null,
|
||||
]);
|
||||
|
||||
$this->assertFalse($article->isValid());
|
||||
}
|
||||
|
||||
public function test_is_approved_returns_true_for_approved_status(): void
|
||||
{
|
||||
$article = Article::factory()->make(['approval_status' => 'approved']);
|
||||
|
||||
$this->assertTrue($article->isApproved());
|
||||
}
|
||||
|
||||
public function test_is_approved_returns_false_for_non_approved_status(): void
|
||||
{
|
||||
$article = Article::factory()->make(['approval_status' => 'pending']);
|
||||
|
||||
$this->assertFalse($article->isApproved());
|
||||
}
|
||||
|
||||
public function test_is_pending_returns_true_for_pending_status(): void
|
||||
{
|
||||
$article = Article::factory()->make(['approval_status' => 'pending']);
|
||||
|
||||
$this->assertTrue($article->isPending());
|
||||
}
|
||||
|
||||
public function test_is_rejected_returns_true_for_rejected_status(): void
|
||||
{
|
||||
$article = Article::factory()->make(['approval_status' => 'rejected']);
|
||||
|
||||
$this->assertTrue($article->isRejected());
|
||||
}
|
||||
|
||||
public function test_approve_updates_status_and_triggers_event(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'pending',
|
||||
]);
|
||||
|
||||
Event::fake();
|
||||
|
||||
$article->approve('test_user');
|
||||
|
||||
$article->refresh();
|
||||
$this->assertEquals('approved', $article->approval_status);
|
||||
|
||||
Event::assertDispatched(ArticleApproved::class, function ($event) use ($article) {
|
||||
return $event->article->id === $article->id;
|
||||
});
|
||||
}
|
||||
|
||||
public function test_approve_without_approved_by_parameter(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'pending',
|
||||
]);
|
||||
|
||||
Event::fake();
|
||||
|
||||
$article->approve();
|
||||
|
||||
$article->refresh();
|
||||
$this->assertEquals('approved', $article->approval_status);
|
||||
}
|
||||
|
||||
public function test_reject_updates_status(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'pending',
|
||||
]);
|
||||
|
||||
$article->reject('test_user');
|
||||
|
||||
$article->refresh();
|
||||
$this->assertEquals('rejected', $article->approval_status);
|
||||
}
|
||||
|
||||
public function test_can_be_published_returns_false_for_invalid_article(): void
|
||||
{
|
||||
$article = Article::factory()->make([
|
||||
'approval_status' => 'rejected', // rejected = not valid
|
||||
]);
|
||||
|
||||
$this->assertFalse($article->canBePublished());
|
||||
}
|
||||
|
||||
public function test_can_be_published_requires_approval_when_approvals_enabled(): void
|
||||
{
|
||||
// Create a setting that enables approvals
|
||||
Setting::create(['key' => 'enable_publishing_approvals', 'value' => '1']);
|
||||
|
||||
$pendingArticle = Article::factory()->make([
|
||||
'approval_status' => 'pending',
|
||||
'validated_at' => now(),
|
||||
]);
|
||||
|
||||
$approvedArticle = Article::factory()->make([
|
||||
'approval_status' => 'approved',
|
||||
'validated_at' => now(),
|
||||
]);
|
||||
|
||||
$this->assertFalse($pendingArticle->canBePublished());
|
||||
$this->assertTrue($approvedArticle->canBePublished());
|
||||
}
|
||||
|
||||
public function test_can_be_published_returns_true_when_approvals_disabled(): void
|
||||
{
|
||||
// Make sure approvals are disabled (default behavior)
|
||||
Setting::where('key', 'enable_publishing_approvals')->delete();
|
||||
|
||||
$article = Article::factory()->make([
|
||||
'approval_status' => 'approved',
|
||||
'validated_at' => now(),
|
||||
]);
|
||||
|
||||
$this->assertTrue($article->canBePublished());
|
||||
}
|
||||
|
||||
public function test_feed_relationship(): void
|
||||
|
|
@ -194,6 +32,14 @@ public function test_feed_relationship(): void
|
|||
$this->assertEquals($feed->id, $article->feed->id);
|
||||
}
|
||||
|
||||
public function test_route_articles_relationship(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create(['feed_id' => $feed->id]);
|
||||
|
||||
$this->assertCount(0, $article->routeArticles);
|
||||
}
|
||||
|
||||
public function test_dispatch_fetched_event_fires_new_article_fetched_event(): void
|
||||
{
|
||||
Event::fake([NewArticleFetched::class]);
|
||||
|
|
@ -207,4 +53,23 @@ public function test_dispatch_fetched_event_fires_new_article_fetched_event(): v
|
|||
return $event->article->id === $article->id;
|
||||
});
|
||||
}
|
||||
|
||||
public function test_is_published_attribute(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create(['feed_id' => $feed->id]);
|
||||
|
||||
$this->assertFalse($article->is_published);
|
||||
}
|
||||
|
||||
public function test_validated_at_is_cast_to_datetime(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'validated_at' => now(),
|
||||
]);
|
||||
|
||||
$this->assertInstanceOf(\Illuminate\Support\Carbon::class, $article->validated_at);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
namespace Tests\Unit\Services\Publishing;
|
||||
|
||||
use App\Enums\PlatformEnum;
|
||||
use App\Exceptions\PublishException;
|
||||
use App\Models\Article;
|
||||
use App\Models\Feed;
|
||||
use App\Models\PlatformAccount;
|
||||
|
|
@ -45,23 +44,12 @@ protected function tearDown(): void
|
|||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function test_publish_to_routed_channels_throws_exception_for_invalid_article(): void
|
||||
{
|
||||
$article = Article::factory()->create(['approval_status' => 'rejected']);
|
||||
$extractedData = ['title' => 'Test Title'];
|
||||
|
||||
$this->expectException(PublishException::class);
|
||||
$this->expectExceptionMessage('CANNOT_PUBLISH_INVALID_ARTICLE');
|
||||
|
||||
$this->service->publishToRoutedChannels($article, $extractedData);
|
||||
}
|
||||
|
||||
public function test_publish_to_routed_channels_returns_empty_collection_when_no_active_routes(): void
|
||||
{
|
||||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'approved',
|
||||
|
||||
'validated_at' => now(),
|
||||
]);
|
||||
$extractedData = ['title' => 'Test Title'];
|
||||
|
|
@ -78,7 +66,7 @@ public function test_publish_to_routed_channels_skips_routes_without_active_acco
|
|||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'approved',
|
||||
|
||||
'validated_at' => now(),
|
||||
]);
|
||||
|
||||
|
|
@ -106,8 +94,7 @@ public function test_publish_to_routed_channels_successfully_publishes_to_channe
|
|||
{
|
||||
// Arrange
|
||||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create(['feed_id' => $feed->id, 'approval_status' => 'approved',
|
||||
'validated_at' => now()]);
|
||||
$article = Article::factory()->create(['feed_id' => $feed->id, 'validated_at' => now()]);
|
||||
|
||||
$platformInstance = PlatformInstance::factory()->create();
|
||||
$channel = PlatformChannel::factory()->create(['platform_instance_id' => $platformInstance->id]);
|
||||
|
|
@ -153,8 +140,7 @@ public function test_publish_to_routed_channels_handles_publishing_failure_grace
|
|||
{
|
||||
// Arrange
|
||||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create(['feed_id' => $feed->id, 'approval_status' => 'approved',
|
||||
'validated_at' => now()]);
|
||||
$article = Article::factory()->create(['feed_id' => $feed->id, 'validated_at' => now()]);
|
||||
|
||||
$platformInstance = PlatformInstance::factory()->create();
|
||||
$channel = PlatformChannel::factory()->create(['platform_instance_id' => $platformInstance->id]);
|
||||
|
|
@ -195,8 +181,7 @@ public function test_publish_to_routed_channels_publishes_to_multiple_routes():
|
|||
{
|
||||
// Arrange
|
||||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create(['feed_id' => $feed->id, 'approval_status' => 'approved',
|
||||
'validated_at' => now()]);
|
||||
$article = Article::factory()->create(['feed_id' => $feed->id, 'validated_at' => now()]);
|
||||
|
||||
$platformInstance = PlatformInstance::factory()->create();
|
||||
$channel1 = PlatformChannel::factory()->create(['platform_instance_id' => $platformInstance->id]);
|
||||
|
|
@ -251,8 +236,7 @@ public function test_publish_to_routed_channels_filters_out_failed_publications(
|
|||
{
|
||||
// Arrange
|
||||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create(['feed_id' => $feed->id, 'approval_status' => 'approved',
|
||||
'validated_at' => now()]);
|
||||
$article = Article::factory()->create(['feed_id' => $feed->id, 'validated_at' => now()]);
|
||||
|
||||
$platformInstance = PlatformInstance::factory()->create();
|
||||
$channel1 = PlatformChannel::factory()->create(['platform_instance_id' => $platformInstance->id]);
|
||||
|
|
@ -309,7 +293,7 @@ public function test_publish_skips_duplicate_when_url_already_posted_to_channel(
|
|||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'approved',
|
||||
|
||||
'validated_at' => now(),
|
||||
'url' => 'https://example.com/article-1',
|
||||
]);
|
||||
|
|
@ -361,7 +345,7 @@ public function test_publish_skips_duplicate_when_title_already_posted_to_channe
|
|||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'approved',
|
||||
|
||||
'validated_at' => now(),
|
||||
'url' => 'https://example.com/article-new-url',
|
||||
'title' => 'Breaking News: Something Happened',
|
||||
|
|
@ -414,7 +398,7 @@ public function test_publish_proceeds_when_no_duplicate_exists(): void
|
|||
$feed = Feed::factory()->create();
|
||||
$article = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'approval_status' => 'approved',
|
||||
|
||||
'validated_at' => now(),
|
||||
'url' => 'https://example.com/unique-article',
|
||||
]);
|
||||
|
|
|
|||
Loading…
Reference in a new issue