create(); PlatformChannel::factory()->count(3)->create(['platform_instance_id' => $instance->id]); $response = $this->getJson('/api/v1/platform-channels'); $response->assertStatus(200) ->assertJsonStructure([ 'success', 'message', 'data' => [ '*' => [ 'id', 'platform_instance_id', 'channel_id', 'name', 'display_name', 'description', 'is_active', 'created_at', 'updated_at', 'platform_instance' ] ] ]) ->assertJson([ 'success' => true, 'message' => 'Platform channels retrieved successfully.' ]); } public function test_store_creates_platform_channel_successfully(): void { $instance = PlatformInstance::factory()->create(); // Create a platform account for this instance first PlatformAccount::factory()->create([ 'instance_url' => $instance->url, 'is_active' => true, 'settings' => ['api_token' => 'test-token'] ]); // Create a language for the test $language = Language::factory()->create([ 'short_code' => 'en', 'name' => 'English', 'is_active' => true ]); // Mock the ChannelLanguageDetectionService $mockService = Mockery::mock(ChannelLanguageDetectionService::class); $mockService->shouldReceive('detectChannelLanguages') ->with('Test Channel', $instance->id) ->once() ->andReturn([ 'language_id' => $language->id, 'matched_languages' => [$language->id], 'community_details' => ['community' => ['id' => 123]] ]); $this->app->bind(ChannelLanguageDetectionService::class, function () use ($mockService) { return $mockService; }); $data = [ 'platform_instance_id' => $instance->id, 'channel_id' => 'test_channel', 'name' => 'Test Channel', 'display_name' => 'Test Channel Display', 'description' => 'A test channel', 'is_active' => true ]; $response = $this->postJson('/api/v1/platform-channels', $data); $response->assertStatus(201) ->assertJsonStructure([ 'success', 'message', 'data' => [ 'id', 'platform_instance_id', 'channel_id', 'name', 'display_name', 'description', 'is_active', 'created_at', 'updated_at', ] ]) ->assertJson([ 'success' => true, 'message' => 'Platform channel created successfully and linked to platform account!' ]); $this->assertDatabaseHas('platform_channels', [ 'platform_instance_id' => $instance->id, 'channel_id' => 'test_channel', 'name' => 'Test Channel', ]); } public function test_store_validates_required_fields(): void { $response = $this->postJson('/api/v1/platform-channels', []); $response->assertStatus(422) ->assertJsonValidationErrors(['platform_instance_id', 'channel_id', 'name']); } public function test_store_validates_platform_instance_exists(): void { $data = [ 'platform_instance_id' => 999, 'channel_id' => 'test_channel', 'name' => 'Test Channel' ]; $response = $this->postJson('/api/v1/platform-channels', $data); $response->assertStatus(422) ->assertJsonValidationErrors(['platform_instance_id']); } public function test_show_returns_platform_channel_successfully(): void { $instance = PlatformInstance::factory()->create(); $channel = PlatformChannel::factory()->create(['platform_instance_id' => $instance->id]); $response = $this->getJson("/api/v1/platform-channels/{$channel->id}"); $response->assertStatus(200) ->assertJsonStructure([ 'success', 'message', 'data' => [ 'id', 'platform_instance_id', 'channel_id', 'name', 'display_name', 'description', 'is_active', 'created_at', 'updated_at', 'platform_instance' ] ]) ->assertJson([ 'success' => true, 'message' => 'Platform channel retrieved successfully.', 'data' => [ 'id' => $channel->id, 'name' => $channel->name, ] ]); } public function test_update_modifies_platform_channel_successfully(): void { $instance = PlatformInstance::factory()->create(); $channel = PlatformChannel::factory()->create(['platform_instance_id' => $instance->id]); $updateData = [ 'name' => 'Updated Channel', 'display_name' => 'Updated Display Name', 'description' => 'Updated description', 'is_active' => false ]; $response = $this->putJson("/api/v1/platform-channels/{$channel->id}", $updateData); $response->assertStatus(200) ->assertJson([ 'success' => true, 'message' => 'Platform channel updated successfully!' ]); $this->assertDatabaseHas('platform_channels', [ 'id' => $channel->id, 'name' => 'Updated Channel', 'display_name' => 'Updated Display Name', 'is_active' => false, ]); } public function test_destroy_deletes_platform_channel_successfully(): void { $instance = PlatformInstance::factory()->create(); $channel = PlatformChannel::factory()->create(['platform_instance_id' => $instance->id]); $response = $this->deleteJson("/api/v1/platform-channels/{$channel->id}"); $response->assertStatus(200) ->assertJson([ 'success' => true, 'message' => 'Platform channel deleted successfully!' ]); $this->assertDatabaseMissing('platform_channels', [ 'id' => $channel->id ]); } public function test_toggle_activates_inactive_channel(): void { $instance = PlatformInstance::factory()->create(); $channel = PlatformChannel::factory()->create([ 'platform_instance_id' => $instance->id, 'is_active' => false ]); $response = $this->postJson("/api/v1/platform-channels/{$channel->id}/toggle"); $response->assertStatus(200) ->assertJson([ 'success' => true, 'message' => 'Platform channel activated successfully!' ]); $this->assertDatabaseHas('platform_channels', [ 'id' => $channel->id, 'is_active' => true ]); } public function test_toggle_deactivates_active_channel(): void { $instance = PlatformInstance::factory()->create(); $channel = PlatformChannel::factory()->create([ 'platform_instance_id' => $instance->id, 'is_active' => true ]); $response = $this->postJson("/api/v1/platform-channels/{$channel->id}/toggle"); $response->assertStatus(200) ->assertJson([ 'success' => true, 'message' => 'Platform channel deactivated successfully!' ]); $this->assertDatabaseHas('platform_channels', [ 'id' => $channel->id, 'is_active' => false ]); } public function test_get_communities_returns_successful_response(): void { // Arrange $instance = PlatformInstance::factory()->create(['url' => 'lemmy.world']); $account = PlatformAccount::factory()->create([ 'instance_url' => $instance->url, 'is_active' => true, 'settings' => ['api_token' => 'test-token'] ]); // Mock LemmyApiService $mockApiService = Mockery::mock(LemmyApiService::class); $mockApiService->shouldReceive('listCommunities') ->with('test-token', 'Local', 'Active', 50, 1, false) ->once() ->andReturn([ 'communities' => [ [ 'community' => [ 'id' => 1, 'name' => 'technology', 'title' => 'Technology', 'description' => 'Tech discussions', 'nsfw' => false, 'local' => true ], 'counts' => [ 'subscribers' => 1500, 'posts' => 250 ] ], [ 'community' => [ 'id' => 2, 'name' => 'news', 'title' => 'News', 'description' => 'Latest news', 'nsfw' => false, 'local' => true ], 'counts' => [ 'subscribers' => 2300, 'posts' => 450 ] ] ] ]); $this->app->bind(LemmyApiService::class, function () use ($mockApiService) { return $mockApiService; }); // Act $response = $this->getJson('/api/v1/platform-channels/communities?platform_instance_id=' . $instance->id); // Assert $response->assertStatus(200) ->assertJsonStructure([ 'success', 'message', 'data' => [ 'communities' => [ '*' => [ 'id', 'name', 'title', 'description', 'nsfw', 'local', 'subscribers', 'posts', 'display_text' ] ], 'total', 'platform_instance' => [ 'id', 'name', 'url' ], 'parameters' => [ 'type', 'sort', 'limit', 'page', 'show_nsfw' ] ] ]) ->assertJson([ 'success' => true, 'message' => 'Communities retrieved successfully.', 'data' => [ 'communities' => [ [ 'id' => 1, 'name' => 'technology', 'title' => 'Technology', 'subscribers' => 1500, 'display_text' => 'Technology (1,500 subscribers)' ], [ 'id' => 2, 'name' => 'news', 'title' => 'News', 'subscribers' => 2300, 'display_text' => 'News (2,300 subscribers)' ] ], 'total' => 2, 'parameters' => [ 'type' => 'Local', 'sort' => 'Active', 'limit' => 50, 'page' => 1, 'show_nsfw' => false ] ] ]); } public function test_get_communities_with_custom_parameters(): void { // Arrange $instance = PlatformInstance::factory()->create(['url' => 'lemmy.world']); $account = PlatformAccount::factory()->create([ 'instance_url' => $instance->url, 'is_active' => true, 'settings' => ['api_token' => 'test-token'] ]); // Mock LemmyApiService with custom parameters $mockApiService = Mockery::mock(LemmyApiService::class); $mockApiService->shouldReceive('listCommunities') ->with('test-token', 'All', 'TopMonth', 25, 2, true) ->once() ->andReturn(['communities' => []]); $this->app->bind(LemmyApiService::class, function () use ($mockApiService) { return $mockApiService; }); // Act $response = $this->getJson('/api/v1/platform-channels/communities?' . http_build_query([ 'platform_instance_id' => $instance->id, 'type' => 'All', 'sort' => 'TopMonth', 'limit' => 25, 'page' => 2, 'show_nsfw' => true ])); // Assert $response->assertStatus(200) ->assertJson([ 'success' => true, 'data' => [ 'parameters' => [ 'type' => 'All', 'sort' => 'TopMonth', 'limit' => 25, 'page' => 2, 'show_nsfw' => true ] ] ]); } public function test_get_communities_validates_required_platform_instance_id(): void { $response = $this->getJson('/api/v1/platform-channels/communities'); $response->assertStatus(422) ->assertJsonValidationErrors(['platform_instance_id']); } public function test_get_communities_validates_platform_instance_exists(): void { $response = $this->getJson('/api/v1/platform-channels/communities?platform_instance_id=999'); $response->assertStatus(422) ->assertJsonValidationErrors(['platform_instance_id']); } public function test_get_communities_validates_type_parameter(): void { $instance = PlatformInstance::factory()->create(); $response = $this->getJson('/api/v1/platform-channels/communities?' . http_build_query([ 'platform_instance_id' => $instance->id, 'type' => 'InvalidType' ])); $response->assertStatus(422) ->assertJsonValidationErrors(['type']); } public function test_get_communities_validates_sort_parameter(): void { $instance = PlatformInstance::factory()->create(); $response = $this->getJson('/api/v1/platform-channels/communities?' . http_build_query([ 'platform_instance_id' => $instance->id, 'sort' => 'InvalidSort' ])); $response->assertStatus(422) ->assertJsonValidationErrors(['sort']); } public function test_get_communities_validates_limit_parameter(): void { $instance = PlatformInstance::factory()->create(); $response = $this->getJson('/api/v1/platform-channels/communities?' . http_build_query([ 'platform_instance_id' => $instance->id, 'limit' => 0 // Invalid: below minimum ])); $response->assertStatus(422) ->assertJsonValidationErrors(['limit']); $response = $this->getJson('/api/v1/platform-channels/communities?' . http_build_query([ 'platform_instance_id' => $instance->id, 'limit' => 101 // Invalid: above maximum ])); $response->assertStatus(422) ->assertJsonValidationErrors(['limit']); } public function test_get_communities_validates_page_parameter(): void { $instance = PlatformInstance::factory()->create(); $response = $this->getJson('/api/v1/platform-channels/communities?' . http_build_query([ 'platform_instance_id' => $instance->id, 'page' => 0 // Invalid: below minimum ])); $response->assertStatus(422) ->assertJsonValidationErrors(['page']); } public function test_get_communities_fails_when_no_active_account_exists(): void { $instance = PlatformInstance::factory()->create(['url' => 'lemmy.world']); // Create an inactive account PlatformAccount::factory()->create([ 'instance_url' => $instance->url, 'is_active' => false ]); $response = $this->getJson('/api/v1/platform-channels/communities?platform_instance_id=' . $instance->id); $response->assertStatus(422) ->assertJson([ 'success' => false, 'message' => 'Cannot fetch communities: No active platform accounts found for this instance. Please create a platform account first.' ]); } public function test_get_communities_uses_cache(): void { // Arrange $instance = PlatformInstance::factory()->create(['url' => 'lemmy.world']); $account = PlatformAccount::factory()->create([ 'instance_url' => $instance->url, 'is_active' => true, 'settings' => ['api_token' => 'test-token'] ]); $mockData = ['communities' => [['community' => ['id' => 1, 'name' => 'test']]]]; $cacheKey = "communities:{$instance->id}:Local:Active:50:1:0"; // Set cache data Cache::put($cacheKey, $mockData, 600); // Mock should not be called since cache hit $mockApiService = Mockery::mock(LemmyApiService::class); $mockApiService->shouldNotReceive('listCommunities'); $this->app->bind(LemmyApiService::class, function () use ($mockApiService) { return $mockApiService; }); // Act $response = $this->getJson('/api/v1/platform-channels/communities?platform_instance_id=' . $instance->id); // Assert $response->assertStatus(200) ->assertJson(['success' => true]); } public function test_get_communities_clears_cache_on_error(): void { // Arrange $instance = PlatformInstance::factory()->create(['url' => 'lemmy.world']); $account = PlatformAccount::factory()->create([ 'instance_url' => $instance->url, 'is_active' => true, 'settings' => ['api_token' => 'test-token'] ]); $cacheKey = "communities:{$instance->id}:Local:Active:50:1:0"; // Mock LemmyApiService to throw exception $mockApiService = Mockery::mock(LemmyApiService::class); $mockApiService->shouldReceive('listCommunities') ->once() ->andThrow(new \Exception('API Error')); $this->app->bind(LemmyApiService::class, function () use ($mockApiService) { return $mockApiService; }); // Ensure cache is empty initially so API service gets called Cache::forget($cacheKey); $this->assertFalse(Cache::has($cacheKey)); // Act $response = $this->getJson('/api/v1/platform-channels/communities?platform_instance_id=' . $instance->id); // Assert $response->assertStatus(500); // Cache should still not exist since the error prevented caching $this->assertFalse(Cache::has($cacheKey)); } public function test_get_communities_handles_missing_community_data_gracefully(): void { // Arrange $instance = PlatformInstance::factory()->create(['url' => 'lemmy.world']); $account = PlatformAccount::factory()->create([ 'instance_url' => $instance->url, 'is_active' => true, 'settings' => ['api_token' => 'test-token'] ]); // Mock LemmyApiService with incomplete community data $mockApiService = Mockery::mock(LemmyApiService::class); $mockApiService->shouldReceive('listCommunities') ->once() ->andReturn([ 'communities' => [ [ 'community' => [ 'id' => 1, 'name' => 'minimal', // Missing title, description, etc. ], // Missing counts ] ] ]); $this->app->bind(LemmyApiService::class, function () use ($mockApiService) { return $mockApiService; }); // Act $response = $this->getJson('/api/v1/platform-channels/communities?platform_instance_id=' . $instance->id); // Assert $response->assertStatus(200) ->assertJson([ 'success' => true, 'data' => [ 'communities' => [ [ 'id' => 1, 'name' => 'minimal', 'title' => null, 'description' => null, 'nsfw' => false, 'local' => false, 'subscribers' => 0, 'posts' => 0, 'display_text' => 'minimal (0 subscribers)' ] ] ] ]); } }