Fix failing tests
This commit is contained in:
parent
7d4aa3da83
commit
65cb836b51
7 changed files with 85 additions and 345 deletions
|
|
@ -1,177 +0,0 @@
|
|||
<?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',
|
||||
'approval_status' => 'approved',
|
||||
]);
|
||||
|
||||
$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',
|
||||
'approval_status' => 'approved',
|
||||
]);
|
||||
|
||||
// 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',
|
||||
'approval_status' => 'approved',
|
||||
]);
|
||||
|
||||
$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',
|
||||
'approval_status' => 'approved',
|
||||
]);
|
||||
|
||||
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',
|
||||
'approval_status' => 'approved',
|
||||
]);
|
||||
|
||||
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',
|
||||
'approval_status' => 'approved',
|
||||
]);
|
||||
$article2 = Article::factory()->create([
|
||||
'feed_id' => $feed->id,
|
||||
'url' => 'https://example.com/article2',
|
||||
'approval_status' => 'approved',
|
||||
]);
|
||||
|
||||
$listener = new PublishArticle();
|
||||
|
||||
$listener->handle(new ArticleReadyToPublish($article1));
|
||||
$listener->handle(new ArticleReadyToPublish($article2));
|
||||
|
||||
Queue::assertPushed(PublishToLemmyJob::class, 2);
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,13 @@ class LogsControllerTest extends TestCase
|
|||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
// Clear any logs that may have been created during application startup
|
||||
Log::query()->delete();
|
||||
}
|
||||
|
||||
public function test_index_returns_successful_response(): void
|
||||
{
|
||||
Log::factory()->count(5)->create();
|
||||
|
|
|
|||
|
|
@ -285,11 +285,18 @@ public function test_create_channel_validates_required_fields()
|
|||
public function test_create_channel_creates_channel_successfully()
|
||||
{
|
||||
$platformInstance = PlatformInstance::factory()->create();
|
||||
$language = Language::factory()->create();
|
||||
|
||||
// Create a platform account for this instance first
|
||||
PlatformAccount::factory()->create([
|
||||
'instance_url' => $platformInstance->url,
|
||||
'is_active' => true
|
||||
]);
|
||||
|
||||
$channelData = [
|
||||
'name' => 'test_community',
|
||||
'platform_instance_id' => $platformInstance->id,
|
||||
'language_id' => 1,
|
||||
'language_id' => $language->id,
|
||||
'description' => 'Test community description',
|
||||
];
|
||||
|
||||
|
|
@ -310,7 +317,7 @@ public function test_create_channel_creates_channel_successfully()
|
|||
'name' => 'test_community',
|
||||
'channel_id' => 'test_community',
|
||||
'platform_instance_id' => $platformInstance->id,
|
||||
'language_id' => 1,
|
||||
'language_id' => $language->id,
|
||||
'is_active' => true,
|
||||
]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
namespace Tests\Feature\Http\Controllers\Api\V1;
|
||||
|
||||
use App\Models\PlatformAccount;
|
||||
use App\Models\PlatformChannel;
|
||||
use App\Models\PlatformInstance;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
|
@ -46,6 +47,12 @@ public function test_index_returns_successful_response(): void
|
|||
public function test_store_creates_platform_channel_successfully(): void
|
||||
{
|
||||
$instance = PlatformInstance::factory()->create();
|
||||
|
||||
// Create a platform account for this instance first
|
||||
PlatformAccount::factory()->create([
|
||||
'instance_url' => $instance->url,
|
||||
'is_active' => true
|
||||
]);
|
||||
|
||||
$data = [
|
||||
'platform_instance_id' => $instance->id,
|
||||
|
|
@ -76,7 +83,7 @@ public function test_store_creates_platform_channel_successfully(): void
|
|||
])
|
||||
->assertJson([
|
||||
'success' => true,
|
||||
'message' => 'Platform channel created successfully!'
|
||||
'message' => 'Platform channel created successfully and linked to platform account!'
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('platform_channels', [
|
||||
|
|
|
|||
|
|
@ -3,17 +3,17 @@
|
|||
namespace Tests\Feature;
|
||||
|
||||
use App\Events\ArticleApproved;
|
||||
use App\Events\ArticleReadyToPublish;
|
||||
// use App\Events\ArticleReadyToPublish; // Class no longer exists
|
||||
use App\Events\ExceptionLogged;
|
||||
use App\Events\ExceptionOccurred;
|
||||
use App\Events\NewArticleFetched;
|
||||
use App\Jobs\ArticleDiscoveryForFeedJob;
|
||||
use App\Jobs\ArticleDiscoveryJob;
|
||||
use App\Jobs\PublishToLemmyJob;
|
||||
use App\Jobs\PublishNextArticleJob;
|
||||
use App\Jobs\SyncChannelPostsJob;
|
||||
use App\Listeners\LogExceptionToDatabase;
|
||||
use App\Listeners\PublishApprovedArticle;
|
||||
use App\Listeners\PublishArticle;
|
||||
// use App\Listeners\PublishApprovedArticle; // Class no longer exists
|
||||
// use App\Listeners\PublishArticle; // Class no longer exists
|
||||
use App\Listeners\ValidateArticleListener;
|
||||
use App\Models\Article;
|
||||
use App\Models\Feed;
|
||||
|
|
@ -83,14 +83,12 @@ public function test_sync_channel_posts_job_processes_successfully(): void
|
|||
}
|
||||
|
||||
|
||||
public function test_publish_to_lemmy_job_has_correct_configuration(): void
|
||||
public function test_publish_next_article_job_has_correct_configuration(): void
|
||||
{
|
||||
$article = Article::factory()->create();
|
||||
$job = new PublishNextArticleJob();
|
||||
|
||||
$job = new PublishToLemmyJob($article);
|
||||
|
||||
$this->assertEquals('lemmy-posts', $job->queue);
|
||||
$this->assertInstanceOf(PublishToLemmyJob::class, $job);
|
||||
$this->assertEquals('publishing', $job->queue);
|
||||
$this->assertInstanceOf(PublishNextArticleJob::class, $job);
|
||||
}
|
||||
|
||||
public function test_new_article_fetched_event_is_dispatched(): void
|
||||
|
|
@ -120,18 +118,19 @@ public function test_article_approved_event_is_dispatched(): void
|
|||
});
|
||||
}
|
||||
|
||||
public function test_article_ready_to_publish_event_is_dispatched(): void
|
||||
{
|
||||
Event::fake();
|
||||
// Test removed - ArticleReadyToPublish class no longer exists
|
||||
// public function test_article_ready_to_publish_event_is_dispatched(): void
|
||||
// {
|
||||
// Event::fake();
|
||||
|
||||
$article = Article::factory()->create();
|
||||
// $article = Article::factory()->create();
|
||||
|
||||
event(new ArticleReadyToPublish($article));
|
||||
// event(new ArticleReadyToPublish($article));
|
||||
|
||||
Event::assertDispatched(ArticleReadyToPublish::class, function (ArticleReadyToPublish $event) use ($article) {
|
||||
return $event->article->id === $article->id;
|
||||
});
|
||||
}
|
||||
// Event::assertDispatched(ArticleReadyToPublish::class, function (ArticleReadyToPublish $event) use ($article) {
|
||||
// return $event->article->id === $article->id;
|
||||
// });
|
||||
// }
|
||||
|
||||
public function test_exception_occurred_event_is_dispatched(): void
|
||||
{
|
||||
|
|
@ -192,38 +191,40 @@ public function test_validate_article_listener_processes_new_article(): void
|
|||
$this->assertContains($article->approval_status, ['approved', 'rejected']);
|
||||
}
|
||||
|
||||
public function test_publish_approved_article_listener_queues_job(): void
|
||||
{
|
||||
Event::fake();
|
||||
// Test removed - PublishApprovedArticle and ArticleReadyToPublish classes no longer exist
|
||||
// public function test_publish_approved_article_listener_queues_job(): void
|
||||
// {
|
||||
// Event::fake();
|
||||
|
||||
$article = Article::factory()->create([
|
||||
'approval_status' => 'approved',
|
||||
'approval_status' => 'approved',
|
||||
]);
|
||||
// $article = Article::factory()->create([
|
||||
// 'approval_status' => 'approved',
|
||||
// 'approval_status' => 'approved',
|
||||
// ]);
|
||||
|
||||
$listener = new PublishApprovedArticle();
|
||||
$event = new ArticleApproved($article);
|
||||
// $listener = new PublishApprovedArticle();
|
||||
// $event = new ArticleApproved($article);
|
||||
|
||||
$listener->handle($event);
|
||||
// $listener->handle($event);
|
||||
|
||||
Event::assertDispatched(ArticleReadyToPublish::class);
|
||||
}
|
||||
// Event::assertDispatched(ArticleReadyToPublish::class);
|
||||
// }
|
||||
|
||||
public function test_publish_article_listener_queues_publish_job(): void
|
||||
{
|
||||
Queue::fake();
|
||||
// Test removed - PublishArticle and ArticleReadyToPublish classes no longer exist
|
||||
// public function test_publish_article_listener_queues_publish_job(): void
|
||||
// {
|
||||
// Queue::fake();
|
||||
|
||||
$article = Article::factory()->create([
|
||||
'approval_status' => 'approved',
|
||||
]);
|
||||
// $article = Article::factory()->create([
|
||||
// 'approval_status' => 'approved',
|
||||
// ]);
|
||||
|
||||
$listener = new PublishArticle();
|
||||
$event = new ArticleReadyToPublish($article);
|
||||
// $listener = new PublishArticle();
|
||||
// $event = new ArticleReadyToPublish($article);
|
||||
|
||||
$listener->handle($event);
|
||||
// $listener->handle($event);
|
||||
|
||||
Queue::assertPushed(PublishToLemmyJob::class);
|
||||
}
|
||||
// Queue::assertPushed(PublishNextArticleJob::class);
|
||||
// }
|
||||
|
||||
public function test_log_exception_to_database_listener_creates_log(): void
|
||||
{
|
||||
|
|
@ -255,11 +256,13 @@ public function test_event_listener_registration_works(): void
|
|||
$listeners = Event::getListeners(NewArticleFetched::class);
|
||||
$this->assertNotEmpty($listeners);
|
||||
|
||||
$listeners = Event::getListeners(ArticleApproved::class);
|
||||
$this->assertNotEmpty($listeners);
|
||||
// ArticleApproved event exists but has no listeners after publishing redesign
|
||||
// $listeners = Event::getListeners(ArticleApproved::class);
|
||||
// $this->assertNotEmpty($listeners);
|
||||
|
||||
$listeners = Event::getListeners(ArticleReadyToPublish::class);
|
||||
$this->assertNotEmpty($listeners);
|
||||
// ArticleReadyToPublish no longer exists - removed this check
|
||||
// $listeners = Event::getListeners(ArticleReadyToPublish::class);
|
||||
// $this->assertNotEmpty($listeners);
|
||||
|
||||
$listeners = Event::getListeners(ExceptionOccurred::class);
|
||||
$this->assertNotEmpty($listeners);
|
||||
|
|
@ -267,13 +270,11 @@ public function test_event_listener_registration_works(): void
|
|||
|
||||
public function test_job_retry_configuration(): void
|
||||
{
|
||||
$article = Article::factory()->create();
|
||||
$job = new PublishNextArticleJob();
|
||||
|
||||
$job = new PublishToLemmyJob($article);
|
||||
|
||||
// Test that job has retry configuration
|
||||
$this->assertObjectHasProperty('tries', $job);
|
||||
$this->assertObjectHasProperty('backoff', $job);
|
||||
// Test that job has unique configuration
|
||||
$this->assertObjectHasProperty('uniqueFor', $job);
|
||||
$this->assertEquals(300, $job->uniqueFor);
|
||||
}
|
||||
|
||||
public function test_job_queue_configuration(): void
|
||||
|
|
@ -284,13 +285,13 @@ public function test_job_queue_configuration(): void
|
|||
|
||||
$discoveryJob = new ArticleDiscoveryJob();
|
||||
$feedJob = new ArticleDiscoveryForFeedJob($feed);
|
||||
$publishJob = new PublishToLemmyJob($article);
|
||||
$publishJob = new PublishNextArticleJob();
|
||||
$syncJob = new SyncChannelPostsJob($channel);
|
||||
|
||||
// Test queue assignments
|
||||
$this->assertEquals('feed-discovery', $discoveryJob->queue ?? 'default');
|
||||
$this->assertEquals('feed-discovery', $feedJob->queue ?? 'discovery');
|
||||
$this->assertEquals('lemmy-posts', $publishJob->queue);
|
||||
$this->assertEquals('publishing', $publishJob->queue);
|
||||
$this->assertEquals('sync', $syncJob->queue ?? 'sync');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,109 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Tests\Unit\Jobs;
|
||||
|
||||
use App\Exceptions\PublishException;
|
||||
use App\Jobs\PublishToLemmyJob;
|
||||
use App\Models\Article;
|
||||
use App\Models\Feed;
|
||||
use App\Services\Article\ArticleFetcher;
|
||||
use App\Services\Publishing\ArticlePublishingService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Mockery;
|
||||
use Tests\TestCase;
|
||||
|
||||
class PublishToLemmyJobTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_constructor_sets_correct_queue_and_properties(): void
|
||||
{
|
||||
// Arrange
|
||||
$article = new Article(['title' => 'Test Article']);
|
||||
|
||||
// Act
|
||||
$job = new PublishToLemmyJob($article);
|
||||
|
||||
// Assert
|
||||
$this->assertEquals('lemmy-posts', $job->queue);
|
||||
$this->assertEquals(3, $job->tries);
|
||||
$this->assertEquals([60, 120, 300], $job->backoff);
|
||||
}
|
||||
|
||||
public function test_job_implements_should_queue(): void
|
||||
{
|
||||
// Arrange
|
||||
$article = new Article(['title' => 'Test Article']);
|
||||
$job = new PublishToLemmyJob($article);
|
||||
|
||||
// Assert
|
||||
$this->assertInstanceOf(\Illuminate\Contracts\Queue\ShouldQueue::class, $job);
|
||||
}
|
||||
|
||||
public function test_job_uses_queueable_trait(): void
|
||||
{
|
||||
// Arrange
|
||||
$article = new Article(['title' => 'Test Article']);
|
||||
$job = new PublishToLemmyJob($article);
|
||||
|
||||
// Assert
|
||||
$this->assertTrue(method_exists($job, 'onQueue'));
|
||||
$this->assertTrue(method_exists($job, 'onConnection'));
|
||||
$this->assertTrue(method_exists($job, 'delay'));
|
||||
$this->assertTrue(method_exists($job, 'fail'));
|
||||
}
|
||||
|
||||
public function test_handle_method_exists(): void
|
||||
{
|
||||
// Arrange
|
||||
$article = new Article(['title' => 'Test Article']);
|
||||
$job = new PublishToLemmyJob($article);
|
||||
|
||||
// Assert
|
||||
$this->assertTrue(method_exists($job, 'handle'));
|
||||
}
|
||||
|
||||
public function test_job_calls_article_fetcher_and_publishing_service(): void
|
||||
{
|
||||
// This is a structural test - we can't easily mock static methods
|
||||
// But we can verify the job has the correct structure
|
||||
|
||||
// Arrange
|
||||
$article = new Article(['title' => 'Test Article']);
|
||||
$job = new PublishToLemmyJob($article);
|
||||
|
||||
// Assert - Job should have handle method that uses the required services
|
||||
$this->assertTrue(method_exists($job, 'handle'));
|
||||
$this->assertIsObject($job);
|
||||
|
||||
// We can't easily test the actual execution due to static method calls
|
||||
// but we can verify the job structure is correct
|
||||
$this->assertTrue(true);
|
||||
}
|
||||
|
||||
public function test_job_properties_are_correct_type(): void
|
||||
{
|
||||
// Arrange
|
||||
$article = new Article(['title' => 'Test Article']);
|
||||
$job = new PublishToLemmyJob($article);
|
||||
|
||||
// Assert
|
||||
$this->assertIsInt($job->tries);
|
||||
$this->assertIsArray($job->backoff);
|
||||
$this->assertGreaterThan(0, $job->tries);
|
||||
$this->assertNotEmpty($job->backoff);
|
||||
}
|
||||
|
||||
public function test_job_backoff_increases_progressively(): void
|
||||
{
|
||||
// Arrange
|
||||
$article = new Article(['title' => 'Test Article']);
|
||||
$job = new PublishToLemmyJob($article);
|
||||
|
||||
// Assert - Backoff should increase with each attempt
|
||||
$backoff = $job->backoff;
|
||||
$this->assertCount(3, $backoff); // Should match tries
|
||||
$this->assertLessThan($backoff[1], $backoff[0]); // Second attempt waits longer than first
|
||||
$this->assertLessThan($backoff[2], $backoff[1]); // Third attempt waits longer than second
|
||||
}
|
||||
}
|
||||
|
|
@ -308,15 +308,19 @@ public function test_publish_to_channel_handles_string_channel_id(): void
|
|||
->once()
|
||||
->andReturn('token');
|
||||
|
||||
// Mock LemmyApiService - should receive integer conversion of channel_id
|
||||
// Mock LemmyApiService - should call getCommunityId for non-numeric channel_id
|
||||
$apiMock = Mockery::mock(LemmyApiService::class);
|
||||
$apiMock->shouldReceive('getCommunityId')
|
||||
->once()
|
||||
->with('string-42', 'token')
|
||||
->andReturn(42);
|
||||
$apiMock->shouldReceive('createPost')
|
||||
->once()
|
||||
->with(
|
||||
'token',
|
||||
'Test Title',
|
||||
'',
|
||||
0, // 'string-42' converts to 0
|
||||
42, // resolved community ID
|
||||
'https://example.com/article',
|
||||
null,
|
||||
null
|
||||
|
|
|
|||
Loading…
Reference in a new issue