fedi-feed-router/backend/tests/Unit/Models/ArticlePublicationTest.php

306 lines
12 KiB
PHP
Raw Permalink Normal View History

2025-08-10 21:18:20 +02:00
<?php
namespace Tests\Unit\Models;
2025-08-15 16:39:18 +02:00
use Domains\Article\Models\Article;
use Domains\Article\Models\ArticlePublication;
use Domains\Platform\Models\PlatformChannel;
2025-08-10 21:18:20 +02:00
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class ArticlePublicationTest extends TestCase
{
use RefreshDatabase;
public function test_fillable_fields(): void
{
$fillableFields = ['article_id', 'platform_channel_id', 'post_id', 'published_at', 'published_by', 'platform', 'publication_data'];
$publication = new ArticlePublication();
$this->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);
}
}