diff --git a/Octokit.Reactive/Clients/IObservableOrganizationsClient.cs b/Octokit.Reactive/Clients/IObservableOrganizationsClient.cs index fb9efd7f..24366e59 100644 --- a/Octokit.Reactive/Clients/IObservableOrganizationsClient.cs +++ b/Octokit.Reactive/Clients/IObservableOrganizationsClient.cs @@ -46,6 +46,7 @@ namespace Octokit.Reactive /// /// The login for the user /// + [Obsolete("Please use IObservableOrganizationsClient.GetAllForUser() instead. This method will be removed in a future version")] IObservable GetAll(string user); /// @@ -54,8 +55,37 @@ namespace Octokit.Reactive /// The login for the user /// Options for changing the API response /// + [Obsolete("Please use IObservableOrganizationsClient.GetAllForUser() instead. This method will be removed in a future version")] IObservable GetAll(string user, ApiOptions options); + /// + /// Returns all the organizations for the specified user + /// + /// The login for the user + /// + IObservable GetAllForUser(string user); + + /// + /// Returns all the organizations for the specified user + /// + /// The login for the user + /// Options for changing the API response + /// + IObservable GetAllForUser(string user, ApiOptions options); + + /// + /// Returns all the organizations + /// + /// + IObservable GetAll(); + + /// + /// Returns all the organizations + /// + /// Search parameters of the last organization seen + /// + IObservable GetAll(OrganizationRequest request); + /// /// Update the specified organization with data from . /// diff --git a/Octokit.Reactive/Clients/ObservableOrganizationsClient.cs b/Octokit.Reactive/Clients/ObservableOrganizationsClient.cs index ff5b3101..e30c4e23 100644 --- a/Octokit.Reactive/Clients/ObservableOrganizationsClient.cs +++ b/Octokit.Reactive/Clients/ObservableOrganizationsClient.cs @@ -64,7 +64,7 @@ namespace Octokit.Reactive { Ensure.ArgumentNotNull(options, "options"); - return _connection.GetAndFlattenAllPages(ApiUrls.Organizations()); + return _connection.GetAndFlattenAllPages(ApiUrls.UserOrganizations()); } /// @@ -72,11 +72,12 @@ namespace Octokit.Reactive /// /// The login for the user /// + [Obsolete("Please use ObservableOrganizationsClient.GetAllForUser() instead. This method will be removed in a future version")] public IObservable GetAll(string user) { Ensure.ArgumentNotNullOrEmptyString(user, "user"); - return _connection.GetAndFlattenAllPages(ApiUrls.Organizations(user)); + return _connection.GetAndFlattenAllPages(ApiUrls.UserOrganizations(user)); } /// @@ -85,12 +86,62 @@ namespace Octokit.Reactive /// The login for the user /// Options for changing the API response /// + [Obsolete("Please use ObservableOrganizationsClient.GetAllForUser() instead. This method will be removed in a future version")] public IObservable GetAll(string user, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(user, "user"); Ensure.ArgumentNotNull(options, "options"); - return _connection.GetAndFlattenAllPages(ApiUrls.Organizations(user), options); + return _connection.GetAndFlattenAllPages(ApiUrls.UserOrganizations(user), options); + } + + /// + /// Returns all the organizations for the specified user + /// + /// The login for the user + /// + public IObservable GetAllForUser(string user) + { + Ensure.ArgumentNotNullOrEmptyString(user, "user"); + + return _connection.GetAndFlattenAllPages(ApiUrls.UserOrganizations(user)); + } + + /// + /// Returns all the organizations for the specified user + /// + /// The login for the user + /// Options for changing the API response + /// + public IObservable GetAllForUser(string user, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(user, "user"); + Ensure.ArgumentNotNull(options, "options"); + + return _connection.GetAndFlattenAllPages(ApiUrls.UserOrganizations(user), options); + } + + /// + /// Returns all the organizations + /// + /// + public IObservable GetAll() + { + return _connection.GetAndFlattenAllPages(ApiUrls.AllOrganizations()); + } + + /// + /// Returns all the organizations + /// + /// Search parameters of the last organization seen + /// + public IObservable GetAll(OrganizationRequest request) + { + Ensure.ArgumentNotNull(request, "request"); + + var url = ApiUrls.AllOrganizations(request.Since); + + return _connection.GetAndFlattenAllPages(url); } /// diff --git a/Octokit.Tests.Integration/Clients/OrganizationClientTests.cs b/Octokit.Tests.Integration/Clients/OrganizationClientTests.cs index 5577f154..1ca0e804 100644 --- a/Octokit.Tests.Integration/Clients/OrganizationClientTests.cs +++ b/Octokit.Tests.Integration/Clients/OrganizationClientTests.cs @@ -1,4 +1,5 @@ -using System.Threading.Tasks; +using System.Collections; +using System.Threading.Tasks; using Xunit; namespace Octokit.Tests.Integration.Clients @@ -18,30 +19,88 @@ namespace Octokit.Tests.Integration.Clients } [GitHubEnterpriseTest] - public async Task CanListOrganizations() - { - string orgLogin = Helper.MakeNameWithTimestamp("MyOrganization"); - string orgName = string.Concat(orgLogin, " Display Name"); - - var newOrganization = new NewOrganization(orgLogin, EnterpriseHelper.UserName, orgName); - var organization = await - _github.Enterprise.Organization.Create(newOrganization); - - Assert.NotNull(organization); - - var milestones = await _organizationsClient.GetAllForCurrent(); - - Assert.NotEmpty(milestones); - } - - [GitHubEnterpriseTest] - public async Task ReturnsCorrectCountOfOrganizationsWithoutStart() + public async Task CanListAllOrganizations() { string orgLogin1 = Helper.MakeNameWithTimestamp("MyOrganization1"); string orgName1 = string.Concat(orgLogin1, " Display Name 1"); string orgLogin2 = Helper.MakeNameWithTimestamp("MyOrganization2"); string orgName2 = string.Concat(orgLogin2, " Display Name 2"); - + + var newOrganization1 = new NewOrganization(orgLogin1, EnterpriseHelper.UserName, orgName1); + var newOrganization2 = new NewOrganization(orgLogin2, EnterpriseHelper.UserName, orgName2); + await _github.Enterprise.Organization.Create(newOrganization1); + await _github.Enterprise.Organization.Create(newOrganization2); + + var organizations = await _organizationsClient.GetAll(); + + Assert.Contains(organizations, (org => org.Login == orgLogin1)); + Assert.Contains(organizations, (org => org.Login == orgLogin2)); + } + + [GitHubEnterpriseTest] + public async Task ReturnsCorrectOrganizationsWithSince() + { + string orgLogin1 = Helper.MakeNameWithTimestamp("MyOrganization1"); + string orgName1 = string.Concat(orgLogin1, " Display Name 1"); + string orgLogin2 = Helper.MakeNameWithTimestamp("MyOrganization2"); + string orgName2 = string.Concat(orgLogin2, " Display Name 2"); + string orgLogin3 = Helper.MakeNameWithTimestamp("MyOrganization3"); + string orgName3 = string.Concat(orgLogin3, " Display Name 3"); + + var newOrganization1 = new NewOrganization(orgLogin1, EnterpriseHelper.UserName, orgName1); + var newOrganization2 = new NewOrganization(orgLogin2, EnterpriseHelper.UserName, orgName2); + var newOrganization3 = new NewOrganization(orgLogin3, EnterpriseHelper.UserName, orgName3); + + var createdOrganization1 = await _github.Enterprise.Organization.Create(newOrganization1); + var createdOrganization2 = await _github.Enterprise.Organization.Create(newOrganization2); + var createdOrganization3 = await _github.Enterprise.Organization.Create(newOrganization3); + + var requestParameter = new OrganizationRequest(createdOrganization1.Id); + + var organizations = await _organizationsClient.GetAll(requestParameter); + + Assert.DoesNotContain(organizations, (org => org.Login == orgLogin1)); + Assert.Contains(organizations, (org => org.Login == orgLogin2)); + Assert.Contains(organizations, (org => org.Login == orgLogin3)); + } + } + + public class TheGetAllForCurrentMethod + { + readonly IGitHubClient _github; + readonly IOrganizationsClient _organizationsClient; + + public TheGetAllForCurrentMethod() + { + _github = EnterpriseHelper.GetAuthenticatedClient(); + + _organizationsClient = _github.Organization; + } + + [GitHubEnterpriseTest] + public async Task CanListUserOrganizations() + { + string orgLogin = Helper.MakeNameWithTimestamp("MyOrganization"); + string orgName = string.Concat(orgLogin, " Display Name"); + + var newOrganization = new NewOrganization(orgLogin, EnterpriseHelper.UserName, orgName); + var organization = await _github.Enterprise.Organization.Create(newOrganization); + + Assert.NotNull(organization); + + var organizations = await _organizationsClient.GetAllForCurrent(); + + Assert.NotEmpty(organizations); + } + + [GitHubEnterpriseTest] + public async Task ReturnsCorrectCountOfUserOrganizationsWithoutStart() + { + string orgLogin1 = Helper.MakeNameWithTimestamp("MyOrganization1"); + string orgName1 = string.Concat(orgLogin1, " Display Name 1"); + string orgLogin2 = Helper.MakeNameWithTimestamp("MyOrganization2"); + string orgName2 = string.Concat(orgLogin2, " Display Name 2"); + var newOrganization1 = new NewOrganization(orgLogin1, EnterpriseHelper.UserName, orgName1); var newOrganization2 = new NewOrganization(orgLogin2, EnterpriseHelper.UserName, orgName2); await _github.Enterprise.Organization.Create(newOrganization1); @@ -59,7 +118,7 @@ namespace Octokit.Tests.Integration.Clients } [GitHubEnterpriseTest] - public async Task ReturnsCorrectCountOfOrganizationsWithStart() + public async Task ReturnsCorrectCountOfUserOrganizationsWithStart() { string orgLogin1 = Helper.MakeNameWithTimestamp("MyOrganization1"); string orgName1 = string.Concat(orgLogin1, " Display Name 1"); diff --git a/Octokit.Tests/Clients/OrganizationsClientTests.cs b/Octokit.Tests/Clients/OrganizationsClientTests.cs index ec5b1584..9bfb8e46 100644 --- a/Octokit.Tests/Clients/OrganizationsClientTests.cs +++ b/Octokit.Tests/Clients/OrganizationsClientTests.cs @@ -81,7 +81,7 @@ namespace Octokit.Tests.Clients var connection = Substitute.For(); var client = new OrganizationsClient(connection); - await Assert.ThrowsAsync(() => client.GetAll(null)); + await Assert.ThrowsAsync(() => client.GetAll((string)null)); await Assert.ThrowsAsync(() => client.GetAll(null, ApiOptions.None)); await Assert.ThrowsAsync(() => client.GetAll("username", null)); @@ -90,6 +90,52 @@ namespace Octokit.Tests.Clients } } + public class TheGetAllForUserMethod + { + [Fact] + public async Task RequestsTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new OrganizationsClient(connection); + + await client.GetAllForUser("username"); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "users/username/orgs"), Args.ApiOptions); + } + + [Fact] + public async Task RequestsTheCorrectUrlWithApiOptions() + { + var connection = Substitute.For(); + var client = new OrganizationsClient(connection); + + var options = new ApiOptions + { + StartPage = 1, + PageCount = 1, + PageSize = 1 + }; + + await client.GetAllForUser("username", options); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "users/username/orgs"), options); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var connection = Substitute.For(); + var client = new OrganizationsClient(connection); + + await Assert.ThrowsAsync(() => client.GetAllForUser(null)); + await Assert.ThrowsAsync(() => client.GetAllForUser(null, ApiOptions.None)); + await Assert.ThrowsAsync(() => client.GetAllForUser("username", null)); + + await Assert.ThrowsAsync(() => client.GetAllForUser("")); + await Assert.ThrowsAsync(() => client.GetAllForUser("", ApiOptions.None)); + } + } + public class TheGetAllForCurrentMethod { [Fact] @@ -130,7 +176,43 @@ namespace Octokit.Tests.Clients await Assert.ThrowsAsync(() => client.GetAllForCurrent(null)); } } + + public class TheGetAllOrganizationsMethod + { + [Fact] + public async Task RequestsTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new OrganizationsClient(connection); + await client.GetAll(); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "organizations")); + } + + [Fact] + public async Task RequestsTheCorrectUrlWithRequestParameter() + { + var connection = Substitute.For(); + var client = new OrganizationsClient(connection); + + var request = new OrganizationRequest(1); + + await client.GetAll(request); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "organizations?since=1")); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var connection = Substitute.For(); + var client = new OrganizationsClient(connection); + + await Assert.ThrowsAsync(() => client.GetAll((OrganizationRequest)null)); + } + } + public class TheUpdateMethod { [Fact] diff --git a/Octokit.Tests/Reactive/ObservableOrganizationsClientTests.cs b/Octokit.Tests/Reactive/ObservableOrganizationsClientTests.cs index 4889a4e5..26324833 100644 --- a/Octokit.Tests/Reactive/ObservableOrganizationsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableOrganizationsClientTests.cs @@ -77,7 +77,7 @@ namespace Octokit.Tests.Reactive var gitHubClient = Substitute.For(); var client = new ObservableOrganizationsClient(gitHubClient); - Assert.Throws(() => client.GetAll(null)); + Assert.Throws(() => client.GetAll((string)null)); Assert.Throws(() => client.GetAll(null, ApiOptions.None)); Assert.Throws(() => client.GetAll("username", null)); diff --git a/Octokit/Clients/IOrganizationsClient.cs b/Octokit/Clients/IOrganizationsClient.cs index fea9ab0a..a0fb42a1 100644 --- a/Octokit/Clients/IOrganizationsClient.cs +++ b/Octokit/Clients/IOrganizationsClient.cs @@ -1,4 +1,5 @@ -#if NET_45 +using System; +#if NET_45 using System.Threading.Tasks; using System.Collections.Generic; #endif @@ -58,6 +59,7 @@ namespace Octokit /// /// Thrown when a general API error occurs. /// A list of the specified user's s. + [Obsolete("Please use IOrganizationsClient.GetAllForUser() instead. This method will be removed in a future version")] Task> GetAll(string user); /// @@ -67,8 +69,40 @@ namespace Octokit /// Options for changing the API response /// Thrown when a general API error occurs. /// A list of the specified user's s. + [Obsolete("Please use IOrganizationsClient.GetAllForUser() instead. This method will be removed in a future version")] Task> GetAll(string user, ApiOptions options); + /// + /// Returns all s for the specified user. + /// + /// Thrown when a general API error occurs. + /// A list of the specified user's s. + Task> GetAllForUser(string user); + + /// + /// Returns all s for the specified user. + /// + /// The login of the user + /// Options for changing the API response + /// Thrown when a general API error occurs. + /// A list of the specified user's s. + Task> GetAllForUser(string user, ApiOptions options); + + /// + /// Returns all s. + /// + /// Thrown when a general API error occurs. + /// A list of s. + Task> GetAll(); + + /// + /// Returns all s. + /// + /// Search parameters of the last organization seen + /// Thrown when a general API error occurs. + /// A list of s. + Task> GetAll(OrganizationRequest request); + /// /// Update the specified organization with data from . /// diff --git a/Octokit/Clients/OrganizationsClient.cs b/Octokit/Clients/OrganizationsClient.cs index 32fa827c..e9796569 100644 --- a/Octokit/Clients/OrganizationsClient.cs +++ b/Octokit/Clients/OrganizationsClient.cs @@ -67,7 +67,7 @@ namespace Octokit { Ensure.ArgumentNotNull(options, "options"); - return ApiConnection.GetAll(ApiUrls.Organizations(), options); + return ApiConnection.GetAll(ApiUrls.UserOrganizations(), options); } /// @@ -76,6 +76,7 @@ namespace Octokit /// The login of the user /// Thrown when a general API error occurs. /// A list of the specified user's s. + [Obsolete("Please use OrganizationsClient.GetAllForUser() instead. This method will be removed in a future version")] public Task> GetAll(string user) { Ensure.ArgumentNotNullOrEmptyString(user, "user"); @@ -90,12 +91,67 @@ namespace Octokit /// Options for changing the API response /// Thrown when a general API error occurs. /// A list of the specified user's s. + [Obsolete("Please use OrganizationsClient.GetAllForUser() instead. This method will be removed in a future version")] public Task> GetAll(string user, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(user, "user"); Ensure.ArgumentNotNull(options, "options"); - return ApiConnection.GetAll(ApiUrls.Organizations(user), options); + return ApiConnection.GetAll(ApiUrls.UserOrganizations(user), options); + } + + /// + /// Returns all s for the specified user. + /// + /// The login of the user + /// Thrown when a general API error occurs. + /// A list of the specified user's s. + public Task> GetAllForUser(string user) + { + Ensure.ArgumentNotNullOrEmptyString(user, "user"); + + return GetAllForUser(user, ApiOptions.None); + } + + /// + /// Returns all s for the specified user. + /// + /// The login of the user + /// Options for changing the API response + /// Thrown when a general API error occurs. + /// A list of the specified user's s. + public Task> GetAllForUser(string user, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(user, "user"); + Ensure.ArgumentNotNull(options, "options"); + + return ApiConnection.GetAll(ApiUrls.UserOrganizations(user), options); + } + + + /// + /// Returns all s. + /// + /// Thrown when a general API error occurs. + /// A list of s. + public Task> GetAll() + { + return ApiConnection.GetAll(ApiUrls.AllOrganizations()); + } + + /// + /// Returns all s. + /// + /// Search parameters of the last organization seen + /// Thrown when a general API error occurs. + /// A list of s. + public Task> GetAll(OrganizationRequest request) + { + Ensure.ArgumentNotNull(request, "request"); + + var url = ApiUrls.AllOrganizations(request.Since); + + return ApiConnection.GetAll(url); } /// diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index 6ae6b0b7..692c27e7 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -75,6 +75,7 @@ namespace Octokit /// Returns the that returns all of the organizations for the currently logged in user. /// /// + [Obsolete("Please use ApiUrls.UserOrganizations() instead. This method will be removed in a future version")] public static Uri Organizations() { return _currentUserOrganizationsUrl; @@ -85,11 +86,50 @@ namespace Octokit /// /// The login for the user /// + [Obsolete("Please use ApiUrls.UserOrganizations() instead. This method will be removed in a future version")] public static Uri Organizations(string login) { return "users/{0}/orgs".FormatUri(login); } + /// + /// Returns the that returns all of the organizations for the currently logged in user. + /// + /// + public static Uri UserOrganizations() + { + return "user/orgs".FormatUri(); + } + + /// + /// Returns the that returns all of the organizations for the specified login. + /// + /// The login for the user + /// + public static Uri UserOrganizations(string login) + { + return "users/{0}/orgs".FormatUri(login); + } + + /// + /// Returns the that returns all of the organizations. + /// + /// + public static Uri AllOrganizations() + { + return "organizations".FormatUri(); + } + + /// + /// Returns the that returns all of the organizations. + /// + /// /// The integer Id of the last Organization that you’ve seen. + /// + public static Uri AllOrganizations(long since) + { + return "organizations?since={0}".FormatUri(since); + } + /// /// Returns the that returns the organization for the specified organization name /// diff --git a/Octokit/Models/Request/OrganizationRequest.cs b/Octokit/Models/Request/OrganizationRequest.cs new file mode 100644 index 00000000..79e34031 --- /dev/null +++ b/Octokit/Models/Request/OrganizationRequest.cs @@ -0,0 +1,37 @@ +using System.Diagnostics; +using System.Globalization; + +namespace Octokit +{ + /// + /// Used as part of the request to retrieve all organizations. + /// + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class OrganizationRequest : RequestParameters + { + + /// + /// Intializes a new instance of the class. + /// + /// The integer Id of the last Organization that you've seen. + public OrganizationRequest(int since) + { + Ensure.ArgumentNotNull(since, "since"); + + Since = since; + } + + /// + /// Gets or sets the integer Id of the last Organization that you've seen. + /// + public long Since { get; set; } + + internal string DebuggerDisplay + { + get + { + return string.Format(CultureInfo.InvariantCulture, "Since: {0} ", Since); + } + } + } +} \ No newline at end of file diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj index 1890b1d9..6bc1726f 100644 --- a/Octokit/Octokit-Mono.csproj +++ b/Octokit/Octokit-Mono.csproj @@ -127,6 +127,7 @@ + diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj index 843d485f..fdfcdcd8 100644 --- a/Octokit/Octokit-MonoAndroid.csproj +++ b/Octokit/Octokit-MonoAndroid.csproj @@ -97,6 +97,7 @@ + diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj index 03f59ce5..2803cca0 100644 --- a/Octokit/Octokit-Monotouch.csproj +++ b/Octokit/Octokit-Monotouch.csproj @@ -93,6 +93,7 @@ + diff --git a/Octokit/Octokit-Portable.csproj b/Octokit/Octokit-Portable.csproj index 2bef9a43..7c038455 100644 --- a/Octokit/Octokit-Portable.csproj +++ b/Octokit/Octokit-Portable.csproj @@ -208,6 +208,7 @@ + diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj index 5c1b1ed4..3533af76 100644 --- a/Octokit/Octokit-netcore45.csproj +++ b/Octokit/Octokit-netcore45.csproj @@ -215,6 +215,7 @@ + diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index 9deb1cd6..08f5be05 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -157,6 +157,7 @@ +