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

393 lines
No EOL
13 KiB
PHP

<?php
namespace Tests\Unit\Modules\Lemmy\Services;
use App\Enums\PlatformEnum;
use App\Exceptions\PlatformAuthException;
use App\Models\Article;
use App\Models\PlatformAccount;
use App\Models\PlatformChannel;
use App\Models\PlatformInstance;
use App\Modules\Lemmy\Services\LemmyApiService;
use App\Modules\Lemmy\Services\LemmyPublisher;
use App\Services\Auth\LemmyAuthService;
use Exception;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Queue;
use Mockery;
use Tests\TestCase;
class LemmyPublisherTest extends TestCase
{
use RefreshDatabase;
protected function setUp(): void
{
parent::setUp();
Queue::fake();
Http::fake();
}
protected function tearDown(): void
{
Mockery::close();
parent::tearDown();
}
public function test_constructor_creates_api_service(): void
{
$account = PlatformAccount::factory()->create([
'platform' => PlatformEnum::LEMMY,
'instance_url' => 'https://lemmy.test'
]);
$publisher = new LemmyPublisher($account);
$this->assertInstanceOf(LemmyPublisher::class, $publisher);
}
public function test_publish_to_channel_with_minimal_data(): void
{
$account = PlatformAccount::factory()->create([
'platform' => PlatformEnum::LEMMY,
'instance_url' => 'https://lemmy.test',
'username' => 'testuser',
'password' => 'testpass'
]);
$article = Article::factory()->create([
'url' => 'https://example.com/article'
]);
$instance = PlatformInstance::factory()->create([
'platform' => PlatformEnum::LEMMY,
'url' => 'https://lemmy.test'
]);
$channel = PlatformChannel::factory()->create([
'platform_instance_id' => $instance->id,
'channel_id' => 123,
'name' => 'testcommunity'
]);
$extractedData = [
'title' => 'Test Article',
'description' => 'Test Description'
];
$expectedResult = [
'post_view' => [
'post' => [
'id' => 456,
'name' => 'Test Article'
]
]
];
// Mock LemmyAuthService
$this->mock(LemmyAuthService::class, function ($mock) use ($account) {
$mock->shouldReceive('getToken')
->once()
->with($account)
->andReturn('test-jwt-token');
});
// Mock LemmyApiService
$apiServiceMock = Mockery::mock(LemmyApiService::class);
$apiServiceMock->shouldReceive('createPost')
->once()
->with(
'test-jwt-token',
'Test Article',
'Test Description',
123,
'https://example.com/article',
null,
null
)
->andReturn($expectedResult);
// Use reflection to replace the api service in the publisher
$publisher = new LemmyPublisher($account);
$reflection = new \ReflectionClass($publisher);
$apiProperty = $reflection->getProperty('api');
$apiProperty->setAccessible(true);
$apiProperty->setValue($publisher, $apiServiceMock);
$result = $publisher->publishToChannel($article, $extractedData, $channel);
$this->assertEquals($expectedResult, $result);
}
public function test_publish_to_channel_with_all_optional_data(): void
{
$account = PlatformAccount::factory()->create([
'platform' => PlatformEnum::LEMMY,
'instance_url' => 'https://lemmy.test',
'username' => 'testuser',
'password' => 'testpass'
]);
$article = Article::factory()->create([
'url' => 'https://example.com/article'
]);
$instance = PlatformInstance::factory()->create([
'platform' => PlatformEnum::LEMMY,
'url' => 'https://lemmy.test'
]);
$channel = PlatformChannel::factory()->create([
'platform_instance_id' => $instance->id,
'channel_id' => 123,
'name' => 'testcommunity'
]);
$extractedData = [
'title' => 'Test Article',
'description' => 'Test Description',
'thumbnail' => 'https://example.com/thumb.jpg',
'language_id' => 2
];
$expectedResult = [
'post_view' => [
'post' => [
'id' => 456,
'name' => 'Test Article'
]
]
];
// Mock LemmyAuthService
$this->mock(LemmyAuthService::class, function ($mock) use ($account) {
$mock->shouldReceive('getToken')
->once()
->with($account)
->andReturn('test-jwt-token');
});
// Mock LemmyApiService
$apiServiceMock = Mockery::mock(LemmyApiService::class);
$apiServiceMock->shouldReceive('createPost')
->once()
->with(
'test-jwt-token',
'Test Article',
'Test Description',
123,
'https://example.com/article',
'https://example.com/thumb.jpg',
2
)
->andReturn($expectedResult);
// Use reflection to replace the api service in the publisher
$publisher = new LemmyPublisher($account);
$reflection = new \ReflectionClass($publisher);
$apiProperty = $reflection->getProperty('api');
$apiProperty->setAccessible(true);
$apiProperty->setValue($publisher, $apiServiceMock);
$result = $publisher->publishToChannel($article, $extractedData, $channel);
$this->assertEquals($expectedResult, $result);
}
public function test_publish_to_channel_with_missing_title_uses_default(): void
{
$this->expectNotToPerformAssertions();
$account = PlatformAccount::factory()->create([
'platform' => PlatformEnum::LEMMY,
'instance_url' => 'https://lemmy.test',
'username' => 'testuser',
'password' => 'testpass'
]);
$article = Article::factory()->create([
'url' => 'https://example.com/article'
]);
$instance = PlatformInstance::factory()->create([
'platform' => PlatformEnum::LEMMY,
'url' => 'https://lemmy.test'
]);
$channel = PlatformChannel::factory()->create([
'platform_instance_id' => $instance->id,
'channel_id' => 123,
'name' => 'testcommunity'
]);
$extractedData = [
'description' => 'Test Description'
];
// Mock LemmyAuthService
$this->mock(LemmyAuthService::class, function ($mock) use ($account) {
$mock->shouldReceive('getToken')
->once()
->with($account)
->andReturn('test-jwt-token');
});
// Mock LemmyApiService
$apiServiceMock = Mockery::mock(LemmyApiService::class);
$apiServiceMock->shouldReceive('createPost')
->once()
->with(
'test-jwt-token',
'Untitled',
'Test Description',
123,
'https://example.com/article',
null,
null
)
->andReturn([]);
// Use reflection to replace the api service in the publisher
$publisher = new LemmyPublisher($account);
$reflection = new \ReflectionClass($publisher);
$apiProperty = $reflection->getProperty('api');
$apiProperty->setAccessible(true);
$apiProperty->setValue($publisher, $apiServiceMock);
$publisher->publishToChannel($article, $extractedData, $channel);
}
public function test_publish_to_channel_with_missing_description_uses_default(): void
{
$this->expectNotToPerformAssertions();
$account = PlatformAccount::factory()->create([
'platform' => PlatformEnum::LEMMY,
'instance_url' => 'https://lemmy.test',
'username' => 'testuser',
'password' => 'testpass'
]);
$article = Article::factory()->create([
'url' => 'https://example.com/article'
]);
$instance = PlatformInstance::factory()->create([
'platform' => PlatformEnum::LEMMY,
'url' => 'https://lemmy.test'
]);
$channel = PlatformChannel::factory()->create([
'platform_instance_id' => $instance->id,
'channel_id' => 123,
'name' => 'testcommunity'
]);
$extractedData = [
'title' => 'Test Title'
];
// Mock LemmyAuthService
$this->mock(LemmyAuthService::class, function ($mock) use ($account) {
$mock->shouldReceive('getToken')
->once()
->with($account)
->andReturn('test-jwt-token');
});
// Mock LemmyApiService
$apiServiceMock = Mockery::mock(LemmyApiService::class);
$apiServiceMock->shouldReceive('createPost')
->once()
->with(
'test-jwt-token',
'Test Title',
'',
123,
'https://example.com/article',
null,
null
)
->andReturn([]);
// Use reflection to replace the api service in the publisher
$publisher = new LemmyPublisher($account);
$reflection = new \ReflectionClass($publisher);
$apiProperty = $reflection->getProperty('api');
$apiProperty->setAccessible(true);
$apiProperty->setValue($publisher, $apiServiceMock);
$publisher->publishToChannel($article, $extractedData, $channel);
}
public function test_publish_to_channel_throws_platform_auth_exception_when_auth_fails(): void
{
$account = PlatformAccount::factory()->create([
'platform' => PlatformEnum::LEMMY,
'instance_url' => 'https://lemmy.test',
'username' => 'testuser',
'password' => 'testpass'
]);
$article = Article::factory()->create();
$channel = PlatformChannel::factory()->create();
$extractedData = ['title' => 'Test', 'description' => 'Test'];
// Mock LemmyAuthService to throw exception
$this->mock(LemmyAuthService::class, function ($mock) use ($account) {
$mock->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_exception_when_create_post_fails(): void
{
$account = PlatformAccount::factory()->create([
'platform' => PlatformEnum::LEMMY,
'instance_url' => 'https://lemmy.test',
'username' => 'testuser',
'password' => 'testpass'
]);
$article = Article::factory()->create();
$channel = PlatformChannel::factory()->create();
$extractedData = ['title' => 'Test', 'description' => 'Test'];
// Mock LemmyAuthService
$this->mock(LemmyAuthService::class, function ($mock) use ($account) {
$mock->shouldReceive('getToken')
->once()
->with($account)
->andReturn('test-jwt-token');
});
// Mock LemmyApiService to throw exception
$apiServiceMock = Mockery::mock(LemmyApiService::class);
$apiServiceMock->shouldReceive('createPost')
->once()
->andThrow(new Exception('Post creation failed'));
// Use reflection to replace the api service in the publisher
$publisher = new LemmyPublisher($account);
$reflection = new \ReflectionClass($publisher);
$apiProperty = $reflection->getProperty('api');
$apiProperty->setAccessible(true);
$apiProperty->setValue($publisher, $apiServiceMock);
$this->expectException(Exception::class);
$this->expectExceptionMessage('Post creation failed');
$publisher->publishToChannel($article, $extractedData, $channel);
}
}