230 lines
8.3 KiB
PHP
230 lines
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);
|
||
|
|
}
|
||
|
|
}
|