Skip to content

Commit 186d85c

Browse files
Copilotjeffhandley
andcommitted
Restore EnumSchemaTests.cs and add back valid enum schema tests without obsolete types
Co-authored-by: jeffhandley <1031940+jeffhandley@users.noreply.github.com>
1 parent 93a6877 commit 186d85c

File tree

2 files changed

+378
-0
lines changed

2 files changed

+378
-0
lines changed
Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
using ModelContextProtocol.Protocol;
2+
using System.Text.Json;
3+
4+
namespace ModelContextProtocol.Tests.Protocol;
5+
6+
public class EnumSchemaTests
7+
{
8+
[Fact]
9+
public void UntitledSingleSelectEnumSchema_Serializes_Correctly()
10+
{
11+
// Arrange
12+
var schema = new ElicitRequestParams.UntitledSingleSelectEnumSchema
13+
{
14+
Title = "Priority",
15+
Description = "Task priority level",
16+
Enum = ["low", "medium", "high"],
17+
Default = "medium"
18+
};
19+
20+
// Act
21+
string json = JsonSerializer.Serialize<ElicitRequestParams.PrimitiveSchemaDefinition>(schema, McpJsonUtilities.DefaultOptions);
22+
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(json, McpJsonUtilities.DefaultOptions);
23+
24+
// Assert
25+
Assert.NotNull(deserialized);
26+
var result = Assert.IsType<ElicitRequestParams.UntitledSingleSelectEnumSchema>(deserialized);
27+
Assert.Equal("string", result.Type);
28+
Assert.Equal("Priority", result.Title);
29+
Assert.Equal("Task priority level", result.Description);
30+
Assert.Equal(["low", "medium", "high"], result.Enum);
31+
Assert.Equal("medium", result.Default);
32+
Assert.Contains("\"type\":\"string\"", json);
33+
Assert.Contains("\"enum\":[\"low\",\"medium\",\"high\"]", json);
34+
Assert.DoesNotContain("enumNames", json);
35+
Assert.DoesNotContain("oneOf", json);
36+
}
37+
38+
[Fact]
39+
public void TitledSingleSelectEnumSchema_Serializes_Correctly()
40+
{
41+
// Arrange
42+
var schema = new ElicitRequestParams.TitledSingleSelectEnumSchema
43+
{
44+
Title = "Severity",
45+
Description = "Issue severity",
46+
OneOf =
47+
[
48+
new ElicitRequestParams.EnumSchemaOption { Const = "critical", Title = "Critical" },
49+
new ElicitRequestParams.EnumSchemaOption { Const = "high", Title = "High Priority" },
50+
new ElicitRequestParams.EnumSchemaOption { Const = "low", Title = "Low Priority" }
51+
],
52+
Default = "high"
53+
};
54+
55+
// Act
56+
string json = JsonSerializer.Serialize<ElicitRequestParams.PrimitiveSchemaDefinition>(schema, McpJsonUtilities.DefaultOptions);
57+
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(json, McpJsonUtilities.DefaultOptions);
58+
59+
// Assert
60+
Assert.NotNull(deserialized);
61+
var result = Assert.IsType<ElicitRequestParams.TitledSingleSelectEnumSchema>(deserialized);
62+
Assert.Equal("string", result.Type);
63+
Assert.Equal("Severity", result.Title);
64+
Assert.Equal("Issue severity", result.Description);
65+
Assert.Equal(3, result.OneOf.Count);
66+
Assert.Equal("critical", result.OneOf[0].Const);
67+
Assert.Equal("Critical", result.OneOf[0].Title);
68+
Assert.Equal("high", result.Default);
69+
Assert.Contains("\"oneOf\":", json);
70+
Assert.Contains("\"const\":\"critical\"", json);
71+
Assert.Contains("\"title\":\"Critical\"", json);
72+
Assert.DoesNotContain("enum\":", json);
73+
Assert.DoesNotContain("enumNames", json);
74+
}
75+
76+
[Fact]
77+
public void UntitledMultiSelectEnumSchema_Serializes_Correctly()
78+
{
79+
// Arrange
80+
var schema = new ElicitRequestParams.UntitledMultiSelectEnumSchema
81+
{
82+
Title = "Tags",
83+
Description = "Select multiple tags",
84+
MinItems = 1,
85+
MaxItems = 3,
86+
Items = new ElicitRequestParams.UntitledEnumItemsSchema
87+
{
88+
Type = "string",
89+
Enum = ["bug", "feature", "documentation", "enhancement"]
90+
},
91+
Default = ["bug", "feature"]
92+
};
93+
94+
// Act
95+
string json = JsonSerializer.Serialize<ElicitRequestParams.PrimitiveSchemaDefinition>(schema, McpJsonUtilities.DefaultOptions);
96+
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(json, McpJsonUtilities.DefaultOptions);
97+
98+
// Assert
99+
Assert.NotNull(deserialized);
100+
var result = Assert.IsType<ElicitRequestParams.UntitledMultiSelectEnumSchema>(deserialized);
101+
Assert.Equal("array", result.Type);
102+
Assert.Equal("Tags", result.Title);
103+
Assert.Equal("Select multiple tags", result.Description);
104+
Assert.Equal(1, result.MinItems);
105+
Assert.Equal(3, result.MaxItems);
106+
Assert.NotNull(result.Items);
107+
Assert.Equal("string", result.Items.Type);
108+
Assert.Equal(["bug", "feature", "documentation", "enhancement"], result.Items.Enum);
109+
Assert.Equal(["bug", "feature"], result.Default);
110+
Assert.Contains("\"type\":\"array\"", json);
111+
Assert.Contains("\"minItems\":1", json);
112+
Assert.Contains("\"maxItems\":3", json);
113+
Assert.Contains("\"items\":", json);
114+
Assert.DoesNotContain("anyOf", json);
115+
}
116+
117+
[Fact]
118+
public void TitledMultiSelectEnumSchema_Serializes_Correctly()
119+
{
120+
// Arrange
121+
var schema = new ElicitRequestParams.TitledMultiSelectEnumSchema
122+
{
123+
Title = "Features",
124+
Description = "Select desired features",
125+
MinItems = 2,
126+
Items = new ElicitRequestParams.TitledEnumItemsSchema
127+
{
128+
AnyOf =
129+
[
130+
new ElicitRequestParams.EnumSchemaOption { Const = "auth", Title = "Authentication" },
131+
new ElicitRequestParams.EnumSchemaOption { Const = "api", Title = "REST API" },
132+
new ElicitRequestParams.EnumSchemaOption { Const = "ui", Title = "User Interface" }
133+
]
134+
},
135+
Default = ["auth", "api"]
136+
};
137+
138+
// Act
139+
string json = JsonSerializer.Serialize<ElicitRequestParams.PrimitiveSchemaDefinition>(schema, McpJsonUtilities.DefaultOptions);
140+
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(json, McpJsonUtilities.DefaultOptions);
141+
142+
// Assert
143+
Assert.NotNull(deserialized);
144+
var result = Assert.IsType<ElicitRequestParams.TitledMultiSelectEnumSchema>(deserialized);
145+
Assert.Equal("array", result.Type);
146+
Assert.Equal("Features", result.Title);
147+
Assert.Equal("Select desired features", result.Description);
148+
Assert.Equal(2, result.MinItems);
149+
Assert.NotNull(result.Items);
150+
Assert.NotNull(result.Items.AnyOf);
151+
Assert.Equal(3, result.Items.AnyOf.Count);
152+
Assert.Equal("auth", result.Items.AnyOf[0].Const);
153+
Assert.Equal("Authentication", result.Items.AnyOf[0].Title);
154+
Assert.Equal(["auth", "api"], result.Default);
155+
Assert.Contains("\"type\":\"array\"", json);
156+
Assert.Contains("\"anyOf\":", json);
157+
Assert.Contains("\"const\":\"auth\"", json);
158+
Assert.Contains("\"title\":\"Authentication\"", json);
159+
}
160+
161+
[Fact]
162+
public void EnumSchema_Deserializes_As_UntitledSingleSelect()
163+
{
164+
// Arrange - JSON without enumNames should deserialize as UntitledSingleSelectEnumSchema
165+
string json = """
166+
{
167+
"type": "string",
168+
"title": "Status",
169+
"enum": ["draft", "published", "archived"],
170+
"default": "draft"
171+
}
172+
""";
173+
174+
// Act
175+
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(json, McpJsonUtilities.DefaultOptions);
176+
177+
// Assert
178+
Assert.NotNull(deserialized);
179+
var result = Assert.IsType<ElicitRequestParams.UntitledSingleSelectEnumSchema>(deserialized);
180+
Assert.Equal("string", result.Type);
181+
Assert.Equal("Status", result.Title);
182+
Assert.Equal(["draft", "published", "archived"], result.Enum);
183+
Assert.Equal("draft", result.Default);
184+
}
185+
186+
[Fact]
187+
public void EnumSchema_WithOneOf_Deserializes_As_TitledSingleSelect()
188+
{
189+
// Arrange - JSON with oneOf should deserialize as TitledSingleSelectEnumSchema
190+
string json = """
191+
{
192+
"type": "string",
193+
"title": "Priority",
194+
"oneOf": [
195+
{ "const": "p0", "title": "P0 - Critical" },
196+
{ "const": "p1", "title": "P1 - High" },
197+
{ "const": "p2", "title": "P2 - Medium" }
198+
],
199+
"default": "p1"
200+
}
201+
""";
202+
203+
// Act
204+
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(json, McpJsonUtilities.DefaultOptions);
205+
206+
// Assert
207+
Assert.NotNull(deserialized);
208+
var result = Assert.IsType<ElicitRequestParams.TitledSingleSelectEnumSchema>(deserialized);
209+
Assert.Equal("string", result.Type);
210+
Assert.Equal("Priority", result.Title);
211+
Assert.Equal(3, result.OneOf.Count);
212+
Assert.Equal("p0", result.OneOf[0].Const);
213+
Assert.Equal("P0 - Critical", result.OneOf[0].Title);
214+
Assert.Equal("p1", result.Default);
215+
}
216+
217+
[Fact]
218+
public void MultiSelectEnum_WithEnum_Deserializes_As_UntitledMultiSelect()
219+
{
220+
// Arrange
221+
string json = """
222+
{
223+
"type": "array",
224+
"title": "Categories",
225+
"items": {
226+
"type": "string",
227+
"enum": ["tech", "business", "lifestyle"]
228+
},
229+
"default": ["tech"]
230+
}
231+
""";
232+
233+
// Act
234+
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(json, McpJsonUtilities.DefaultOptions);
235+
236+
// Assert
237+
Assert.NotNull(deserialized);
238+
var result = Assert.IsType<ElicitRequestParams.UntitledMultiSelectEnumSchema>(deserialized);
239+
Assert.Equal("array", result.Type);
240+
Assert.Equal("Categories", result.Title);
241+
Assert.NotNull(result.Items);
242+
Assert.Equal(["tech", "business", "lifestyle"], result.Items.Enum);
243+
Assert.Equal(["tech"], result.Default);
244+
}
245+
246+
[Fact]
247+
public void MultiSelectEnum_WithAnyOf_Deserializes_As_TitledMultiSelect()
248+
{
249+
// Arrange
250+
string json = """
251+
{
252+
"type": "array",
253+
"title": "Roles",
254+
"items": {
255+
"anyOf": [
256+
{ "const": "admin", "title": "Administrator" },
257+
{ "const": "user", "title": "User" },
258+
{ "const": "guest", "title": "Guest" }
259+
]
260+
},
261+
"default": ["user"]
262+
}
263+
""";
264+
265+
// Act
266+
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(json, McpJsonUtilities.DefaultOptions);
267+
268+
// Assert
269+
Assert.NotNull(deserialized);
270+
var result = Assert.IsType<ElicitRequestParams.TitledMultiSelectEnumSchema>(deserialized);
271+
Assert.Equal("array", result.Type);
272+
Assert.Equal("Roles", result.Title);
273+
Assert.NotNull(result.Items);
274+
Assert.NotNull(result.Items.AnyOf);
275+
Assert.Equal(3, result.Items.AnyOf.Count);
276+
Assert.Equal("admin", result.Items.AnyOf[0].Const);
277+
Assert.Equal("Administrator", result.Items.AnyOf[0].Title);
278+
Assert.Equal(["user"], result.Default);
279+
}
280+
}

tests/ModelContextProtocol.Tests/Protocol/PrimitiveSchemaDefinitionTests.cs

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,46 @@ public static void BooleanSchema_UnknownMixedProperties_AreIgnored()
107107
Assert.False(boolSchema.Default);
108108
}
109109

110+
[Fact]
111+
public static void EnumSchema_UnknownNestedArrays_AreIgnored()
112+
{
113+
// Test complex unknown properties with arrays of objects
114+
115+
const string jsonWithNestedArrays = """
116+
{
117+
"type": "string",
118+
"enum": ["option1", "option2", "option3"],
119+
"unknownComplex": [
120+
{
121+
"nested": [
122+
{"deep": "value1"},
123+
{"deep": "value2"}
124+
]
125+
},
126+
{
127+
"nested": [
128+
{"deep": "value3"}
129+
]
130+
}
131+
],
132+
"default": "option1"
133+
}
134+
""";
135+
136+
var result = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(
137+
jsonWithNestedArrays,
138+
McpJsonUtilities.DefaultOptions);
139+
140+
Assert.NotNull(result);
141+
var enumSchema = Assert.IsType<ElicitRequestParams.UntitledSingleSelectEnumSchema>(result);
142+
Assert.Equal("string", enumSchema.Type);
143+
Assert.Equal(3, enumSchema.Enum.Count);
144+
Assert.Contains("option1", enumSchema.Enum);
145+
Assert.Contains("option2", enumSchema.Enum);
146+
Assert.Contains("option3", enumSchema.Enum);
147+
Assert.Equal("option1", enumSchema.Default);
148+
}
149+
110150
[Fact]
111151
public static void StringSchema_MultipleUnknownProperties_AllIgnored()
112152
{
@@ -223,6 +263,33 @@ public static void NumberSchema_EmptyUnknownObject_IsIgnored()
223263
Assert.Equal(100.0, numberSchema.Maximum);
224264
}
225265

266+
[Fact]
267+
public static void EnumSchema_UnknownPropertiesBetweenRequired_AreIgnored()
268+
{
269+
// Test unknown properties interspersed with required ones
270+
271+
const string jsonWithInterspersedUnknown = """
272+
{
273+
"unknownFirst": {"x": 1},
274+
"type": "string",
275+
"unknownSecond": [1, 2],
276+
"enum": ["a", "b"],
277+
"unknownThird": {"nested": {"value": true}}
278+
}
279+
""";
280+
281+
var result = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(
282+
jsonWithInterspersedUnknown,
283+
McpJsonUtilities.DefaultOptions);
284+
285+
Assert.NotNull(result);
286+
var enumSchema = Assert.IsType<ElicitRequestParams.UntitledSingleSelectEnumSchema>(result);
287+
Assert.Equal("string", enumSchema.Type);
288+
Assert.Equal(2, enumSchema.Enum.Count);
289+
Assert.Contains("a", enumSchema.Enum);
290+
Assert.Contains("b", enumSchema.Enum);
291+
}
292+
226293
[Fact]
227294
public static void BooleanSchema_VeryDeeplyNestedUnknown_IsIgnored()
228295
{
@@ -257,4 +324,35 @@ public static void BooleanSchema_VeryDeeplyNestedUnknown_IsIgnored()
257324
Assert.Equal("boolean", boolSchema.Type);
258325
Assert.True(boolSchema.Default);
259326
}
327+
328+
[Fact]
329+
public static void EnumSchema_Deserialization_PreservesKnownProperties()
330+
{
331+
// Test deserialization of enum schema with all properties
332+
333+
const string enumSchemaJson = """
334+
{
335+
"type": "string",
336+
"title": "Test Enum",
337+
"description": "A test enum schema",
338+
"enum": ["option1", "option2", "option3"],
339+
"default": "option2"
340+
}
341+
""";
342+
343+
var deserialized = JsonSerializer.Deserialize<ElicitRequestParams.PrimitiveSchemaDefinition>(
344+
enumSchemaJson,
345+
McpJsonUtilities.DefaultOptions);
346+
347+
Assert.NotNull(deserialized);
348+
var enumSchema = Assert.IsType<ElicitRequestParams.UntitledSingleSelectEnumSchema>(deserialized);
349+
Assert.Equal("string", enumSchema.Type);
350+
Assert.Equal("Test Enum", enumSchema.Title);
351+
Assert.Equal("A test enum schema", enumSchema.Description);
352+
Assert.Equal(3, enumSchema.Enum.Count);
353+
Assert.Contains("option1", enumSchema.Enum);
354+
Assert.Contains("option2", enumSchema.Enum);
355+
Assert.Contains("option3", enumSchema.Enum);
356+
Assert.Equal("option2", enumSchema.Default);
357+
}
260358
}

0 commit comments

Comments
 (0)