fedi-feed-router/backend/tests/Unit/Services/Platform/ChannelLanguageDetectionServiceTest.php
2025-08-16 09:43:38 +02:00

230 lines
No EOL
8.3 KiB
PHP

<?php
namespace Tests\Unit\Services\Platform;
use Domains\Platform\Services\ChannelLanguageDetectionService;
use Domains\Platform\Models\PlatformInstance;
use Domains\Platform\Models\PlatformAccount;
use Domains\Settings\Models\Language;
use Domains\Platform\Exceptions\ChannelException;
use Domains\Platform\Api\Lemmy\LemmyApiService;
use Tests\TestCase;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Mockery;
class ChannelLanguageDetectionServiceTest extends TestCase
{
use RefreshDatabase;
private ChannelLanguageDetectionService $service;
private PlatformInstance $platformInstance;
private PlatformAccount $platformAccount;
private Language $englishLanguage;
private Language $dutchLanguage;
protected function setUp(): void
{
parent::setUp();
$this->service = new ChannelLanguageDetectionService();
// Create test data
$this->platformInstance = PlatformInstance::factory()->create([
'url' => 'https://lemmy.example.com',
'platform' => 'lemmy'
]);
$this->platformAccount = PlatformAccount::factory()->create([
'instance_url' => $this->platformInstance->url,
'is_active' => true,
'settings' => ['api_token' => 'test-token']
]);
$this->englishLanguage = Language::factory()->create([
'short_code' => 'en',
'name' => 'English',
'is_active' => true
]);
$this->dutchLanguage = Language::factory()->create([
'short_code' => 'nl',
'name' => 'Dutch',
'is_active' => true
]);
}
protected function tearDown(): void
{
Mockery::close();
parent::tearDown();
}
public function test_successfully_detects_channel_language_when_community_exists(): void
{
// Mock the LemmyApiService
$mockApiService = Mockery::mock(LemmyApiService::class);
// Mock community details response
$communityDetails = [
'community' => [
'id' => 123,
'name' => 'test-community',
'language_id' => 1
]
];
// Mock platform languages response
$platformLanguages = [
['id' => 1, 'code' => 'en', 'name' => 'English'],
['id' => 2, 'code' => 'nl', 'name' => 'Dutch']
];
$mockApiService->shouldReceive('getCommunityDetails')
->with('test-community', 'test-token')
->once()
->andReturn($communityDetails);
$mockApiService->shouldReceive('getLanguages')
->once()
->andReturn($platformLanguages);
// Mock the service to use our mock API service
$service = Mockery::mock(ChannelLanguageDetectionService::class)->makePartial();
$service->shouldAllowMockingProtectedMethods();
// Override the API service creation
$service->shouldReceive('createApiService')
->with($this->platformInstance->url)
->andReturn($mockApiService);
$result = $service->detectChannelLanguages('test-community', $this->platformInstance->id);
$this->assertIsArray($result);
$this->assertArrayHasKey('language_id', $result);
$this->assertArrayHasKey('matched_languages', $result);
$this->assertArrayHasKey('community_details', $result);
$this->assertIsInt($result['language_id']);
$this->assertIsArray($result['matched_languages']);
}
public function test_throws_exception_when_no_active_platform_account_exists(): void
{
// Deactivate the platform account
$this->platformAccount->update(['is_active' => false]);
$this->expectException(ChannelException::class);
$this->expectExceptionMessage('No active platform account found for this instance');
$this->service->detectChannelLanguages('test-community', $this->platformInstance->id);
}
public function test_throws_exception_when_no_authentication_token_exists(): void
{
// Remove the API token
$this->platformAccount->update(['settings' => []]);
$this->expectException(ChannelException::class);
$this->expectExceptionMessage('Failed to authenticate with platform instance');
$this->service->detectChannelLanguages('test-community', $this->platformInstance->id);
}
public function test_throws_channel_not_found_exception_when_community_does_not_exist(): void
{
// Mock the LemmyApiService to throw a 404 exception
$mockApiService = Mockery::mock(LemmyApiService::class);
$mockApiService->shouldReceive('getCommunityDetails')
->with('nonexistent-community', 'test-token')
->once()
->andThrow(new \Exception("Community 'nonexistent-community' not found on this instance"));
// Override service behavior
$service = Mockery::mock(ChannelLanguageDetectionService::class)->makePartial();
$service->shouldAllowMockingProtectedMethods();
$service->shouldReceive('createApiService')
->with($this->platformInstance->url)
->andReturn($mockApiService);
$this->expectException(ChannelException::class);
$this->expectExceptionMessage("Channel 'nonexistent-community' not found on instance");
$service->detectChannelLanguages('nonexistent-community', $this->platformInstance->id);
}
public function test_falls_back_to_default_language_when_api_fails(): void
{
// Set up default language in config
config(['languages.default' => 'en']);
// Mock the LemmyApiService to throw a connection exception
$mockApiService = Mockery::mock(LemmyApiService::class);
$mockApiService->shouldReceive('getCommunityDetails')
->with('test-community', 'test-token')
->once()
->andThrow(new \Exception('Connection timeout'));
// Override service behavior
$service = Mockery::mock(ChannelLanguageDetectionService::class)->makePartial();
$service->shouldAllowMockingProtectedMethods();
$service->shouldReceive('createApiService')
->with($this->platformInstance->url)
->andReturn($mockApiService);
$result = $service->detectChannelLanguages('test-community', $this->platformInstance->id);
$this->assertIsArray($result);
$this->assertArrayHasKey('fallback_used', $result);
$this->assertTrue($result['fallback_used']);
$this->assertEquals($this->englishLanguage->id, $result['language_id']);
$this->assertArrayHasKey('original_error', $result);
}
public function test_throws_exception_when_no_matching_languages_and_no_fallback(): void
{
// Create a language that won't match
Language::factory()->create([
'short_code' => 'fr',
'name' => 'French',
'is_active' => true
]);
// Deactivate English so no fallback is available
$this->englishLanguage->update(['is_active' => false]);
$this->dutchLanguage->update(['is_active' => false]);
// Mock the LemmyApiService
$mockApiService = Mockery::mock(LemmyApiService::class);
$communityDetails = [
'community' => [
'id' => 123,
'name' => 'test-community',
'language_id' => 1
]
];
// Platform only supports German, which we don't have in system
$platformLanguages = [
['id' => 1, 'code' => 'de', 'name' => 'German']
];
$mockApiService->shouldReceive('getCommunityDetails')
->andReturn($communityDetails);
$mockApiService->shouldReceive('getLanguages')
->andReturn($platformLanguages);
$service = Mockery::mock(ChannelLanguageDetectionService::class)->makePartial();
$service->shouldAllowMockingProtectedMethods();
$service->shouldReceive('createApiService')
->with($this->platformInstance->url)
->andReturn($mockApiService);
$this->expectException(ChannelException::class);
$this->expectExceptionMessage('No matching languages found');
$service->detectChannelLanguages('test-community', $this->platformInstance->id);
}
}