assertEquals($fillableFields, $publication->getFillable()); } public function test_table_name(): void { $publication = new ArticlePublication(); $this->assertEquals('article_publications', $publication->getTable()); } public function test_casts_published_at_to_datetime(): void { $timestamp = now()->subHours(2); $publication = ArticlePublication::factory()->create(['published_at' => $timestamp]); $this->assertInstanceOf(\Carbon\Carbon::class, $publication->published_at); $this->assertEquals($timestamp->format('Y-m-d H:i:s'), $publication->published_at->format('Y-m-d H:i:s')); } public function test_casts_publication_data_to_array(): void { $publicationData = [ 'post_url' => 'https://lemmy.world/post/123', 'platform_response' => [ 'id' => 123, 'status' => 'success', 'metadata' => ['views' => 0, 'votes' => 0] ], 'retry_count' => 0 ]; $publication = ArticlePublication::factory()->create(['publication_data' => $publicationData]); $this->assertIsArray($publication->publication_data); $this->assertEquals($publicationData, $publication->publication_data); } public function test_belongs_to_article_relationship(): void { $article = Article::factory()->create(); $publication = ArticlePublication::factory()->create(['article_id' => $article->id]); $this->assertInstanceOf(Article::class, $publication->article); $this->assertEquals($article->id, $publication->article->id); $this->assertEquals($article->title, $publication->article->title); } public function test_publication_creation_with_factory(): void { $publication = ArticlePublication::factory()->create(); $this->assertInstanceOf(ArticlePublication::class, $publication); $this->assertNotNull($publication->article_id); $this->assertNotNull($publication->platform_channel_id); $this->assertIsString($publication->post_id); $this->assertInstanceOf(\Carbon\Carbon::class, $publication->published_at); $this->assertIsString($publication->published_by); } public function test_publication_creation_with_explicit_values(): void { $article = Article::factory()->create(); $channel = PlatformChannel::factory()->create(); $publicationData = ['status' => 'success', 'external_id' => '12345']; $publishedAt = now()->subHours(1); $publication = ArticlePublication::create([ 'article_id' => $article->id, 'platform_channel_id' => $channel->id, 'post_id' => 'post-123', 'published_at' => $publishedAt, 'published_by' => 'test_bot', 'platform' => 'lemmy', 'publication_data' => $publicationData ]); $this->assertEquals($article->id, $publication->article_id); $this->assertEquals($channel->id, $publication->platform_channel_id); $this->assertEquals('post-123', $publication->post_id); $this->assertEquals($publishedAt->format('Y-m-d H:i:s'), $publication->published_at->format('Y-m-d H:i:s')); $this->assertEquals('test_bot', $publication->published_by); $this->assertEquals('lemmy', $publication->platform); $this->assertEquals($publicationData, $publication->publication_data); } public function test_publication_factory_recently_published_state(): void { $publication = ArticlePublication::factory()->recentlyPublished()->create(); $this->assertInstanceOf(\Carbon\Carbon::class, $publication->published_at); $this->assertTrue($publication->published_at->isAfter(now()->subDay())); $this->assertTrue($publication->published_at->isBefore(now()->addMinute())); } public function test_publication_update(): void { $publication = ArticlePublication::factory()->create([ 'post_id' => 'original-id', 'published_by' => 'original_user' ]); $publication->update([ 'post_id' => 'updated-id', 'published_by' => 'updated_user' ]); $publication->refresh(); $this->assertEquals('updated-id', $publication->post_id); $this->assertEquals('updated_user', $publication->published_by); } public function test_publication_deletion(): void { $publication = ArticlePublication::factory()->create(); $publicationId = $publication->id; $publication->delete(); $this->assertDatabaseMissing('article_publications', ['id' => $publicationId]); } public function test_publication_data_can_be_empty_array(): void { $publication = ArticlePublication::factory()->create(['publication_data' => []]); $this->assertIsArray($publication->publication_data); $this->assertEmpty($publication->publication_data); } public function test_publication_data_can_be_null(): void { $publication = ArticlePublication::factory()->create(['publication_data' => null]); $this->assertNull($publication->publication_data); } public function test_publication_data_can_be_complex_structure(): void { $complexData = [ 'platform_response' => [ 'post_id' => 'abc123', 'url' => 'https://lemmy.world/post/abc123', 'created_at' => '2023-01-01T12:00:00Z', 'author' => [ 'id' => 456, 'name' => 'bot_user', 'display_name' => 'Bot User' ] ], 'metadata' => [ 'retry_attempts' => 1, 'processing_time_ms' => 1250, 'error_log' => [] ], 'analytics' => [ 'initial_views' => 0, 'initial_votes' => 0, 'engagement_tracked' => false ] ]; $publication = ArticlePublication::factory()->create(['publication_data' => $complexData]); $this->assertEquals($complexData, $publication->publication_data); $this->assertEquals('abc123', $publication->publication_data['platform_response']['post_id']); $this->assertEquals(1, $publication->publication_data['metadata']['retry_attempts']); $this->assertFalse($publication->publication_data['analytics']['engagement_tracked']); } public function test_publication_with_specific_published_at(): void { $timestamp = now()->subHours(3); $publication = ArticlePublication::factory()->create(['published_at' => $timestamp]); $this->assertInstanceOf(\Carbon\Carbon::class, $publication->published_at); $this->assertEquals($timestamp->format('Y-m-d H:i:s'), $publication->published_at->format('Y-m-d H:i:s')); } public function test_publication_with_specific_published_by(): void { $publication = ArticlePublication::factory()->create(['published_by' => 'custom_bot']); $this->assertEquals('custom_bot', $publication->published_by); } public function test_publication_with_specific_platform(): void { $publication = ArticlePublication::factory()->create(['platform' => 'lemmy']); $this->assertEquals('lemmy', $publication->platform); } public function test_publication_timestamps(): void { $publication = ArticlePublication::factory()->create(); $this->assertNotNull($publication->created_at); $this->assertNotNull($publication->updated_at); $this->assertInstanceOf(\Carbon\Carbon::class, $publication->created_at); $this->assertInstanceOf(\Carbon\Carbon::class, $publication->updated_at); } public function test_multiple_publications_for_same_article(): void { $article = Article::factory()->create(); $channel1 = PlatformChannel::factory()->create(); $channel2 = PlatformChannel::factory()->create(); $publication1 = ArticlePublication::factory()->create([ 'article_id' => $article->id, 'platform_channel_id' => $channel1->id, 'post_id' => 'post-1' ]); $publication2 = ArticlePublication::factory()->create([ 'article_id' => $article->id, 'platform_channel_id' => $channel2->id, 'post_id' => 'post-2' ]); $this->assertEquals($article->id, $publication1->article_id); $this->assertEquals($article->id, $publication2->article_id); $this->assertNotEquals($publication1->platform_channel_id, $publication2->platform_channel_id); $this->assertNotEquals($publication1->post_id, $publication2->post_id); } public function test_publication_with_different_platforms(): void { $publication1 = ArticlePublication::factory()->create(['platform' => 'lemmy']); $publication2 = ArticlePublication::factory()->create(['platform' => 'lemmy']); $this->assertEquals('lemmy', $publication1->platform); $this->assertEquals('lemmy', $publication2->platform); } public function test_publication_post_id_variations(): void { $publications = [ ArticlePublication::factory()->create(['post_id' => 'numeric-123']), ArticlePublication::factory()->create(['post_id' => 'uuid-' . fake()->uuid()]), ArticlePublication::factory()->create(['post_id' => 'alphanumeric_post_456']), ArticlePublication::factory()->create(['post_id' => '12345']), ]; foreach ($publications as $publication) { $this->assertIsString($publication->post_id); $this->assertNotEmpty($publication->post_id); } } public function test_publication_data_with_error_information(): void { $errorData = [ 'status' => 'failed', 'error' => [ 'code' => 403, 'message' => 'Insufficient permissions', 'details' => 'Bot account lacks posting privileges' ], 'retry_info' => [ 'max_retries' => 3, 'current_attempt' => 2, 'next_retry_at' => '2023-01-01T13:00:00Z' ] ]; $publication = ArticlePublication::factory()->create(['publication_data' => $errorData]); $this->assertEquals('failed', $publication->publication_data['status']); $this->assertEquals(403, $publication->publication_data['error']['code']); $this->assertEquals(2, $publication->publication_data['retry_info']['current_attempt']); } public function test_publication_relationship_with_article_data(): void { $article = Article::factory()->create([ 'title' => 'Test Article Title', 'description' => 'Test article description' ]); $publication = ArticlePublication::factory()->create(['article_id' => $article->id]); $this->assertEquals('Test Article Title', $publication->article->title); $this->assertEquals('Test article description', $publication->article->description); } }