fedi-feed-router/backend/tests/Unit/Modules/Lemmy/Services/LemmyPublisherTest.php

338 lines
11 KiB
PHP
Raw Normal View History

2025-08-10 04:16:53 +02:00
<?php
namespace Tests\Unit\Modules\Lemmy\Services;
use App\Modules\Lemmy\Services\LemmyPublisher;
use App\Modules\Lemmy\Services\LemmyApiService;
use App\Services\Auth\LemmyAuthService;
use App\Models\Article;
use App\Models\PlatformAccount;
use App\Models\PlatformChannel;
use App\Exceptions\PlatformAuthException;
use App\Enums\PlatformEnum;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
use Mockery;
use Exception;
class LemmyPublisherTest extends TestCase
{
use RefreshDatabase;
protected function tearDown(): void
{
Mockery::close();
parent::tearDown();
}
public function test_constructor_initializes_api_service(): void
{
$account = PlatformAccount::factory()->make([
'instance_url' => 'https://lemmy.world'
]);
$publisher = new LemmyPublisher($account);
$reflection = new \ReflectionClass($publisher);
$apiProperty = $reflection->getProperty('api');
$apiProperty->setAccessible(true);
$this->assertInstanceOf(LemmyApiService::class, $apiProperty->getValue($publisher));
$accountProperty = $reflection->getProperty('account');
$accountProperty->setAccessible(true);
$this->assertSame($account, $accountProperty->getValue($publisher));
}
public function test_publish_to_channel_with_all_data(): void
{
$account = PlatformAccount::factory()->make([
'instance_url' => 'https://lemmy.world'
]);
$article = Article::factory()->make([
'url' => 'https://example.com/article'
]);
$channel = PlatformChannel::factory()->make([
'channel_id' => '42'
]);
$extractedData = [
'title' => 'Test Article',
'description' => 'Test Description',
'thumbnail' => 'https://example.com/thumb.jpg',
'language_id' => 5
];
2025-08-10 15:20:28 +02:00
// Mock LemmyAuthService via service container
$authMock = Mockery::mock(LemmyAuthService::class);
2025-08-10 04:16:53 +02:00
$authMock->shouldReceive('getToken')
->once()
->with($account)
->andReturn('test-token');
2025-08-10 15:20:28 +02:00
$this->app->instance(LemmyAuthService::class, $authMock);
2025-08-10 04:16:53 +02:00
// Mock LemmyApiService
$apiMock = Mockery::mock(LemmyApiService::class);
$apiMock->shouldReceive('createPost')
->once()
->with(
'test-token',
'Test Article',
'Test Description',
42,
'https://example.com/article',
'https://example.com/thumb.jpg',
5
)
->andReturn(['post_view' => ['post' => ['id' => 999]]]);
// Create publisher and inject mocked API using reflection
$publisher = new LemmyPublisher($account);
$reflection = new \ReflectionClass($publisher);
$apiProperty = $reflection->getProperty('api');
$apiProperty->setAccessible(true);
$apiProperty->setValue($publisher, $apiMock);
$result = $publisher->publishToChannel($article, $extractedData, $channel);
$this->assertEquals(['post_view' => ['post' => ['id' => 999]]], $result);
}
public function test_publish_to_channel_with_minimal_data(): void
{
$account = PlatformAccount::factory()->make([
'instance_url' => 'https://lemmy.world'
]);
$article = Article::factory()->make([
'url' => 'https://example.com/article'
]);
$channel = PlatformChannel::factory()->make([
'channel_id' => '24'
]);
$extractedData = [];
// Mock LemmyAuthService
2025-08-10 15:20:28 +02:00
$authMock = Mockery::mock(LemmyAuthService::class);
2025-08-10 04:16:53 +02:00
$authMock->shouldReceive('getToken')
->once()
->with($account)
->andReturn('minimal-token');
2025-08-10 15:20:28 +02:00
$this->app->instance(LemmyAuthService::class, $authMock);
2025-08-10 04:16:53 +02:00
// Mock LemmyApiService
$apiMock = Mockery::mock(LemmyApiService::class);
$apiMock->shouldReceive('createPost')
->once()
->with(
'minimal-token',
'Untitled',
'',
24,
'https://example.com/article',
null,
null
)
->andReturn(['post_view' => ['post' => ['id' => 777]]]);
// Create publisher and inject mocked API using reflection
$publisher = new LemmyPublisher($account);
$reflection = new \ReflectionClass($publisher);
$apiProperty = $reflection->getProperty('api');
$apiProperty->setAccessible(true);
$apiProperty->setValue($publisher, $apiMock);
$result = $publisher->publishToChannel($article, $extractedData, $channel);
$this->assertEquals(['post_view' => ['post' => ['id' => 777]]], $result);
}
public function test_publish_to_channel_without_thumbnail(): void
{
$account = PlatformAccount::factory()->make([
'instance_url' => 'https://lemmy.world'
]);
$article = Article::factory()->make([
'url' => 'https://example.com/article'
]);
$channel = PlatformChannel::factory()->make([
'channel_id' => '33'
]);
$extractedData = [
'title' => 'No Thumbnail Article',
'description' => 'Article without thumbnail',
'language_id' => 2
];
// Mock LemmyAuthService
2025-08-10 15:20:28 +02:00
$authMock = Mockery::mock(LemmyAuthService::class);
$this->app->instance(LemmyAuthService::class, $authMock);
2025-08-10 04:16:53 +02:00
$authMock->shouldReceive('getToken')
->once()
->with($account)
->andReturn('no-thumb-token');
// Mock LemmyApiService
$apiMock = Mockery::mock(LemmyApiService::class);
$apiMock->shouldReceive('createPost')
->once()
->with(
'no-thumb-token',
'No Thumbnail Article',
'Article without thumbnail',
33,
'https://example.com/article',
null,
2
)
->andReturn(['post_view' => ['post' => ['id' => 555]]]);
// Create publisher and inject mocked API using reflection
$publisher = new LemmyPublisher($account);
$reflection = new \ReflectionClass($publisher);
$apiProperty = $reflection->getProperty('api');
$apiProperty->setAccessible(true);
$apiProperty->setValue($publisher, $apiMock);
$result = $publisher->publishToChannel($article, $extractedData, $channel);
$this->assertEquals(['post_view' => ['post' => ['id' => 555]]], $result);
}
public function test_publish_to_channel_throws_platform_auth_exception(): void
{
$account = PlatformAccount::factory()->make([
'instance_url' => 'https://lemmy.world'
]);
$article = Article::factory()->make();
$channel = PlatformChannel::factory()->make();
$extractedData = [];
// Mock LemmyAuthService to throw exception
2025-08-10 15:20:28 +02:00
$authMock = Mockery::mock(LemmyAuthService::class);
$this->app->instance(LemmyAuthService::class, $authMock);
2025-08-10 04:16:53 +02:00
$authMock->shouldReceive('getToken')
->once()
->with($account)
->andThrow(new PlatformAuthException(PlatformEnum::LEMMY, 'Auth failed'));
$publisher = new LemmyPublisher($account);
$this->expectException(PlatformAuthException::class);
$this->expectExceptionMessage('Auth failed');
$publisher->publishToChannel($article, $extractedData, $channel);
}
public function test_publish_to_channel_throws_api_exception(): void
{
$account = PlatformAccount::factory()->make([
'instance_url' => 'https://lemmy.world'
]);
$article = Article::factory()->make([
'url' => 'https://example.com/article'
]);
$channel = PlatformChannel::factory()->make([
'channel_id' => '42'
]);
$extractedData = [
'title' => 'Test Article'
];
2025-08-10 15:20:28 +02:00
// Mock LemmyAuthService via service container
$authMock = Mockery::mock(LemmyAuthService::class);
2025-08-10 04:16:53 +02:00
$authMock->shouldReceive('getToken')
->once()
->with($account)
->andReturn('test-token');
2025-08-10 15:20:28 +02:00
$this->app->instance(LemmyAuthService::class, $authMock);
2025-08-10 04:16:53 +02:00
// Mock LemmyApiService to throw exception
$apiMock = Mockery::mock(LemmyApiService::class);
$apiMock->shouldReceive('createPost')
->once()
->andThrow(new Exception('API Error'));
// Create publisher and inject mocked API using reflection
$publisher = new LemmyPublisher($account);
$reflection = new \ReflectionClass($publisher);
$apiProperty = $reflection->getProperty('api');
$apiProperty->setAccessible(true);
$apiProperty->setValue($publisher, $apiMock);
$this->expectException(Exception::class);
$this->expectExceptionMessage('API Error');
$publisher->publishToChannel($article, $extractedData, $channel);
}
public function test_publish_to_channel_handles_string_channel_id(): void
{
$account = PlatformAccount::factory()->make([
'instance_url' => 'https://lemmy.world'
]);
$article = Article::factory()->make([
'url' => 'https://example.com/article'
]);
$channel = PlatformChannel::factory()->make([
'channel_id' => 'string-42'
]);
$extractedData = [
'title' => 'Test Title'
];
// Mock LemmyAuthService
2025-08-10 15:20:28 +02:00
$authMock = Mockery::mock(LemmyAuthService::class);
$this->app->instance(LemmyAuthService::class, $authMock);
2025-08-10 04:16:53 +02:00
$authMock->shouldReceive('getToken')
->once()
->andReturn('token');
// Mock LemmyApiService - should receive integer conversion of channel_id
$apiMock = Mockery::mock(LemmyApiService::class);
$apiMock->shouldReceive('createPost')
->once()
->with(
'token',
'Test Title',
'',
0, // 'string-42' converts to 0
'https://example.com/article',
null,
null
)
->andReturn(['success' => true]);
// Create publisher and inject mocked API using reflection
$publisher = new LemmyPublisher($account);
$reflection = new \ReflectionClass($publisher);
$apiProperty = $reflection->getProperty('api');
$apiProperty->setAccessible(true);
$apiProperty->setValue($publisher, $apiMock);
$result = $publisher->publishToChannel($article, $extractedData, $channel);
$this->assertEquals(['success' => true], $result);
}
}