184 lines
5.5 KiB
PHP
184 lines
5.5 KiB
PHP
|
|
<?php
|
||
|
|
|
||
|
|
namespace Tests\Feature;
|
||
|
|
|
||
|
|
use App\Events\ArticleReadyToPublish;
|
||
|
|
use App\Jobs\PublishToLemmyJob;
|
||
|
|
use App\Listeners\PublishArticle;
|
||
|
|
use App\Models\Article;
|
||
|
|
use App\Models\ArticlePublication;
|
||
|
|
use App\Models\Feed;
|
||
|
|
use App\Services\Publishing\ArticlePublishingService;
|
||
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||
|
|
use Illuminate\Support\Facades\Event;
|
||
|
|
use Illuminate\Support\Facades\Queue;
|
||
|
|
use Tests\TestCase;
|
||
|
|
|
||
|
|
class ArticlePublishingTest extends TestCase
|
||
|
|
{
|
||
|
|
use RefreshDatabase;
|
||
|
|
|
||
|
|
public function test_publish_article_listener_queues_publish_job(): void
|
||
|
|
{
|
||
|
|
Queue::fake();
|
||
|
|
|
||
|
|
$feed = Feed::factory()->create();
|
||
|
|
$article = Article::factory()->create([
|
||
|
|
'feed_id' => $feed->id,
|
||
|
|
'url' => 'https://example.com/article',
|
||
|
|
'validated_at' => now(),
|
||
|
|
'is_valid' => true,
|
||
|
|
]);
|
||
|
|
|
||
|
|
$listener = new PublishArticle();
|
||
|
|
$event = new ArticleReadyToPublish($article);
|
||
|
|
|
||
|
|
$listener->handle($event);
|
||
|
|
|
||
|
|
Queue::assertPushed(PublishToLemmyJob::class);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_publish_article_listener_skips_already_published_articles(): void
|
||
|
|
{
|
||
|
|
Queue::fake();
|
||
|
|
|
||
|
|
$feed = Feed::factory()->create();
|
||
|
|
$article = Article::factory()->create([
|
||
|
|
'feed_id' => $feed->id,
|
||
|
|
'url' => 'https://example.com/article',
|
||
|
|
'validated_at' => now(),
|
||
|
|
'is_valid' => true,
|
||
|
|
]);
|
||
|
|
|
||
|
|
// Create existing publication
|
||
|
|
ArticlePublication::create([
|
||
|
|
'article_id' => $article->id,
|
||
|
|
'post_id' => 'existing-post-id',
|
||
|
|
'platform_channel_id' => 1,
|
||
|
|
'published_at' => now(),
|
||
|
|
'published_by' => 'test-user',
|
||
|
|
]);
|
||
|
|
|
||
|
|
$listener = new PublishArticle();
|
||
|
|
$event = new ArticleReadyToPublish($article);
|
||
|
|
|
||
|
|
$listener->handle($event);
|
||
|
|
|
||
|
|
Queue::assertNotPushed(PublishToLemmyJob::class);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_publish_to_lemmy_job_calls_publishing_service(): void
|
||
|
|
{
|
||
|
|
$feed = Feed::factory()->create();
|
||
|
|
$article = Article::factory()->create([
|
||
|
|
'feed_id' => $feed->id,
|
||
|
|
'url' => 'https://example.com/article',
|
||
|
|
'validated_at' => now(),
|
||
|
|
'is_valid' => true,
|
||
|
|
]);
|
||
|
|
|
||
|
|
$job = new PublishToLemmyJob($article);
|
||
|
|
|
||
|
|
$this->assertEquals('lemmy-posts', $job->queue);
|
||
|
|
$this->assertInstanceOf(PublishToLemmyJob::class, $job);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_article_ready_to_publish_event_integration(): void
|
||
|
|
{
|
||
|
|
Queue::fake();
|
||
|
|
Event::fake();
|
||
|
|
|
||
|
|
$feed = Feed::factory()->create();
|
||
|
|
$article = Article::factory()->create([
|
||
|
|
'feed_id' => $feed->id,
|
||
|
|
'url' => 'https://example.com/article',
|
||
|
|
'validated_at' => now(),
|
||
|
|
'is_valid' => true,
|
||
|
|
]);
|
||
|
|
|
||
|
|
event(new ArticleReadyToPublish($article));
|
||
|
|
|
||
|
|
Event::assertDispatched(ArticleReadyToPublish::class, function (ArticleReadyToPublish $event) use ($article) {
|
||
|
|
return $event->article->id === $article->id;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_publishing_prevents_duplicate_publications(): void
|
||
|
|
{
|
||
|
|
$feed = Feed::factory()->create();
|
||
|
|
$article = Article::factory()->create([
|
||
|
|
'feed_id' => $feed->id,
|
||
|
|
'url' => 'https://example.com/article',
|
||
|
|
'validated_at' => now(),
|
||
|
|
'is_valid' => true,
|
||
|
|
]);
|
||
|
|
|
||
|
|
ArticlePublication::create([
|
||
|
|
'article_id' => $article->id,
|
||
|
|
'post_id' => 'first-post-id',
|
||
|
|
'platform_channel_id' => 1,
|
||
|
|
'published_at' => now(),
|
||
|
|
'published_by' => 'test-user',
|
||
|
|
]);
|
||
|
|
|
||
|
|
$this->mock(ArticlePublishingService::class, function ($mock) {
|
||
|
|
$mock->shouldNotReceive('publishToRoutedChannels');
|
||
|
|
});
|
||
|
|
|
||
|
|
$listener = new PublishArticle();
|
||
|
|
$event = new ArticleReadyToPublish($article);
|
||
|
|
|
||
|
|
$listener->handle($event);
|
||
|
|
|
||
|
|
$this->assertEquals(1, ArticlePublication::where('article_id', $article->id)->count());
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_publish_article_listener_has_correct_queue_configuration(): void
|
||
|
|
{
|
||
|
|
$listener = new PublishArticle();
|
||
|
|
|
||
|
|
$this->assertEquals('lemmy-publish', $listener->queue);
|
||
|
|
$this->assertEquals(300, $listener->delay);
|
||
|
|
$this->assertEquals(3, $listener->tries);
|
||
|
|
$this->assertEquals(300, $listener->backoff);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_publish_to_lemmy_job_has_correct_queue_configuration(): void
|
||
|
|
{
|
||
|
|
$feed = Feed::factory()->create();
|
||
|
|
$article = Article::factory()->create([
|
||
|
|
'feed_id' => $feed->id,
|
||
|
|
'url' => 'https://example.com/article',
|
||
|
|
]);
|
||
|
|
|
||
|
|
$job = new PublishToLemmyJob($article);
|
||
|
|
|
||
|
|
$this->assertEquals('lemmy-posts', $job->queue);
|
||
|
|
}
|
||
|
|
|
||
|
|
public function test_multiple_articles_can_be_queued_independently(): void
|
||
|
|
{
|
||
|
|
Queue::fake();
|
||
|
|
|
||
|
|
$feed = Feed::factory()->create();
|
||
|
|
$article1 = Article::factory()->create([
|
||
|
|
'feed_id' => $feed->id,
|
||
|
|
'url' => 'https://example.com/article1',
|
||
|
|
'validated_at' => now(),
|
||
|
|
'is_valid' => true,
|
||
|
|
]);
|
||
|
|
$article2 = Article::factory()->create([
|
||
|
|
'feed_id' => $feed->id,
|
||
|
|
'url' => 'https://example.com/article2',
|
||
|
|
'validated_at' => now(),
|
||
|
|
'is_valid' => true,
|
||
|
|
]);
|
||
|
|
|
||
|
|
$listener = new PublishArticle();
|
||
|
|
|
||
|
|
$listener->handle(new ArticleReadyToPublish($article1));
|
||
|
|
$listener->handle(new ArticleReadyToPublish($article2));
|
||
|
|
|
||
|
|
Queue::assertPushed(PublishToLemmyJob::class, 2);
|
||
|
|
}
|
||
|
|
}
|