Skip to content

Commit a71efa0

Browse files
Update Todo app to include nullable enum
Update the Todo app and tests to prepare to reproduce #3683.
1 parent e315116 commit a71efa0

28 files changed

Lines changed: 769 additions & 31 deletions

test/Swashbuckle.AspNetCore.IntegrationTests/CodeGenerationTests.cs

Lines changed: 62 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
#if NET10_0_OR_GREATER
22

3-
using System.Net;
4-
using System.Net.Http.Json;
53
using System.Reflection;
64
using System.Text.Json;
7-
using DocumentationSnippets;
85
using Microsoft.AspNetCore.Http;
9-
using Microsoft.AspNetCore.Mvc;
106
using Microsoft.Kiota.Abstractions.Authentication;
117
using Microsoft.Kiota.Http.HttpClientLibrary;
128
using Microsoft.OpenApi;
13-
using TodoApp.Models;
14-
using Xunit;
9+
using TodoApp.Client;
10+
using TodoApp.Client.Models;
1511

1612
namespace Swashbuckle.AspNetCore.IntegrationTests;
1713

@@ -105,10 +101,11 @@ await WithTodoAppClientAsync(async (client) =>
105101

106102
// Arrange
107103
var text = "Buy eggs";
108-
var newItem = new TodoApp.Client.Models.CreateTodoItemModel { Text = text };
109104

110105
// Act - Add a new item
111-
var createdItem = await client.Api.Items.PostAsync(newItem, cancellationToken: cancellationToken);
106+
var createdItem = await client.Api.Items.PostAsync(
107+
new() { Text = text },
108+
cancellationToken: cancellationToken);
112109

113110
// Assert - An item was created
114111
Assert.NotNull(createdItem);
@@ -126,6 +123,22 @@ await WithTodoAppClientAsync(async (client) =>
126123
Assert.Null(item.CompletedAt);
127124
Assert.NotEqual(default, item.CreatedAt);
128125
Assert.Equal(item.CreatedAt.Value, item.LastUpdated);
126+
Assert.Null(item.Priority);
127+
Assert.Equal(text, item.Text);
128+
129+
// Act - Update the item to be high priority
130+
await client.Api.Items[new(itemId)].Priority.PatchAsync(
131+
new() { Priority = TodoPriority.High },
132+
cancellationToken: cancellationToken);
133+
134+
item = await client.Api.Items[new(itemId)].GetAsync(cancellationToken: cancellationToken);
135+
136+
Assert.NotNull(item);
137+
Assert.Equal(itemId, item.Id);
138+
Assert.Null(item.CompletedAt);
139+
Assert.NotEqual(default, item.CreatedAt);
140+
Assert.Equal(item.CreatedAt.Value, item.LastUpdated);
141+
Assert.Equal(TodoPriority.High, item.Priority);
129142
Assert.Equal(text, item.Text);
130143

131144
// Act - Mark the item as being completed
@@ -170,7 +183,7 @@ await WithTodoAppClientAsync(async (client) =>
170183
Assert.DoesNotContain(items.Items, (x) => x.Id == itemId);
171184

172185
// Act
173-
var problem = await Assert.ThrowsAsync<TodoApp.Client.Models.ProblemDetails>(
186+
var problem = await Assert.ThrowsAsync<ProblemDetails>(
174187
() => client.Api.Items[new(itemId)].GetAsync(cancellationToken: cancellationToken));
175188

176189
// Assert
@@ -180,6 +193,30 @@ await WithTodoAppClientAsync(async (client) =>
180193
Assert.Equal("Item not found.", problem.Detail);
181194
Assert.Equal("https://tools.ietf.org/html/rfc9110#section-15.5.5", problem.Type);
182195
Assert.Null(problem.Instance);
196+
197+
// Act
198+
problem = await Assert.ThrowsAsync<ProblemDetails>(
199+
() => client.Api.Items[new(itemId)].Complete.PostAsync(cancellationToken: cancellationToken));
200+
201+
// Assert
202+
Assert.NotNull(problem);
203+
Assert.Equal(StatusCodes.Status404NotFound, problem.Status);
204+
Assert.Equal("Not Found", problem.Title);
205+
Assert.Equal("Item not found.", problem.Detail);
206+
Assert.Equal("https://tools.ietf.org/html/rfc9110#section-15.5.5", problem.Type);
207+
Assert.Null(problem.Instance);
208+
209+
// Act
210+
problem = await Assert.ThrowsAsync<ProblemDetails>(
211+
() => client.Api.Items[new(itemId)].Priority.PatchAsync(new() { Priority = TodoPriority.Low }, cancellationToken: cancellationToken));
212+
213+
// Assert
214+
Assert.NotNull(problem);
215+
Assert.Equal(StatusCodes.Status404NotFound, problem.Status);
216+
Assert.Equal("Not Found", problem.Title);
217+
Assert.Equal("Item not found.", problem.Detail);
218+
Assert.Equal("https://tools.ietf.org/html/rfc9110#section-15.5.5", problem.Type);
219+
Assert.Null(problem.Instance);
183220
});
184221
}
185222

@@ -190,11 +227,10 @@ public async Task Cannot_Create_Todo_Item_With_No_Text()
190227
await WithTodoAppClientAsync(async (client) =>
191228
{
192229
var cancellationToken = TestContext.Current.CancellationToken;
193-
var item = new TodoApp.Client.Models.CreateTodoItemModel { Text = string.Empty };
194230

195231
// Act
196-
var problem = await Assert.ThrowsAsync<TodoApp.Client.Models.ProblemDetails>(
197-
() => client.Api.Items.PostAsync(item, cancellationToken: cancellationToken));
232+
var problem = await Assert.ThrowsAsync<ProblemDetails>(
233+
() => client.Api.Items.PostAsync(new() { Text = string.Empty }, cancellationToken: cancellationToken));
198234

199235
// Assert
200236
Assert.NotNull(problem);
@@ -213,14 +249,15 @@ public async Task Cannot_Complete_Todo_Item_Multiple_Times()
213249
await WithTodoAppClientAsync(async (client) =>
214250
{
215251
var cancellationToken = TestContext.Current.CancellationToken;
216-
var item = new TodoApp.Client.Models.CreateTodoItemModel { Text = "Something" };
217252

218-
var createdItem = await client.Api.Items.PostAsync(item, cancellationToken: cancellationToken);
253+
var createdItem = await client.Api.Items.PostAsync(
254+
new() { Text = "Something" },
255+
cancellationToken: cancellationToken);
219256

220257
await client.Api.Items[new(createdItem.Id)].Complete.PostAsync(cancellationToken: cancellationToken);
221258

222259
// Act
223-
var problem = await Assert.ThrowsAsync<TodoApp.Client.Models.ProblemDetails>(
260+
var problem = await Assert.ThrowsAsync<ProblemDetails>(
224261
() => client.Api.Items[new(createdItem.Id)].Complete.PostAsync(cancellationToken: cancellationToken));
225262

226263
// Assert
@@ -240,14 +277,15 @@ public async Task Cannot_Complete_Deleted_Todo_Item()
240277
await WithTodoAppClientAsync(async (client) =>
241278
{
242279
var cancellationToken = TestContext.Current.CancellationToken;
243-
var item = new TodoApp.Client.Models.CreateTodoItemModel { Text = "Something" };
244280

245-
var createdItem = await client.Api.Items.PostAsync(item, cancellationToken: cancellationToken);
281+
var createdItem = await client.Api.Items.PostAsync(
282+
new() { Text = "Something" },
283+
cancellationToken: cancellationToken);
246284

247285
await client.Api.Items[new(createdItem.Id)].DeleteAsync(cancellationToken: cancellationToken);
248286

249287
// Act
250-
var problem = await Assert.ThrowsAsync<TodoApp.Client.Models.ProblemDetails>(
288+
var problem = await Assert.ThrowsAsync<ProblemDetails>(
251289
() => client.Api.Items[new(createdItem.Id)].Complete.PostAsync(cancellationToken: cancellationToken));
252290

253291
// Assert
@@ -267,14 +305,15 @@ public async Task Cannot_Delete_Todo_Item_Multiple_Times()
267305
await WithTodoAppClientAsync(async (client) =>
268306
{
269307
var cancellationToken = TestContext.Current.CancellationToken;
270-
var item = new TodoApp.Client.Models.CreateTodoItemModel { Text = "Something" };
271308

272-
var createdItem = await client.Api.Items.PostAsync(item, cancellationToken: cancellationToken);
309+
var createdItem = await client.Api.Items.PostAsync(
310+
new() { Text = "Something" },
311+
cancellationToken: cancellationToken);
273312

274313
await client.Api.Items[new(createdItem.Id)].DeleteAsync(cancellationToken: cancellationToken);
275314

276315
// Act
277-
var problem = await Assert.ThrowsAsync<TodoApp.Client.Models.ProblemDetails>(
316+
var problem = await Assert.ThrowsAsync<ProblemDetails>(
278317
() => client.Api.Items[new(createdItem.Id)].DeleteAsync(cancellationToken: cancellationToken));
279318

280319
// Assert
@@ -302,14 +341,14 @@ private static string GetProjectRoot() =>
302341
.First((p) => p.Key is "ProjectRoot")
303342
.Value!;
304343

305-
private static async Task WithTodoAppClientAsync(Func<TodoApp.Client.TodoApiClient, Task> callback)
344+
private static async Task WithTodoAppClientAsync(Func<TodoApiClient, Task> callback)
306345
{
307346
using var httpClient = SwaggerIntegrationTests.GetHttpClientForTestApplication(typeof(TodoApp.Program));
308347

309348
var provider = new AnonymousAuthenticationProvider();
310349
using var request = new HttpClientRequestAdapter(provider, httpClient: httpClient);
311350

312-
var client = new TodoApp.Client.TodoApiClient(request);
351+
var client = new TodoApiClient(request);
313352

314353
await callback(client);
315354
}

test/Swashbuckle.AspNetCore.IntegrationTests/TodoClient/Api/Items/Item/ItemsItemRequestBuilder.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Threading;
1010
using System;
1111
using TodoApp.Client.Api.Items.Item.Complete;
12+
using TodoApp.Client.Api.Items.Item.Priority;
1213
using TodoApp.Client.Models;
1314
namespace TodoApp.Client.Api.Items.Item
1415
{
@@ -23,6 +24,11 @@ public partial class ItemsItemRequestBuilder : BaseRequestBuilder
2324
{
2425
get => new global::TodoApp.Client.Api.Items.Item.Complete.CompleteRequestBuilder(PathParameters, RequestAdapter);
2526
}
27+
/// <summary>The priority property</summary>
28+
public global::TodoApp.Client.Api.Items.Item.Priority.PriorityRequestBuilder Priority
29+
{
30+
get => new global::TodoApp.Client.Api.Items.Item.Priority.PriorityRequestBuilder(PathParameters, RequestAdapter);
31+
}
2632
/// <summary>
2733
/// Instantiates a new <see cref="global::TodoApp.Client.Api.Items.Item.ItemsItemRequestBuilder"/> and sets the default values.
2834
/// </summary>
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
// <auto-generated/>
2+
#pragma warning disable CS0618
3+
using Microsoft.Kiota.Abstractions.Extensions;
4+
using Microsoft.Kiota.Abstractions.Serialization;
5+
using Microsoft.Kiota.Abstractions;
6+
using System.Collections.Generic;
7+
using System.IO;
8+
using System.Threading.Tasks;
9+
using System.Threading;
10+
using System;
11+
using TodoApp.Client.Models;
12+
namespace TodoApp.Client.Api.Items.Item.Priority
13+
{
14+
/// <summary>
15+
/// Builds and executes requests for operations under \api\items\{id}\priority
16+
/// </summary>
17+
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
18+
public partial class PriorityRequestBuilder : BaseRequestBuilder
19+
{
20+
/// <summary>
21+
/// Instantiates a new <see cref="global::TodoApp.Client.Api.Items.Item.Priority.PriorityRequestBuilder"/> and sets the default values.
22+
/// </summary>
23+
/// <param name="pathParameters">Path parameters for the request</param>
24+
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
25+
public PriorityRequestBuilder(Dictionary<string, object> pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/items/{id}/priority", pathParameters)
26+
{
27+
}
28+
/// <summary>
29+
/// Instantiates a new <see cref="global::TodoApp.Client.Api.Items.Item.Priority.PriorityRequestBuilder"/> and sets the default values.
30+
/// </summary>
31+
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
32+
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
33+
public PriorityRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/api/items/{id}/priority", rawUrl)
34+
{
35+
}
36+
/// <summary>
37+
/// Updates the priority of the todo item with the specified ID to the specified priority.
38+
/// </summary>
39+
/// <param name="body">Represents the model for updating the priority of a Todo item.</param>
40+
/// <param name="cancellationToken">Cancellation token to use when cancelling requests</param>
41+
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
42+
/// <exception cref="global::TodoApp.Client.Models.ProblemDetails">When receiving a 400 status code</exception>
43+
/// <exception cref="global::TodoApp.Client.Models.ProblemDetails">When receiving a 404 status code</exception>
44+
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
45+
#nullable enable
46+
public async Task PatchAsync(global::TodoApp.Client.Models.UpdateTodoItemPriorityModel body, Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default)
47+
{
48+
#nullable restore
49+
#else
50+
public async Task PatchAsync(global::TodoApp.Client.Models.UpdateTodoItemPriorityModel body, Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default, CancellationToken cancellationToken = default)
51+
{
52+
#endif
53+
if(ReferenceEquals(body, null)) throw new ArgumentNullException(nameof(body));
54+
var requestInfo = ToPatchRequestInformation(body, requestConfiguration);
55+
var errorMapping = new Dictionary<string, ParsableFactory<IParsable>>
56+
{
57+
{ "400", global::TodoApp.Client.Models.ProblemDetails.CreateFromDiscriminatorValue },
58+
{ "404", global::TodoApp.Client.Models.ProblemDetails.CreateFromDiscriminatorValue },
59+
};
60+
await RequestAdapter.SendNoContentAsync(requestInfo, errorMapping, cancellationToken).ConfigureAwait(false);
61+
}
62+
/// <summary>
63+
/// Updates the priority of the todo item with the specified ID to the specified priority.
64+
/// </summary>
65+
/// <returns>A <see cref="RequestInformation"/></returns>
66+
/// <param name="body">Represents the model for updating the priority of a Todo item.</param>
67+
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
68+
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
69+
#nullable enable
70+
public RequestInformation ToPatchRequestInformation(global::TodoApp.Client.Models.UpdateTodoItemPriorityModel body, Action<RequestConfiguration<DefaultQueryParameters>>? requestConfiguration = default)
71+
{
72+
#nullable restore
73+
#else
74+
public RequestInformation ToPatchRequestInformation(global::TodoApp.Client.Models.UpdateTodoItemPriorityModel body, Action<RequestConfiguration<DefaultQueryParameters>> requestConfiguration = default)
75+
{
76+
#endif
77+
if(ReferenceEquals(body, null)) throw new ArgumentNullException(nameof(body));
78+
var requestInfo = new RequestInformation(Method.PATCH, UrlTemplate, PathParameters);
79+
requestInfo.Configure(requestConfiguration);
80+
requestInfo.Headers.TryAdd("Accept", "application/problem+json");
81+
requestInfo.SetContentFromParsable(RequestAdapter, "application/json", body);
82+
return requestInfo;
83+
}
84+
/// <summary>
85+
/// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored.
86+
/// </summary>
87+
/// <returns>A <see cref="global::TodoApp.Client.Api.Items.Item.Priority.PriorityRequestBuilder"/></returns>
88+
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
89+
public global::TodoApp.Client.Api.Items.Item.Priority.PriorityRequestBuilder WithUrl(string rawUrl)
90+
{
91+
return new global::TodoApp.Client.Api.Items.Item.Priority.PriorityRequestBuilder(rawUrl, RequestAdapter);
92+
}
93+
}
94+
}
95+
#pragma warning restore CS0618

test/Swashbuckle.AspNetCore.IntegrationTests/TodoClient/Models/CreatedTodoItemModel.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
namespace TodoApp.Client.Models
99
{
1010
/// <summary>
11-
/// Represents the model for a created Todo item. This class cannot be inherited.
11+
/// Represents the model for a created Todo item.
1212
/// </summary>
1313
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
1414
public partial class CreatedTodoItemModel : IParsable

test/Swashbuckle.AspNetCore.IntegrationTests/TodoClient/Models/TodoItemModel.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ public partial class TodoItemModel : IParsable
2727
#endif
2828
/// <summary>Gets or sets the date and time the Todo item was last updated.</summary>
2929
public DateTimeOffset? LastUpdated { get; set; }
30+
/// <summary>The priority levels for a Todo item.</summary>
31+
public global::TodoApp.Client.Models.TodoPriority? Priority { get; set; }
3032
/// <summary>Gets or sets the text of the Todo item.</summary>
3133
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
3234
#nullable enable
@@ -57,6 +59,7 @@ public virtual IDictionary<string, Action<IParseNode>> GetFieldDeserializers()
5759
{ "createdAt", n => { CreatedAt = n.GetDateTimeOffsetValue(); } },
5860
{ "id", n => { Id = n.GetStringValue(); } },
5961
{ "lastUpdated", n => { LastUpdated = n.GetDateTimeOffsetValue(); } },
62+
{ "priority", n => { Priority = n.GetEnumValue<global::TodoApp.Client.Models.TodoPriority>(); } },
6063
{ "text", n => { Text = n.GetStringValue(); } },
6164
};
6265
}
@@ -71,6 +74,7 @@ public virtual void Serialize(ISerializationWriter writer)
7174
writer.WriteDateTimeOffsetValue("createdAt", CreatedAt);
7275
writer.WriteStringValue("id", Id);
7376
writer.WriteDateTimeOffsetValue("lastUpdated", LastUpdated);
77+
writer.WriteEnumValue<global::TodoApp.Client.Models.TodoPriority>("priority", Priority);
7478
writer.WriteStringValue("text", Text);
7579
}
7680
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// <auto-generated/>
2+
using System.Runtime.Serialization;
3+
using System;
4+
namespace TodoApp.Client.Models
5+
{
6+
/// <summary>The priority levels for a Todo item.</summary>
7+
[global::System.CodeDom.Compiler.GeneratedCode("Kiota", "1.0.0")]
8+
public enum TodoPriority
9+
{
10+
[EnumMember(Value = "Normal")]
11+
#pragma warning disable CS1591
12+
Normal,
13+
#pragma warning restore CS1591
14+
[EnumMember(Value = "Low")]
15+
#pragma warning disable CS1591
16+
Low,
17+
#pragma warning restore CS1591
18+
[EnumMember(Value = "High")]
19+
#pragma warning disable CS1591
20+
High,
21+
#pragma warning restore CS1591
22+
}
23+
}

0 commit comments

Comments
 (0)