From c8d99c30f48c96a8eab2a538338a28735216eda5 Mon Sep 17 00:00:00 2001 From: pmacnaughton Date: Fri, 10 Jan 2014 15:11:02 -0700 Subject: [PATCH] Implemented DeploymentsClient and unit tests --- .../Clients/DeploymentsClientTests.cs | 163 ++++++++++++++++++ Octokit.Tests/Octokit.Tests.csproj | 1 + Octokit/Clients/DeploymentsClient.cs | 34 ++++ Octokit/Clients/IDeploymentsClient.cs | 11 ++ Octokit/GitHubClient.cs | 2 + Octokit/Helpers/ApiUrls.cs | 4 + Octokit/IGitHubClient.cs | 3 +- Octokit/Models/Request/NewDeployment.cs | 12 ++ Octokit/Models/Response/GitDeployment.cs | 25 +++ Octokit/Octokit-Mono.csproj | 4 + Octokit/Octokit-MonoAndroid.csproj | 4 + Octokit/Octokit-Monotouch.csproj | 4 + Octokit/Octokit-netcore45.csproj | 4 + Octokit/Octokit.csproj | 4 + 14 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 Octokit.Tests/Clients/DeploymentsClientTests.cs create mode 100644 Octokit/Clients/DeploymentsClient.cs create mode 100644 Octokit/Clients/IDeploymentsClient.cs create mode 100644 Octokit/Models/Request/NewDeployment.cs create mode 100644 Octokit/Models/Response/GitDeployment.cs diff --git a/Octokit.Tests/Clients/DeploymentsClientTests.cs b/Octokit.Tests/Clients/DeploymentsClientTests.cs new file mode 100644 index 00000000..21f97ec0 --- /dev/null +++ b/Octokit.Tests/Clients/DeploymentsClientTests.cs @@ -0,0 +1,163 @@ +using NSubstitute; +using Octokit; +using Octokit.Tests.Helpers; +using System; +using System.Collections.Generic; +using Xunit; +using Xunit.Extensions; + +public class DeploymentsClientTests +{ + const string expectedAcceptsHeader = "application/vnd.github.cannonball-preview+json"; + + public class TheGetAllMethod + { + [Fact] + public async void EnsuresNonNullArguments() + { + var client = new DeploymentsClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.GetAll(null, "name")); + await AssertEx.Throws(async () => await client.GetAll("owner", null)); + } + + [Fact] + public async void EnsuresNonEmptyArguments() + { + var client = new DeploymentsClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.GetAll("", "name")); + await AssertEx.Throws(async () => await client.GetAll("owner", "")); + } + + [Theory] + [InlineData(" ")] + [InlineData("\n")] + [InlineData("\t")] + [InlineData(" ")] + [InlineData("\n\r")] + public async void EnsuresNonWhitespaceArguments(string whitespace) + { + var client = new DeploymentsClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.GetAll(whitespace, "name")); + await AssertEx.Throws(async () => await client.GetAll("owner", whitespace)); + } + + [Fact] + public void RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new DeploymentsClient(connection); + var expectedUrl = "repos/owner/name/deployments"; + + client.GetAll("owner", "name"); + connection.Received().GetAll(Arg.Is(u => u.ToString() == expectedUrl), + Arg.Any>(), + Arg.Any()); + } + + [Fact] + public void UsesPreviewAcceptsHeader() + { + var connection = Substitute.For(); + var client = new DeploymentsClient(connection); + + client.GetAll("owner", "name"); + connection.Received().GetAll(Arg.Any(), + Arg.Any>(), + expectedAcceptsHeader); + } + } + + public class TheCreateMethod + { + readonly NewDeployment newDeployment = new NewDeployment { Ref = "aRef" }; + + [Fact] + public async void EnsuresNonNullArguments() + { + var client = new DeploymentsClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.Create(null, "name", newDeployment)); + await AssertEx.Throws(async () => await client.Create("owner", null, newDeployment)); + await AssertEx.Throws(async () => await client.Create("owner", "name", null)); + } + + [Fact] + public async void EnsuresNonEmptyArguments() + { + var client = new DeploymentsClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.Create("", "name", newDeployment)); + await AssertEx.Throws(async () => await client.Create("owner", "", newDeployment)); + } + + [Theory] + [InlineData(" ")] + [InlineData("\n")] + [InlineData("\t")] + [InlineData(" ")] + [InlineData("\n\r")] + public async void EnsuresNonWhitespaceArguments(string whitespace) + { + var client = new DeploymentsClient(Substitute.For()); + + await AssertEx.Throws(async () => await client.Create(whitespace, "name", newDeployment)); + await AssertEx.Throws(async () => await client.Create("owner", whitespace, newDeployment)); + } + + [Fact] + public void PostsToDeploymentsUrl() + { + var connection = Substitute.For(); + var client = new DeploymentsClient(connection); + var expectedUrl = "repos/owner/name/deployments"; + + client.Create("owner", "name", newDeployment); + connection.Received().Post(Arg.Is(u => u.ToString() == expectedUrl), + Arg.Any(), + Arg.Any()); + } + + [Fact] + public void PassesNewDeploymentRequest() + { + var connection = Substitute.For(); + var client = new DeploymentsClient(connection); + + client.Create("owner", "name", newDeployment); + connection.Received().Post(Arg.Any(), + newDeployment, + Arg.Any()); + } + + [Fact] + public void UsesPreviewAcceptsHeader() + { + var connection = Substitute.For(); + var client = new DeploymentsClient(connection); + + client.Create("owner", "name", newDeployment); + connection.Received().Post(Arg.Any(), + Arg.Any(), + Arg.Is(expectedAcceptsHeader)); + } + } + + public class TheCtor + { + [Fact] + public void EnsuresArgument() + { + Assert.Throws(() => new DeploymentsClient(null)); + } + + [Fact] + public void SetsStatusesClient() + { + var client = new DeploymentsClient(Substitute.For()); + Assert.NotNull(client.Status); + } + } +} \ No newline at end of file diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj index 6ad0f6c0..1f5b2327 100644 --- a/Octokit.Tests/Octokit.Tests.csproj +++ b/Octokit.Tests/Octokit.Tests.csproj @@ -62,6 +62,7 @@ + diff --git a/Octokit/Clients/DeploymentsClient.cs b/Octokit/Clients/DeploymentsClient.cs new file mode 100644 index 00000000..5b8765c7 --- /dev/null +++ b/Octokit/Clients/DeploymentsClient.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Octokit +{ + public class DeploymentsClient : ApiClient, IDeploymentsClient + { + const string acceptsHeader = "application/vnd.github.cannonball-preview+json"; + + public DeploymentsClient(IApiConnection apiConnection) + : base(apiConnection) + { + } + + public Task> GetAll(string owner, string name) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "login"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + + return ApiConnection.GetAll(ApiUrls.Deployments(owner, name), + null, acceptsHeader); + } + + public Task Create(string owner, string name, NewDeployment newDeployment) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNull(newDeployment, "deployment"); + + return ApiConnection.Post(ApiUrls.Deployments(owner, name), + newDeployment, acceptsHeader); + } + } +} diff --git a/Octokit/Clients/IDeploymentsClient.cs b/Octokit/Clients/IDeploymentsClient.cs new file mode 100644 index 00000000..78995359 --- /dev/null +++ b/Octokit/Clients/IDeploymentsClient.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace Octokit +{ + public interface IDeploymentsClient + { + Task> GetAll(string owner, string name); + Task Create(string owner, string name, NewDeployment newDeployment); + } +} \ No newline at end of file diff --git a/Octokit/GitHubClient.cs b/Octokit/GitHubClient.cs index d0967157..94e4bebd 100644 --- a/Octokit/GitHubClient.cs +++ b/Octokit/GitHubClient.cs @@ -94,6 +94,7 @@ namespace Octokit GitDatabase = new GitDatabaseClient(apiConnection); Tree = new TreesClient(apiConnection); Search = new SearchClient(apiConnection); + Deployment = new DeploymentsClient(apiConnection); } /// @@ -145,6 +146,7 @@ namespace Octokit public IGitDatabaseClient GitDatabase { get; private set; } public ITreesClient Tree { get; private set; } public ISearchClient Search { get; private set; } + public IDeploymentsClient Deployment { get; private set; } static Uri FixUpBaseUri(Uri uri) { diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index 5dd43a7e..72c73421 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -782,5 +782,9 @@ namespace Octokit { return "search/code".FormatUri(); } + public static Uri Deployments(string owner, string name) + { + return "repos/{0}/{1}/deployments".FormatUri(owner, name); + } } } diff --git a/Octokit/IGitHubClient.cs b/Octokit/IGitHubClient.cs index 6dcedb17..3593e08d 100644 --- a/Octokit/IGitHubClient.cs +++ b/Octokit/IGitHubClient.cs @@ -24,5 +24,6 @@ namespace Octokit IGitDatabaseClient GitDatabase { get; } ITreesClient Tree { get; } ISearchClient Search { get; } + IDeploymentsClient Deployment { get; } } -} +} \ No newline at end of file diff --git a/Octokit/Models/Request/NewDeployment.cs b/Octokit/Models/Request/NewDeployment.cs new file mode 100644 index 00000000..f72f2358 --- /dev/null +++ b/Octokit/Models/Request/NewDeployment.cs @@ -0,0 +1,12 @@ + +namespace Octokit +{ + public class NewDeployment + { + public string Ref { get; set; } + public bool? Force { get; set; } + public string Payload { get; set; } + public bool? AutoMerge { get; set; } + public string Description { get; set; } + } +} diff --git a/Octokit/Models/Response/GitDeployment.cs b/Octokit/Models/Response/GitDeployment.cs new file mode 100644 index 00000000..b2c2f67a --- /dev/null +++ b/Octokit/Models/Response/GitDeployment.cs @@ -0,0 +1,25 @@ +using System; + +namespace Octokit +{ + public class GitDeployment + { + public int Id { get; set; } + + public string Sha { get; set; } + + public string Url { get; set; } + + public User Creator { get; set; } + + public string Payload { get; set; } + + public DateTime CreatedAt { get; set; } + + public DateTime UpdatedAt { get; set; } + + public string Description { get; set; } + + public string StatusesUrl { get; set; } + } +} \ No newline at end of file diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj index 24df4fe1..c82c3616 100644 --- a/Octokit/Octokit-Mono.csproj +++ b/Octokit/Octokit-Mono.csproj @@ -246,6 +246,10 @@ + + + + \ No newline at end of file diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj index 43029a83..710dd1b3 100644 --- a/Octokit/Octokit-MonoAndroid.csproj +++ b/Octokit/Octokit-MonoAndroid.csproj @@ -256,6 +256,10 @@ + + + + \ No newline at end of file diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj index 6a9f7032..b21b9178 100644 --- a/Octokit/Octokit-Monotouch.csproj +++ b/Octokit/Octokit-Monotouch.csproj @@ -251,6 +251,10 @@ + + + + \ No newline at end of file diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj index 4b487091..64f02a2a 100644 --- a/Octokit/Octokit-netcore45.csproj +++ b/Octokit/Octokit-netcore45.csproj @@ -244,6 +244,10 @@ + + + + diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index c77f10c0..7f0bc76c 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -54,6 +54,10 @@ Properties\SolutionInfo.cs + + + +