Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,18 @@ public AccountHolderTest()


[TestMethod]
public async Task Given_AccountHolder_When_Unknown_Enum_Then_Result_Deserialize_To_Null()
public async Task Given_AccountHolder_When_Unknown_Enum_Then_Result_Deserialize_PreservesRawValue()
{
// Arrange
string json = TestUtilities.GetTestFileContent("mocks/balanceplatform/AccountHolderWithUnknownEnum.json");

// Act
var response = JsonSerializer.Deserialize<AccountHolder>(json, _jsonSerializerOptionsProvider.Options);

// Assert
// Assert - unknown enum values are now preserved (not null) per IEX-3037 IEnum pattern
Assert.IsNotNull(response);
Assert.IsNull(response.Status);
Assert.IsNotNull(response.Status);
Assert.AreEqual("unknown-enum", response.Status.Value);
}

[TestMethod]
Expand Down
254 changes: 254 additions & 0 deletions Adyen.Test/Checkout/IEnumCheckoutTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
using Adyen.Checkout.Client;
using Adyen.Checkout.Extensions;
using Adyen.Checkout.Models;
using Adyen.Core.Options;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Text.Json;

namespace Adyen.Test.Checkout
{
/// <summary>
/// Tests for the IEnum pattern applied to generated Checkout models:
/// - Result (standalone IEnum, generated by modelEnum.mustache)
/// - PixPayByBankDetails (model with optional inner TypeEnum, generated by modelInnerEnum.mustache)
/// </summary>
[TestClass]
public class IEnumCheckoutTest
{
private readonly JsonSerializerOptionsProvider _jsonSerializerOptionsProvider;

public IEnumCheckoutTest()
{
IHost testHost = Host.CreateDefaultBuilder()
.ConfigureCheckout((context, services, config) =>
{
config.ConfigureAdyenOptions(options =>
{
options.Environment = AdyenEnvironment.Test;
});
})
.Build();

_jsonSerializerOptionsProvider = testHost.Services.GetRequiredService<JsonSerializerOptionsProvider>();
}

// ── Result: standalone IEnum ──────────────────────────────────────────────

[TestMethod]
public void Given_Result_When_DeserializeKnownValue_Then_ReturnsStaticInstance()
{
Result? result = JsonSerializer.Deserialize<Result>("\"VALID\"", _jsonSerializerOptionsProvider.Options);
Assert.AreEqual(Result.VALID, result);
Assert.AreEqual("VALID", result?.Value);
}

[TestMethod]
public void Given_Result_When_DeserializeAllKnownValues_Then_EachMatchesStaticInstance()
{
var opts = _jsonSerializerOptionsProvider.Options;
Assert.AreEqual(Result.VALID, JsonSerializer.Deserialize<Result>("\"VALID\"", opts));
Assert.AreEqual(Result.INVALID, JsonSerializer.Deserialize<Result>("\"INVALID\"", opts));
Assert.AreEqual(Result.UNKNOWN, JsonSerializer.Deserialize<Result>("\"UNKNOWN\"", opts));
Assert.AreEqual(Result.NOTREQUIRED, JsonSerializer.Deserialize<Result>("\"NOT_REQUIRED\"", opts));
}

[TestMethod]
public void Given_Result_When_DeserializeUnknownValue_Then_PreservesRawString()
{
Result? result = JsonSerializer.Deserialize<Result>("\"FUTURE_VALUE\"", _jsonSerializerOptionsProvider.Options);
Assert.IsNotNull(result);
Assert.AreEqual("FUTURE_VALUE", result!.Value);
Assert.AreNotEqual(Result.VALID, result);
}

[TestMethod]
public void Given_Result_When_DeserializeUnknownValue_Then_DoesNotThrow()
{
Exception? ex = null;
Result? result = null;
try { result = JsonSerializer.Deserialize<Result>("\"NEW_RESULT_TYPE\"", _jsonSerializerOptionsProvider.Options); }
catch (Exception e) { ex = e; }
Assert.IsNull(ex);
Assert.IsNotNull(result);
}

[TestMethod]
public void Given_Result_When_DeserializeNull_Then_ReturnsNull()
Comment thread
gcatanese marked this conversation as resolved.
{
Result? result = JsonSerializer.Deserialize<Result>("null", _jsonSerializerOptionsProvider.Options);
Assert.IsNull(result);
}

[TestMethod]
public void Given_Result_When_SerializeKnownValue_Then_WritesCorrectString()
{
string json = JsonSerializer.Serialize(Result.VALID, _jsonSerializerOptionsProvider.Options);
Assert.AreEqual("\"VALID\"", json);

json = JsonSerializer.Serialize(Result.NOTREQUIRED, _jsonSerializerOptionsProvider.Options);
Assert.AreEqual("\"NOT_REQUIRED\"", json);
}

[TestMethod]
public void Given_Result_When_SerializeUnknownValue_Then_PreservesRawString()
{
Result unknown = (Result)"FUTURE_RESULT";
string json = JsonSerializer.Serialize(unknown, _jsonSerializerOptionsProvider.Options);
Assert.AreEqual("\"FUTURE_RESULT\"", json);
}

[TestMethod]
public void Given_Result_When_RoundTripUnknownValue_Then_ValueIsPreserved()
{
var opts = _jsonSerializerOptionsProvider.Options;
Result original = (Result)"FUTURE_RESULT";
string serialized = JsonSerializer.Serialize(original, opts);
Result? deserialized = JsonSerializer.Deserialize<Result>(serialized, opts);
Assert.IsNotNull(deserialized);
Assert.AreEqual("FUTURE_RESULT", deserialized!.Value);
}

[TestMethod]
public void Given_Result_When_FromStringOrDefaultKnownValue_Then_ReturnsStaticInstance()
{
Assert.AreEqual(Result.VALID, Result.FromStringOrDefault("VALID"));
Assert.AreEqual(Result.INVALID, Result.FromStringOrDefault("INVALID"));
Assert.AreEqual(Result.UNKNOWN, Result.FromStringOrDefault("UNKNOWN"));
Assert.AreEqual(Result.NOTREQUIRED, Result.FromStringOrDefault("NOT_REQUIRED"));
}

[TestMethod]
public void Given_Result_When_FromStringOrDefaultUnknownValue_Then_ReturnsNull()
{
Assert.IsNull(Result.FromStringOrDefault("SOMETHING_ELSE"));
}

[TestMethod]
public void Given_Result_When_ToJsonValueKnownEnum_Then_ReturnsString()
{
Assert.AreEqual("VALID", Result.ToJsonValue(Result.VALID));
Assert.AreEqual("NOT_REQUIRED", Result.ToJsonValue(Result.NOTREQUIRED));
}

[TestMethod]
public void Given_Result_When_ToJsonValueUnknown_Then_ReturnsRawString()
{
Result unknown = (Result)"FUTURE_RESULT";
Assert.AreEqual("FUTURE_RESULT", Result.ToJsonValue(unknown));
}

[TestMethod]
public void Given_Result_When_ToJsonValueNull_Then_ReturnsNull()
{
Assert.IsNull(Result.ToJsonValue(null));
}

[TestMethod]
public void Given_Result_When_EqualityBetweenKnownInstances_Then_Equal()
{
Assert.AreEqual(Result.VALID, Result.VALID);
Assert.IsTrue(Result.VALID == Result.VALID);
Assert.AreNotEqual(Result.VALID, Result.INVALID);
}

[TestMethod]
public void Given_Result_When_EqualityIsCaseInsensitive_Then_Equal()
{
Result lower = (Result)"valid";
Result upper = (Result)"VALID";
Assert.AreEqual(lower, upper);
Assert.IsTrue(lower == upper);
}

// ── PixPayByBankDetails: model with optional inner TypeEnum ───────────────

[TestMethod]
public void Given_PixPayByBankDetails_When_DeserializeWithKnownType_Then_TypeMatchesStaticInstance()
{
string json = """{"type":"paybybank_pix"}""";
PixPayByBankDetails? result = JsonSerializer.Deserialize<PixPayByBankDetails>(json, _jsonSerializerOptionsProvider.Options);
Assert.IsNotNull(result);
Assert.AreEqual(PixPayByBankDetails.TypeEnum.PaybybankPix, result!.Type);
Assert.AreEqual("paybybank_pix", result.Type?.Value);
}

[TestMethod]
public void Given_PixPayByBankDetails_When_DeserializeWithUnknownType_Then_PreservesRawString()
{
string json = """{"type":"paybybank_future"}""";
PixPayByBankDetails? result = JsonSerializer.Deserialize<PixPayByBankDetails>(json, _jsonSerializerOptionsProvider.Options);
Assert.IsNotNull(result);
Assert.IsNotNull(result!.Type);
Assert.AreEqual("paybybank_future", result.Type!.Value);
Assert.AreNotEqual(PixPayByBankDetails.TypeEnum.PaybybankPix, result.Type);
}

[TestMethod]
public void Given_PixPayByBankDetails_When_DeserializeWithUnknownType_Then_DoesNotThrow()
{
string json = """{"type":"completely_new_type","checkoutAttemptId":"abc"}""";
Exception? ex = null;
PixPayByBankDetails? result = null;
try { result = JsonSerializer.Deserialize<PixPayByBankDetails>(json, _jsonSerializerOptionsProvider.Options); }
catch (Exception e) { ex = e; }
Assert.IsNull(ex);
Assert.IsNotNull(result);
Assert.AreEqual("completely_new_type", result!.Type?.Value);
}

[TestMethod]
public void Given_PixPayByBankDetails_When_DeserializeWithoutTypeField_Then_TypeUsesDefault()
{
string json = """{"checkoutAttemptId":"abc123"}""";
PixPayByBankDetails? result = JsonSerializer.Deserialize<PixPayByBankDetails>(json, _jsonSerializerOptionsProvider.Options);
Assert.IsNotNull(result);
// Constructor sets _TypeOption = TypeEnum.PaybybankPix (the default)
Assert.AreEqual(PixPayByBankDetails.TypeEnum.PaybybankPix, result!.Type);
}

[TestMethod]
public void Given_PixPayByBankDetails_When_SerializeWithKnownType_Then_WritesCorrectString()
{
string json = """{"type":"paybybank_pix"}""";
PixPayByBankDetails? deserialized = JsonSerializer.Deserialize<PixPayByBankDetails>(json, _jsonSerializerOptionsProvider.Options);
string reserialized = JsonSerializer.Serialize(deserialized, _jsonSerializerOptionsProvider.Options);
Assert.IsTrue(reserialized.Contains("\"paybybank_pix\""), $"Unexpected JSON: {reserialized}");
}

[TestMethod]
public void Given_PixPayByBankDetails_When_SerializeWithUnknownType_Then_PreservesRawString()
{
string json = """{"type":"paybybank_future"}""";
PixPayByBankDetails? deserialized = JsonSerializer.Deserialize<PixPayByBankDetails>(json, _jsonSerializerOptionsProvider.Options);
string reserialized = JsonSerializer.Serialize(deserialized, _jsonSerializerOptionsProvider.Options);
Assert.IsTrue(reserialized.Contains("\"paybybank_future\""), $"Unexpected JSON: {reserialized}");
}

[TestMethod]
public void Given_PixPayByBankDetails_When_RoundTripWithOtherFields_Then_AllFieldsPreserved()
{
string json = """{"type":"paybybank_pix","checkoutAttemptId":"attempt-123","issuer":"BankXYZ"}""";
var opts = _jsonSerializerOptionsProvider.Options;
PixPayByBankDetails? deserialized = JsonSerializer.Deserialize<PixPayByBankDetails>(json, opts);
Assert.IsNotNull(deserialized);
Assert.AreEqual(PixPayByBankDetails.TypeEnum.PaybybankPix, deserialized!.Type);
Assert.AreEqual("attempt-123", deserialized.CheckoutAttemptId);
Assert.AreEqual("BankXYZ", deserialized.Issuer);
}

[TestMethod]
public void Given_PixPayByBankDetails_When_TypeEnumFromStringOrDefaultKnown_Then_ReturnsStaticInstance()
{
Assert.AreEqual(PixPayByBankDetails.TypeEnum.PaybybankPix,
PixPayByBankDetails.TypeEnum.FromStringOrDefault("paybybank_pix"));
}

[TestMethod]
public void Given_PixPayByBankDetails_When_TypeEnumFromStringOrDefaultUnknown_Then_ReturnsNull()
{
Assert.IsNull(PixPayByBankDetails.TypeEnum.FromStringOrDefault("unknown_type"));
}
}
}
20 changes: 12 additions & 8 deletions Adyen.Test/Core/IEnumTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,12 @@ public async Task Given_ToJsonValue_When_Null_Then_Returns_Null()
}

[TestMethod]
public async Task Given_ToJsonValue_When_CustomEnum_Then_Returns_Null()
public async Task Given_ToJsonValue_When_CustomEnum_Then_Returns_RawValue()
{
ExampleEnum custom = ExampleEnum.FromStringOrDefault("this-is-not-a-valid-enum");
Assert.IsNull(ExampleEnum.ToJsonValue(custom));
// After the modelInnerEnum.mustache fix, ToJsonValue preserves unknown values
// for round-trip safety instead of returning null.
ExampleEnum? custom = (ExampleEnum)"this-is-not-a-valid-enum";
Assert.AreEqual("this-is-not-a-valid-enum", ExampleEnum.ToJsonValue(custom));
}

[TestMethod]
Expand All @@ -137,17 +139,19 @@ public async Task Given_JsonSerialization_When_KnownEnum_Then_Serialize_and_Dese
}

[TestMethod]
public async Task Given_JsonSerialization_When_EnumNotInList_Then_Returns_Null()
public async Task Given_JsonSerialization_When_EnumNotInList_Then_PreservesRawValue()
{
// After the modelInnerEnum.mustache fix, unknown values are preserved for round-trip safety.
var options = new JsonSerializerOptions();
options.Converters.Add(new ExampleEnum.ExampleJsonConverter());

ExampleEnum? value = ExampleEnum.FromStringOrDefault("not-in-list");
ExampleEnum? value = (ExampleEnum)"not-in-list";
string serialized = JsonSerializer.Serialize(value, options);
Assert.AreEqual("null", serialized);
Assert.AreEqual("\"not-in-list\"", serialized);

ExampleEnum? deserialized = JsonSerializer.Deserialize<ExampleEnum>(serialized, options);
Assert.AreEqual(null, deserialized);
Assert.IsNotNull(deserialized);
Assert.AreEqual("not-in-list", deserialized!.Value);
}

[TestMethod]
Expand Down Expand Up @@ -338,7 +342,7 @@ private ExampleEnum(string? value)
if (value == ExampleEnum.B)
return "b";

return null;
return value.Value;
}

public class ExampleJsonConverter : JsonConverter<ExampleEnum>
Expand Down
Loading
Loading