diff --git a/src/GregModmanager.Core/Models/AppJsonContext.cs b/src/GregModmanager.Core/Models/AppJsonContext.cs index d7fe96d..8a3cc3c 100644 --- a/src/GregModmanager.Core/Models/AppJsonContext.cs +++ b/src/GregModmanager.Core/Models/AppJsonContext.cs @@ -34,6 +34,7 @@ namespace GregModmanager.Models; [JsonSerializable(typeof(int))] [JsonSerializable(typeof(RalphTaskStatus))] [JsonSerializable(typeof(AssetModMetadata))] +[JsonSerializable(typeof(object))] public partial class AppJsonContext : JsonSerializerContext { } diff --git a/src/GregModmanager.Core/Services/BetaPluginSource.cs b/src/GregModmanager.Core/Services/BetaPluginSource.cs index 3970159..b45d023 100644 --- a/src/GregModmanager.Core/Services/BetaPluginSource.cs +++ b/src/GregModmanager.Core/Services/BetaPluginSource.cs @@ -1,51 +1,52 @@ -using System.Text.Json; -using GregModmanager.Models; - -namespace GregModmanager.Services; - -/// -/// Beta distribution channel served from a custom backend. -/// Configure base URL via Preferences. -/// -public sealed class BetaPluginSource : IgregPluginChannelSource -{ - /// Preferences key for the beta server base URL. - public const string PrefKeyBetaServerUrl = "greg_beta_server_url"; - - private static readonly HttpClient _http = new(); - - public string ChannelName => "beta"; - - public IReadOnlyList ListPlugins() - { -#if WINDOWS || ANDROID || IOS || MACCATALYST - var url = Preferences.Default.Get(PrefKeyBetaServerUrl, string.Empty); -#else - var url = ""; -#endif - if (string.IsNullOrWhiteSpace(url)) - { - throw new InvalidOperationException( - "Beta-Kanal: Server-URL ist noch nicht konfiguriert. " + - "Setze die URL unter Einstellungen (Preferences-Key: greg_beta_server_url)."); - } - - var endpoint = url.TrimEnd('/') + "/api/plugins"; - - try - { - var response = _http.GetAsync(endpoint).GetAwaiter().GetResult(); - response.EnsureSuccessStatusCode(); - - var json = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); - - var plugins = JsonSerializer.Deserialize(json, AppJsonContext.Default.ListPluginPackageInfo); - - return plugins ?? new List(); - } - catch (Exception ex) - { - throw new InvalidOperationException($"Beta-Kanal: Fehler beim Abrufen der Plugins (URL: {endpoint}). Details: {ex.Message}", ex); - } - } -} +using System.Text.Json; +using GregModmanager.Models; +using GregModmanager.Localization; +using System.Collections.Generic; +using System.Net.Http; +using System; + +namespace GregModmanager.Services; + +/// +/// Beta distribution channel served from a custom backend. +/// Configure base URL via Preferences. +/// +public sealed class BetaPluginSource : IgregPluginChannelSource +{ + /// Preferences key for the beta server base URL. + public const string PrefKeyBetaServerUrl = "greg_beta_server_url"; + + private static readonly HttpClient _http = new(); + + public string ChannelName => "beta"; + + public IReadOnlyList ListPlugins() + { + var url = S.Preferences.GetString(PrefKeyBetaServerUrl, string.Empty); + if (string.IsNullOrWhiteSpace(url)) + { + throw new InvalidOperationException( + "Beta-Kanal: Server-URL ist noch nicht konfiguriert. " + + "Setze die URL unter Einstellungen (Preferences-Key: greg_beta_server_url)."); + } + + var endpoint = url.TrimEnd('/') + "/api/plugins"; + + try + { + using var request = new HttpRequestMessage(HttpMethod.Get, endpoint); + using var response = _http.Send(request); + response.EnsureSuccessStatusCode(); + + using var stream = response.Content.ReadAsStream(); + + var plugins = JsonSerializer.Deserialize(stream, AppJsonContext.Default.ListPluginPackageInfo); + + return plugins ?? new List(); + } + catch (Exception ex) + { + throw new InvalidOperationException($"Beta-Kanal: Fehler beim Abrufen der Plugins (URL: {endpoint}). Details: {ex.Message}", ex); + } + } +} diff --git a/src/GregModmanager.Core/Services/TelemetryService.cs b/src/GregModmanager.Core/Services/TelemetryService.cs index 8531b66..0c3f72c 100644 --- a/src/GregModmanager.Core/Services/TelemetryService.cs +++ b/src/GregModmanager.Core/Services/TelemetryService.cs @@ -99,7 +99,7 @@ public async Task TrackEventAsync(string eventName, object payload, Dictionary JsonSerializer.Serialize(sync, AppJsonContext.Default.SyncCollectionEvent), - _ => JsonSerializer.Serialize(payload, payload.GetType(), AppJsonContext.Default.Options) + _ => JsonSerializer.Serialize(payload, AppJsonContext.Default.Object) }; await PushToLokiAsync(eventName, message, labels); diff --git a/tests/GregModmanager.Tests/BetaPluginSourceTests.cs b/tests/GregModmanager.Tests/BetaPluginSourceTests.cs new file mode 100644 index 0000000..944d745 --- /dev/null +++ b/tests/GregModmanager.Tests/BetaPluginSourceTests.cs @@ -0,0 +1,50 @@ +using System; +using Xunit; +using GregModmanager.Services; +using GregModmanager.Localization; +using System.Collections.Generic; + +namespace GregModmanager.Tests; + +public class BetaPluginSourceTests +{ + private class MockPreferences : IPreferences + { + private readonly Dictionary _data = new(); + + public string GetString(string key, string defaultValue) => _data.TryGetValue(key, out var val) && val is string s ? s : defaultValue; + public bool GetBool(string key, bool defaultValue) => _data.TryGetValue(key, out var val) && val is bool b ? b : defaultValue; + public int GetInt(string key, int defaultValue) => _data.TryGetValue(key, out var val) && val is int i ? i : defaultValue; + + public void SetString(string key, string value) => _data[key] = value; + public void SetBool(string key, bool value) => _data[key] = value; + public void SetInt(string key, int value) => _data[key] = value; + public void Remove(string key) => _data.Remove(key); + } + + [Fact] + public void ListPlugins_ThrowsWhenUrlNotConfigured() + { + var mockPrefs = new MockPreferences(); + S.Preferences = mockPrefs; + + var source = new BetaPluginSource(); + + var ex = Assert.Throws(() => source.ListPlugins()); + Assert.Contains("Server-URL ist noch nicht konfiguriert", ex.Message); + } + + [Fact] + public void ListPlugins_ThrowsWhenUrlIsInvalidOrEndpointFails() + { + var mockPrefs = new MockPreferences(); + mockPrefs.SetString(BetaPluginSource.PrefKeyBetaServerUrl, "http://localhost:12345/invalid"); + S.Preferences = mockPrefs; + + var source = new BetaPluginSource(); + + var ex = Assert.Throws(() => source.ListPlugins()); + Assert.Contains("Fehler beim Abrufen der Plugins", ex.Message); + Assert.Contains("http://localhost:12345/invalid/api/plugins", ex.Message); + } +}