Skip to content

Commit c653e11

Browse files
committed
Extract request body into variable, add missing Kiota tests
1 parent d464ee2 commit c653e11

File tree

67 files changed

+4639
-50
lines changed

Some content is hidden

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

67 files changed

+4639
-50
lines changed
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
using System.Net;
2+
using FluentAssertions;
3+
using Microsoft.Kiota.Http.HttpClientLibrary;
4+
using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode;
5+
using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models;
6+
using OpenApiTests;
7+
using OpenApiTests.ClientIdGenerationModes;
8+
using TestBuildingBlocks;
9+
using Xunit;
10+
using Xunit.Abstractions;
11+
12+
namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes;
13+
14+
public sealed class ClientIdGenerationModesTests
15+
: IClassFixture<IntegrationTestContext<OpenApiStartup<ClientIdGenerationDbContext>, ClientIdGenerationDbContext>>
16+
{
17+
private readonly IntegrationTestContext<OpenApiStartup<ClientIdGenerationDbContext>, ClientIdGenerationDbContext> _testContext;
18+
private readonly TestableHttpClientRequestAdapterFactory _requestAdapterFactory;
19+
private readonly ClientIdGenerationFakers _fakers = new();
20+
21+
public ClientIdGenerationModesTests(IntegrationTestContext<OpenApiStartup<ClientIdGenerationDbContext>, ClientIdGenerationDbContext> testContext,
22+
ITestOutputHelper testOutputHelper)
23+
{
24+
_testContext = testContext;
25+
_requestAdapterFactory = new TestableHttpClientRequestAdapterFactory(testOutputHelper);
26+
27+
testContext.UseController<PlayersController>();
28+
testContext.UseController<GamesController>();
29+
testContext.UseController<PlayerGroupsController>();
30+
}
31+
32+
[Fact]
33+
public async Task Cannot_create_resource_without_ID_when_supplying_ID_is_required()
34+
{
35+
// Arrange
36+
Player newPlayer = _fakers.Player.Generate();
37+
38+
using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory);
39+
ClientIdGenerationModesClient apiClient = new(requestAdapter);
40+
41+
var requestBody = new PlayerPostRequestDocument
42+
{
43+
Data = new PlayerDataInPostRequest
44+
{
45+
Type = PlayerResourceType.Players,
46+
Attributes = new PlayerAttributesInPostRequest
47+
{
48+
UserName = newPlayer.UserName
49+
}
50+
}
51+
};
52+
53+
// Act
54+
Func<Task> action = async () => _ = await apiClient.Players.PostAsync(requestBody);
55+
56+
// Assert
57+
ErrorResponseDocument exception = (await action.Should().ThrowExactlyAsync<ErrorResponseDocument>()).Which;
58+
exception.ResponseStatusCode.Should().Be((int)HttpStatusCode.UnprocessableEntity);
59+
exception.Errors.ShouldHaveCount(1);
60+
61+
ErrorObject error = exception.Errors[0];
62+
error.Status.Should().Be("422");
63+
error.Title.Should().Be("Failed to deserialize request body: The 'id' element is required.");
64+
error.Detail.Should().BeNull();
65+
error.Source.ShouldNotBeNull();
66+
error.Source.Pointer.Should().Be("/data");
67+
}
68+
69+
[Fact]
70+
public async Task Can_create_resource_with_ID_when_supplying_ID_is_required()
71+
{
72+
// Arrange
73+
Player newPlayer = _fakers.Player.Generate();
74+
newPlayer.Id = Guid.NewGuid();
75+
76+
using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory);
77+
ClientIdGenerationModesClient apiClient = new(requestAdapter);
78+
79+
var requestBody = new PlayerPostRequestDocument
80+
{
81+
Data = new PlayerDataInPostRequest
82+
{
83+
Type = PlayerResourceType.Players,
84+
Id = newPlayer.StringId,
85+
Attributes = new PlayerAttributesInPostRequest
86+
{
87+
UserName = newPlayer.UserName
88+
}
89+
}
90+
};
91+
92+
// Act
93+
PlayerPrimaryResponseDocument? document = await apiClient.Players.PostAsync(requestBody);
94+
95+
// Assert
96+
document.Should().BeNull();
97+
98+
await _testContext.RunOnDatabaseAsync(async dbContext =>
99+
{
100+
Player playerInDatabase = await dbContext.Players.FirstWithIdAsync(newPlayer.Id);
101+
102+
playerInDatabase.UserName.Should().Be(newPlayer.UserName);
103+
});
104+
}
105+
106+
[Fact]
107+
public async Task Can_create_resource_without_ID_when_supplying_ID_is_allowed()
108+
{
109+
// Arrange
110+
Game newGame = _fakers.Game.Generate();
111+
112+
using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory);
113+
ClientIdGenerationModesClient apiClient = new(requestAdapter);
114+
115+
var requestBody = new GamePostRequestDocument
116+
{
117+
Data = new GameDataInPostRequest
118+
{
119+
Type = GameResourceType.Games,
120+
Attributes = new GameAttributesInPostRequest
121+
{
122+
Title = newGame.Title,
123+
PurchasePrice = (double)newGame.PurchasePrice
124+
}
125+
}
126+
};
127+
128+
// Act
129+
GamePrimaryResponseDocument? document = await apiClient.Games.PostAsync(requestBody);
130+
131+
// Assert
132+
document.ShouldNotBeNull();
133+
document.Data.ShouldNotBeNull();
134+
document.Data.Id.ShouldNotBeNullOrEmpty();
135+
136+
Guid newGameId = Guid.Parse(document.Data.Id);
137+
138+
await _testContext.RunOnDatabaseAsync(async dbContext =>
139+
{
140+
Game gameInDatabase = await dbContext.Games.FirstWithIdAsync(newGameId);
141+
142+
gameInDatabase.Title.Should().Be(newGame.Title);
143+
gameInDatabase.PurchasePrice.Should().Be(newGame.PurchasePrice);
144+
});
145+
}
146+
147+
[Fact]
148+
public async Task Can_create_resource_with_ID_when_supplying_ID_is_allowed()
149+
{
150+
// Arrange
151+
Game newGame = _fakers.Game.Generate();
152+
newGame.Id = Guid.NewGuid();
153+
154+
using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory);
155+
ClientIdGenerationModesClient apiClient = new(requestAdapter);
156+
157+
var requestBody = new GamePostRequestDocument
158+
{
159+
Data = new GameDataInPostRequest
160+
{
161+
Type = GameResourceType.Games,
162+
Id = newGame.StringId,
163+
Attributes = new GameAttributesInPostRequest
164+
{
165+
Title = newGame.Title,
166+
PurchasePrice = (double)newGame.PurchasePrice
167+
}
168+
}
169+
};
170+
171+
// Act
172+
GamePrimaryResponseDocument? document = await apiClient.Games.PostAsync(requestBody);
173+
174+
// Assert
175+
document.Should().BeNull();
176+
177+
await _testContext.RunOnDatabaseAsync(async dbContext =>
178+
{
179+
Game gameInDatabase = await dbContext.Games.FirstWithIdAsync(newGame.Id);
180+
181+
gameInDatabase.Title.Should().Be(newGame.Title);
182+
gameInDatabase.PurchasePrice.Should().Be(newGame.PurchasePrice);
183+
});
184+
}
185+
186+
[Fact]
187+
public async Task Can_create_resource_without_ID_when_supplying_ID_is_forbidden()
188+
{
189+
// Arrange
190+
PlayerGroup newPlayerGroup = _fakers.Group.Generate();
191+
192+
using HttpClientRequestAdapter requestAdapter = _requestAdapterFactory.CreateAdapter(_testContext.Factory);
193+
ClientIdGenerationModesClient apiClient = new(requestAdapter);
194+
195+
var requestBody = new PlayerGroupPostRequestDocument
196+
{
197+
Data = new PlayerGroupDataInPostRequest
198+
{
199+
Type = PlayerGroupResourceType.PlayerGroups,
200+
Attributes = new PlayerGroupAttributesInPostRequest
201+
{
202+
Name = newPlayerGroup.Name
203+
}
204+
}
205+
};
206+
207+
// Act
208+
PlayerGroupPrimaryResponseDocument? document = await apiClient.PlayerGroups.PostAsync(requestBody);
209+
210+
// Assert
211+
document.ShouldNotBeNull();
212+
document.Data.ShouldNotBeNull();
213+
document.Data.Id.ShouldNotBeNullOrEmpty();
214+
215+
long newPlayerGroupId = long.Parse(document.Data.Id);
216+
217+
await _testContext.RunOnDatabaseAsync(async dbContext =>
218+
{
219+
PlayerGroup playerGroupInDatabase = await dbContext.PlayerGroups.FirstWithIdAsync(newPlayerGroupId);
220+
221+
playerGroupInDatabase.Name.Should().Be(newPlayerGroup.Name);
222+
});
223+
}
224+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// <auto-generated/>
2+
using Microsoft.Kiota.Abstractions.Extensions;
3+
using Microsoft.Kiota.Abstractions.Store;
4+
using Microsoft.Kiota.Abstractions;
5+
using Microsoft.Kiota.Serialization.Form;
6+
using Microsoft.Kiota.Serialization.Json;
7+
using Microsoft.Kiota.Serialization.Multipart;
8+
using Microsoft.Kiota.Serialization.Text;
9+
using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Games;
10+
using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.PlayerGroups;
11+
using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Players;
12+
using System.Collections.Generic;
13+
using System.IO;
14+
using System.Linq;
15+
using System.Threading.Tasks;
16+
using System;
17+
namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode {
18+
/// <summary>
19+
/// The main entry point of the SDK, exposes the configuration and the fluent API.
20+
/// </summary>
21+
public class ClientIdGenerationModesClient : BaseRequestBuilder {
22+
/// <summary>The games property</summary>
23+
public GamesRequestBuilder Games { get =>
24+
new GamesRequestBuilder(PathParameters, RequestAdapter);
25+
}
26+
/// <summary>The playerGroups property</summary>
27+
public PlayerGroupsRequestBuilder PlayerGroups { get =>
28+
new PlayerGroupsRequestBuilder(PathParameters, RequestAdapter);
29+
}
30+
/// <summary>The players property</summary>
31+
public PlayersRequestBuilder Players { get =>
32+
new PlayersRequestBuilder(PathParameters, RequestAdapter);
33+
}
34+
/// <summary>
35+
/// Instantiates a new ClientIdGenerationModesClient and sets the default values.
36+
/// </summary>
37+
/// <param name="backingStore">The backing store to use for the models.</param>
38+
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
39+
public ClientIdGenerationModesClient(IRequestAdapter requestAdapter, IBackingStoreFactory backingStore = default) : base(requestAdapter, "{+baseurl}", new Dictionary<string, object>()) {
40+
ApiClientBuilder.RegisterDefaultSerializer<JsonSerializationWriterFactory>();
41+
ApiClientBuilder.RegisterDefaultSerializer<TextSerializationWriterFactory>();
42+
ApiClientBuilder.RegisterDefaultSerializer<FormSerializationWriterFactory>();
43+
ApiClientBuilder.RegisterDefaultSerializer<MultipartSerializationWriterFactory>();
44+
ApiClientBuilder.RegisterDefaultDeserializer<JsonParseNodeFactory>();
45+
ApiClientBuilder.RegisterDefaultDeserializer<TextParseNodeFactory>();
46+
ApiClientBuilder.RegisterDefaultDeserializer<FormParseNodeFactory>();
47+
if (string.IsNullOrEmpty(RequestAdapter.BaseUrl)) {
48+
RequestAdapter.BaseUrl = "http://localhost";
49+
}
50+
PathParameters.TryAdd("baseurl", RequestAdapter.BaseUrl);
51+
RequestAdapter.EnableBackingStore(backingStore);
52+
}
53+
}
54+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// <auto-generated/>
2+
using Microsoft.Kiota.Abstractions.Serialization;
3+
using Microsoft.Kiota.Abstractions;
4+
using OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Models;
5+
using System.Collections.Generic;
6+
using System.IO;
7+
using System.Linq;
8+
using System.Threading.Tasks;
9+
using System.Threading;
10+
using System;
11+
namespace OpenApiKiotaEndToEndTests.ClientIdGenerationModes.GeneratedCode.Games {
12+
/// <summary>
13+
/// Builds and executes requests for operations under \games
14+
/// </summary>
15+
public class GamesRequestBuilder : BaseRequestBuilder {
16+
/// <summary>
17+
/// Instantiates a new GamesRequestBuilder and sets the default values.
18+
/// </summary>
19+
/// <param name="pathParameters">Path parameters for the request</param>
20+
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
21+
public GamesRequestBuilder(Dictionary<string, object> pathParameters, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/games{?query*}", pathParameters) {
22+
}
23+
/// <summary>
24+
/// Instantiates a new GamesRequestBuilder and sets the default values.
25+
/// </summary>
26+
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
27+
/// <param name="requestAdapter">The request adapter to use to execute the requests.</param>
28+
public GamesRequestBuilder(string rawUrl, IRequestAdapter requestAdapter) : base(requestAdapter, "{+baseurl}/games{?query*}", rawUrl) {
29+
}
30+
/// <summary>
31+
/// Creates a new game.
32+
/// </summary>
33+
/// <param name="body">The request body</param>
34+
/// <param name="cancellationToken">Cancellation token to use when cancelling requests</param>
35+
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
36+
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
37+
#nullable enable
38+
public async Task<GamePrimaryResponseDocument?> PostAsync(GamePostRequestDocument body, Action<RequestConfiguration<GamesRequestBuilderPostQueryParameters>>? requestConfiguration = default, CancellationToken cancellationToken = default) {
39+
#nullable restore
40+
#else
41+
public async Task<GamePrimaryResponseDocument> PostAsync(GamePostRequestDocument body, Action<RequestConfiguration<GamesRequestBuilderPostQueryParameters>> requestConfiguration = default, CancellationToken cancellationToken = default) {
42+
#endif
43+
_ = body ?? throw new ArgumentNullException(nameof(body));
44+
var requestInfo = ToPostRequestInformation(body, requestConfiguration);
45+
var errorMapping = new Dictionary<string, ParsableFactory<IParsable>> {
46+
{"400", ErrorResponseDocument.CreateFromDiscriminatorValue},
47+
{"409", ErrorResponseDocument.CreateFromDiscriminatorValue},
48+
{"422", ErrorResponseDocument.CreateFromDiscriminatorValue},
49+
};
50+
return await RequestAdapter.SendAsync<GamePrimaryResponseDocument>(requestInfo, GamePrimaryResponseDocument.CreateFromDiscriminatorValue, errorMapping, cancellationToken).ConfigureAwait(false);
51+
}
52+
/// <summary>
53+
/// Creates a new game.
54+
/// </summary>
55+
/// <param name="body">The request body</param>
56+
/// <param name="requestConfiguration">Configuration for the request such as headers, query parameters, and middleware options.</param>
57+
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
58+
#nullable enable
59+
public RequestInformation ToPostRequestInformation(GamePostRequestDocument body, Action<RequestConfiguration<GamesRequestBuilderPostQueryParameters>>? requestConfiguration = default) {
60+
#nullable restore
61+
#else
62+
public RequestInformation ToPostRequestInformation(GamePostRequestDocument body, Action<RequestConfiguration<GamesRequestBuilderPostQueryParameters>> requestConfiguration = default) {
63+
#endif
64+
_ = body ?? throw new ArgumentNullException(nameof(body));
65+
var requestInfo = new RequestInformation(Method.POST, UrlTemplate, PathParameters);
66+
requestInfo.Configure(requestConfiguration);
67+
requestInfo.Headers.TryAdd("Accept", "application/vnd.api+json");
68+
requestInfo.SetContentFromParsable(RequestAdapter, "application/vnd.api+json", body);
69+
return requestInfo;
70+
}
71+
/// <summary>
72+
/// Returns a request builder with the provided arbitrary URL. Using this method means any other path or query parameters are ignored.
73+
/// </summary>
74+
/// <param name="rawUrl">The raw URL to use for the request builder.</param>
75+
public GamesRequestBuilder WithUrl(string rawUrl) {
76+
return new GamesRequestBuilder(rawUrl, RequestAdapter);
77+
}
78+
/// <summary>
79+
/// Creates a new game.
80+
/// </summary>
81+
public class GamesRequestBuilderPostQueryParameters {
82+
/// <summary>For syntax, see the documentation for the [`include`](https://www.jsonapi.net/usage/reading/including-relationships.html)/[`filter`](https://www.jsonapi.net/usage/reading/filtering.html)/[`sort`](https://www.jsonapi.net/usage/reading/sorting.html)/[`page`](https://www.jsonapi.net/usage/reading/pagination.html)/[`fields`](https://www.jsonapi.net/usage/reading/sparse-fieldset-selection.html) query string parameters.</summary>
83+
#if NETSTANDARD2_1_OR_GREATER || NETCOREAPP3_1_OR_GREATER
84+
#nullable enable
85+
[QueryParameter("query")]
86+
public string? Query { get; set; }
87+
#nullable restore
88+
#else
89+
[QueryParameter("query")]
90+
public string Query { get; set; }
91+
#endif
92+
}
93+
}
94+
}

0 commit comments

Comments
 (0)