From 51d11f9a815582a0ced73e8054a182b25b829b56 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sat, 12 Oct 2024 22:10:39 +0100 Subject: [PATCH 1/7] Added custom serialization settings --- .../ServiceCollectionExtensions.cs | 27 ++++++- .../ServiceCollectionExtensions.cs | 25 ++++++- ...oreUnderscorePropertiesConverterFactory.cs | 71 +++++++++++++++++++ 3 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 src/PinguApps.Appwrite.Shared/Converters/IgnoreUnderscorePropertiesConverterFactory.cs diff --git a/src/PinguApps.Appwrite.Client/ServiceCollectionExtensions.cs b/src/PinguApps.Appwrite.Client/ServiceCollectionExtensions.cs index 2ec4fa24..254fd9c4 100644 --- a/src/PinguApps.Appwrite.Client/ServiceCollectionExtensions.cs +++ b/src/PinguApps.Appwrite.Client/ServiceCollectionExtensions.cs @@ -1,10 +1,13 @@ using System; using System.Net.Http; using System.Runtime.InteropServices; +using System.Text.Json; +using System.Text.Json.Serialization; using Microsoft.Extensions.DependencyInjection; using PinguApps.Appwrite.Client.Handlers; using PinguApps.Appwrite.Client.Internals; using PinguApps.Appwrite.Shared; +using PinguApps.Appwrite.Shared.Converters; using Refit; namespace PinguApps.Appwrite.Client; @@ -24,11 +27,13 @@ public static class ServiceCollectionExtensions /// The service collection, enabling chaining public static IServiceCollection AddAppwriteClient(this IServiceCollection services, string projectId, string endpoint = "https://cloud.appwrite.io/v1", RefitSettings? refitSettings = null) { + var customRefitSettings = AddSerializationConfigToRefitSettings(refitSettings); + services.AddSingleton(new Config(endpoint, projectId)); services.AddTransient(); services.AddTransient(); - services.AddRefitClient(refitSettings) + services.AddRefitClient(customRefitSettings) .ConfigureHttpClient(x => ConfigureHttpClient(x, endpoint)) .AddHttpMessageHandler() .AddHttpMessageHandler(); @@ -50,10 +55,12 @@ public static IServiceCollection AddAppwriteClient(this IServiceCollection servi /// The service collection, enabling chaining public static IServiceCollection AddAppwriteClientForServer(this IServiceCollection services, string projectId, string endpoint = "https://cloud.appwrite.io/v1", RefitSettings? refitSettings = null) { + var customRefitSettings = AddSerializationConfigToRefitSettings(refitSettings); + services.AddSingleton(new Config(endpoint, projectId)); services.AddTransient(); - services.AddRefitClient(refitSettings) + services.AddRefitClient(customRefitSettings) .ConfigureHttpClient(x => ConfigureHttpClient(x, endpoint)) .AddHttpMessageHandler() .ConfigurePrimaryHttpMessageHandler(ConfigurePrimaryHttpMessageHandler); @@ -78,6 +85,22 @@ private static void ConfigureHttpClient(HttpClient client, string endpoint) client.DefaultRequestHeaders.UserAgent.ParseAdd(BuildUserAgent()); } + private static RefitSettings AddSerializationConfigToRefitSettings(RefitSettings? refitSettings) + { + var settings = refitSettings ?? new RefitSettings(); + + var jsonOptions = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; + + jsonOptions.Converters.Add(new IgnoreUnderscorePropertiesConverterFactory()); + + settings.ContentSerializer = new SystemTextJsonContentSerializer(jsonOptions); + + return settings; + } + public static string BuildUserAgent() { var dotnetVersion = RuntimeInformation.FrameworkDescription.Replace("Microsoft .NET", ".NET").Trim(); diff --git a/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs b/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs index 032e60a9..787628da 100644 --- a/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs +++ b/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs @@ -1,11 +1,14 @@ using System; using System.Net.Http; using System.Runtime.InteropServices; +using System.Text.Json; +using System.Text.Json.Serialization; using Microsoft.Extensions.DependencyInjection; using PinguApps.Appwrite.Server.Clients; using PinguApps.Appwrite.Server.Handlers; using PinguApps.Appwrite.Server.Internals; using PinguApps.Appwrite.Shared; +using PinguApps.Appwrite.Shared.Converters; using Refit; namespace PinguApps.Appwrite.Server; @@ -26,15 +29,17 @@ public static class ServiceCollectionExtensions /// The service collection, enabling chaining public static IServiceCollection AddAppwriteServer(this IServiceCollection services, string projectId, string apiKey, string endpoint = "https://cloud.appwrite.io/v1", RefitSettings? refitSettings = null) { + var customRefitSettings = AddSerializationConfigToRefitSettings(refitSettings); + services.AddSingleton(new Config(endpoint, projectId, apiKey)); services.AddTransient(); - services.AddRefitClient(refitSettings) + services.AddRefitClient(customRefitSettings) .ConfigureHttpClient(x => ConfigureHttpClient(x, endpoint)) .AddHttpMessageHandler() .ConfigurePrimaryHttpMessageHandler(ConfigurePrimaryHttpMessageHandler); - services.AddRefitClient(refitSettings) + services.AddRefitClient(customRefitSettings) .ConfigureHttpClient(x => ConfigureHttpClient(x, endpoint)) .AddHttpMessageHandler() .ConfigurePrimaryHttpMessageHandler(ConfigurePrimaryHttpMessageHandler); @@ -60,6 +65,22 @@ private static void ConfigureHttpClient(HttpClient client, string endpoint) client.DefaultRequestHeaders.UserAgent.ParseAdd(BuildUserAgent()); } + private static RefitSettings AddSerializationConfigToRefitSettings(RefitSettings? refitSettings) + { + var settings = refitSettings ?? new RefitSettings(); + + var jsonOptions = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; + + jsonOptions.Converters.Add(new IgnoreUnderscorePropertiesConverterFactory()); + + settings.ContentSerializer = new SystemTextJsonContentSerializer(jsonOptions); + + return settings; + } + public static string BuildUserAgent() { var dotnetVersion = RuntimeInformation.FrameworkDescription.Replace("Microsoft .NET", ".NET").Trim(); diff --git a/src/PinguApps.Appwrite.Shared/Converters/IgnoreUnderscorePropertiesConverterFactory.cs b/src/PinguApps.Appwrite.Shared/Converters/IgnoreUnderscorePropertiesConverterFactory.cs new file mode 100644 index 00000000..0b3e6b8c --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Converters/IgnoreUnderscorePropertiesConverterFactory.cs @@ -0,0 +1,71 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace PinguApps.Appwrite.Shared.Converters; + +public class IgnoreUnderscorePropertiesConverterFactory : JsonConverterFactory +{ + public override bool CanConvert(Type typeToConvert) + { + // Apply to all non-abstract classes + return typeToConvert.IsClass && !typeToConvert.IsAbstract; + } + + public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options) + { + // Create a generic converter for the specific type + var converterType = typeof(IgnoreUnderscorePropertiesConverter<>).MakeGenericType(type); + return (JsonConverter)Activator.CreateInstance(converterType); + } + + private class IgnoreUnderscorePropertiesConverter : JsonConverter where T : class + { + public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + // Delegate deserialization to the default serializer + return JsonSerializer.Deserialize(ref reader, options); + } + + public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + { + if (value == null) + { + writer.WriteNullValue(); + return; + } + + writer.WriteStartObject(); + + // Retrieve all public instance properties + var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance) + .Where(prop => prop.CanRead && prop.GetMethod != null); + + foreach (var prop in properties) + { + // Determine the JSON property name + var jsonPropertyName = prop.GetCustomAttribute()?.Name + ?? options.PropertyNamingPolicy?.ConvertName(prop.Name) + ?? prop.Name; + + // Skip properties with JSON names starting with '_' + if (jsonPropertyName.StartsWith("_")) + continue; + + var propValue = prop.GetValue(value); + + // Respect the DefaultIgnoreCondition + if (propValue == null && options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingNull) + continue; + + writer.WritePropertyName(jsonPropertyName); + + JsonSerializer.Serialize(writer, propValue, prop.PropertyType, options); + } + + writer.WriteEndObject(); + } + } +} From 5fd354b9044c5b15f6ac8357c13109cebf37cf67 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sat, 12 Oct 2024 23:42:18 +0100 Subject: [PATCH 2/7] Created custom content serializer and added this to both projects. --- .../Handlers/HeaderHandler.cs | 8 ++- .../ServiceCollectionExtensions.cs | 11 +--- src/PinguApps.Appwrite.Playground/App.cs | 10 ++-- .../ServiceCollectionExtensions.cs | 11 +--- .../Converters/CustomContentSerializer.cs | 60 +++++++++++++++++++ ...oreUnderscorePropertiesConverterFactory.cs | 36 +++++++---- 6 files changed, 97 insertions(+), 39 deletions(-) create mode 100644 src/PinguApps.Appwrite.Shared/Converters/CustomContentSerializer.cs diff --git a/src/PinguApps.Appwrite.Client/Handlers/HeaderHandler.cs b/src/PinguApps.Appwrite.Client/Handlers/HeaderHandler.cs index bc22abad..1f25afdc 100644 --- a/src/PinguApps.Appwrite.Client/Handlers/HeaderHandler.cs +++ b/src/PinguApps.Appwrite.Client/Handlers/HeaderHandler.cs @@ -13,10 +13,14 @@ public HeaderHandler(Config config) _projectId = config.ProjectId; } - protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { request.Headers.Add("x-appwrite-project", _projectId); - return base.SendAsync(request, cancellationToken); + var content = await request.Content.ReadAsStringAsync(); + + var uri = request.RequestUri.ToString(); + + return await base.SendAsync(request, cancellationToken); } } diff --git a/src/PinguApps.Appwrite.Client/ServiceCollectionExtensions.cs b/src/PinguApps.Appwrite.Client/ServiceCollectionExtensions.cs index 254fd9c4..0a9044eb 100644 --- a/src/PinguApps.Appwrite.Client/ServiceCollectionExtensions.cs +++ b/src/PinguApps.Appwrite.Client/ServiceCollectionExtensions.cs @@ -1,8 +1,6 @@ using System; using System.Net.Http; using System.Runtime.InteropServices; -using System.Text.Json; -using System.Text.Json.Serialization; using Microsoft.Extensions.DependencyInjection; using PinguApps.Appwrite.Client.Handlers; using PinguApps.Appwrite.Client.Internals; @@ -89,14 +87,7 @@ private static RefitSettings AddSerializationConfigToRefitSettings(RefitSettings { var settings = refitSettings ?? new RefitSettings(); - var jsonOptions = new JsonSerializerOptions - { - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull - }; - - jsonOptions.Converters.Add(new IgnoreUnderscorePropertiesConverterFactory()); - - settings.ContentSerializer = new SystemTextJsonContentSerializer(jsonOptions); + settings.ContentSerializer = new CustomContentSerializer(); return settings; } diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index c7efba13..216733cf 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -17,13 +17,15 @@ public App(Client.IAppwriteClient client, Server.Clients.IAppwriteClient server, public async Task Run(string[] args) { - var request = new CreateSessionRequest() + _client.SetSession(_session); + + var request = new CreateAccountRequest() { - UserId = "664aac1a00113f82e620", - Secret = "80af6605407a3918cd9bb1796b6bfdc5d4b2dc57dad4677432d902e8bef9ba6f" + Email = "pingu@example.com", + Password = "MyCoolPassword" }; - var response = await _client.Account.CreateSession(request); + var response = await _client.Account.Create(request); Console.WriteLine(response.Result.Match( result => result.ToString(), diff --git a/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs b/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs index 787628da..60d0a20b 100644 --- a/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs +++ b/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs @@ -1,8 +1,6 @@ using System; using System.Net.Http; using System.Runtime.InteropServices; -using System.Text.Json; -using System.Text.Json.Serialization; using Microsoft.Extensions.DependencyInjection; using PinguApps.Appwrite.Server.Clients; using PinguApps.Appwrite.Server.Handlers; @@ -69,14 +67,7 @@ private static RefitSettings AddSerializationConfigToRefitSettings(RefitSettings { var settings = refitSettings ?? new RefitSettings(); - var jsonOptions = new JsonSerializerOptions - { - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull - }; - - jsonOptions.Converters.Add(new IgnoreUnderscorePropertiesConverterFactory()); - - settings.ContentSerializer = new SystemTextJsonContentSerializer(jsonOptions); + settings.ContentSerializer = new CustomContentSerializer(); return settings; } diff --git a/src/PinguApps.Appwrite.Shared/Converters/CustomContentSerializer.cs b/src/PinguApps.Appwrite.Shared/Converters/CustomContentSerializer.cs new file mode 100644 index 00000000..33d6e01b --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Converters/CustomContentSerializer.cs @@ -0,0 +1,60 @@ +using System; +using System.Net.Http; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; +using System.Threading; +using System.Threading.Tasks; +using Refit; + +namespace PinguApps.Appwrite.Shared.Converters; +public class CustomContentSerializer : IHttpContentSerializer +{ + private readonly JsonSerializerOptions _serializerOptions; + + public CustomContentSerializer() + { + _serializerOptions = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + + _serializerOptions.Converters.Add(new IgnoreUnderscorePropertiesConverterFactory()); + } + + public async Task FromHttpContentAsync(HttpContent content, CancellationToken cancellationToken = default) + { + if (content is null) + throw new ArgumentNullException(nameof(content)); + + var json = await content.ReadAsStringAsync().ConfigureAwait(false); + + return JsonSerializer.Deserialize(json, _serializerOptions); + } + + public HttpContent ToHttpContent(T item) + { + if (item is null) + throw new ArgumentNullException(nameof(item)); + + // Serialize the object using the configured JsonSerializerOptions + var json = JsonSerializer.Serialize(item, _serializerOptions); + + return new StringContent(json, System.Text.Encoding.UTF8, "application/json"); + } + + public string? GetFieldNameForProperty(PropertyInfo propertyInfo) + { + if (propertyInfo is null) + throw new ArgumentNullException(nameof(propertyInfo)); + + var jsonPropertyNameAttr = propertyInfo.GetCustomAttribute(); + + if (jsonPropertyNameAttr is not null) + return jsonPropertyNameAttr.Name; + + // Apply naming policy if set + return _serializerOptions.PropertyNamingPolicy?.ConvertName(propertyInfo.Name) ?? propertyInfo.Name; + } +} diff --git a/src/PinguApps.Appwrite.Shared/Converters/IgnoreUnderscorePropertiesConverterFactory.cs b/src/PinguApps.Appwrite.Shared/Converters/IgnoreUnderscorePropertiesConverterFactory.cs index 0b3e6b8c..0ca44c31 100644 --- a/src/PinguApps.Appwrite.Shared/Converters/IgnoreUnderscorePropertiesConverterFactory.cs +++ b/src/PinguApps.Appwrite.Shared/Converters/IgnoreUnderscorePropertiesConverterFactory.cs @@ -10,15 +10,29 @@ public class IgnoreUnderscorePropertiesConverterFactory : JsonConverterFactory { public override bool CanConvert(Type typeToConvert) { - // Apply to all non-abstract classes + // Exclude primitive types, enums, strings, and object + if (typeToConvert.IsPrimitive || + typeToConvert.IsEnum || + typeToConvert == typeof(string) || + typeToConvert == typeof(decimal) || + typeToConvert == typeof(DateTime) || + typeToConvert == typeof(DateTimeOffset) || + typeToConvert == typeof(TimeSpan) || + typeToConvert == typeof(Guid) || + typeToConvert == typeof(object)) + { + return false; + } + + // Apply to all other non-abstract classes return typeToConvert.IsClass && !typeToConvert.IsAbstract; } - public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options) + public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { - // Create a generic converter for the specific type - var converterType = typeof(IgnoreUnderscorePropertiesConverter<>).MakeGenericType(type); - return (JsonConverter)Activator.CreateInstance(converterType); + var converterType = typeof(IgnoreUnderscorePropertiesConverter<>).MakeGenericType(typeToConvert); + + return (JsonConverter)Activator.CreateInstance(converterType)!; } private class IgnoreUnderscorePropertiesConverter : JsonConverter where T : class @@ -39,16 +53,13 @@ public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions writer.WriteStartObject(); - // Retrieve all public instance properties var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance) - .Where(prop => prop.CanRead && prop.GetMethod != null); + .Where(prop => prop.CanRead && prop.GetMethod != null); foreach (var prop in properties) { - // Determine the JSON property name - var jsonPropertyName = prop.GetCustomAttribute()?.Name - ?? options.PropertyNamingPolicy?.ConvertName(prop.Name) - ?? prop.Name; + var jsonPropertyName = prop.GetCustomAttribute()?.Name ?? + (options.PropertyNamingPolicy?.ConvertName(prop.Name) ?? prop.Name); // Skip properties with JSON names starting with '_' if (jsonPropertyName.StartsWith("_")) @@ -56,8 +67,7 @@ public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions var propValue = prop.GetValue(value); - // Respect the DefaultIgnoreCondition - if (propValue == null && options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingNull) + if (propValue is null && options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingNull) continue; writer.WritePropertyName(jsonPropertyName); From a0117648205a60b02f908b64750795c67921e14a Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sun, 13 Oct 2024 00:00:34 +0100 Subject: [PATCH 3/7] removed trace from header handler --- src/PinguApps.Appwrite.Client/Handlers/HeaderHandler.cs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/PinguApps.Appwrite.Client/Handlers/HeaderHandler.cs b/src/PinguApps.Appwrite.Client/Handlers/HeaderHandler.cs index 1f25afdc..bc22abad 100644 --- a/src/PinguApps.Appwrite.Client/Handlers/HeaderHandler.cs +++ b/src/PinguApps.Appwrite.Client/Handlers/HeaderHandler.cs @@ -13,14 +13,10 @@ public HeaderHandler(Config config) _projectId = config.ProjectId; } - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + protected override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { request.Headers.Add("x-appwrite-project", _projectId); - var content = await request.Content.ReadAsStringAsync(); - - var uri = request.RequestUri.ToString(); - - return await base.SendAsync(request, cancellationToken); + return base.SendAsync(request, cancellationToken); } } From 1bbb43cef4fe0f26dce94509ee6f469d4be1a415 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sun, 13 Oct 2024 00:00:42 +0100 Subject: [PATCH 4/7] updated account requests --- .../Requests/Account/AddAuthenticatorRequest.cs | 2 +- .../Requests/Account/CreateOauth2SessionRequest.cs | 5 +++++ .../Requests/Account/CreateOauth2TokenRequest.cs | 5 +++++ .../Requests/Account/DeleteAuthenticatorRequest.cs | 2 +- .../Requests/Account/DeleteIdentityRequest.cs | 2 +- .../Requests/Account/DeleteSessionRequest.cs | 2 +- .../Requests/Account/GetSessionRequest.cs | 2 +- .../Requests/Account/UpdateSessionRequest.cs | 2 +- .../Requests/Account/VerifyAuthenticatorRequest.cs | 2 +- 9 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/AddAuthenticatorRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/AddAuthenticatorRequest.cs index ef207315..b694d048 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/AddAuthenticatorRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/AddAuthenticatorRequest.cs @@ -11,6 +11,6 @@ public class AddAuthenticatorRequest : BaseRequest /// Type of authenticator. Must be `totp` /// - [JsonIgnore] + [JsonPropertyName("_type")] public string Type { get; set; } = "totp"; } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2SessionRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2SessionRequest.cs index 05a17d9e..24f5a82a 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2SessionRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2SessionRequest.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Text.Json.Serialization; using PinguApps.Appwrite.Shared.Attributes; using PinguApps.Appwrite.Shared.Requests.Account.Validators; @@ -14,24 +15,28 @@ public class CreateOauth2SessionRequest : QueryParamBaseRequestamazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom /// [UrlReplacement("{provider}")] + [JsonPropertyName("_provider")] public string Provider { get; set; } = string.Empty; /// /// URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an open redirect attack against your project API /// [QueryParameter("success")] + [JsonPropertyName("_success")] public string? SuccessUri { get; set; } /// /// URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an open redirect attack against your project API /// [QueryParameter("failure")] + [JsonPropertyName("_failure")] public string? FailureUri { get; set; } /// /// A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long /// [QueryParameter("scopes[]")] + [JsonPropertyName("_scopes")] public List? Scopes { get; set; } protected override string Path => "/account/sessions/oauth2/{provider}"; diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2TokenRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2TokenRequest.cs index ca9f536d..b4620559 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2TokenRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2TokenRequest.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Text.Json.Serialization; using PinguApps.Appwrite.Shared.Attributes; using PinguApps.Appwrite.Shared.Requests.Account.Validators; @@ -14,24 +15,28 @@ public class CreateOauth2TokenRequest : QueryParamBaseRequestamazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom /// [UrlReplacement("{provider}")] + [JsonPropertyName("_provider")] public string Provider { get; set; } = string.Empty; /// /// URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an open redirect attack against your project API /// [QueryParameter("success")] + [JsonPropertyName("_success")] public string? SuccessUri { get; set; } /// /// URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an open redirect attack against your project API /// [QueryParameter("failure")] + [JsonPropertyName("_failure")] public string? FailureUri { get; set; } /// /// A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long /// [QueryParameter("scopes[]")] + [JsonPropertyName("_scopes")] public List? Scopes { get; set; } protected override string Path => "/account/tokens/oauth2/{provider}"; diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteAuthenticatorRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteAuthenticatorRequest.cs index 6da7bc16..02e72e7d 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteAuthenticatorRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteAuthenticatorRequest.cs @@ -11,7 +11,7 @@ public class DeleteAuthenticatorRequest : BaseRequest /// Type of authenticator /// - [JsonIgnore] + [JsonPropertyName("_type")] public string Type { get; set; } = "totp"; /// diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteIdentityRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteIdentityRequest.cs index fc22f432..042a4762 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteIdentityRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteIdentityRequest.cs @@ -11,6 +11,6 @@ public class DeleteIdentityRequest : BaseRequest /// Identity ID /// - [JsonPropertyName("identityId")] + [JsonPropertyName("_identityId")] public string IdentityId { get; set; } = string.Empty; } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteSessionRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteSessionRequest.cs index 017f2a95..d8db7cf6 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteSessionRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteSessionRequest.cs @@ -11,6 +11,6 @@ public class DeleteSessionRequest : BaseRequest /// Session ID. Use the string 'current' to delete the current device session. /// - [JsonPropertyName("sessionId")] + [JsonPropertyName("_sessionId")] public string SessionId { get; set; } = "current"; } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/GetSessionRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/GetSessionRequest.cs index bf140823..f417369f 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/GetSessionRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/GetSessionRequest.cs @@ -11,6 +11,6 @@ public class GetSessionRequest : BaseRequest /// Session ID. Use the string 'current' to get the current device session /// - [JsonPropertyName("sessionId")] + [JsonPropertyName("_sessionId")] public string SessionId { get; set; } = "current"; } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/UpdateSessionRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/UpdateSessionRequest.cs index fb7871a3..9eb5a766 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/UpdateSessionRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/UpdateSessionRequest.cs @@ -11,6 +11,6 @@ public class UpdateSessionRequest : BaseRequest /// Session ID. Use the string 'current' to get the current device session /// - [JsonPropertyName("sessionId")] + [JsonPropertyName("_sessionId")] public string SessionId { get; set; } = "current"; } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/VerifyAuthenticatorRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/VerifyAuthenticatorRequest.cs index 010b41d1..191ef311 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/VerifyAuthenticatorRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/VerifyAuthenticatorRequest.cs @@ -17,6 +17,6 @@ public class VerifyAuthenticatorRequest : BaseRequest /// Type of authenticator /// - [JsonIgnore] + [JsonPropertyName("_type")] public string Type { get; set; } = "totp"; } From e035babb1973351ed9180e10dc3b45edd5af8c9a Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sun, 13 Oct 2024 01:36:58 +0100 Subject: [PATCH 5/7] Switched over to using an attribute to determine whether a property should be not serialized within the sdk --- .../ServiceCollectionExtensions.cs | 12 +- .../ServiceCollectionExtensions.cs | 12 +- .../Attributes/SdkExcludeAttribute.cs | 8 ++ .../Converters/CustomContentSerializer.cs | 60 -------- ...reSdkExcludedPropertiesConverterFactory.cs | 129 ++++++++++++++++++ ...oreUnderscorePropertiesConverterFactory.cs | 81 ----------- .../Account/AddAuthenticatorRequest.cs | 4 +- .../Account/CreateOauth2SessionRequest.cs | 13 +- .../Account/CreateOauth2TokenRequest.cs | 13 +- .../Account/DeleteAuthenticatorRequest.cs | 4 +- .../Requests/Account/DeleteIdentityRequest.cs | 4 +- .../Requests/Account/DeleteSessionRequest.cs | 4 +- .../Requests/Account/GetSessionRequest.cs | 4 +- .../Requests/Account/UpdateSessionRequest.cs | 4 +- .../Account/VerifyAuthenticatorRequest.cs | 4 +- .../Account/AccountClientTests.Create.cs | 6 +- ...entTests.Create2faChallengeConfirmation.cs | 6 +- ...tClientTests.CreateEmailPasswordSession.cs | 6 +- .../AccountClientTests.CreateEmailToken.cs | 6 +- ...ountClientTests.CreateEmailVerification.cs | 6 +- ...sts.CreateEmailVerificationConfirmation.cs | 6 +- .../AccountClientTests.CreateMagicUrlToken.cs | 6 +- ...countClientTests.CreatePasswordRecovery.cs | 6 +- ...ests.CreatePasswordRecoveryConfirmation.cs | 6 +- .../AccountClientTests.CreatePhoneToken.cs | 6 +- .../AccountClientTests.CreateSesssion.cs | 6 +- .../AccountClientTests.DeleteAuthenticator.cs | 8 +- .../Account/AccountClientTests.UpdateEmail.cs | 6 +- ...ccountClientTests.UpdateMagicUrlSession.cs | 6 +- .../Account/AccountClientTests.UpdateMfa.cs | 6 +- .../Account/AccountClientTests.UpdateName.cs | 6 +- .../AccountClientTests.UpdatePassword.cs | 6 +- .../Account/AccountClientTests.UpdatePhone.cs | 6 +- .../AccountClientTests.UpdatePhoneSession.cs | 6 +- ...sts.UpdatePhoneVerificationConfirmation.cs | 6 +- .../AccountClientTests.UpdatePreferences.cs | 6 +- .../AccountClientTests.VerifyAuthenticator.cs | 8 +- .../Clients/Account/AccountClientTests.cs | 14 +- .../Account/AccountClientTests.Create.cs | 6 +- ...tClientTests.CreateEmailPasswordSession.cs | 6 +- .../AccountClientTests.CreateEmailToken.cs | 6 +- .../AccountClientTests.CreateMagicUrlToken.cs | 6 +- .../AccountClientTests.CreatePhoneToken.cs | 6 +- .../AccountClientTests.CreateSession.cs | 6 +- ...ccountClientTests.UpdateMagicUrlSession.cs | 6 +- .../AccountClientTests.UpdatePhoneSession.cs | 6 +- .../Clients/Account/AccountClientTests.cs | 14 +- .../Users/UsersClientTests.CreateUser.cs | 6 +- .../Users/UsersClientTests.CreateUserJwt.cs | 6 +- .../UsersClientTests.CreateUserTarget.cs | 6 +- ...lientTests.CreateUserWithArgon2Password.cs | 6 +- ...lientTests.CreateUserWithBcryptPassword.cs | 6 +- ...rsClientTests.CreateUserWithMd5Password.cs | 6 +- ...lientTests.CreateUserWithPhpassPassword.cs | 6 +- ...ts.CreateUserWithScryptModifiedPassword.cs | 6 +- ...lientTests.CreateUserWithScryptPassword.cs | 6 +- ...rsClientTests.CreateUserWithShaPassword.cs | 6 +- .../Users/UsersClientTests.UpdateEmail.cs | 6 +- ...sersClientTests.UpdateEmailVerification.cs | 6 +- .../Users/UsersClientTests.UpdateMfa.cs | 6 +- ...sersClientTests.UpdatePhoneVerification.cs | 6 +- .../UsersClientTests.UpdateUserLabels.cs | 6 +- .../UsersClientTests.UpdateUserPreferences.cs | 6 +- .../UsersClientTests.UpdateUserStatus.cs | 6 +- .../Clients/Users/UsersClientTests.cs | 14 +- 65 files changed, 380 insertions(+), 304 deletions(-) create mode 100644 src/PinguApps.Appwrite.Shared/Attributes/SdkExcludeAttribute.cs delete mode 100644 src/PinguApps.Appwrite.Shared/Converters/CustomContentSerializer.cs create mode 100644 src/PinguApps.Appwrite.Shared/Converters/IgnoreSdkExcludedPropertiesConverterFactory.cs delete mode 100644 src/PinguApps.Appwrite.Shared/Converters/IgnoreUnderscorePropertiesConverterFactory.cs diff --git a/src/PinguApps.Appwrite.Client/ServiceCollectionExtensions.cs b/src/PinguApps.Appwrite.Client/ServiceCollectionExtensions.cs index 0a9044eb..c691b7e8 100644 --- a/src/PinguApps.Appwrite.Client/ServiceCollectionExtensions.cs +++ b/src/PinguApps.Appwrite.Client/ServiceCollectionExtensions.cs @@ -1,6 +1,8 @@ using System; using System.Net.Http; using System.Runtime.InteropServices; +using System.Text.Json; +using System.Text.Json.Serialization; using Microsoft.Extensions.DependencyInjection; using PinguApps.Appwrite.Client.Handlers; using PinguApps.Appwrite.Client.Internals; @@ -87,7 +89,15 @@ private static RefitSettings AddSerializationConfigToRefitSettings(RefitSettings { var settings = refitSettings ?? new RefitSettings(); - settings.ContentSerializer = new CustomContentSerializer(); + var options = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + + options.Converters.Add(new IgnoreSdkExcludedPropertiesConverterFactory()); + + settings.ContentSerializer = new SystemTextJsonContentSerializer(options); return settings; } diff --git a/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs b/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs index 60d0a20b..0d935b02 100644 --- a/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs +++ b/src/PinguApps.Appwrite.Server/ServiceCollectionExtensions.cs @@ -1,6 +1,8 @@ using System; using System.Net.Http; using System.Runtime.InteropServices; +using System.Text.Json; +using System.Text.Json.Serialization; using Microsoft.Extensions.DependencyInjection; using PinguApps.Appwrite.Server.Clients; using PinguApps.Appwrite.Server.Handlers; @@ -67,7 +69,15 @@ private static RefitSettings AddSerializationConfigToRefitSettings(RefitSettings { var settings = refitSettings ?? new RefitSettings(); - settings.ContentSerializer = new CustomContentSerializer(); + var options = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + + options.Converters.Add(new IgnoreSdkExcludedPropertiesConverterFactory()); + + settings.ContentSerializer = new SystemTextJsonContentSerializer(options); return settings; } diff --git a/src/PinguApps.Appwrite.Shared/Attributes/SdkExcludeAttribute.cs b/src/PinguApps.Appwrite.Shared/Attributes/SdkExcludeAttribute.cs new file mode 100644 index 00000000..f9c20c26 --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Attributes/SdkExcludeAttribute.cs @@ -0,0 +1,8 @@ +using System; + +namespace PinguApps.Appwrite.Shared.Attributes; + +[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] +public class SdkExcludeAttribute : Attribute +{ +} diff --git a/src/PinguApps.Appwrite.Shared/Converters/CustomContentSerializer.cs b/src/PinguApps.Appwrite.Shared/Converters/CustomContentSerializer.cs deleted file mode 100644 index 33d6e01b..00000000 --- a/src/PinguApps.Appwrite.Shared/Converters/CustomContentSerializer.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Net.Http; -using System.Reflection; -using System.Text.Json; -using System.Text.Json.Serialization; -using System.Threading; -using System.Threading.Tasks; -using Refit; - -namespace PinguApps.Appwrite.Shared.Converters; -public class CustomContentSerializer : IHttpContentSerializer -{ - private readonly JsonSerializerOptions _serializerOptions; - - public CustomContentSerializer() - { - _serializerOptions = new JsonSerializerOptions - { - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, - PropertyNamingPolicy = JsonNamingPolicy.CamelCase - }; - - _serializerOptions.Converters.Add(new IgnoreUnderscorePropertiesConverterFactory()); - } - - public async Task FromHttpContentAsync(HttpContent content, CancellationToken cancellationToken = default) - { - if (content is null) - throw new ArgumentNullException(nameof(content)); - - var json = await content.ReadAsStringAsync().ConfigureAwait(false); - - return JsonSerializer.Deserialize(json, _serializerOptions); - } - - public HttpContent ToHttpContent(T item) - { - if (item is null) - throw new ArgumentNullException(nameof(item)); - - // Serialize the object using the configured JsonSerializerOptions - var json = JsonSerializer.Serialize(item, _serializerOptions); - - return new StringContent(json, System.Text.Encoding.UTF8, "application/json"); - } - - public string? GetFieldNameForProperty(PropertyInfo propertyInfo) - { - if (propertyInfo is null) - throw new ArgumentNullException(nameof(propertyInfo)); - - var jsonPropertyNameAttr = propertyInfo.GetCustomAttribute(); - - if (jsonPropertyNameAttr is not null) - return jsonPropertyNameAttr.Name; - - // Apply naming policy if set - return _serializerOptions.PropertyNamingPolicy?.ConvertName(propertyInfo.Name) ?? propertyInfo.Name; - } -} diff --git a/src/PinguApps.Appwrite.Shared/Converters/IgnoreSdkExcludedPropertiesConverterFactory.cs b/src/PinguApps.Appwrite.Shared/Converters/IgnoreSdkExcludedPropertiesConverterFactory.cs new file mode 100644 index 00000000..47f5bce8 --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Converters/IgnoreSdkExcludedPropertiesConverterFactory.cs @@ -0,0 +1,129 @@ +using System; +using System.Collections; +using System.Linq; +using System.Reflection; +using System.Text.Json; +using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Attributes; + +namespace PinguApps.Appwrite.Shared.Converters; + +public class IgnoreSdkExcludedPropertiesConverterFactory : JsonConverterFactory +{ + public override bool CanConvert(Type typeToConvert) + { + if (typeToConvert.IsPrimitive || + typeToConvert.IsEnum || + typeToConvert == typeof(string) || + typeToConvert == typeof(decimal) || + typeToConvert == typeof(DateTime) || + typeToConvert == typeof(DateTimeOffset) || + typeToConvert == typeof(TimeSpan) || + typeToConvert == typeof(Guid) || + typeToConvert == typeof(object)) + { + return false; + } + + if (typeof(IEnumerable).IsAssignableFrom(typeToConvert) && typeToConvert != typeof(string)) + { + return false; + } + + return typeToConvert.IsClass && !typeToConvert.IsAbstract; + } + + public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + var converterType = typeof(IgnoreSdkExcludedPropertiesConverter<>).MakeGenericType(typeToConvert); + + return (JsonConverter)Activator.CreateInstance(converterType)!; + } + + private class IgnoreSdkExcludedPropertiesConverter : JsonConverter where T : class + { + public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + using var jsonDoc = JsonDocument.ParseValue(ref reader); + + var json = jsonDoc.RootElement.GetRawText(); + + var newOptions = new JsonSerializerOptions(options); + + var converterToRemove = newOptions.Converters.FirstOrDefault(x => x.GetType() == typeof(IgnoreSdkExcludedPropertiesConverterFactory)); + + if (converterToRemove is not null) + { + newOptions.Converters.Remove(converterToRemove); + } + + return JsonSerializer.Deserialize(json, newOptions); + } + + public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) + { + if (value is null) + { + writer.WriteNullValue(); + return; + } + + writer.WriteStartObject(); + + var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance) + .Where(x => x.CanRead && x.GetMethod is not null); + + foreach (var prop in properties) + { + if (prop.GetCustomAttribute() is not null) + continue; + + var jsonPropertyNameAttr = prop.GetCustomAttribute(); + + var jsonPropertyName = jsonPropertyNameAttr is not null + ? jsonPropertyNameAttr.Name + : (options.PropertyNamingPolicy?.ConvertName(prop.Name) ?? prop.Name); + + var propValue = prop.GetValue(value); + + if (propValue is null && options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingNull) + continue; + + writer.WritePropertyName(jsonPropertyName); + + var jsonConverterAttr = prop.GetCustomAttribute(); + if (jsonConverterAttr is not null && jsonConverterAttr.ConverterType is not null) + { + // Instantiate the specified converter + var converterInstance = (JsonConverter?)Activator.CreateInstance(jsonConverterAttr.ConverterType); + + if (converterInstance is null) + throw new InvalidOperationException($"Cannot create an instance of converter type {jsonConverterAttr.ConverterType.FullName}."); + + // Create a new JsonSerializerOptions instance without the custom converter factory to prevent recursion + var newOptions = new JsonSerializerOptions(options); + + // Remove the custom converter factory to prevent it from being invoked again + var converterToRemove = newOptions.Converters + .FirstOrDefault(c => c.GetType() == typeof(IgnoreSdkExcludedPropertiesConverterFactory)); + + if (converterToRemove != null) + newOptions.Converters.Remove(converterToRemove); + + newOptions.Converters.Add(converterInstance); + + // Serialize the property value using the specified converter and the new options + JsonSerializer.Serialize(writer, propValue, prop.PropertyType, newOptions); + + // Move to the next property after handling with the custom converter + continue; + } + + // If no custom converter is specified, serialize normally + JsonSerializer.Serialize(writer, propValue, prop.PropertyType, options); + } + + writer.WriteEndObject(); + } + } +} diff --git a/src/PinguApps.Appwrite.Shared/Converters/IgnoreUnderscorePropertiesConverterFactory.cs b/src/PinguApps.Appwrite.Shared/Converters/IgnoreUnderscorePropertiesConverterFactory.cs deleted file mode 100644 index 0ca44c31..00000000 --- a/src/PinguApps.Appwrite.Shared/Converters/IgnoreUnderscorePropertiesConverterFactory.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Linq; -using System.Reflection; -using System.Text.Json; -using System.Text.Json.Serialization; - -namespace PinguApps.Appwrite.Shared.Converters; - -public class IgnoreUnderscorePropertiesConverterFactory : JsonConverterFactory -{ - public override bool CanConvert(Type typeToConvert) - { - // Exclude primitive types, enums, strings, and object - if (typeToConvert.IsPrimitive || - typeToConvert.IsEnum || - typeToConvert == typeof(string) || - typeToConvert == typeof(decimal) || - typeToConvert == typeof(DateTime) || - typeToConvert == typeof(DateTimeOffset) || - typeToConvert == typeof(TimeSpan) || - typeToConvert == typeof(Guid) || - typeToConvert == typeof(object)) - { - return false; - } - - // Apply to all other non-abstract classes - return typeToConvert.IsClass && !typeToConvert.IsAbstract; - } - - public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) - { - var converterType = typeof(IgnoreUnderscorePropertiesConverter<>).MakeGenericType(typeToConvert); - - return (JsonConverter)Activator.CreateInstance(converterType)!; - } - - private class IgnoreUnderscorePropertiesConverter : JsonConverter where T : class - { - public override T? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - // Delegate deserialization to the default serializer - return JsonSerializer.Deserialize(ref reader, options); - } - - public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions options) - { - if (value == null) - { - writer.WriteNullValue(); - return; - } - - writer.WriteStartObject(); - - var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance) - .Where(prop => prop.CanRead && prop.GetMethod != null); - - foreach (var prop in properties) - { - var jsonPropertyName = prop.GetCustomAttribute()?.Name ?? - (options.PropertyNamingPolicy?.ConvertName(prop.Name) ?? prop.Name); - - // Skip properties with JSON names starting with '_' - if (jsonPropertyName.StartsWith("_")) - continue; - - var propValue = prop.GetValue(value); - - if (propValue is null && options.DefaultIgnoreCondition == JsonIgnoreCondition.WhenWritingNull) - continue; - - writer.WritePropertyName(jsonPropertyName); - - JsonSerializer.Serialize(writer, propValue, prop.PropertyType, options); - } - - writer.WriteEndObject(); - } - } -} diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/AddAuthenticatorRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/AddAuthenticatorRequest.cs index b694d048..3c75ea48 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/AddAuthenticatorRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/AddAuthenticatorRequest.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Attributes; using PinguApps.Appwrite.Shared.Requests.Account.Validators; namespace PinguApps.Appwrite.Shared.Requests.Account; @@ -11,6 +12,7 @@ public class AddAuthenticatorRequest : BaseRequest /// Type of authenticator. Must be `totp` /// - [JsonPropertyName("_type")] + [JsonPropertyName("type")] + [SdkExclude] public string Type { get; set; } = "totp"; } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2SessionRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2SessionRequest.cs index 24f5a82a..9bf2acfe 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2SessionRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2SessionRequest.cs @@ -15,29 +15,34 @@ public class CreateOauth2SessionRequest : QueryParamBaseRequestamazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom /// [UrlReplacement("{provider}")] - [JsonPropertyName("_provider")] + [JsonPropertyName("provider")] + [SdkExclude] public string Provider { get; set; } = string.Empty; /// /// URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an open redirect attack against your project API /// [QueryParameter("success")] - [JsonPropertyName("_success")] + [JsonPropertyName("success")] + [SdkExclude] public string? SuccessUri { get; set; } /// /// URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an open redirect attack against your project API /// [QueryParameter("failure")] - [JsonPropertyName("_failure")] + [JsonPropertyName("failure")] + [SdkExclude] public string? FailureUri { get; set; } /// /// A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long /// [QueryParameter("scopes[]")] - [JsonPropertyName("_scopes")] + [JsonPropertyName("scopes")] + [SdkExclude] public List? Scopes { get; set; } + [JsonIgnore] protected override string Path => "/account/sessions/oauth2/{provider}"; } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2TokenRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2TokenRequest.cs index b4620559..b063d9e6 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2TokenRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/CreateOauth2TokenRequest.cs @@ -15,29 +15,34 @@ public class CreateOauth2TokenRequest : QueryParamBaseRequestamazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom /// [UrlReplacement("{provider}")] - [JsonPropertyName("_provider")] + [JsonPropertyName("provider")] + [SdkExclude] public string Provider { get; set; } = string.Empty; /// /// URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an open redirect attack against your project API /// [QueryParameter("success")] - [JsonPropertyName("_success")] + [JsonPropertyName("success")] + [SdkExclude] public string? SuccessUri { get; set; } /// /// URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an open redirect attack against your project API /// [QueryParameter("failure")] - [JsonPropertyName("_failure")] + [JsonPropertyName("failure")] + [SdkExclude] public string? FailureUri { get; set; } /// /// A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long /// [QueryParameter("scopes[]")] - [JsonPropertyName("_scopes")] + [JsonPropertyName("scopes")] + [SdkExclude] public List? Scopes { get; set; } + [JsonIgnore] protected override string Path => "/account/tokens/oauth2/{provider}"; } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteAuthenticatorRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteAuthenticatorRequest.cs index 02e72e7d..bddabcb9 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteAuthenticatorRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteAuthenticatorRequest.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Attributes; using PinguApps.Appwrite.Shared.Requests.Account.Validators; namespace PinguApps.Appwrite.Shared.Requests.Account; @@ -11,7 +12,8 @@ public class DeleteAuthenticatorRequest : BaseRequest /// Type of authenticator /// - [JsonPropertyName("_type")] + [JsonPropertyName("type")] + [SdkExclude] public string Type { get; set; } = "totp"; /// diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteIdentityRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteIdentityRequest.cs index 042a4762..5620c636 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteIdentityRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteIdentityRequest.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Attributes; using PinguApps.Appwrite.Shared.Requests.Account.Validators; namespace PinguApps.Appwrite.Shared.Requests.Account; @@ -11,6 +12,7 @@ public class DeleteIdentityRequest : BaseRequest /// Identity ID /// - [JsonPropertyName("_identityId")] + [JsonPropertyName("identityId")] + [SdkExclude] public string IdentityId { get; set; } = string.Empty; } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteSessionRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteSessionRequest.cs index d8db7cf6..4855828c 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteSessionRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/DeleteSessionRequest.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Attributes; using PinguApps.Appwrite.Shared.Requests.Account.Validators; namespace PinguApps.Appwrite.Shared.Requests.Account; @@ -11,6 +12,7 @@ public class DeleteSessionRequest : BaseRequest /// Session ID. Use the string 'current' to delete the current device session. /// - [JsonPropertyName("_sessionId")] + [JsonPropertyName("sessionId")] + [SdkExclude] public string SessionId { get; set; } = "current"; } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/GetSessionRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/GetSessionRequest.cs index f417369f..dfb3fd4a 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/GetSessionRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/GetSessionRequest.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Attributes; using PinguApps.Appwrite.Shared.Requests.Account.Validators; namespace PinguApps.Appwrite.Shared.Requests.Account; @@ -11,6 +12,7 @@ public class GetSessionRequest : BaseRequest /// Session ID. Use the string 'current' to get the current device session /// - [JsonPropertyName("_sessionId")] + [JsonPropertyName("sessionId")] + [SdkExclude] public string SessionId { get; set; } = "current"; } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/UpdateSessionRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/UpdateSessionRequest.cs index 9eb5a766..dca88232 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/UpdateSessionRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/UpdateSessionRequest.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Attributes; using PinguApps.Appwrite.Shared.Requests.Account.Validators; namespace PinguApps.Appwrite.Shared.Requests.Account; @@ -11,6 +12,7 @@ public class UpdateSessionRequest : BaseRequest /// Session ID. Use the string 'current' to get the current device session /// - [JsonPropertyName("_sessionId")] + [JsonPropertyName("sessionId")] + [SdkExclude] public string SessionId { get; set; } = "current"; } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/VerifyAuthenticatorRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/VerifyAuthenticatorRequest.cs index 191ef311..b6588937 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Account/VerifyAuthenticatorRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/VerifyAuthenticatorRequest.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Attributes; using PinguApps.Appwrite.Shared.Requests.Account.Validators; namespace PinguApps.Appwrite.Shared.Requests.Account; @@ -17,6 +18,7 @@ public class VerifyAuthenticatorRequest : BaseRequest /// Type of authenticator /// - [JsonPropertyName("_type")] + [JsonPropertyName("type")] + [SdkExclude] public string Type { get; set; } = "totp"; } diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create.cs index 38c6cac3..7fa4f414 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create.cs @@ -19,7 +19,7 @@ public async Task Create_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); // Act @@ -42,7 +42,7 @@ public async Task Create_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -66,7 +66,7 @@ public async Task Create_ShouldReturnErrorResponse_WhenExceptionOccurs() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create2faChallengeConfirmation.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create2faChallengeConfirmation.cs index 56ba1855..eb628bc4 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create2faChallengeConfirmation.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create2faChallengeConfirmation.cs @@ -20,7 +20,7 @@ public async Task Create2faChallengeConfirmation_ShouldReturnSuccess_WhenApiCall _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/mfa/challenge") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.NoContent); _appwriteClient.SetSession(TestConstants.Session); @@ -63,7 +63,7 @@ public async Task Create2faChallengeConfirmation_ShouldHandleException_WhenApiCa _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/mfa/challenge") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); _appwriteClient.SetSession(TestConstants.Session); @@ -88,7 +88,7 @@ public async Task Create2faChallengeConfirmation_ShouldReturnErrorResponse_WhenE _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/mfa/challenge") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); _appwriteClient.SetSession(TestConstants.Session); diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailPasswordSession.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailPasswordSession.cs index 1d9a7524..1f95616d 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailPasswordSession.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailPasswordSession.cs @@ -18,7 +18,7 @@ public async Task CreateEmailPasswordSession_ShouldReturnSuccess_WhenApiCallSucc _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/sessions/email") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.SessionResponse); // Act @@ -40,7 +40,7 @@ public async Task CreateEmailPasswordSession_ShouldHandleException_WhenApiCallFa _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/sessions/email") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -63,7 +63,7 @@ public async Task CreateEmailPasswordSession_ShouldReturnErrorResponse_WhenExcep _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/sessions/email") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailToken.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailToken.cs index 1efe0418..9b093591 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailToken.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailToken.cs @@ -18,7 +18,7 @@ public async Task CreateEmailToken_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/email") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.TokenResponse); // Act @@ -40,7 +40,7 @@ public async Task CreateEmailToken_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/email") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -63,7 +63,7 @@ public async Task CreateEmailToken_ShouldReturnErrorResponse_WhenExceptionOccurs _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/email") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailVerification.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailVerification.cs index cf453aec..3974f0f5 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailVerification.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailVerification.cs @@ -18,7 +18,7 @@ public async Task CreateEmailVerification_ShouldReturnSuccess_WhenApiCallSucceed _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/verification") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.TokenResponse); _appwriteClient.SetSession(TestConstants.Session); @@ -59,7 +59,7 @@ public async Task CreateEmailVerification_ShouldHandleException_WhenApiCallFails _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/verification") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); _appwriteClient.SetSession(TestConstants.Session); @@ -83,7 +83,7 @@ public async Task CreateEmailVerification_ShouldReturnErrorResponse_WhenExceptio _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/verification") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); _appwriteClient.SetSession(TestConstants.Session); diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailVerificationConfirmation.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailVerificationConfirmation.cs index a87c56ea..fb61350a 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailVerificationConfirmation.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailVerificationConfirmation.cs @@ -18,7 +18,7 @@ public async Task CreateEmailVerificationConfirmation_ShouldReturnSuccess_WhenAp _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/verification") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.TokenResponse); // Act @@ -40,7 +40,7 @@ public async Task CreateEmailVerificationConfirmation_ShouldHandleException_When _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/verification") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -63,7 +63,7 @@ public async Task CreateEmailVerificationConfirmation_ShouldReturnErrorResponse_ _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/verification") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateMagicUrlToken.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateMagicUrlToken.cs index 629be249..e6fbbb9d 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateMagicUrlToken.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateMagicUrlToken.cs @@ -19,7 +19,7 @@ public async Task CreateMagicUrlToken_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/magic-url") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.TokenResponse); // Act @@ -42,7 +42,7 @@ public async Task CreateMagicUrlToken_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/magic-url") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -66,7 +66,7 @@ public async Task CreateMagicUrlToken_ShouldReturnErrorResponse_WhenExceptionOcc _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/magic-url") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreatePasswordRecovery.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreatePasswordRecovery.cs index d583f610..b0ffce79 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreatePasswordRecovery.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreatePasswordRecovery.cs @@ -18,7 +18,7 @@ public async Task CreatePasswordRecovery_ShouldReturnSuccess_WhenApiCallSucceeds _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/recovery") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.TokenResponse); // Act @@ -40,7 +40,7 @@ public async Task CreatePasswordRecovery_ShouldHandleException_WhenApiCallFails( _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/recovery") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -63,7 +63,7 @@ public async Task CreatePasswordRecovery_ShouldReturnErrorResponse_WhenException _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/recovery") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreatePasswordRecoveryConfirmation.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreatePasswordRecoveryConfirmation.cs index 1992130a..0427b807 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreatePasswordRecoveryConfirmation.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreatePasswordRecoveryConfirmation.cs @@ -19,7 +19,7 @@ public async Task CreatePasswordRecoveryConfirmation_ShouldReturnSuccess_WhenApi _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/recovery") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.TokenResponse); // Act @@ -42,7 +42,7 @@ public async Task CreatePasswordRecoveryConfirmation_ShouldHandleException_WhenA _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/recovery") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -66,7 +66,7 @@ public async Task CreatePasswordRecoveryConfirmation_ShouldReturnErrorResponse_W _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/recovery") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreatePhoneToken.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreatePhoneToken.cs index f20296c3..d48ba368 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreatePhoneToken.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreatePhoneToken.cs @@ -18,7 +18,7 @@ public async Task CreatePhoneToken_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.TokenResponse); // Act @@ -40,7 +40,7 @@ public async Task CreatePhoneToken_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -63,7 +63,7 @@ public async Task CreatePhoneToken_ShouldReturnErrorResponse_WhenExceptionOccurs _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateSesssion.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateSesssion.cs index c1e3a72d..47cc2762 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateSesssion.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateSesssion.cs @@ -18,7 +18,7 @@ public async Task CreateSession_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/sessions/token") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.SessionResponse); // Act @@ -40,7 +40,7 @@ public async Task CreateSession_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/sessions/token") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -63,7 +63,7 @@ public async Task CreateSession_ShouldReturnErrorResponse_WhenExceptionOccurs() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/sessions/token") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.DeleteAuthenticator.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.DeleteAuthenticator.cs index 6dbb3560..da59ab3e 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.DeleteAuthenticator.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.DeleteAuthenticator.cs @@ -18,7 +18,7 @@ public async Task DeleteAuthenticator_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Delete, $"{TestConstants.Endpoint}/account/mfa/authenticators/totp") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.MfaTypeResponse); _appwriteClient.SetSession(TestConstants.Session); @@ -43,7 +43,7 @@ public async Task DeleteAuthenticator_ShouldHitDifferentEndpoint_WhenNewTypeIsUs var requestUri = $"{TestConstants.Endpoint}/account/mfa/authenticators/{type}"; var mockRequest = _mockHttp.Expect(HttpMethod.Delete, requestUri) .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.MfaTypeResponse); _appwriteClient.SetSession(TestConstants.Session); @@ -86,7 +86,7 @@ public async Task DeleteAuthenticator_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Delete, $"{TestConstants.Endpoint}/account/mfa/authenticators/totp") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); _appwriteClient.SetSession(TestConstants.Session); @@ -110,7 +110,7 @@ public async Task DeleteAuthenticator_ShouldReturnErrorResponse_WhenExceptionOcc _mockHttp.Expect(HttpMethod.Delete, $"{TestConstants.Endpoint}/account/mfa/authenticators/totp") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); _appwriteClient.SetSession(TestConstants.Session); diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateEmail.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateEmail.cs index 895ef2d8..6a884109 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateEmail.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateEmail.cs @@ -19,7 +19,7 @@ public async Task UpdateEmail_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/email") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); _appwriteClient.SetSession(TestConstants.Session); @@ -62,7 +62,7 @@ public async Task UpdateEmail_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/email") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); _appwriteClient.SetSession(TestConstants.Session); @@ -87,7 +87,7 @@ public async Task UpdateEmail_ShouldReturnErrorResponse_WhenExceptionOccurs() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/email") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); _appwriteClient.SetSession(TestConstants.Session); diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateMagicUrlSession.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateMagicUrlSession.cs index de2d18a4..e2b02924 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateMagicUrlSession.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateMagicUrlSession.cs @@ -18,7 +18,7 @@ public async Task UpdateMagicUrlSession_ShouldReturnSuccess_WhenApiCallSucceeds( _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/sessions/magic-url") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.SessionResponse); // Act @@ -40,7 +40,7 @@ public async Task UpdateMagicUrlSession_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/sessions/magic-url") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -63,7 +63,7 @@ public async Task UpdateMagicUrlSession_ShouldReturnErrorResponse_WhenExceptionO _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/sessions/magic-url") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateMfa.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateMfa.cs index e632ecbf..c435de36 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateMfa.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateMfa.cs @@ -18,7 +18,7 @@ public async Task UpdateMfa_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/mfa") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); _appwriteClient.SetSession(TestConstants.Session); @@ -59,7 +59,7 @@ public async Task UpdateMfa_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/mfa") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); _appwriteClient.SetSession(TestConstants.Session); @@ -83,7 +83,7 @@ public async Task UpdateMfa_ShouldReturnErrorResponse_WhenExceptionOccurs() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/mfa") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); _appwriteClient.SetSession(TestConstants.Session); diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateName.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateName.cs index 6ecac0ca..5203d0bc 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateName.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateName.cs @@ -18,7 +18,7 @@ public async Task UpdateName_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/name") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); _appwriteClient.SetSession(TestConstants.Session); @@ -59,7 +59,7 @@ public async Task UpdateName_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/name") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); _appwriteClient.SetSession(TestConstants.Session); @@ -83,7 +83,7 @@ public async Task UpdateName_ShouldReturnErrorResponse_WhenExceptionOccurs() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/name") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); _appwriteClient.SetSession(TestConstants.Session); diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePassword.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePassword.cs index 24d908c1..50970b03 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePassword.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePassword.cs @@ -19,7 +19,7 @@ public async Task UpdatePassword_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/password") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); _appwriteClient.SetSession(TestConstants.Session); @@ -62,7 +62,7 @@ public async Task UpdatePassword_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/password") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); _appwriteClient.SetSession(TestConstants.Session); @@ -87,7 +87,7 @@ public async Task UpdatePassword_ShouldReturnErrorResponse_WhenExceptionOccurs() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/password") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); _appwriteClient.SetSession(TestConstants.Session); diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhone.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhone.cs index 1a7a65a9..5f6f5745 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhone.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhone.cs @@ -19,7 +19,7 @@ public async Task UpdatePhone_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/phone") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); _appwriteClient.SetSession(TestConstants.Session); @@ -62,7 +62,7 @@ public async Task UpdatePhone_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/phone") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); _appwriteClient.SetSession(TestConstants.Session); @@ -87,7 +87,7 @@ public async Task UpdatePhone_ShouldReturnErrorResponse_WhenExceptionOccurs() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/phone") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); _appwriteClient.SetSession(TestConstants.Session); diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhoneSession.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhoneSession.cs index 8578a84e..e8c6bc49 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhoneSession.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhoneSession.cs @@ -18,7 +18,7 @@ public async Task UpdatePhoneSession_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/sessions/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.SessionResponse); // Act @@ -40,7 +40,7 @@ public async Task UpdatePhoneSession_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/sessions/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -63,7 +63,7 @@ public async Task UpdatePhoneSession_ShouldReturnErrorResponse_WhenExceptionOccu _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/sessions/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhoneVerificationConfirmation.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhoneVerificationConfirmation.cs index ccf2e724..71d0f08a 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhoneVerificationConfirmation.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhoneVerificationConfirmation.cs @@ -19,7 +19,7 @@ public async Task UpdatePhoneVerificationConfirmation_ShouldReturnSuccess_WhenAp _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/verification/phone") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.TokenResponse); _appwriteClient.SetSession(TestConstants.Session); @@ -62,7 +62,7 @@ public async Task UpdatePhoneVerificationConfirmation_ShouldHandleException_When _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/verification/phone") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); _appwriteClient.SetSession(TestConstants.Session); @@ -87,7 +87,7 @@ public async Task UpdatePhoneVerificationConfirmation_ShouldReturnErrorResponse_ _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/verification/phone") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); _appwriteClient.SetSession(TestConstants.Session); diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePreferences.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePreferences.cs index fce9fd3e..f8806320 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePreferences.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePreferences.cs @@ -18,7 +18,7 @@ public async Task UpdatePreferences_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/prefs") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); _appwriteClient.SetSession(TestConstants.Session); @@ -59,7 +59,7 @@ public async Task UpdatePreferences_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/prefs") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); _appwriteClient.SetSession(TestConstants.Session); @@ -83,7 +83,7 @@ public async Task UpdatePreferences_ShouldReturnErrorResponse_WhenExceptionOccur _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/account/prefs") .ExpectedHeaders(true) - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); _appwriteClient.SetSession(TestConstants.Session); diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.VerifyAuthenticator.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.VerifyAuthenticator.cs index 85bc9acd..f8c25f2f 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.VerifyAuthenticator.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.VerifyAuthenticator.cs @@ -16,7 +16,7 @@ public async Task VerifyAuthenticator_ShouldReturnSuccess_WhenApiCallSucceeds() Otp = "123456" }; _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/mfa/authenticators/totp") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders(true) .Respond(TestConstants.AppJson, TestConstants.UserResponse); @@ -41,7 +41,7 @@ public async Task VerifyAuthenticator_ShouldHitDifferentEndpoint_WhenNewTypeIsUs Type = type }; var request = _mockHttp.Expect(HttpMethod.Put, requestUri) - .WithJsonContent(requestBody) + .WithJsonContent(requestBody, _jsonSerializerOptions) .ExpectedHeaders(true) .Respond(TestConstants.AppJson, TestConstants.UserResponse); @@ -83,7 +83,7 @@ public async Task VerifyAuthenticator_ShouldHandleException_WhenApiCallFails() Otp = "123456" }; _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/mfa/authenticators/totp") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders(true) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); @@ -106,7 +106,7 @@ public async Task VerifyAuthenticator_ShouldReturnErrorResponse_WhenExceptionOcc Otp = "123456" }; _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/mfa/authenticators/totp") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders(true) .Throw(new HttpRequestException("An error occurred")); diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.cs index 4173732d..968d22ad 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.cs @@ -1,8 +1,11 @@ -using Microsoft.Extensions.DependencyInjection; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.Extensions.DependencyInjection; using Moq; using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Client.Internals; using PinguApps.Appwrite.Shared; +using PinguApps.Appwrite.Shared.Converters; using PinguApps.Appwrite.Shared.Tests; using Refit; using RichardSzalay.MockHttp; @@ -12,6 +15,7 @@ public partial class AccountClientTests { private readonly MockHttpMessageHandler _mockHttp; private readonly IAppwriteClient _appwriteClient; + private readonly JsonSerializerOptions _jsonSerializerOptions; public AccountClientTests() { @@ -26,6 +30,14 @@ public AccountClientTests() var serviceProvider = services.BuildServiceProvider(); _appwriteClient = serviceProvider.GetRequiredService(); + + _jsonSerializerOptions = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + + _jsonSerializerOptions.Converters.Add(new IgnoreSdkExcludedPropertiesConverterFactory()); } [Fact] diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.Create.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.Create.cs index 56e23072..4e216b95 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.Create.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.Create.cs @@ -20,7 +20,7 @@ public async Task Create_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); // Act @@ -43,7 +43,7 @@ public async Task Create_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -67,7 +67,7 @@ public async Task Create_ShouldReturnErrorResponse_WhenExceptionOccurs() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateEmailPasswordSession.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateEmailPasswordSession.cs index 577b8f61..3c0fa6d5 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateEmailPasswordSession.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateEmailPasswordSession.cs @@ -19,7 +19,7 @@ public async Task CreateEmailPasswordSession_ShouldReturnSuccess_WhenApiCallSucc _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/sessions/email") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.SessionResponse); // Act @@ -41,7 +41,7 @@ public async Task CreateEmailPasswordSession_ShouldHandleException_WhenApiCallFa _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/sessions/email") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -64,7 +64,7 @@ public async Task CreateEmailPasswordSession_ShouldReturnErrorResponse_WhenExcep _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/sessions/email") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateEmailToken.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateEmailToken.cs index d68c6879..03a79ada 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateEmailToken.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateEmailToken.cs @@ -19,7 +19,7 @@ public async Task CreateEmailToken_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/email") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.TokenResponse); // Act @@ -41,7 +41,7 @@ public async Task CreateEmailToken_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/email") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -64,7 +64,7 @@ public async Task CreateEmailToken_ShouldReturnErrorResponse_WhenExceptionOccurs _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/email") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateMagicUrlToken.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateMagicUrlToken.cs index 5e1a3fd5..2421fcf0 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateMagicUrlToken.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateMagicUrlToken.cs @@ -20,7 +20,7 @@ public async Task CreateMagicUrlToken_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/magic-url") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.TokenResponse); // Act @@ -43,7 +43,7 @@ public async Task CreateMagicUrlToken_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/magic-url") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -67,7 +67,7 @@ public async Task CreateMagicUrlToken_ShouldReturnErrorResponse_WhenExceptionOcc _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/magic-url") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreatePhoneToken.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreatePhoneToken.cs index e12c3e5c..25f13e8c 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreatePhoneToken.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreatePhoneToken.cs @@ -19,7 +19,7 @@ public async Task CreatePhoneToken_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.TokenResponse); // Act @@ -41,7 +41,7 @@ public async Task CreatePhoneToken_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -64,7 +64,7 @@ public async Task CreatePhoneToken_ShouldReturnErrorResponse_WhenExceptionOccurs _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/tokens/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateSession.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateSession.cs index d921aeb6..3eed7174 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateSession.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.CreateSession.cs @@ -19,7 +19,7 @@ public async Task CreateSession_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/sessions/token") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.SessionResponse); // Act @@ -41,7 +41,7 @@ public async Task CreateSession_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/sessions/token") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -64,7 +64,7 @@ public async Task CreateSession_ShouldReturnErrorResponse_WhenExceptionOccurs() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/account/sessions/token") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.UpdateMagicUrlSession.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.UpdateMagicUrlSession.cs index eafebea5..bd4d0546 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.UpdateMagicUrlSession.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.UpdateMagicUrlSession.cs @@ -19,7 +19,7 @@ public async Task UpdateMagicUrlSession_ShouldReturnSuccess_WhenApiCallSucceeds( _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/sessions/magic-url") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.SessionResponse); // Act @@ -41,7 +41,7 @@ public async Task UpdateMagicUrlSession_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/sessions/magic-url") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -64,7 +64,7 @@ public async Task UpdateMagicUrlSession_ShouldReturnErrorResponse_WhenExceptionO _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/sessions/magic-url") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.UpdatePhoneSession.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.UpdatePhoneSession.cs index f23a1faf..3c0b388a 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.UpdatePhoneSession.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.UpdatePhoneSession.cs @@ -19,7 +19,7 @@ public async Task UpdatePhoneSession_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/sessions/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.SessionResponse); // Act @@ -41,7 +41,7 @@ public async Task UpdatePhoneSession_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/sessions/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -64,7 +64,7 @@ public async Task UpdatePhoneSession_ShouldReturnErrorResponse_WhenExceptionOccu _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/account/sessions/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.cs index c827a99b..a8a2f835 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Account/AccountClientTests.cs @@ -1,5 +1,8 @@ -using Microsoft.Extensions.DependencyInjection; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.Extensions.DependencyInjection; using PinguApps.Appwrite.Server.Clients; +using PinguApps.Appwrite.Shared.Converters; using PinguApps.Appwrite.Shared.Tests; using Refit; using RichardSzalay.MockHttp; @@ -9,6 +12,7 @@ public partial class AccountClientTests { private readonly MockHttpMessageHandler _mockHttp; private readonly IAppwriteClient _appwriteServer; + private readonly JsonSerializerOptions _jsonSerializerOptions; public AccountClientTests() { @@ -23,5 +27,13 @@ public AccountClientTests() var serviceProvider = services.BuildServiceProvider(); _appwriteServer = serviceProvider.GetRequiredService(); + + _jsonSerializerOptions = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + + _jsonSerializerOptions.Converters.Add(new IgnoreSdkExcludedPropertiesConverterFactory()); } } diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUser.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUser.cs index bbbc025a..7c8254e7 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUser.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUser.cs @@ -19,7 +19,7 @@ public async Task CreateUser_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); // Act @@ -42,7 +42,7 @@ public async Task CreateUser_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -66,7 +66,7 @@ public async Task CreateUser_ShouldReturnErrorResponse_WhenExceptionOccurs() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserJwt.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserJwt.cs index c54b2a35..15f9c24e 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserJwt.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserJwt.cs @@ -27,7 +27,7 @@ public async Task CreateUserJwt_ShouldReturnSuccess_WhenApiCallSucceeds(CreateUs { // Arrange _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/{request.UserId}/jwts") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(TestConstants.AppJson, TestConstants.JwtResponse); @@ -48,7 +48,7 @@ public async Task CreateUserJwt_ShouldHandleException_WhenApiCallFails() }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/{request.UserId}/jwts") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); @@ -70,7 +70,7 @@ public async Task CreateUserJwt_ShouldReturnErrorResponse_WhenExceptionOccurs() }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/{request.UserId}/jwts") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Throw(new HttpRequestException("An error occurred")); diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserTarget.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserTarget.cs index b3f3b4d0..2cfa2c2f 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserTarget.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserTarget.cs @@ -20,7 +20,7 @@ public async Task CreateUserTarget_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/{request.UserId}/targets") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.TargetResponse); // Act @@ -43,7 +43,7 @@ public async Task CreateUserTarget_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/{request.UserId}/targets") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -67,7 +67,7 @@ public async Task CreateUserTarget_ShouldReturnErrorResponse_WhenExceptionOccurs _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/{request.UserId}/targets") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithArgon2Password.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithArgon2Password.cs index da7f64fc..a963b612 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithArgon2Password.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithArgon2Password.cs @@ -19,7 +19,7 @@ public async Task CreateUserWithArgon2Password_ShouldReturnSuccess_WhenApiCallSu _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/argon2") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); // Act @@ -42,7 +42,7 @@ public async Task CreateUserWithArgon2Password_ShouldHandleException_WhenApiCall _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/argon2") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -66,7 +66,7 @@ public async Task CreateUserWithArgon2Password_ShouldReturnErrorResponse_WhenExc _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/argon2") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithBcryptPassword.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithBcryptPassword.cs index 2e6dd64f..23532790 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithBcryptPassword.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithBcryptPassword.cs @@ -19,7 +19,7 @@ public async Task CreateUserWithBcryptPassword_ShouldReturnSuccess_WhenApiCallSu _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/bcrypt") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); // Act @@ -42,7 +42,7 @@ public async Task CreateUserWithBcryptPassword_ShouldHandleException_WhenApiCall _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/bcrypt") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -66,7 +66,7 @@ public async Task CreateUserWithBcryptPassword_ShouldReturnErrorResponse_WhenExc _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/bcrypt") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithMd5Password.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithMd5Password.cs index bf2eecba..dc6fad88 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithMd5Password.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithMd5Password.cs @@ -17,7 +17,7 @@ public async Task CreateUserWithMd5Password_ShouldReturnSuccess_WhenApiCallSucce }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/md5") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(TestConstants.AppJson, TestConstants.UserResponse); @@ -39,7 +39,7 @@ public async Task CreateUserWithMd5Password_ShouldHandleException_WhenApiCallFai }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/md5") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); @@ -62,7 +62,7 @@ public async Task CreateUserWithMd5Password_ShouldReturnErrorResponse_WhenExcept }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/md5") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Throw(new HttpRequestException("An error occurred")); diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithPhpassPassword.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithPhpassPassword.cs index a171e61a..f2356727 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithPhpassPassword.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithPhpassPassword.cs @@ -17,7 +17,7 @@ public async Task CreateUserWithPhpassPassword_ShouldReturnSuccess_WhenApiCallSu }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/phpass") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(TestConstants.AppJson, TestConstants.UserResponse); @@ -39,7 +39,7 @@ public async Task CreateUserWithPhpassPassword_ShouldHandleException_WhenApiCall }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/phpass") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); @@ -62,7 +62,7 @@ public async Task CreateUserWithPhpassPassword_ShouldReturnErrorResponse_WhenExc }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/phpass") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Throw(new HttpRequestException("An error occurred")); diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithScryptModifiedPassword.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithScryptModifiedPassword.cs index e0a27ef2..0251ca53 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithScryptModifiedPassword.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithScryptModifiedPassword.cs @@ -20,7 +20,7 @@ public async Task CreateUserWithScryptModifiedPassword_ShouldReturnSuccess_WhenA }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/scrypt-modified") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(TestConstants.AppJson, TestConstants.UserResponse); @@ -45,7 +45,7 @@ public async Task CreateUserWithScryptModifiedPassword_ShouldHandleException_Whe }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/scrypt-modified") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); @@ -71,7 +71,7 @@ public async Task CreateUserWithScryptModifiedPassword_ShouldReturnErrorResponse }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/scrypt-modified") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Throw(new HttpRequestException("An error occurred")); diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithScryptPassword.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithScryptPassword.cs index f62fcc02..b6130e9e 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithScryptPassword.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithScryptPassword.cs @@ -18,7 +18,7 @@ public async Task CreateUserWithScryptPassword_ShouldReturnSuccess_WhenApiCallSu }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/scrypt") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(TestConstants.AppJson, TestConstants.UserResponse); @@ -41,7 +41,7 @@ public async Task CreateUserWithScryptPassword_ShouldHandleException_WhenApiCall }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/scrypt") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); @@ -65,7 +65,7 @@ public async Task CreateUserWithScryptPassword_ShouldReturnErrorResponse_WhenExc }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/scrypt") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Throw(new HttpRequestException("An error occurred")); diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithShaPassword.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithShaPassword.cs index d7ee7dc0..8d6d3379 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithShaPassword.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.CreateUserWithShaPassword.cs @@ -18,7 +18,7 @@ public async Task CreateUserWithShaPassword_ShouldReturnSuccess_WhenApiCallSucce }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/sha") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(TestConstants.AppJson, TestConstants.UserResponse); @@ -41,7 +41,7 @@ public async Task CreateUserWithShaPassword_ShouldHandleException_WhenApiCallFai }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/sha") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); @@ -65,7 +65,7 @@ public async Task CreateUserWithShaPassword_ShouldReturnErrorResponse_WhenExcept }; _mockHttp.Expect(HttpMethod.Post, $"{TestConstants.Endpoint}/users/sha") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Throw(new HttpRequestException("An error occurred")); diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateEmail.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateEmail.cs index 5318bb41..412244a1 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateEmail.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateEmail.cs @@ -19,7 +19,7 @@ public async Task UpdateEmail_ShouldReturnSuccess_WhenApiCallSucceeds(string use }; _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{userId}/email") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(TestConstants.AppJson, TestConstants.UserResponse); @@ -41,7 +41,7 @@ public async Task UpdateEmail_ShouldHandleException_WhenApiCallFails() }; _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/user123/email") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); @@ -64,7 +64,7 @@ public async Task UpdateEmail_ShouldReturnErrorResponse_WhenExceptionOccurs() }; _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/user123/email") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Throw(new HttpRequestException("An error occurred")); diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateEmailVerification.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateEmailVerification.cs index 5bfcebb0..13220d00 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateEmailVerification.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateEmailVerification.cs @@ -19,7 +19,7 @@ public async Task UpdateEmailVerification_ShouldReturnSuccess_WhenApiCallSucceed _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/verification") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); // Act @@ -41,7 +41,7 @@ public async Task UpdateEmailVerification_ShouldHandleException_WhenApiCallFails _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/verification") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -64,7 +64,7 @@ public async Task UpdateEmailVerification_ShouldReturnErrorResponse_WhenExceptio _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/verification") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateMfa.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateMfa.cs index a188279a..a79e0efe 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateMfa.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateMfa.cs @@ -18,7 +18,7 @@ public async Task UpdateMfa_ShouldReturnSuccess_WhenApiCallSucceeds() }; _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/mfa") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(TestConstants.AppJson, TestConstants.UserResponse); @@ -40,7 +40,7 @@ public async Task UpdateMfa_ShouldHandleException_WhenApiCallFails() }; _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/mfa") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); @@ -63,7 +63,7 @@ public async Task UpdateMfa_ShouldReturnErrorResponse_WhenExceptionOccurs() }; _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/mfa") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Throw(new HttpRequestException("An error occurred")); diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdatePhoneVerification.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdatePhoneVerification.cs index 61c490ec..48c3ab05 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdatePhoneVerification.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdatePhoneVerification.cs @@ -18,7 +18,7 @@ public async Task UpdatePhoneVerification_ShouldReturnSuccess_WhenApiCallSucceed _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/verification/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); // Act @@ -40,7 +40,7 @@ public async Task UpdatePhoneVerification_ShouldHandleException_WhenApiCallFails _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/verification/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -63,7 +63,7 @@ public async Task UpdatePhoneVerification_ShouldReturnErrorResponse_WhenExceptio _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/verification/phone") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateUserLabels.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateUserLabels.cs index 2f72dcd2..c8749ec8 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateUserLabels.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateUserLabels.cs @@ -27,7 +27,7 @@ public async Task UpdateUserLabels_ShouldReturnSuccess_WhenApiCallSucceeds(Updat { // Arrange _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/users/{request.UserId}/labels") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(TestConstants.AppJson, TestConstants.UserResponse); @@ -49,7 +49,7 @@ public async Task UpdateUserLabels_ShouldHandleException_WhenApiCallFails() }; _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/users/user123/labels") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); @@ -72,7 +72,7 @@ public async Task UpdateUserLabels_ShouldReturnErrorResponse_WhenExceptionOccurs }; _mockHttp.Expect(HttpMethod.Put, $"{TestConstants.Endpoint}/users/user123/labels") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Throw(new HttpRequestException("An error occurred")); diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateUserPreferences.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateUserPreferences.cs index 856b17b0..7f655b84 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateUserPreferences.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateUserPreferences.cs @@ -22,7 +22,7 @@ public async Task UpdateUserPreferences_ShouldReturnSuccess_WhenApiCallSucceeds( }; _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/prefs") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(TestConstants.AppJson, TestConstants.PreferencesResponse); @@ -48,7 +48,7 @@ public async Task UpdateUserPreferences_ShouldHandleException_WhenApiCallFails() }; _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/prefs") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); @@ -75,7 +75,7 @@ public async Task UpdateUserPreferences_ShouldReturnErrorResponse_WhenExceptionO }; _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/prefs") - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .ExpectedHeaders() .Throw(new HttpRequestException("An error occurred")); diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateUserStatus.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateUserStatus.cs index c34052bf..c746d6da 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateUserStatus.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.UpdateUserStatus.cs @@ -19,7 +19,7 @@ public async Task UpdateUserStatus_ShouldReturnSuccess_WhenApiCallSucceeds() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/status") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(TestConstants.AppJson, TestConstants.UserResponse); // Act @@ -41,7 +41,7 @@ public async Task UpdateUserStatus_ShouldHandleException_WhenApiCallFails() _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/status") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); // Act @@ -64,7 +64,7 @@ public async Task UpdateUserStatus_ShouldReturnErrorResponse_WhenExceptionOccurs _mockHttp.Expect(HttpMethod.Patch, $"{TestConstants.Endpoint}/users/{request.UserId}/status") .ExpectedHeaders() - .WithJsonContent(request) + .WithJsonContent(request, _jsonSerializerOptions) .Throw(new HttpRequestException("An error occurred")); // Act diff --git a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.cs b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.cs index 3fcbd236..94044230 100644 --- a/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.cs +++ b/tests/PinguApps.Appwrite.Server.Tests/Clients/Users/UsersClientTests.cs @@ -1,5 +1,8 @@ -using Microsoft.Extensions.DependencyInjection; +using System.Text.Json; +using System.Text.Json.Serialization; +using Microsoft.Extensions.DependencyInjection; using PinguApps.Appwrite.Server.Clients; +using PinguApps.Appwrite.Shared.Converters; using PinguApps.Appwrite.Shared.Tests; using Refit; using RichardSzalay.MockHttp; @@ -9,6 +12,7 @@ public partial class UsersClientTests { private readonly MockHttpMessageHandler _mockHttp; private readonly IAppwriteClient _appwriteClient; + private readonly JsonSerializerOptions _jsonSerializerOptions; public UsersClientTests() { @@ -23,5 +27,13 @@ public UsersClientTests() var serviceProvider = services.BuildServiceProvider(); _appwriteClient = serviceProvider.GetRequiredService(); + + _jsonSerializerOptions = new JsonSerializerOptions + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + + _jsonSerializerOptions.Converters.Add(new IgnoreSdkExcludedPropertiesConverterFactory()); } } From 71a26d2c619607ac7e908ba4bfc2814e21de343b Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sun, 13 Oct 2024 03:01:32 +0100 Subject: [PATCH 6/7] added exclude to base query class --- src/PinguApps.Appwrite.Shared/Requests/QueryBaseRequest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PinguApps.Appwrite.Shared/Requests/QueryBaseRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/QueryBaseRequest.cs index f60af00f..0b6d6e24 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/QueryBaseRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/QueryBaseRequest.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.Text.Json.Serialization; using FluentValidation; +using PinguApps.Appwrite.Shared.Attributes; using PinguApps.Appwrite.Shared.Utils; namespace PinguApps.Appwrite.Shared.Requests; @@ -18,5 +19,6 @@ public abstract class QueryBaseRequest : BaseRequestLearn more about queries. Maximum of 100 queries are allowed, each 4096 characters long. /// [JsonPropertyName("queries")] + [SdkExclude] public virtual List? Queries { get; set; } = null; } From 4ecf688dedfa1afdb228c8c5aad4194d73dff0ac Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sun, 13 Oct 2024 03:01:56 +0100 Subject: [PATCH 7/7] added test coverage for json serialisation changes --- ...reSdkExcludedPropertiesConverterFactory.cs | 5 +- ...ExcludedPropertiesConverterFactoryTests.cs | 310 ++++++++++++++++++ 2 files changed, 311 insertions(+), 4 deletions(-) create mode 100644 tests/PinguApps.Appwrite.Shared.Tests/Converters/IgnoreSdkExcludedPropertiesConverterFactoryTests.cs diff --git a/src/PinguApps.Appwrite.Shared/Converters/IgnoreSdkExcludedPropertiesConverterFactory.cs b/src/PinguApps.Appwrite.Shared/Converters/IgnoreSdkExcludedPropertiesConverterFactory.cs index 47f5bce8..766cefa4 100644 --- a/src/PinguApps.Appwrite.Shared/Converters/IgnoreSdkExcludedPropertiesConverterFactory.cs +++ b/src/PinguApps.Appwrite.Shared/Converters/IgnoreSdkExcludedPropertiesConverterFactory.cs @@ -95,10 +95,7 @@ public override void Write(Utf8JsonWriter writer, T value, JsonSerializerOptions if (jsonConverterAttr is not null && jsonConverterAttr.ConverterType is not null) { // Instantiate the specified converter - var converterInstance = (JsonConverter?)Activator.CreateInstance(jsonConverterAttr.ConverterType); - - if (converterInstance is null) - throw new InvalidOperationException($"Cannot create an instance of converter type {jsonConverterAttr.ConverterType.FullName}."); + var converterInstance = (JsonConverter?)Activator.CreateInstance(jsonConverterAttr.ConverterType)!; // Create a new JsonSerializerOptions instance without the custom converter factory to prevent recursion var newOptions = new JsonSerializerOptions(options); diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Converters/IgnoreSdkExcludedPropertiesConverterFactoryTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Converters/IgnoreSdkExcludedPropertiesConverterFactoryTests.cs new file mode 100644 index 00000000..cdc67218 --- /dev/null +++ b/tests/PinguApps.Appwrite.Shared.Tests/Converters/IgnoreSdkExcludedPropertiesConverterFactoryTests.cs @@ -0,0 +1,310 @@ +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Attributes; +using PinguApps.Appwrite.Shared.Converters; + +namespace PinguApps.Appwrite.Shared.Tests.Converters; +public class IgnoreSdkExcludedPropertiesConverterFactoryTests +{ + private readonly JsonSerializerOptions _options; + + public IgnoreSdkExcludedPropertiesConverterFactoryTests() + { + _options = new JsonSerializerOptions + { + Converters = { new IgnoreSdkExcludedPropertiesConverterFactory() } + }; + } + + [Fact] + public void CanConvert_PrimitiveTypes_ReturnsFalse() + { + var factory = new IgnoreSdkExcludedPropertiesConverterFactory(); + + Assert.False(factory.CanConvert(typeof(int))); + Assert.False(factory.CanConvert(typeof(string))); + Assert.False(factory.CanConvert(typeof(decimal))); + Assert.False(factory.CanConvert(typeof(DateTime))); + Assert.False(factory.CanConvert(typeof(DateTimeOffset))); + Assert.False(factory.CanConvert(typeof(TimeSpan))); + Assert.False(factory.CanConvert(typeof(Guid))); + Assert.False(factory.CanConvert(typeof(object))); + } + + [Fact] + public void CanConvert_EnumerableTypes_ReturnsFalse() + { + var factory = new IgnoreSdkExcludedPropertiesConverterFactory(); + + Assert.False(factory.CanConvert(typeof(List))); + Assert.False(factory.CanConvert(typeof(string[]))); + } + + [Fact] + public void CanConvert_ClassTypes_ReturnsTrue() + { + var factory = new IgnoreSdkExcludedPropertiesConverterFactory(); + + Assert.True(factory.CanConvert(typeof(TestClass))); + } + + [Fact] + public void CanConvert_AbstractClassTypes_ReturnsFalse() + { + var factory = new IgnoreSdkExcludedPropertiesConverterFactory(); + + Assert.False(factory.CanConvert(typeof(AbstractTestClass))); + } + + [Fact] + public void CanConvert_NonClassNonAbstractTypes_ReturnsFalse() + { + var factory = new IgnoreSdkExcludedPropertiesConverterFactory(); + + // Create a type that is not a class and not abstract but bypasses all previous checks + var type = typeof(NonClassNonAbstractType); + + Assert.False(factory.CanConvert(type)); + } + + [Fact] + public void CreateConverter_ReturnsCorrectConverter() + { + var factory = new IgnoreSdkExcludedPropertiesConverterFactory(); + var converter = factory.CreateConverter(typeof(TestClass), _options); + + Assert.NotNull(converter); + } + + [Fact] + public void Read_DeserializesCorrectly() + { + var json = "{\"Name\":\"Test\",\"Age\":30}"; + var result = JsonSerializer.Deserialize(json, _options); + + Assert.NotNull(result); + Assert.Equal("Test", result.Name); + Assert.Equal(30, result.Age); + } + + [Fact] + public void Write_SerializesCorrectly() + { + var testClass = new TestClass { Name = "Test", Age = 30 }; + var json = JsonSerializer.Serialize(testClass, _options); + + Assert.Contains("\"Name\":\"Test\"", json); + Assert.Contains("\"Age\":30", json); + } + + [Fact] + public void Write_ExcludesSdkExcludedProperties() + { + var testClass = new TestClassWithExcludedProperty { Name = "Test", Age = 30, Secret = "Secret" }; + var json = JsonSerializer.Serialize(testClass, _options); + + Assert.Contains("\"Name\":\"Test\"", json); + Assert.Contains("\"Age\":30", json); + Assert.DoesNotContain("\"Secret\"", json); + } + + [Fact] + public void Write_UsesCustomConverter() + { + var testClass = new TestClassWithCustomConverter { Name = "Test", Age = 30, CustomDate = new DateTime(2023, 1, 1) }; + var json = JsonSerializer.Serialize(testClass, _options); + + Assert.Contains("\"Name\":\"Test\"", json); + Assert.Contains("\"Age\":30", json); + Assert.Contains("\"CustomDate\":\"2023-01-01\"", json); + } + + [Fact] + public void Write_ValueIsNull_WritesNullValue() + { + // Arrange + var factory = new IgnoreSdkExcludedPropertiesConverterFactory(); + var converter = factory.CreateConverter(typeof(TestClass), _options) as JsonConverter; + + using var stream = new MemoryStream(); + using var writer = new Utf8JsonWriter(stream); + + // Act + converter?.Write(writer, null!, _options); + writer.Flush(); + + // Assert + var json = Encoding.UTF8.GetString(stream.ToArray()); + Assert.Equal("null", json); + } + + [Fact] + public void Write_PropertyWithoutGetMethod_IsIgnored() + { + // Arrange + var factory = new IgnoreSdkExcludedPropertiesConverterFactory(); + var converter = factory.CreateConverter(typeof(TestClassWithSetOnlyProperty), _options) as JsonConverter; + + var testClass = new TestClassWithSetOnlyProperty { Name = "Test" }; + + using var stream = new MemoryStream(); + using var writer = new Utf8JsonWriter(stream); + + // Act + converter?.Write(writer, testClass, _options); + writer.Flush(); + + // Assert + var json = Encoding.UTF8.GetString(stream.ToArray()); + Assert.Contains("\"Name\":\"Test\"", json); + Assert.DoesNotContain("\"SetOnlyProperty\"", json); + } + + [Fact] + public void Write_PropertyWithJsonPropertyNameAttribute_UsesCustomName() + { + // Arrange + var factory = new IgnoreSdkExcludedPropertiesConverterFactory(); + var converter = factory.CreateConverter(typeof(TestClassWithJsonPropertyName), _options) as JsonConverter; + + var testClass = new TestClassWithJsonPropertyName { CustomName = "Test" }; + + using var stream = new MemoryStream(); + using var writer = new Utf8JsonWriter(stream); + + // Act + converter?.Write(writer, testClass, _options); + writer.Flush(); + + // Assert + var json = Encoding.UTF8.GetString(stream.ToArray()); + Assert.Contains("\"custom_name\":\"Test\"", json); + } + + [Fact] + public void Write_PropertyWithNamingPolicy_UsesConvertedName() + { + // Arrange + var optionsWithNamingPolicy = new JsonSerializerOptions(_options) + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase + }; + + var factory = new IgnoreSdkExcludedPropertiesConverterFactory(); + var converter = factory.CreateConverter(typeof(TestClassWithNamingPolicy), optionsWithNamingPolicy) as JsonConverter; + + var testClass = new TestClassWithNamingPolicy { CustomName = "Test" }; + + using var stream = new MemoryStream(); + using var writer = new Utf8JsonWriter(stream); + + // Act + converter?.Write(writer, testClass, optionsWithNamingPolicy); + writer.Flush(); + + // Assert + var json = Encoding.UTF8.GetString(stream.ToArray()); + Assert.Contains("\"customName\":\"Test\"", json); + } + + [Fact] + public void Write_PropertyValueIsNullAndDefaultIgnoreConditionIsWhenWritingNull_PropertyIsIgnored() + { + // Arrange + var optionsWithIgnoreCondition = new JsonSerializerOptions(_options) + { + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull + }; + + var factory = new IgnoreSdkExcludedPropertiesConverterFactory(); + var converter = factory.CreateConverter(typeof(TestClassWithNullProperty), optionsWithIgnoreCondition) as JsonConverter; + + var testClass = new TestClassWithNullProperty { Name = null }; + + using var stream = new MemoryStream(); + using var writer = new Utf8JsonWriter(stream); + + // Act + converter?.Write(writer, testClass, optionsWithIgnoreCondition); + writer.Flush(); + + // Assert + var json = Encoding.UTF8.GetString(stream.ToArray()); + Assert.DoesNotContain("\"Name\"", json); + } + + private class TestClass + { + public string Name { get; set; } = string.Empty; + public int Age { get; set; } + } + + private abstract class AbstractTestClass + { + public string Name { get; set; } = string.Empty; + } + + private class TestClassWithExcludedProperty + { + public string Name { get; set; } = string.Empty; + public int Age { get; set; } + + [SdkExclude] + public string Secret { get; set; } = string.Empty; + } + + private class TestClassWithCustomConverter + { + public string Name { get; set; } = string.Empty; + public int Age { get; set; } + + [JsonConverter(typeof(CustomDateTimeConverter))] + public DateTime CustomDate { get; set; } + } + + private class CustomDateTimeConverter : JsonConverter + { + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return DateTime.Parse(reader.GetString()!); + } + + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + writer.WriteStringValue(value.ToString("yyyy-MM-dd")); + } + } + + private struct NonClassNonAbstractType + { + public int Value { get; set; } + } + + private class TestClassWithSetOnlyProperty + { + public string Name { get; set; } = string.Empty; + + // Property with only a set method + public int SetOnlyProperty + { + set { /* Do nothing */ } + } + } + + private class TestClassWithJsonPropertyName + { + [JsonPropertyName("custom_name")] + public string CustomName { get; set; } = string.Empty; + } + + private class TestClassWithNamingPolicy + { + public string CustomName { get; set; } = string.Empty; + } + + private class TestClassWithNullProperty + { + public string? Name { get; set; } + } +}