Skip to content

Commit 5acc898

Browse files
SDK update: forward-compatible enums
🌿 Fern Regeneration -- June 30, 2025
2 parents 6b063c4 + a2332cd commit 5acc898

File tree

1,349 files changed

+32539
-7299
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,349 files changed

+32539
-7299
lines changed

src/Merge.Client.Test/Core/Json/EnumSerializerTests.cs

Lines changed: 0 additions & 60 deletions
This file was deleted.
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
using System.Text.Json;
2+
using System.Text.Json.Serialization;
3+
using Merge.Client.Core;
4+
using NUnit.Framework;
5+
6+
namespace Merge.Client.Test.Core.Json;
7+
8+
[TestFixture]
9+
[Parallelizable(ParallelScope.All)]
10+
public class StringEnumSerializerTests
11+
{
12+
private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true };
13+
14+
private static readonly DummyEnum KnownEnumValue2 = DummyEnum.KnownValue2;
15+
private static readonly DummyEnum UnknownEnumValue = DummyEnum.FromCustom("unknown_value");
16+
17+
private static readonly string JsonWithKnownEnum2 = $$"""
18+
{
19+
"enum_property": "{{KnownEnumValue2}}"
20+
}
21+
""";
22+
23+
private static readonly string JsonWithUnknownEnum = $$"""
24+
{
25+
"enum_property": "{{UnknownEnumValue}}"
26+
}
27+
""";
28+
29+
[Test]
30+
public void ShouldParseKnownEnumValue2()
31+
{
32+
var obj = JsonSerializer.Deserialize<DummyObject>(JsonWithKnownEnum2, JsonOptions);
33+
Assert.That(obj, Is.Not.Null);
34+
Assert.That(obj.EnumProperty, Is.EqualTo(KnownEnumValue2));
35+
}
36+
37+
[Test]
38+
public void ShouldParseUnknownEnum()
39+
{
40+
var obj = JsonSerializer.Deserialize<DummyObject>(JsonWithUnknownEnum, JsonOptions);
41+
Assert.That(obj, Is.Not.Null);
42+
Assert.That(obj.EnumProperty, Is.EqualTo(UnknownEnumValue));
43+
}
44+
45+
[Test]
46+
public void ShouldSerializeKnownEnumValue2()
47+
{
48+
var json = JsonSerializer.SerializeToElement(
49+
new DummyObject { EnumProperty = KnownEnumValue2 },
50+
JsonOptions
51+
);
52+
TestContext.Out.WriteLine("Serialized JSON: \n" + json);
53+
var enumString = json.GetProperty("enum_property").GetString();
54+
Assert.That(enumString, Is.Not.Null);
55+
Assert.That(enumString, Is.EqualTo(KnownEnumValue2));
56+
}
57+
58+
[Test]
59+
public void ShouldSerializeUnknownEnum()
60+
{
61+
var json = JsonSerializer.SerializeToElement(
62+
new DummyObject { EnumProperty = UnknownEnumValue },
63+
JsonOptions
64+
);
65+
TestContext.Out.WriteLine("Serialized JSON: \n" + json);
66+
var enumString = json.GetProperty("enum_property").GetString();
67+
Assert.That(enumString, Is.Not.Null);
68+
Assert.That(enumString, Is.EqualTo(UnknownEnumValue));
69+
}
70+
}
71+
72+
public class DummyObject
73+
{
74+
[JsonPropertyName("enum_property")]
75+
public DummyEnum EnumProperty { get; set; }
76+
}
77+
78+
[JsonConverter(typeof(StringEnumSerializer<DummyEnum>))]
79+
public readonly record struct DummyEnum : IStringEnum
80+
{
81+
public DummyEnum(string value)
82+
{
83+
Value = value;
84+
}
85+
86+
/// <summary>
87+
/// The string value of the enum.
88+
/// </summary>
89+
public string Value { get; }
90+
91+
public static readonly DummyEnum KnownValue1 = FromCustom(Values.KnownValue1);
92+
93+
public static readonly DummyEnum KnownValue2 = FromCustom(Values.KnownValue2);
94+
95+
/// <summary>
96+
/// Constant strings for enum values
97+
/// </summary>
98+
public static class Values
99+
{
100+
public const string KnownValue1 = "known_value1";
101+
102+
public const string KnownValue2 = "known_value2";
103+
}
104+
105+
/// <summary>
106+
/// Create a string enum with the given value.
107+
/// </summary>
108+
public static DummyEnum FromCustom(string value)
109+
{
110+
return new DummyEnum(value);
111+
}
112+
113+
/// <summary>
114+
/// Returns the string value of the enum.
115+
/// </summary>
116+
public override string ToString()
117+
{
118+
return Value;
119+
}
120+
121+
public bool Equals(string? other)
122+
{
123+
return Value.Equals(other);
124+
}
125+
126+
public override int GetHashCode()
127+
{
128+
return Value.GetHashCode();
129+
}
130+
131+
public static explicit operator string(DummyEnum value) => value.Value;
132+
133+
public static explicit operator DummyEnum(string value) => new(value);
134+
135+
public static bool operator ==(DummyEnum value1, string value2) => value1.Value.Equals(value2);
136+
137+
public static bool operator !=(DummyEnum value1, string value2) => !value1.Value.Equals(value2);
138+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using Merge.Client;
2+
using Merge.Client.Core;
3+
using NUnit.Framework;
4+
using WireMock.Logging;
5+
using WireMock.Server;
6+
using WireMock.Settings;
7+
8+
namespace Merge.Client.Test.Unit.MockServer;
9+
10+
[SetUpFixture]
11+
public class BaseMockServerTest
12+
{
13+
protected static WireMockServer Server { get; set; } = null!;
14+
15+
protected static BaseMergeClient Client { get; set; } = null!;
16+
17+
protected static RequestOptions RequestOptions { get; set; } = new();
18+
19+
[OneTimeSetUp]
20+
public void GlobalSetup()
21+
{
22+
// Start the WireMock server
23+
Server = WireMockServer.Start(
24+
new WireMockServerSettings { Logger = new WireMockConsoleLogger() }
25+
);
26+
27+
// Initialize the Client
28+
Client = new BaseMergeClient(
29+
"API_KEY",
30+
clientOptions: new ClientOptions { BaseUrl = Server.Urls[0], MaxRetries = 0 }
31+
);
32+
}
33+
34+
[OneTimeTearDown]
35+
public void GlobalTeardown()
36+
{
37+
Server.Stop();
38+
Server.Dispose();
39+
}
40+
}
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
using global::System.Threading.Tasks;
2+
using Merge.Client.Ats;
3+
using Merge.Client.Core;
4+
using NUnit.Framework;
5+
6+
namespace Merge.Client.Test.Unit.MockServer;
7+
8+
[TestFixture]
9+
public class ChangeStageCreateTest : BaseMockServerTest
10+
{
11+
[Test]
12+
public async global::System.Threading.Tasks.Task MockServerTest()
13+
{
14+
const string requestJson = """
15+
{}
16+
""";
17+
18+
const string mockResponse = """
19+
{
20+
"model": {
21+
"id": "92e8a369-fffe-430d-b93a-f7e8a16563f1",
22+
"remote_id": "98796",
23+
"created_at": "2021-09-15T00:00:00.000Z",
24+
"modified_at": "2021-10-16T00:00:00.000Z",
25+
"candidate": "candidate",
26+
"job": "job",
27+
"applied_at": "2021-10-15T00:00:00.000Z",
28+
"rejected_at": "2021-11-15T00:00:00.000Z",
29+
"offers": [
30+
"e9b5c11d-c588-468e-8567-cd6992e42b62"
31+
],
32+
"source": "Campus recruiting event",
33+
"credited_to": "credited_to",
34+
"screening_question_answers": [
35+
"screening_question_answers",
36+
"screening_question_answers"
37+
],
38+
"current_stage": "current_stage",
39+
"reject_reason": "reject_reason",
40+
"remote_was_deleted": true,
41+
"field_mappings": {
42+
"organization_defined_targets": {
43+
"custom_key": "custom_value"
44+
},
45+
"linked_account_defined_targets": {
46+
"custom_key": "custom_value"
47+
}
48+
},
49+
"remote_data": [
50+
{
51+
"path": "/candidacies",
52+
"data": [
53+
"Varies by platform"
54+
]
55+
}
56+
]
57+
},
58+
"warnings": [
59+
{
60+
"source": {
61+
"pointer": "pointer"
62+
},
63+
"title": "Unrecognized Field",
64+
"detail": "An unrecognized field, age, was passed in with request data.",
65+
"problem_type": "UNRECOGNIZED_FIELD"
66+
}
67+
],
68+
"errors": [
69+
{
70+
"source": {
71+
"pointer": "pointer"
72+
},
73+
"title": "Missing Required Field",
74+
"detail": "custom_fields is a required field on model.",
75+
"problem_type": "MISSING_REQUIRED_FIELD"
76+
}
77+
],
78+
"logs": [
79+
{
80+
"log_id": "99433219-8017-4acd-bb3c-ceb23d663832",
81+
"dashboard_view": "https://app.merge.dev/logs/99433219-8017-4acd-bb3c-ceb23d663832",
82+
"log_summary": {
83+
"url": "www.exampleintegration.com/api/v1/exampleapi",
84+
"method": "POST",
85+
"status_code": 200
86+
}
87+
}
88+
]
89+
}
90+
""";
91+
92+
Server
93+
.Given(
94+
WireMock
95+
.RequestBuilders.Request.Create()
96+
.WithPath("/ats/v1/applications/id/change-stage")
97+
.WithHeader("Content-Type", "application/json")
98+
.UsingPost()
99+
.WithBodyAsJson(requestJson)
100+
)
101+
.RespondWith(
102+
WireMock
103+
.ResponseBuilders.Response.Create()
104+
.WithStatusCode(200)
105+
.WithBody(mockResponse)
106+
);
107+
108+
var response = await Client.Ats.Applications.ChangeStageCreateAsync(
109+
"id",
110+
new UpdateApplicationStageRequest()
111+
);
112+
Assert.That(
113+
response,
114+
Is.EqualTo(JsonUtils.Deserialize<ApplicationResponse>(mockResponse)).UsingDefaults()
115+
);
116+
}
117+
}

0 commit comments

Comments
 (0)