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); } }