From 0ed6704859472f9f2d9f3989ef1f0b38892cb260 Mon Sep 17 00:00:00 2001 From: Ryan Gribble Date: Sat, 30 Jan 2016 16:04:14 +1000 Subject: [PATCH] Implement Enterprise Organization client --- .../EnterpriseOrganizationClientTests.cs | 34 +++++++++++ .../Octokit.Tests.Integration.csproj | 1 + .../EnterpriseOrganizationClientTests.cs | 50 ++++++++++++++++ Octokit.Tests/Octokit.Tests.csproj | 1 + .../Clients/Enterprise/EnterpriseClient.cs | 9 +++ .../EnterpriseOrganizationClient.cs | 34 +++++++++++ .../Clients/Enterprise/IEnterpriseClient.cs | 8 +++ .../IEnterpriseOrganizationClient.cs | 23 ++++++++ Octokit/Helpers/ApiUrls.cs | 5 ++ Octokit/Models/Request/NewOrganization.cs | 58 +++++++++++++++++++ Octokit/Octokit.csproj | 3 + 11 files changed, 226 insertions(+) create mode 100644 Octokit.Tests.Integration/Clients/Enterprise/EnterpriseOrganizationClientTests.cs create mode 100644 Octokit.Tests/Clients/Enterprise/EnterpriseOrganizationClientTests.cs create mode 100644 Octokit/Clients/Enterprise/EnterpriseOrganizationClient.cs create mode 100644 Octokit/Clients/Enterprise/IEnterpriseOrganizationClient.cs create mode 100644 Octokit/Models/Request/NewOrganization.cs diff --git a/Octokit.Tests.Integration/Clients/Enterprise/EnterpriseOrganizationClientTests.cs b/Octokit.Tests.Integration/Clients/Enterprise/EnterpriseOrganizationClientTests.cs new file mode 100644 index 00000000..61ace7d2 --- /dev/null +++ b/Octokit.Tests.Integration/Clients/Enterprise/EnterpriseOrganizationClientTests.cs @@ -0,0 +1,34 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using Octokit; +using Octokit.Tests.Integration; +using Xunit; + +public class EnterpriseOrganizationClientTests +{ + readonly IGitHubClient _github; + + public EnterpriseOrganizationClientTests() + { + _github = EnterpriseHelper.GetAuthenticatedClient(); + } + + [GitHubEnterpriseTest] + public async Task CanCreateOrganization() + { + string orgLogin = Helper.MakeNameWithTimestamp("MyOrganization"); + string orgName = String.Concat(orgLogin, " Display Name"); + + var newOrganization = new NewOrganization(orgLogin, EnterpriseHelper.GHEUserName, orgName); + var organization = await + _github.Enterprise.Organization.Create(newOrganization); + + Assert.NotNull(organization); + + // Get organization and check login/name + var checkOrg = await _github.Organization.Get(orgLogin); + Assert.Equal(checkOrg.Login, orgLogin); + Assert.Equal(checkOrg.Name, orgName); + } +} diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index 89c33b91..e5a117d5 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -79,6 +79,7 @@ + diff --git a/Octokit.Tests/Clients/Enterprise/EnterpriseOrganizationClientTests.cs b/Octokit.Tests/Clients/Enterprise/EnterpriseOrganizationClientTests.cs new file mode 100644 index 00000000..4b078b12 --- /dev/null +++ b/Octokit.Tests/Clients/Enterprise/EnterpriseOrganizationClientTests.cs @@ -0,0 +1,50 @@ +using System; +using System.Threading.Tasks; +using NSubstitute; +using Xunit; + +namespace Octokit.Tests.Clients +{ + public class EnterpriseOrganizationClientTests + { + public class TheCreateMethod + { + [Fact] + public void RequestsCorrectUrl() + { + var connection = Substitute.For(); + var client = new EnterpriseOrganizationClient(connection); + + string expectedUri = "admin/organizations"; + client.Create(new NewOrganization("org", "admin", "org name")); + + connection.Received().Post(Arg.Is(u => u.ToString() == expectedUri), Arg.Any()); + } + + [Fact] + public void PassesRequestObject() + { + var connection = Substitute.For(); + var client = new EnterpriseOrganizationClient(connection); + + client.Create(new NewOrganization("org", "admin", "org name")); + + connection.Received().Post( + Arg.Any(), + Arg.Is(a => + a.Login == "org" + && a.Admin == "admin" + && a.ProfileName == "org name")); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var connection = Substitute.For(); + var client = new EnterpriseOrganizationClient(connection); + + await Assert.ThrowsAsync(() => client.Create(null)); + } + } + } +} diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj index df74b652..f6a0b24a 100644 --- a/Octokit.Tests/Octokit.Tests.csproj +++ b/Octokit.Tests/Octokit.Tests.csproj @@ -86,6 +86,7 @@ + diff --git a/Octokit/Clients/Enterprise/EnterpriseClient.cs b/Octokit/Clients/Enterprise/EnterpriseClient.cs index 70b74a5b..e0109d15 100644 --- a/Octokit/Clients/Enterprise/EnterpriseClient.cs +++ b/Octokit/Clients/Enterprise/EnterpriseClient.cs @@ -16,6 +16,7 @@ { AdminStats = new EnterpriseAdminStatsClient(apiConnection); License = new EnterpriseLicenseClient(apiConnection); + Organization = new EnterpriseOrganizationClient(apiConnection); } /// @@ -33,5 +34,13 @@ /// See the Enterprise License API documentation for more information. /// public IEnterpriseLicenseClient License { get; private set; } + + /// + /// A client for GitHub's Enterprise Organization API + /// + /// + /// See the Enterprise Organization API documentation for more information. + /// + public IEnterpriseOrganizationClient Organization { get; private set; } } } diff --git a/Octokit/Clients/Enterprise/EnterpriseOrganizationClient.cs b/Octokit/Clients/Enterprise/EnterpriseOrganizationClient.cs new file mode 100644 index 00000000..0848ff8e --- /dev/null +++ b/Octokit/Clients/Enterprise/EnterpriseOrganizationClient.cs @@ -0,0 +1,34 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + /// + /// A client for GitHub's Enterprise Organization API + /// + /// + /// See the Enterprise Organization API documentation for more information. + /// + public class EnterpriseOrganizationClient : ApiClient, IEnterpriseOrganizationClient + { + public EnterpriseOrganizationClient(IApiConnection apiConnection) + : base(apiConnection) + { } + + /// + /// Creates an Organization on a GitHub Enterprise appliance (must be Site Admin user). + /// + /// + /// https://developer.github.com/v3/enterprise/orgs/#create-an-organization + /// + /// A instance describing the organization to be created + /// The created. + public async Task Create(NewOrganization newOrganization) + { + Ensure.ArgumentNotNull(newOrganization, "newOrganization"); + + var endpoint = ApiUrls.EnterpriseOrganization(); + + return await ApiConnection.Post(endpoint, newOrganization); + } + } +} diff --git a/Octokit/Clients/Enterprise/IEnterpriseClient.cs b/Octokit/Clients/Enterprise/IEnterpriseClient.cs index 1d685013..f1c6209f 100644 --- a/Octokit/Clients/Enterprise/IEnterpriseClient.cs +++ b/Octokit/Clients/Enterprise/IEnterpriseClient.cs @@ -23,5 +23,13 @@ /// See the Enterprise License API documentation for more information. /// IEnterpriseLicenseClient License { get; } + + /// + /// A client for GitHub's Enterprise Organization API + /// + /// + /// See the Enterprise Organization API documentation for more information. + /// + IEnterpriseOrganizationClient Organization { get; } } } diff --git a/Octokit/Clients/Enterprise/IEnterpriseOrganizationClient.cs b/Octokit/Clients/Enterprise/IEnterpriseOrganizationClient.cs new file mode 100644 index 00000000..4904480c --- /dev/null +++ b/Octokit/Clients/Enterprise/IEnterpriseOrganizationClient.cs @@ -0,0 +1,23 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + /// + /// A client for GitHub's Enterprise Organization API + /// + /// + /// See the Enterprise Organization API documentation for more information. + /// + public interface IEnterpriseOrganizationClient + { + /// + /// Creates an Organization on a GitHub Enterprise appliance (must be Site Admin user). + /// + /// + /// https://developer.github.com/v3/enterprise/orgs/#create-an-organization + /// + /// A instance describing the organization to be created + /// The created. + Task Create(NewOrganization newOrganization); + } +} diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index b2ee1b6b..156cbd2d 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -1657,5 +1657,10 @@ namespace Octokit { return "enterprise/settings/license".FormatUri(); } + + public static Uri EnterpriseOrganization() + { + return "admin/organizations".FormatUri(); + } } } diff --git a/Octokit/Models/Request/NewOrganization.cs b/Octokit/Models/Request/NewOrganization.cs new file mode 100644 index 00000000..2a8a4a61 --- /dev/null +++ b/Octokit/Models/Request/NewOrganization.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + /// + /// Describes a new organization to create via the method. + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class NewOrganization + { + /// + /// Initializes a new instance of the class. + /// + /// The organization's username + /// The login of the user who will manage this organization + public NewOrganization(string login, string admin) : this(login, admin, null) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The organization's username + /// The login of the user who will manage this organization + /// The organization's display name + public NewOrganization(string login, string admin, string profileName) + { + Login = login; + Admin = admin; + ProfileName = profileName; + } + + /// + /// The organization's username (required) + /// + public string Login { get; private set; } + + /// + /// The login of the user who will manage this organization (required) + /// + public string Admin { get; private set; } + + /// + /// The organization's display name + /// + public string ProfileName { get; private set; } + + internal string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, "Login: {0} Admin: {1} ProfileName: {2}", Login, Admin, ProfileName ?? ""); + } + } + } +} diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index fb7cade8..a1a1ab8a 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -59,8 +59,10 @@ + + @@ -106,6 +108,7 @@ +