using System; using System.Net; using System.Collections.Generic; using System.IO; using System.Threading; using System.Threading.Tasks; using NSubstitute; using Octokit.Internal; using Octokit.Tests.Helpers; using Xunit; namespace Octokit.Tests.Http { public class ApiConnectionTests { public class TheGetMethod { [Fact] public async Task MakesGetRequestForItem() { var getUri = new Uri("anything", UriKind.Relative); IResponse response = new ApiResponse {BodyAsObject = new object()}; var connection = Substitute.For(); connection.GetAsync(Args.Uri, null, null).Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); var data = await apiConnection.Get(getUri); Assert.Same(response.BodyAsObject, data); connection.Received().GetAsync(getUri); } [Fact] public async Task EnsuresArgumentNotNull() { var client = new ApiConnection(Substitute.For()); await AssertEx.Throws(async () => await client.Get(null)); } } public class TheGetHtmlMethod { [Fact] public async Task MakesHtmlRequest() { var getUri = new Uri("anything", UriKind.Relative); IResponse response = new ApiResponse {Body = ""}; var connection = Substitute.For(); connection.GetHtml(Args.Uri, null).Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); var data = await apiConnection.GetHtml(getUri); Assert.Same("", data); connection.Received().GetHtml(getUri); } [Fact] public async Task EnsuresArgumentNotNull() { var client = new ApiConnection(Substitute.For()); await AssertEx.Throws(async () => await client.GetHtml(null)); } } public class TheGetAllMethod { [Fact] public async Task MakesGetRequestForAllItems() { var getAllUri = new Uri("anything", UriKind.Relative); var links = new Dictionary(); var scopes = new List(); IResponse> response = new ApiResponse> { ApiInfo = new ApiInfo(links, scopes, scopes, "etag", new RateLimit(new Dictionary())), BodyAsObject = new List {new object(), new object()} }; var connection = Substitute.For(); connection.GetAsync>(Args.Uri, null, null).Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); var data = await apiConnection.GetAll(getAllUri); Assert.Equal(2, data.Count); connection.Received().GetAsync>(getAllUri, null, null); } [Fact] public async Task EnsuresArgumentNotNull() { var client = new ApiConnection(Substitute.For()); // One argument await AssertEx.Throws(async () => await client.GetAll(null)); // Two argument await AssertEx.Throws(async () => await client.GetAll(null, new Dictionary())); // Three arguments await AssertEx.Throws(async () => await client.GetAll(null, new Dictionary(), "accepts")); } } public class ThePatchMethod { [Fact] public async Task MakesPatchRequestWithSuppliedData() { var patchUri = new Uri("anything", UriKind.Relative); var sentData = new object(); IResponse response = new ApiResponse {BodyAsObject = new object()}; var connection = Substitute.For(); connection.PatchAsync(Args.Uri, Args.Object).Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); var data = await apiConnection.Patch(patchUri, sentData); Assert.Same(data, response.BodyAsObject); connection.Received().PatchAsync(patchUri, sentData); } [Fact] public async Task EnsuresArgumentNotNull() { var connection = new ApiConnection(Substitute.For()); var patchUri = new Uri("", UriKind.Relative); await AssertEx.Throws(async () => await connection.Patch(null, new object())); await AssertEx.Throws(async () => await connection.Patch(patchUri, null)); } } public class ThePostMethod { [Fact] public async Task MakesPostRequestWithSuppliedData() { var postUri = new Uri("anything", UriKind.Relative); var sentData = new object(); IResponse response = new ApiResponse {BodyAsObject = new object()}; var connection = Substitute.For(); connection.PostAsync(Args.Uri, Args.Object, null, null).Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); var data = await apiConnection.Post(postUri, sentData); Assert.Same(data, response.BodyAsObject); connection.Received().PostAsync(postUri, sentData, null, null); } [Fact] public async Task MakesUploadRequest() { var uploadUrl = new Uri("anything", UriKind.Relative); IResponse response = new ApiResponse {BodyAsObject = "the response"}; var connection = Substitute.For(); connection.PostAsync(Args.Uri, Arg.Any(), Args.String, Args.String) .Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); var rawData = new MemoryStream(); await apiConnection.Post(uploadUrl, rawData, "accepts", "content-type"); connection.Received().PostAsync(uploadUrl, rawData, "accepts", "content-type"); } [Fact] public async Task EnsuresArgumentsNotNull() { var postUri = new Uri("", UriKind.Relative); var connection = new ApiConnection(Substitute.For()); // 2 parameter overload await AssertEx.Throws(async () => await connection.Post(null, new object())); await AssertEx.Throws(async () => await connection.Post(postUri, null)); // 3 parameters await AssertEx.Throws(async () => await connection.Post(null, new MemoryStream(), "anAccept", "some-content-type")); await AssertEx.Throws(async () => await connection.Post(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(); IResponse response = new ApiResponse { BodyAsObject = new object() }; var connection = Substitute.For(); connection.PutAsync(Args.Uri, Args.Object).Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); var data = await apiConnection.Put(putUri, sentData); Assert.Same(data, response.BodyAsObject); connection.Received().PutAsync(putUri, sentData); } [Fact] public async Task MakesPutRequestWithSuppliedDataAndTwoFactorCode() { var putUri = new Uri("anything", UriKind.Relative); var sentData = new object(); IResponse response = new ApiResponse { BodyAsObject = new object() }; var connection = Substitute.For(); connection.PutAsync(Args.Uri, Args.Object, "two-factor").Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); var data = await apiConnection.Put(putUri, sentData, "two-factor"); Assert.Same(data, response.BodyAsObject); connection.Received().PutAsync(putUri, sentData, "two-factor"); } [Fact] public async Task EnsuresArgumentsNotNull() { var putUri = new Uri("", UriKind.Relative); var connection = new ApiConnection(Substitute.For()); // 2 parameter overload await AssertEx.Throws(async () => await connection.Put(null, new object())); await AssertEx.Throws(async () => await connection.Put(putUri, null)); // 3 parameters await AssertEx.Throws(async () => await connection.Put(null, new MemoryStream(), "two-factor")); await AssertEx.Throws(async () => await connection.Put(putUri, null, "two-factor")); await AssertEx.Throws(async () => await connection.Put(putUri, new MemoryStream(), null)); await AssertEx.Throws(async () => await connection.Put(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(); connection.DeleteAsync(Args.Uri).Returns(Task.FromResult(statusCode)); var apiConnection = new ApiConnection(connection); await apiConnection.Delete(deleteUri); connection.Received().DeleteAsync(deleteUri); } [Fact] public async Task EnsuresArgumentNotNull() { var connection = new ApiConnection(Substitute.For()); await AssertEx.Throws(async () => await connection.Delete(null)); } } public class TheGetQueuedOperationMethod { [Fact] public async Task MakesGetRequest() { var queuedOperationUrl = new Uri("anything", UriKind.Relative); const HttpStatusCode statusCode = HttpStatusCode.OK; IResponse response = new ApiResponse { BodyAsObject = new object(), StatusCode = statusCode }; var connection = Substitute.For(); connection.GetAsync(queuedOperationUrl,Args.CancellationToken).Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); await apiConnection.GetQueuedOperation(queuedOperationUrl,CancellationToken.None); connection.Received().GetAsync(queuedOperationUrl, Args.CancellationToken); } [Fact] public async Task WhenGetReturnsNotOkOrAcceptedApiExceptionIsThrown() { var queuedOperationUrl = new Uri("anything", UriKind.Relative); const HttpStatusCode statusCode = HttpStatusCode.PartialContent; IResponse response = new ApiResponse { BodyAsObject = new object(), StatusCode = statusCode }; var connection = Substitute.For(); connection.GetAsync(queuedOperationUrl, Args.CancellationToken).Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); await AssertEx.Throws(async () => await apiConnection.GetQueuedOperation(queuedOperationUrl, Args.CancellationToken)); } [Fact] public async Task WhenGetReturnsOkThenBodyAsObjectIsReturned() { var queuedOperationUrl = new Uri("anything", UriKind.Relative); var result = new object(); const HttpStatusCode statusCode = HttpStatusCode.OK; IResponse response = new ApiResponse { BodyAsObject = result, StatusCode = statusCode }; var connection = Substitute.For(); connection.GetAsync(queuedOperationUrl, Args.CancellationToken).Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); var actualResult = await apiConnection.GetQueuedOperation(queuedOperationUrl, Args.CancellationToken); Assert.Same(actualResult,result); } [Fact] public async Task GetIsRepeatedUntilHttpStatusCodeOkIsReturned() { var queuedOperationUrl = new Uri("anything", UriKind.Relative); var result = new object(); IResponse firstResponse = new ApiResponse { BodyAsObject = result, StatusCode = HttpStatusCode.Accepted }; IResponse completedResponse = new ApiResponse { BodyAsObject = result, StatusCode = HttpStatusCode.OK }; var connection = Substitute.For(); connection.GetAsync(queuedOperationUrl, Args.CancellationToken) .Returns(x => Task.FromResult(firstResponse), x => Task.FromResult(firstResponse), x => Task.FromResult(completedResponse)); var apiConnection = new ApiConnection(connection); await apiConnection.GetQueuedOperation(queuedOperationUrl, CancellationToken.None); connection.Received(3).GetAsync(queuedOperationUrl, Args.CancellationToken); } public async Task CanCancelQueuedOperation() { var queuedOperationUrl = new Uri("anything", UriKind.Relative); var result = new object(); IResponse accepted = new ApiResponse { BodyAsObject = result, StatusCode = HttpStatusCode.Accepted }; var connection = Substitute.For(); connection.GetAsync(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(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()); await AssertEx.Throws(async () => await connection.GetQueuedOperation(null, CancellationToken.None)); } } public class TheCtor { [Fact] public void EnsuresNonNullArguments() { Assert.Throws(() => new ApiConnection(null)); } } } }