Files
octokit.net/Octokit.Tests/Http/ApiConnectionTests.cs
Tom Longhurst cd1835326b Fix xUnit Warnings (#2906)
* Fix xUnit Warnings

* Fix

* Fix formatting in AsyncPaginationExtensionGenerator.cs

---------

Co-authored-by: Keegan Campbell <me@kfcampbell.com>
2024-04-15 13:19:26 -07:00

436 lines
20 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using NSubstitute;
using Octokit.Internal;
using Xunit;
using static Octokit.Internal.TestSetup;
namespace Octokit.Tests.Http
{
public class ApiConnectionTests
{
public class TheGetMethod
{
[Fact]
public async Task MakesGetRequestForItem()
{
var getUri = new Uri("anything", UriKind.Relative);
IApiResponse<object> response = new ApiResponse<object>(CreateResponse(HttpStatusCode.OK));
var connection = Substitute.For<IConnection>();
connection.Get<object>(Args.Uri, null).Returns(Task.FromResult(response));
var apiConnection = new ApiConnection(connection);
var data = await apiConnection.Get<object>(getUri);
Assert.Same(response.Body, data);
var calls = connection.ReceivedCalls();
connection.Received().Get<object>(getUri, null, null);
}
[Fact]
public async Task MakesGetRequestForItemWithAcceptsOverride()
{
var getUri = new Uri("anything", UriKind.Relative);
const string accepts = "custom/accepts";
IApiResponse<object> response = new ApiResponse<object>(CreateResponse(HttpStatusCode.OK));
var connection = Substitute.For<IConnection>();
connection.Get<object>(Args.Uri, null, Args.String).Returns(Task.FromResult(response));
var apiConnection = new ApiConnection(connection);
var data = await apiConnection.Get<object>(getUri, null, accepts);
Assert.Same(response.Body, data);
connection.Received().Get<object>(getUri, null, accepts);
}
[Fact]
public async Task EnsuresArgumentNotNull()
{
var getUri = new Uri("anything", UriKind.Relative);
var client = new ApiConnection(Substitute.For<IConnection>());
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Get<object>(null));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Get<object>(getUri, new Dictionary<string, string>(), null));
}
}
public class TheGetHtmlMethod
{
[Fact]
public async Task MakesHtmlRequest()
{
var getUri = new Uri("anything", UriKind.Relative);
IApiResponse<string> response = new ApiResponse<string>(CreateResponse(HttpStatusCode.OK), "<html />");
var connection = Substitute.For<IConnection>();
connection.GetHtml(Args.Uri, null).Returns(Task.FromResult(response));
var apiConnection = new ApiConnection(connection);
var data = await apiConnection.GetHtml(getUri);
Assert.Equal("<html />", data);
connection.Received().GetHtml(getUri);
}
[Fact]
public async Task EnsuresArgumentNotNull()
{
var client = new ApiConnection(Substitute.For<IConnection>());
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetHtml(null));
}
}
public class TheGetAllMethod
{
[Fact]
public async Task MakesGetRequestForAllItems()
{
var getAllUri = new Uri("anything", UriKind.Relative);
IApiResponse<List<object>> response = new ApiResponse<List<object>>(
CreateResponse(HttpStatusCode.OK),
new List<object> { new object(), new object() });
var connection = Substitute.For<IConnection>();
connection.Get<List<object>>(Args.Uri, Args.EmptyDictionary, null).Returns(Task.FromResult(response));
var apiConnection = new ApiConnection(connection);
var data = await apiConnection.GetAll<object>(getAllUri);
Assert.Empty(data);
connection.Received().Get<List<object>>(getAllUri, Args.EmptyDictionary, null, CancellationToken.None, null);
}
[Fact]
public async Task EnsuresArgumentNotNull()
{
var client = new ApiConnection(Substitute.For<IConnection>());
// One argument
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll<object>(null));
// Two argument
await Assert.ThrowsAsync<ArgumentNullException>(async () =>
await client.GetAll<object>(null, new Dictionary<string, string>()));
// Three arguments
await Assert.ThrowsAsync<ArgumentNullException>(async () =>
await client.GetAll<object>(null, new Dictionary<string, string>(), "accepts"));
}
}
public class ThePatchMethod
{
[Fact]
public async Task MakesPatchRequestWithSuppliedData()
{
var patchUri = new Uri("anything", UriKind.Relative);
var sentData = new object();
IApiResponse<object> response = new ApiResponse<object>(CreateResponse(HttpStatusCode.OK), new object());
var connection = Substitute.For<IConnection>();
connection.Patch<object>(Args.Uri, Args.Object).Returns(Task.FromResult(response));
var apiConnection = new ApiConnection(connection);
var data = await apiConnection.Patch<object>(patchUri, sentData);
Assert.Same(data, response.Body);
connection.Received().Patch<object>(patchUri, sentData);
}
[Fact]
public async Task MakesPatchRequestWithAcceptsOverride()
{
var patchUri = new Uri("anything", UriKind.Relative);
var sentData = new object();
var accepts = "custom/accepts";
IApiResponse<object> response = new ApiResponse<object>(CreateResponse(HttpStatusCode.OK));
var connection = Substitute.For<IConnection>();
connection.Patch<object>(Args.Uri, Args.Object, Args.String).Returns(Task.FromResult(response));
var apiConnection = new ApiConnection(connection);
var data = await apiConnection.Patch<object>(patchUri, sentData, accepts);
Assert.Same(data, response.Body);
connection.Received().Patch<object>(patchUri, sentData, accepts);
}
[Fact]
public async Task EnsuresArgumentNotNull()
{
var connection = new ApiConnection(Substitute.For<IConnection>());
var patchUri = new Uri("", UriKind.Relative);
await Assert.ThrowsAsync<ArgumentNullException>(() => connection.Patch<object>(null, new object()));
await Assert.ThrowsAsync<ArgumentNullException>(() => connection.Patch<object>(patchUri, null));
await Assert.ThrowsAsync<ArgumentNullException>(() => connection.Patch<object>(patchUri, new object(), null));
}
}
public class ThePostMethod
{
[Fact]
public async Task MakesPostRequestWithoutData()
{
var postUri = new Uri("anything", UriKind.Relative);
var statusCode = HttpStatusCode.Accepted;
var connection = Substitute.For<IConnection>();
connection.Post(Args.Uri).Returns(Task.FromResult(statusCode));
var apiConnection = new ApiConnection(connection);
await apiConnection.Post(postUri);
connection.Received().Post(postUri);
}
[Fact]
public async Task MakesPostRequestWithSuppliedData()
{
var postUri = new Uri("anything", UriKind.Relative);
var sentData = new object();
IApiResponse<object> response = new ApiResponse<object>(CreateResponse(HttpStatusCode.OK), new object());
var connection = Substitute.For<IConnection>();
connection.Post<object>(Args.Uri, Args.Object, null, null).Returns(Task.FromResult(response));
var apiConnection = new ApiConnection(connection);
var data = await apiConnection.Post<object>(postUri, sentData);
Assert.Same(data, response.Body);
connection.Received().Post<object>(postUri, sentData, null, null);
}
[Fact]
public async Task MakesUploadRequest()
{
var uploadUrl = new Uri("anything", UriKind.Relative);
IApiResponse<string> response = new ApiResponse<string>(CreateResponse(HttpStatusCode.OK), "the response");
var connection = Substitute.For<IConnection>();
connection.Post<string>(Args.Uri, Arg.Any<Stream>(), Args.String, Args.String)
.Returns(Task.FromResult(response));
var apiConnection = new ApiConnection(connection);
var rawData = new MemoryStream();
await apiConnection.Post<string>(uploadUrl, rawData, "accepts", "content-type");
connection.Received().Post<string>(uploadUrl, rawData, "accepts", "content-type");
}
[Fact]
public async Task EnsuresArgumentsNotNull()
{
var postUri = new Uri("", UriKind.Relative);
var connection = new ApiConnection(Substitute.For<IConnection>());
// 1 parameter overload
await Assert.ThrowsAsync<ArgumentNullException>(() => connection.Post(null));
// 2 parameter overload
await Assert.ThrowsAsync<ArgumentNullException>(() => connection.Post<object>(null, new object()));
await Assert.ThrowsAsync<ArgumentNullException>(() => connection.Post<object>(postUri, null));
// 3 parameters
await Assert.ThrowsAsync<ArgumentNullException>(() => connection.Post<object>(null, new MemoryStream(), "anAccept", "some-content-type"));
await Assert.ThrowsAsync<ArgumentNullException>(() => connection.Post<object>(postUri, null, "anAccept", "some-content-type"));
}
}
public class ThePutMethod
{
[Fact]
public async Task MakesPutRequestWithSuppliedData()
{
var putUri = new Uri("anything", UriKind.Relative);
var sentData = new object();
IApiResponse<object> response = new ApiResponse<object>(CreateResponse(HttpStatusCode.OK));
var connection = Substitute.For<IConnection>();
connection.Put<object>(Args.Uri, Args.Object).Returns(Task.FromResult(response));
var apiConnection = new ApiConnection(connection);
var data = await apiConnection.Put<object>(putUri, sentData);
Assert.Same(data, response.Body);
connection.Received().Put<object>(putUri, sentData);
}
[Fact]
public async Task MakesPutRequestWithSuppliedDataAndTwoFactorCode()
{
var putUri = new Uri("anything", UriKind.Relative);
var sentData = new object();
IApiResponse<object> response = new ApiResponse<object>(CreateResponse(HttpStatusCode.OK));
var connection = Substitute.For<IConnection>();
connection.Put<object>(Args.Uri, Args.Object, "two-factor").Returns(Task.FromResult(response));
var apiConnection = new ApiConnection(connection);
var data = await apiConnection.Put<object>(putUri, sentData, "two-factor");
Assert.Same(data, response.Body);
connection.Received().Put<object>(putUri, sentData, "two-factor");
}
[Fact]
public async Task EnsuresArgumentsNotNull()
{
var putUri = new Uri("", UriKind.Relative);
var connection = new ApiConnection(Substitute.For<IConnection>());
// 2 parameter overload
await Assert.ThrowsAsync<ArgumentNullException>(async () =>
await connection.Put<object>(null, new object()));
await Assert.ThrowsAsync<ArgumentNullException>(async () =>
await connection.Put<object>(putUri, null));
// 3 parameters
await Assert.ThrowsAsync<ArgumentNullException>(async () =>
await connection.Put<object>(null, new MemoryStream(), "two-factor"));
await Assert.ThrowsAsync<ArgumentNullException>(async () =>
await connection.Put<object>(putUri, null, "two-factor"));
await Assert.ThrowsAsync<ArgumentNullException>(async () =>
await connection.Put<object>(putUri, new MemoryStream(), null));
await Assert.ThrowsAsync<ArgumentException>(async () =>
await connection.Put<object>(putUri, new MemoryStream(), ""));
}
}
public class TheDeleteMethod
{
[Fact]
public async Task MakesDeleteRequest()
{
var deleteUri = new Uri("anything", UriKind.Relative);
HttpStatusCode statusCode = HttpStatusCode.NoContent;
var connection = Substitute.For<IConnection>();
connection.Delete(Args.Uri).Returns(Task.FromResult(statusCode));
var apiConnection = new ApiConnection(connection);
await apiConnection.Delete(deleteUri);
connection.Received().Delete(deleteUri);
}
[Fact]
public async Task EnsuresArgumentNotNull()
{
var connection = new ApiConnection(Substitute.For<IConnection>());
await Assert.ThrowsAsync<ArgumentNullException>(() => connection.Delete(null));
}
}
public class TheGetQueuedOperationMethod
{
[Fact]
public async Task WhenGetReturnsNotOkOrAcceptedApiExceptionIsThrown()
{
var queuedOperationUrl = new Uri("anything", UriKind.Relative);
IApiResponse<object> response = new ApiResponse<object>(CreateResponse(HttpStatusCode.PartialContent), new object());
var connection = Substitute.For<IConnection>();
connection.GetResponse<object>(queuedOperationUrl, Args.CancellationToken).Returns(Task.FromResult(response));
var apiConnection = new ApiConnection(connection);
await Assert.ThrowsAsync<ApiException>(() => apiConnection.GetQueuedOperation<object>(queuedOperationUrl, Args.CancellationToken));
}
[Fact]
public async Task WhenGetReturnsOkThenBodyAsObjectIsReturned()
{
var queuedOperationUrl = new Uri("anything", UriKind.Relative);
var result = new[] { new object() };
var httpResponse = CreateResponse(HttpStatusCode.OK);
IApiResponse<IReadOnlyList<object>> response = new ApiResponse<IReadOnlyList<object>>(httpResponse, result);
var connection = Substitute.For<IConnection>();
connection.GetResponse<IReadOnlyList<object>>(queuedOperationUrl, Args.CancellationToken)
.Returns(Task.FromResult(response));
var apiConnection = new ApiConnection(connection);
var actualResult = await apiConnection.GetQueuedOperation<object>(queuedOperationUrl, CancellationToken.None);
Assert.Same(actualResult, result);
}
[Fact]
public async Task WhenGetReturnsNoContentThenReturnsEmptyCollection()
{
var queuedOperationUrl = new Uri("anything", UriKind.Relative);
var result = new[] { new object() };
var httpResponse = CreateResponse(HttpStatusCode.NoContent);
IApiResponse<IReadOnlyList<object>> response = new ApiResponse<IReadOnlyList<object>>(
httpResponse, result);
var connection = Substitute.For<IConnection>();
connection.GetResponse<IReadOnlyList<object>>(queuedOperationUrl, Args.CancellationToken)
.Returns(Task.FromResult(response));
var apiConnection = new ApiConnection(connection);
var actualResult = await apiConnection.GetQueuedOperation<object>(queuedOperationUrl, CancellationToken.None);
Assert.Empty(actualResult);
}
[Fact]
public async Task GetIsRepeatedUntilHttpStatusCodeOkIsReturned()
{
var queuedOperationUrl = new Uri("anything", UriKind.Relative);
var result = new[] { new object() };
IApiResponse<IReadOnlyList<object>> firstResponse = new ApiResponse<IReadOnlyList<object>>(CreateResponse(HttpStatusCode.Accepted), result);
IApiResponse<IReadOnlyList<object>> completedResponse = new ApiResponse<IReadOnlyList<object>>(CreateResponse(HttpStatusCode.OK), result);
var connection = Substitute.For<IConnection>();
connection.GetResponse<IReadOnlyList<object>>(queuedOperationUrl, Args.CancellationToken)
.Returns(x => Task.FromResult(firstResponse),
x => Task.FromResult(firstResponse),
x => Task.FromResult(completedResponse));
var apiConnection = new ApiConnection(connection);
await apiConnection.GetQueuedOperation<object>(queuedOperationUrl, CancellationToken.None);
connection.Received(3).GetResponse<IReadOnlyList<object>>(queuedOperationUrl, Args.CancellationToken);
}
[Fact(Skip = "Test triggers deadlock when run, needs to be investigated")]
public async Task CanCancelQueuedOperation()
{
var queuedOperationUrl = new Uri("anything", UriKind.Relative);
var result = new[] { new object() };
IApiResponse<IReadOnlyList<object>> accepted = new ApiResponse<IReadOnlyList<object>>(CreateResponse(HttpStatusCode.Accepted), result);
var connection = Substitute.For<IConnection>();
connection.GetResponse<IReadOnlyList<object>>(queuedOperationUrl, Args.CancellationToken)
.Returns(x => Task.FromResult(accepted));
var apiConnection = new ApiConnection(connection);
var cancellationTokenSource = new CancellationTokenSource();
cancellationTokenSource.CancelAfter(100);
var canceled = false;
var operationResult = await apiConnection.GetQueuedOperation<object>(queuedOperationUrl, cancellationTokenSource.Token)
.ContinueWith(task =>
{
canceled = task.IsCanceled;
return task;
}, TaskContinuationOptions.OnlyOnCanceled)
.ContinueWith(task => task, TaskContinuationOptions.OnlyOnFaulted);
Assert.True(canceled);
Assert.Null(operationResult);
}
[Fact]
public async Task EnsuresArgumentNotNull()
{
var connection = new ApiConnection(Substitute.For<IConnection>());
await Assert.ThrowsAsync<ArgumentNullException>(() => connection.GetQueuedOperation<object>(null, CancellationToken.None));
}
}
public class TheCtor
{
[Fact]
public void EnsuresNonNullArguments()
{
Assert.Throws<ArgumentNullException>(() => new ApiConnection(null));
}
}
}
}