From 2b9f83b876fb475385f36042c7fdfbbdea8522d9 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Thu, 19 Mar 2015 16:07:33 +0930 Subject: [PATCH 01/77] add ApiOptions to support tailoring the response details --- Octokit/Models/Request/ApiOptions.cs | 62 ++++++++++++++++++++++++++++ Octokit/Octokit-Mono.csproj | 1 + Octokit/Octokit-MonoAndroid.csproj | 1 + Octokit/Octokit-Monotouch.csproj | 1 + Octokit/Octokit-Portable.csproj | 1 + Octokit/Octokit-netcore45.csproj | 1 + Octokit/Octokit.csproj | 1 + 7 files changed, 68 insertions(+) create mode 100644 Octokit/Models/Request/ApiOptions.cs diff --git a/Octokit/Models/Request/ApiOptions.cs b/Octokit/Models/Request/ApiOptions.cs new file mode 100644 index 00000000..ef149633 --- /dev/null +++ b/Octokit/Models/Request/ApiOptions.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace Octokit +{ + [DebuggerDisplay("{DebuggerDisplay,nq}")] + public class ApiOptions + { + public static ApiOptions None + { + get { return new ApiOptions(); } + } + + /// + /// Specify the start page for pagination actions + /// + /// + /// Page numbering is 1-based on the server + /// + public int? StartPage { get; set; } + + /// + /// Specify the number of pages to return + /// + public int? PageCount { get; set; } + + /// + /// Specify the number of results to return for each page + /// + /// + /// Results returned may be less than this total if you reach the final page of results + /// + public int? PageSize { get; set; } + + internal string DebuggerDisplay + { + get + { + var values = new List(); + + if (StartPage.HasValue) + { + values.Add("StartPage: " + StartPage.Value); + } + + if (PageCount.HasValue) + { + values.Add("PageCount: " + PageCount.Value); + } + + if (PageSize.HasValue) + { + values.Add("PageSize: " + PageSize.Value); + } + + return String.Join(", ", values); + } + } + } + +} diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj index cf4adab8..c518b97d 100644 --- a/Octokit/Octokit-Mono.csproj +++ b/Octokit/Octokit-Mono.csproj @@ -447,6 +447,7 @@ + \ No newline at end of file diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj index ca3641e9..904a34c0 100644 --- a/Octokit/Octokit-MonoAndroid.csproj +++ b/Octokit/Octokit-MonoAndroid.csproj @@ -455,6 +455,7 @@ + \ No newline at end of file diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj index 9b911c87..9816e046 100644 --- a/Octokit/Octokit-Monotouch.csproj +++ b/Octokit/Octokit-Monotouch.csproj @@ -451,6 +451,7 @@ + diff --git a/Octokit/Octokit-Portable.csproj b/Octokit/Octokit-Portable.csproj index 54301735..f2faa095 100644 --- a/Octokit/Octokit-Portable.csproj +++ b/Octokit/Octokit-Portable.csproj @@ -444,6 +444,7 @@ + diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj index 47276432..2a4d4aa8 100644 --- a/Octokit/Octokit-netcore45.csproj +++ b/Octokit/Octokit-netcore45.csproj @@ -451,6 +451,7 @@ + diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index d293cab7..22536261 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -110,6 +110,7 @@ + From f9f72106be7f5a4b6842b20b031b824425e5704e Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Thu, 19 Mar 2015 17:27:39 +0930 Subject: [PATCH 02/77] implemented a test to verify that overloads are implemented for GetAll usages --- .../Exception/ApiOptionsMissingException.cs | 32 ++++++++ .../Octokit.Tests.Conventions.csproj | 2 + Octokit.Tests.Conventions/PaginationTests.cs | 75 +++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 Octokit.Tests.Conventions/Exception/ApiOptionsMissingException.cs create mode 100644 Octokit.Tests.Conventions/PaginationTests.cs diff --git a/Octokit.Tests.Conventions/Exception/ApiOptionsMissingException.cs b/Octokit.Tests.Conventions/Exception/ApiOptionsMissingException.cs new file mode 100644 index 00000000..f913ab94 --- /dev/null +++ b/Octokit.Tests.Conventions/Exception/ApiOptionsMissingException.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; + +namespace Octokit.Tests.Conventions +{ + public class ApiOptionsMissingException : Exception + { + public ApiOptionsMissingException(Type type, IEnumerable methods) + : base(CreateMessage(type, methods)) { } + + static string CreateMessage(Type type, IEnumerable methods) + { + var methodsFormatted = String.Join("\r\n", methods.Select(FormatMethod)); + return "Methods found on type {0} require an overload which accepts an parameter of type ApiOptions:\r\n{1}" + .FormatWithNewLine( + type.Name, + methodsFormatted); + } + + static string FormatMethod(MethodInfo m) + { + var parametersFormatteds = m.GetParameters() + .Select(p => string.Format("{0} {1}", p.ParameterType.Name, p.Name)); + + var parameterList = string.Join(", ", parametersFormatteds); + + return string.Format(" - {0}({1})", m.Name, parameterList); + } + } +} diff --git a/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj b/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj index fe11b292..c6012156 100644 --- a/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj +++ b/Octokit.Tests.Conventions/Octokit.Tests.Conventions.csproj @@ -68,6 +68,7 @@ + @@ -76,6 +77,7 @@ + diff --git a/Octokit.Tests.Conventions/PaginationTests.cs b/Octokit.Tests.Conventions/PaginationTests.cs new file mode 100644 index 00000000..135d7bc2 --- /dev/null +++ b/Octokit.Tests.Conventions/PaginationTests.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Xunit; + +namespace Octokit.Tests.Conventions +{ + public class PaginationTests + { + [Theory(Skip = "Disable this to run it and find all the places where things break")] + [MemberData("GetClientInterfaces")] + public void CheckObservableClients(Type clientInterface) + { + var methodsOrdered = clientInterface.GetMethodsOrdered(); + + var methodsWhichCanPaginate = methodsOrdered + .Where(x => x.Name.StartsWith("GetAll")); + + var invalidMethods = methodsWhichCanPaginate + .Where(method => MethodHasAppropriateOverload(method, methodsOrdered) == null) + .ToList(); + + if (invalidMethods.Any()) + { + throw new ApiOptionsMissingException(clientInterface, invalidMethods); + } + } + + static MethodInfo MethodHasAppropriateOverload(MethodInfo method, MethodInfo[] methodsOrdered) + { + var parameters = method.GetParametersOrdered(); + var name = method.Name; + return methodsOrdered + .Where(x => x.Name == name) + .FirstOrDefault(x => MethodHasOverloadForApiOptions(x, parameters)); + } + + static bool MethodHasOverloadForApiOptions(MethodInfo methodInfo, ParameterInfo[] expected) + { + var actual = methodInfo.GetParameters(); + + if (actual.Length != expected.Length + 1) + { + return false; + } + + for (var i = 0; i < expected.Length; i++) + { + var a = actual.ElementAt(i); + var e = expected.ElementAt(i); + + if (a.Name != e.Name) + { + return false; + } + + if (a.ParameterType != e.ParameterType) + { + return false; + } + } + + var lastParameter = actual.Last(); + + return lastParameter.Name == "options" + && lastParameter.ParameterType == typeof(ApiOptions); + } + + public static IEnumerable GetClientInterfaces() + { + return typeof(IEventsClient).Assembly.ExportedTypes.Where(TypeExtensions.IsClientInterface).Select(type => new[] { type }); + } + } +} From 740b70f3c72d586762663ecc4f9760a34282db9d Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sun, 14 Feb 2016 15:00:08 +1100 Subject: [PATCH 03/77] moved test to new home --- Octokit.Tests.Conventions/ModelTests.cs | 21 ---------------- Octokit.Tests.Conventions/PaginationTests.cs | 25 +++++++++++++++++++- 2 files changed, 24 insertions(+), 22 deletions(-) diff --git a/Octokit.Tests.Conventions/ModelTests.cs b/Octokit.Tests.Conventions/ModelTests.cs index f126e8cd..0cfcb3c8 100644 --- a/Octokit.Tests.Conventions/ModelTests.cs +++ b/Octokit.Tests.Conventions/ModelTests.cs @@ -95,27 +95,6 @@ namespace Octokit.Tests.Conventions } } - //TODO: This should (probably) be moved to the PaginationTests class that is being introduced in PR #760 - [Theory] - [MemberData("GetClientInterfaces")] - public void CheckPaginationGetAllMethodNames(Type clientInterface) - { - var methodsOrdered = clientInterface.GetMethodsOrdered(); - - var methodsThatCanPaginate = methodsOrdered - .Where(x => x.ReturnType.GetTypeInfo().TypeCategory == TypeCategory.ReadOnlyList) - .Where(x => x.Name.StartsWith("Get")); - - var invalidMethods = methodsThatCanPaginate - .Where(x => !x.Name.StartsWith("GetAll")) - .ToList(); - - if (invalidMethods.Any()) - { - throw new PaginationGetAllMethodNameMismatchException(clientInterface, invalidMethods); - } - } - public static IEnumerable GetClientInterfaces() { return typeof(IEventsClient) diff --git a/Octokit.Tests.Conventions/PaginationTests.cs b/Octokit.Tests.Conventions/PaginationTests.cs index 135d7bc2..fcd76b63 100644 --- a/Octokit.Tests.Conventions/PaginationTests.cs +++ b/Octokit.Tests.Conventions/PaginationTests.cs @@ -27,6 +27,26 @@ namespace Octokit.Tests.Conventions } } + [Theory] + [MemberData("GetClientInterfaces")] + public void CheckPaginationGetAllMethodNames(Type clientInterface) + { + var methodsOrdered = clientInterface.GetMethodsOrdered(); + + var methodsThatCanPaginate = methodsOrdered + .Where(x => x.ReturnType.GetTypeInfo().TypeCategory == TypeCategory.ReadOnlyList) + .Where(x => x.Name.StartsWith("Get")); + + var invalidMethods = methodsThatCanPaginate + .Where(x => !x.Name.StartsWith("GetAll")) + .ToList(); + + if (invalidMethods.Any()) + { + throw new PaginationGetAllMethodNameMismatchException(clientInterface, invalidMethods); + } + } + static MethodInfo MethodHasAppropriateOverload(MethodInfo method, MethodInfo[] methodsOrdered) { var parameters = method.GetParametersOrdered(); @@ -69,7 +89,10 @@ namespace Octokit.Tests.Conventions public static IEnumerable GetClientInterfaces() { - return typeof(IEventsClient).Assembly.ExportedTypes.Where(TypeExtensions.IsClientInterface).Select(type => new[] { type }); + return typeof(IEventsClient).Assembly.ExportedTypes + .Where(TypeExtensions.IsClientInterface) + .Where(type => type != typeof(IStatisticsClient)) + .Select(type => new[] { type }); } } } From c098ecda60e4df23a59f8e05846508d326aae012 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sun, 14 Feb 2016 15:29:02 +1100 Subject: [PATCH 04/77] added overloads to IApiConnection which support passing in ApiOptions --- .../Clients/AuthorizationsClientTests.cs | 2 +- Octokit.Tests/Http/ApiConnectionTests.cs | 4 +- Octokit/Clients/AuthorizationsClient.cs | 2 +- Octokit/Helpers/ApiExtensions.cs | 2 +- Octokit/Http/ApiConnection.cs | 110 +++++++++++++++++- Octokit/Http/IApiConnection.cs | 33 ++++++ 6 files changed, 146 insertions(+), 7 deletions(-) diff --git a/Octokit.Tests/Clients/AuthorizationsClientTests.cs b/Octokit.Tests/Clients/AuthorizationsClientTests.cs index af18967e..1a05b4f4 100644 --- a/Octokit.Tests/Clients/AuthorizationsClientTests.cs +++ b/Octokit.Tests/Clients/AuthorizationsClientTests.cs @@ -35,7 +35,7 @@ namespace Octokit.Tests.Clients client.Received().GetAll( Arg.Is(u => u.ToString() == "authorizations"), - null); + Arg.Is>(d => d == null)); } } diff --git a/Octokit.Tests/Http/ApiConnectionTests.cs b/Octokit.Tests/Http/ApiConnectionTests.cs index f0dd7b6d..5f3b7d22 100644 --- a/Octokit.Tests/Http/ApiConnectionTests.cs +++ b/Octokit.Tests/Http/ApiConnectionTests.cs @@ -90,13 +90,13 @@ namespace Octokit.Tests.Http new Response(), new List { new object(), new object() }); var connection = Substitute.For(); - connection.Get>(Args.Uri, null, null).Returns(Task.FromResult(response)); + connection.Get>(Args.Uri, Args.EmptyDictionary, null).Returns(Task.FromResult(response)); var apiConnection = new ApiConnection(connection); var data = await apiConnection.GetAll(getAllUri); Assert.Equal(2, data.Count); - connection.Received().Get>(getAllUri, null, null); + connection.Received().Get>(getAllUri, Args.EmptyDictionary, null); } [Fact] diff --git a/Octokit/Clients/AuthorizationsClient.cs b/Octokit/Clients/AuthorizationsClient.cs index 440918a5..e7fd862e 100644 --- a/Octokit/Clients/AuthorizationsClient.cs +++ b/Octokit/Clients/AuthorizationsClient.cs @@ -36,7 +36,7 @@ namespace Octokit /// A list of s. public Task> GetAll() { - return ApiConnection.GetAll(ApiUrls.Authorizations(), null); + return ApiConnection.GetAll(ApiUrls.Authorizations(), (IDictionary)null); } /// diff --git a/Octokit/Helpers/ApiExtensions.cs b/Octokit/Helpers/ApiExtensions.cs index 5a3c9a15..81b1ab8e 100644 --- a/Octokit/Helpers/ApiExtensions.cs +++ b/Octokit/Helpers/ApiExtensions.cs @@ -26,7 +26,7 @@ namespace Octokit Ensure.ArgumentNotNull(connection, "connection"); Ensure.ArgumentNotNull(uri, "uri"); - return connection.GetAll(uri, null); + return connection.GetAll(uri, ApiOptions.None); } /// diff --git a/Octokit/Http/ApiConnection.cs b/Octokit/Http/ApiConnection.cs index 5821e327..179d898d 100644 --- a/Octokit/Http/ApiConnection.cs +++ b/Octokit/Http/ApiConnection.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.Globalization; +using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; @@ -115,7 +117,20 @@ namespace Octokit /// Thrown when an API error occurs. public Task> GetAll(Uri uri) { - return GetAll(uri, null, null); + return GetAll(uri, ApiOptions.None); + } + + /// + /// Gets all API resources in the list at the specified URI. + /// + /// Type of the API resource in the list. + /// URI of the API resource to get + /// Options for changing the API response + /// of the The API resources in the list. + /// Thrown when an API error occurs. + public Task> GetAll(Uri uri, ApiOptions options) + { + return GetAll(uri, null, null, options); } /// @@ -128,7 +143,21 @@ namespace Octokit /// Thrown when an API error occurs. public Task> GetAll(Uri uri, IDictionary parameters) { - return GetAll(uri, parameters, null); + return GetAll(uri, parameters, null, ApiOptions.None); + } + + /// + /// Gets all API resources in the list at the specified URI. + /// + /// Type of the API resource in the list. + /// URI of the API resource to get + /// Parameters to add to the API request + /// Options for changing the API response + /// of the The API resources in the list. + /// Thrown when an API error occurs. + public Task> GetAll(Uri uri, IDictionary parameters, ApiOptions options) + { + return GetAll(uri, parameters, null, options); } /// @@ -148,6 +177,27 @@ namespace Octokit .ConfigureAwait(false), uri); } + public Task> GetAll(Uri uri, IDictionary parameters, string accepts, ApiOptions options) + { + Ensure.ArgumentNotNull(uri, "uri"); + Ensure.ArgumentNotNull(options, "options"); + + parameters = parameters ?? new Dictionary(); + + if (options.PageSize.HasValue) + { + parameters.Add("per_page", options.PageSize.Value.ToString(CultureInfo.InvariantCulture)); + } + + if (options.StartPage.HasValue) + { + parameters.Add("page", options.StartPage.Value.ToString(CultureInfo.InvariantCulture)); + } + + return _pagination.GetAllPages(async () => await GetPage(uri, parameters, accepts, options) + .ConfigureAwait(false), uri); + } + /// /// Creates a new API resource in the list at the specified URI. /// @@ -483,5 +533,61 @@ namespace Octokit response, nextPageUri => Connection.Get>(nextPageUri, parameters, accepts)); } + + async Task> GetPage( + Uri uri, + IDictionary parameters, + string accepts, + ApiOptions options) + { + Ensure.ArgumentNotNull(uri, "uri"); + + var connection = Connection; + + var response = await connection.Get>(uri, parameters, accepts).ConfigureAwait(false); + return new ReadOnlyPagedCollection( + response, + nextPageUri => + { + if (nextPageUri.Query.Contains("page=") && options.PageCount.HasValue) + { + var allValues = ToQueryStringDictionary(nextPageUri); + + string pageValue; + if (allValues.TryGetValue("page", out pageValue)) + { + var startPage = options.StartPage ?? 1; + var pageCount = options.PageCount.Value; + + var endPage = startPage + pageCount; + if (pageValue.Equals(endPage.ToString(), StringComparison.OrdinalIgnoreCase)) + { + return null; + } + } + } + + return connection.Get>(nextPageUri, parameters, accepts); + }); + } + + static Dictionary ToQueryStringDictionary(Uri uri) + { + return uri.Query.Split('&') + .Select(keyValue => + { + var indexOf = keyValue.IndexOf('='); + if (indexOf > 0) + { + var key = keyValue.Substring(0, indexOf); + var value = keyValue.Substring(indexOf + 1); + return new KeyValuePair(key, value); + } + + //just a plain old value, return it + return new KeyValuePair(keyValue, null); + }) + .ToDictionary(x => x.Key, x => x.Value); + } } } diff --git a/Octokit/Http/IApiConnection.cs b/Octokit/Http/IApiConnection.cs index c111707b..37239067 100644 --- a/Octokit/Http/IApiConnection.cs +++ b/Octokit/Http/IApiConnection.cs @@ -71,6 +71,16 @@ namespace Octokit /// Thrown when an API error occurs. Task> GetAll(Uri uri); + /// + /// Gets all API resources in the list at the specified URI. + /// + /// Type of the API resource in the list. + /// URI of the API resource to get + /// Options for changing the API response + /// of the The API resources in the list. + /// Thrown when an API error occurs. + Task> GetAll(Uri uri, ApiOptions options); + /// /// Gets all API resources in the list at the specified URI. /// @@ -81,6 +91,17 @@ namespace Octokit /// Thrown when an API error occurs. Task> GetAll(Uri uri, IDictionary parameters); + /// + /// Gets all API resources in the list at the specified URI. + /// + /// Type of the API resource in the list. + /// URI of the API resource to get + /// Parameters to add to the API request + /// Options for changing the API response + /// of the The API resources in the list. + /// Thrown when an API error occurs. + Task> GetAll(Uri uri, IDictionary parameters, ApiOptions options); + /// /// Gets all API resources in the list at the specified URI. /// @@ -92,6 +113,18 @@ namespace Octokit /// Thrown when an API error occurs. Task> GetAll(Uri uri, IDictionary parameters, string accepts); + /// + /// Gets all API resources in the list at the specified URI. + /// + /// Type of the API resource in the list. + /// URI of the API resource to get + /// Parameters to add to the API request + /// Accept header to use for the API request + /// Options for changing the API response + /// of the The API resources in the list. + /// Thrown when an API error occurs. + Task> GetAll(Uri uri, IDictionary parameters, string accepts, ApiOptions options); + /// /// Creates a new API resource in the list at the specified URI. /// From 03ea83148995711fc47148489e2123e65f33bd82 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sun, 14 Feb 2016 15:46:41 +1100 Subject: [PATCH 05/77] implemented IReleaseClient.GetAll with overloads to take ApiOptions --- Octokit.Tests/Clients/ReleasesClientTests.cs | 6 +++--- Octokit.Tests/Helpers/Arg.cs | 5 +++++ Octokit/Clients/IReleasesClient.cs | 13 ++++++++++++ Octokit/Clients/ReleasesClient.cs | 22 +++++++++++++++++++- 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/Octokit.Tests/Clients/ReleasesClientTests.cs b/Octokit.Tests/Clients/ReleasesClientTests.cs index b78ec427..bb0ef316 100644 --- a/Octokit.Tests/Clients/ReleasesClientTests.cs +++ b/Octokit.Tests/Clients/ReleasesClientTests.cs @@ -2,14 +2,13 @@ using System.IO; using System.Threading.Tasks; using NSubstitute; -using Octokit.Tests.Helpers; using Xunit; namespace Octokit.Tests.Clients { public class ReleasesClientTests { - public class TheGetReleasesMethod + public class TheGetAllMethod { [Fact] public void RequestsCorrectUrl() @@ -21,7 +20,8 @@ namespace Octokit.Tests.Clients client.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/releases"), null, - "application/vnd.github.v3"); + AcceptHeaders.StableVersion, + Args.ApiOptions); } [Fact] diff --git a/Octokit.Tests/Helpers/Arg.cs b/Octokit.Tests/Helpers/Arg.cs index 391255fa..5408f72d 100644 --- a/Octokit.Tests/Helpers/Arg.cs +++ b/Octokit.Tests/Helpers/Arg.cs @@ -67,5 +67,10 @@ namespace Octokit.Tests { get { return Arg.Any(); } } + + public static ApiOptions ApiOptions + { + get { return Arg.Any(); } + } } } diff --git a/Octokit/Clients/IReleasesClient.cs b/Octokit/Clients/IReleasesClient.cs index d04b0cd3..435f67ae 100644 --- a/Octokit/Clients/IReleasesClient.cs +++ b/Octokit/Clients/IReleasesClient.cs @@ -26,6 +26,19 @@ namespace Octokit /// The list of s for the specified repository. Task> GetAll(string owner, string name); + /// + /// Gets all s for the specified repository. + /// + /// + /// See the API documentation for more information. + /// + /// The repository's owner + /// The repository's name + /// Options for changing the API response + /// Thrown when a general API error occurs. + /// The list of s for the specified repository. + Task> GetAll(string owner, string name, ApiOptions options); + /// /// Gets a single for the specified repository. /// diff --git a/Octokit/Clients/ReleasesClient.cs b/Octokit/Clients/ReleasesClient.cs index fae7bc4d..7fd95fea 100644 --- a/Octokit/Clients/ReleasesClient.cs +++ b/Octokit/Clients/ReleasesClient.cs @@ -36,8 +36,28 @@ namespace Octokit Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(name, "repository"); + return GetAll(owner, name, ApiOptions.None); + } + + /// + /// Gets all s for the specified repository. + /// + /// + /// See the API documentation for more information. + /// + /// The repository's owner + /// The repository's name + /// Options for changing the API response + /// Thrown when a general API error occurs. + /// The list of s for the specified repository. + public Task> GetAll(string owner, string name, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "repository"); + Ensure.ArgumentNotNull(options, "options"); + var endpoint = ApiUrls.Releases(owner, name); - return ApiConnection.GetAll(endpoint, null, AcceptHeaders.StableVersion); + return ApiConnection.GetAll(endpoint, null, AcceptHeaders.StableVersion, options); } /// From 4da9f3e8f76bca109b74925774ab9864a58d761f Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sun, 14 Feb 2016 15:47:29 +1100 Subject: [PATCH 06/77] wrote some tests to verify the behaviour of the pagination --- .../Clients/ReleasesClientTests.cs | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/Octokit.Tests.Integration/Clients/ReleasesClientTests.cs b/Octokit.Tests.Integration/Clients/ReleasesClientTests.cs index 0dd4df70..34892219 100644 --- a/Octokit.Tests.Integration/Clients/ReleasesClientTests.cs +++ b/Octokit.Tests.Integration/Clients/ReleasesClientTests.cs @@ -75,6 +75,83 @@ public class ReleasesClientTests } } + public class TheGetAllMethod + { + readonly IReleasesClient _releaseClient; + const string owner = "octokit"; + const string name = "octokit.net"; + + public TheGetAllMethod() + { + var github = Helper.GetAuthenticatedClient(); + _releaseClient = github.Repository.Release; + } + + [IntegrationTest] + public async Task ReturnsReleases() + { + var releases = await _releaseClient.GetAll(owner, name); + + Assert.NotEmpty(releases); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfReleasesWithoutStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var releases = await _releaseClient.GetAll(owner, name, options); + + Assert.Equal(5, releases.Count); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfReleasesWithStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var releases = await _releaseClient.GetAll(owner, name, options); + + Assert.Equal(5, releases.Count); + } + + [IntegrationTest] + public async Task ReturnsDistinctResultsBasedOnStartPage() + { + var startOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var firstPage = await _releaseClient.GetAll(owner, name, startOptions); + + var skipStartOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var secondPage = await _releaseClient.GetAll(owner, name, skipStartOptions); + + Assert.NotEqual(firstPage[0].Id, secondPage[0].Id); + Assert.NotEqual(firstPage[1].Id, secondPage[1].Id); + Assert.NotEqual(firstPage[2].Id, secondPage[2].Id); + Assert.NotEqual(firstPage[3].Id, secondPage[3].Id); + Assert.NotEqual(firstPage[4].Id, secondPage[4].Id); + } + } + public class TheEditMethod : IDisposable { private readonly IGitHubClient _github; From a4765c8b630691852ab859a604448e132da90d17 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sun, 14 Feb 2016 16:09:07 +1100 Subject: [PATCH 07/77] HACK: i'm abusing _nextPageFun to help identify when to exit --- Octokit/Http/ReadOnlyPagedCollection.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Octokit/Http/ReadOnlyPagedCollection.cs b/Octokit/Http/ReadOnlyPagedCollection.cs index 9e642824..520f107b 100644 --- a/Octokit/Http/ReadOnlyPagedCollection.cs +++ b/Octokit/Http/ReadOnlyPagedCollection.cs @@ -28,7 +28,14 @@ namespace Octokit.Internal var nextPageUrl = _info.GetNextPageUrl(); if (nextPageUrl == null) return null; - var response = await _nextPageFunc(nextPageUrl).ConfigureAwait(false); + var maybeTask = _nextPageFunc(nextPageUrl); + + if (maybeTask == null) + { + return null; + } + + var response = await maybeTask.ConfigureAwait(false); return new ReadOnlyPagedCollection(response, _nextPageFunc); } } From 0ea28a94f386de546849ee388c4c1e4975875e61 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sun, 14 Feb 2016 16:26:25 +1100 Subject: [PATCH 08/77] added some basic documentation --- docs/extensibility.md | 25 +++++++++++++++++++++++++ mkdocs.yml | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 docs/extensibility.md diff --git a/docs/extensibility.md b/docs/extensibility.md new file mode 100644 index 00000000..abab1675 --- /dev/null +++ b/docs/extensibility.md @@ -0,0 +1,25 @@ +# Extensibility + +Octokit.net has been designed to be easy to get started, but there are options +available to tweak the default behaviour once you know the basics. + +## Pagination + +The GitHub API supports paging results whenever collections are returned. + +By default, Octokit.net will fetch the entire set of data. Any method prefixed with +`GetAll*` now has an overload which accepts an `ApiOptions` parameter. + +```csharp +var options = new ApiOptions(); +var repositories = await client.Repository.GetAllForCurrent(options); +``` + +`ApiOptions` has a number of properties: + + - `PageCount` - return a set number of pages + - `PageSize` - change the number of results to return per page + - `StartPage` - start results from a given page + +These parameters can be used in any sort of group. If you don't specify a +`PageSize` the default page size is 30. diff --git a/mkdocs.yml b/mkdocs.yml index 713d7cbf..a2ea05de 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -29,8 +29,9 @@ pages: - 'Exploring Pull Requests' : 'demos/exploring-pull-requests.md' - Advanced: + - 'API Options': 'extensibility.md' - 'Debugging from Source': 'debugging-source.md' - - 'OAuth Flow': 'oauth-flow.md' + - 'HttpClient': 'http-client.md' - 'HttpClient': 'http-client.md' - Contributing: From 3a9dcc33f72631c7bcb61b9d8a297c352ee3099f Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sun, 14 Feb 2016 16:48:11 +1100 Subject: [PATCH 09/77] added tests for new behaviour within pagination --- .../Models/ReadOnlyPagedCollectionTests.cs | 64 +++++++++++++++++++ mkdocs.yml | 2 +- 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/Octokit.Tests/Models/ReadOnlyPagedCollectionTests.cs b/Octokit.Tests/Models/ReadOnlyPagedCollectionTests.cs index 6fa1e4c2..6b690a63 100644 --- a/Octokit.Tests/Models/ReadOnlyPagedCollectionTests.cs +++ b/Octokit.Tests/Models/ReadOnlyPagedCollectionTests.cs @@ -33,6 +33,70 @@ namespace Octokit.Tests.Models Assert.NotNull(nextPage); Assert.Equal(2, nextPage.Count); } + + [Fact] + public async Task WhenNoInformationSetReturnsNull() + { + var nextPageUrl = new Uri("https://example.com/page/2"); + var nextPageResponse = Task.Factory.StartNew>>(() => + new ApiResponse>(new Response(), new List { new object(), new object() })); + + var links = new Dictionary(); + var scopes = new List(); + var httpResponse = Substitute.For(); + httpResponse.ApiInfo.Returns(new ApiInfo(links, scopes, scopes, "etag", new RateLimit(new Dictionary()))); + + var response = new ApiResponse>(httpResponse, new List()); + var connection = Substitute.For(); + + connection.Get>(nextPageUrl, null, null).Returns(nextPageResponse); + + var pagedCollection = new ReadOnlyPagedCollection( + response, + nextPageUri => connection.Get>(nextPageUrl, null, null)); + + var nextPage = await pagedCollection.GetNextPage(); + + Assert.Null(nextPage); + } + + [Fact] + public async Task WhenInlineFuncKillsPaginationReturnNull() + { + var nextPageUrl = new Uri("https://example.com/page/2"); + var nextPageResponse = Task.Factory.StartNew>>(() => + new ApiResponse>(new Response(), new List { new object(), new object() })); + + var links = new Dictionary { { "next", nextPageUrl } }; + var scopes = new List(); + var httpResponse = Substitute.For(); + httpResponse.ApiInfo.Returns(new ApiInfo(links, scopes, scopes, "etag", new RateLimit(new Dictionary()))); + + var response = new ApiResponse>(httpResponse, new List()); + var connection = Substitute.For(); + + connection.Get>(nextPageUrl, null, null).Returns(nextPageResponse); + + var pageCount = 0; + + var pagedCollection = new ReadOnlyPagedCollection( + response, + nextPageUri => + { + if (pageCount > 1) + { + return null; + } + pageCount++; + return connection.Get>(nextPageUrl, null, null); + }); + + var first = await pagedCollection.GetNextPage(); + var second = await pagedCollection.GetNextPage(); + + Assert.NotNull(first); + Assert.NotNull(second); + } } } } diff --git a/mkdocs.yml b/mkdocs.yml index a2ea05de..3ac0cf66 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -31,7 +31,7 @@ pages: - Advanced: - 'API Options': 'extensibility.md' - 'Debugging from Source': 'debugging-source.md' - - 'HttpClient': 'http-client.md' + - 'OAuth Flow': 'oauth-flow.md' - 'HttpClient': 'http-client.md' - Contributing: From aa3ce0db9210b778414e290af7f17c4a646bdeec Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sun, 14 Feb 2016 16:54:27 +1100 Subject: [PATCH 10/77] updated IObservableReleasesClient to use ApiOptions, and added some tests --- .../Clients/IObservableReleasesClient.cs | 13 +++ .../Clients/ObservableReleasesClient.cs | 20 +++++ .../Helpers/ConnectionExtensions.cs | 77 ++++++++++++++++ .../Octokit.Tests.Integration.csproj | 1 + .../Reactive/ObservableReleaseClientTests.cs | 88 +++++++++++++++++++ 5 files changed, 199 insertions(+) create mode 100644 Octokit.Tests.Integration/Reactive/ObservableReleaseClientTests.cs diff --git a/Octokit.Reactive/Clients/IObservableReleasesClient.cs b/Octokit.Reactive/Clients/IObservableReleasesClient.cs index a8bfa4cc..242e13d2 100644 --- a/Octokit.Reactive/Clients/IObservableReleasesClient.cs +++ b/Octokit.Reactive/Clients/IObservableReleasesClient.cs @@ -18,6 +18,19 @@ namespace Octokit.Reactive /// The list of s for the specified repository. IObservable GetAll(string owner, string name); + /// + /// Gets all s for the specified repository. + /// + /// + /// See the API documentation for more information. + /// + /// The repository's owner + /// The repository's name + /// Options for changing the API response + /// Thrown when a general API error occurs. + /// The list of s for the specified repository. + IObservable GetAll(string owner, string name, ApiOptions options); + /// /// Gets a single for the specified repository. /// diff --git a/Octokit.Reactive/Clients/ObservableReleasesClient.cs b/Octokit.Reactive/Clients/ObservableReleasesClient.cs index dfc9478e..100bd131 100644 --- a/Octokit.Reactive/Clients/ObservableReleasesClient.cs +++ b/Octokit.Reactive/Clients/ObservableReleasesClient.cs @@ -36,6 +36,26 @@ namespace Octokit.Reactive return _connection.GetAndFlattenAllPages(ApiUrls.Releases(owner, name)); } + /// + /// Gets all s for the specified repository. + /// + /// + /// See the API documentation for more information. + /// + /// The repository's owner + /// The repository's name + /// Options for changing the API response + /// Thrown when a general API error occurs. + /// The list of s for the specified repository. + public IObservable GetAll(string owner, string name, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNull(options, "options"); + + return _connection.GetAndFlattenAllPages(ApiUrls.Releases(owner, name), options); + } + /// /// Gets a single for the specified repository. /// diff --git a/Octokit.Reactive/Helpers/ConnectionExtensions.cs b/Octokit.Reactive/Helpers/ConnectionExtensions.cs index 0094134c..63f8eb72 100644 --- a/Octokit.Reactive/Helpers/ConnectionExtensions.cs +++ b/Octokit.Reactive/Helpers/ConnectionExtensions.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Globalization; +using System.Linq; using System.Reactive.Linq; using System.Reactive.Threading.Tasks; @@ -12,6 +14,26 @@ namespace Octokit.Reactive.Internal return GetPages(url, null, (pageUrl, pageParams) => connection.Get>(pageUrl, null, null).ToObservable()); } + public static IObservable GetAndFlattenAllPages(this IConnection connection, Uri url, ApiOptions options) + { + return GetPagesWithOptions(url, options, (pageUrl, o) => + { + var parameters = new Dictionary(); + + if (options.PageSize.HasValue) + { + parameters.Add("per_page", options.PageSize.Value.ToString(CultureInfo.InvariantCulture)); + } + + if (options.StartPage.HasValue) + { + parameters.Add("page", options.StartPage.Value.ToString(CultureInfo.InvariantCulture)); + } + + return connection.Get>(pageUrl, parameters, null).ToObservable(); + }); + } + public static IObservable GetAndFlattenAllPages(this IConnection connection, Uri url, IDictionary parameters) { return GetPages(url, parameters, (pageUrl, pageParams) => connection.Get>(pageUrl, pageParams, null).ToObservable()); @@ -35,5 +57,60 @@ namespace Octokit.Reactive.Internal .Where(resp => resp != null) .SelectMany(resp => resp.Body); } + + static IObservable GetPagesWithOptions(Uri uri, ApiOptions options, + Func>>> getPageFunc) + { + return getPageFunc(uri, options).Expand(resp => + { + var nextPageUri = resp.HttpResponse.ApiInfo.GetNextPageUrl(); + + if (nextPageUri == null) + { + return Observable.Empty>>(); + } + + if (nextPageUri.Query.Contains("page=") && options.PageCount.HasValue) + { + var allValues = ToQueryStringDictionary(nextPageUri); + + string pageValue; + if (allValues.TryGetValue("page", out pageValue)) + { + var startPage = options.StartPage ?? 1; + var pageCount = options.PageCount.Value; + + var endPage = startPage + pageCount; + if (pageValue.Equals(endPage.ToString(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase)) + { + return Observable.Empty>>(); + } + } + } + + return Observable.Defer(() => getPageFunc(nextPageUri, null)); + }) + .Where(resp => resp != null) + .SelectMany(resp => resp.Body); + } + + static Dictionary ToQueryStringDictionary(Uri uri) + { + return uri.Query.Split('&') + .Select(keyValue => + { + var indexOf = keyValue.IndexOf('='); + if (indexOf > 0) + { + var key = keyValue.Substring(0, indexOf); + var value = keyValue.Substring(indexOf + 1); + return new KeyValuePair(key, value); + } + + //just a plain old value, return it + return new KeyValuePair(keyValue, null); + }) + .ToDictionary(x => x.Key, x => x.Value); + } } } diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index d8df0040..563b5313 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -132,6 +132,7 @@ + diff --git a/Octokit.Tests.Integration/Reactive/ObservableReleaseClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableReleaseClientTests.cs new file mode 100644 index 00000000..337f2894 --- /dev/null +++ b/Octokit.Tests.Integration/Reactive/ObservableReleaseClientTests.cs @@ -0,0 +1,88 @@ +using System.Reactive.Linq; +using System.Threading.Tasks; +using Octokit.Reactive; +using Xunit; + +namespace Octokit.Tests.Integration.Reactive +{ + public class ObservableReleaseClientTests + { + public class TheGetAllMethod + { + readonly ObservableReleasesClient _releaseClient; + const string owner = "octokit"; + const string name = "octokit.net"; + + public TheGetAllMethod() + { + var github = Helper.GetAuthenticatedClient(); + + _releaseClient = new ObservableReleasesClient(github); + } + + [IntegrationTest] + public async Task ReturnsReleases() + { + var releases = await _releaseClient.GetAll(owner, name).ToList(); + + Assert.NotEmpty(releases); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfReleasesWithoutStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var releases = await _releaseClient.GetAll(owner, name, options).ToList(); + + Assert.Equal(5, releases.Count); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfReleasesWithStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var releases = await _releaseClient.GetAll(owner, name, options).ToList(); + + Assert.Equal(5, releases.Count); + } + + [IntegrationTest] + public async Task ReturnsDistinctResultsBasedOnStartPage() + { + var startOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var firstPage = await _releaseClient.GetAll(owner, name, startOptions).ToList(); + + var skipStartOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var secondPage = await _releaseClient.GetAll(owner, name, skipStartOptions).ToList(); + + Assert.NotEqual(firstPage[0].Id, secondPage[0].Id); + Assert.NotEqual(firstPage[1].Id, secondPage[1].Id); + Assert.NotEqual(firstPage[2].Id, secondPage[2].Id); + Assert.NotEqual(firstPage[3].Id, secondPage[3].Id); + Assert.NotEqual(firstPage[4].Id, secondPage[4].Id); + } + } + } +} From b41c00c4c450bbae4f48447db1bcc67697e78e48 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sun, 14 Feb 2016 18:04:28 +1100 Subject: [PATCH 11/77] extracted pagination function to separate type --- Octokit.Reactive/Octokit.Reactive-Mono.csproj | 5 +- .../Octokit.Reactive-MonoAndroid.csproj | 5 +- .../Octokit.Reactive-Monotouch.csproj | 5 +- Octokit.Reactive/Octokit.Reactive.csproj | 3 + Octokit/Helpers/Pagination.cs | 76 +++++++++++++++++++ Octokit/Octokit-Mono.csproj | 1 + Octokit/Octokit-MonoAndroid.csproj | 1 + Octokit/Octokit-Monotouch.csproj | 1 + Octokit/Octokit-Portable.csproj | 1 + Octokit/Octokit-netcore45.csproj | 1 + Octokit/Octokit.csproj | 3 +- 11 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 Octokit/Helpers/Pagination.cs diff --git a/Octokit.Reactive/Octokit.Reactive-Mono.csproj b/Octokit.Reactive/Octokit.Reactive-Mono.csproj index 10d63457..80fd88f2 100644 --- a/Octokit.Reactive/Octokit.Reactive-Mono.csproj +++ b/Octokit.Reactive/Octokit.Reactive-Mono.csproj @@ -52,6 +52,9 @@ Helpers\Ensure.cs + + Helpers\Pagination.cs + Properties\SolutionInfo.cs @@ -179,4 +182,4 @@ Octokit-Mono - \ No newline at end of file + diff --git a/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj b/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj index d0f878da..ce887c4c 100644 --- a/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj +++ b/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj @@ -60,6 +60,9 @@ Helpers\Ensure.cs + + Helpers\Pagination.cs + Properties\SolutionInfo.cs @@ -187,4 +190,4 @@ Octokit-MonoAndroid - \ No newline at end of file + diff --git a/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj b/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj index ce3efdbe..14a1c7ea 100644 --- a/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj +++ b/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj @@ -56,6 +56,9 @@ Helpers\Ensure.cs + + Helpers\Pagination.cs + Properties\SolutionInfo.cs @@ -183,4 +186,4 @@ Octokit-Monotouch - \ No newline at end of file + diff --git a/Octokit.Reactive/Octokit.Reactive.csproj b/Octokit.Reactive/Octokit.Reactive.csproj index 607a71eb..ebf316aa 100644 --- a/Octokit.Reactive/Octokit.Reactive.csproj +++ b/Octokit.Reactive/Octokit.Reactive.csproj @@ -72,6 +72,9 @@ Helpers\Ensure.cs + + Helpers\Pagination.cs + Properties\SolutionInfo.cs diff --git a/Octokit/Helpers/Pagination.cs b/Octokit/Helpers/Pagination.cs new file mode 100644 index 00000000..1acf39ea --- /dev/null +++ b/Octokit/Helpers/Pagination.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + +namespace Octokit +{ + internal static class Pagination + { + internal static IDictionary Setup(IDictionary parameters, ApiOptions options) + { + parameters = parameters ?? new Dictionary(); + + if (options.PageSize.HasValue) + { + parameters.Add("per_page", options.PageSize.Value.ToString(CultureInfo.InvariantCulture)); + } + + if (options.StartPage.HasValue) + { + parameters.Add("page", options.StartPage.Value.ToString(CultureInfo.InvariantCulture)); + } + + return parameters; + } + + internal static bool ShouldContinue( + Uri uri, + ApiOptions options) + { + if (uri == null) + { + return false; + } + + if (uri.Query.Contains("page=") && options.PageCount.HasValue) + { + var allValues = ToQueryStringDictionary(uri); + + string pageValue; + if (allValues.TryGetValue("page", out pageValue)) + { + var startPage = options.StartPage ?? 1; + var pageCount = options.PageCount.Value; + + var endPage = startPage + pageCount; + if (pageValue.Equals(endPage.ToString(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase)) + { + return false; + } + } + } + + return true; + } + + static Dictionary ToQueryStringDictionary(Uri uri) + { + return uri.Query.Split('&') + .Select(keyValue => + { + var indexOf = keyValue.IndexOf('='); + if (indexOf > 0) + { + var key = keyValue.Substring(0, indexOf); + var value = keyValue.Substring(indexOf + 1); + return new KeyValuePair(key, value); + } + + //just a plain old value, return it + return new KeyValuePair(keyValue, null); + }) + .ToDictionary(x => x.Key, x => x.Value); + } + } +} diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj index c518b97d..3e4bcc99 100644 --- a/Octokit/Octokit-Mono.csproj +++ b/Octokit/Octokit-Mono.csproj @@ -448,6 +448,7 @@ + \ No newline at end of file diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj index 904a34c0..4bda9bba 100644 --- a/Octokit/Octokit-MonoAndroid.csproj +++ b/Octokit/Octokit-MonoAndroid.csproj @@ -456,6 +456,7 @@ + \ No newline at end of file diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj index 9816e046..8dabb0fa 100644 --- a/Octokit/Octokit-Monotouch.csproj +++ b/Octokit/Octokit-Monotouch.csproj @@ -452,6 +452,7 @@ + diff --git a/Octokit/Octokit-Portable.csproj b/Octokit/Octokit-Portable.csproj index f2faa095..6f03fac3 100644 --- a/Octokit/Octokit-Portable.csproj +++ b/Octokit/Octokit-Portable.csproj @@ -445,6 +445,7 @@ + diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj index 2a4d4aa8..7268c43b 100644 --- a/Octokit/Octokit-netcore45.csproj +++ b/Octokit/Octokit-netcore45.csproj @@ -452,6 +452,7 @@ + diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index 22536261..0eb8c1d0 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -102,6 +102,7 @@ + @@ -484,4 +485,4 @@ --> - + \ No newline at end of file From b97254c5a715589dce61645274f0059cba3c4b04 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Sun, 14 Feb 2016 18:04:51 +1100 Subject: [PATCH 12/77] swap in shared component for existing rules --- .../Helpers/ConnectionExtensions.cs | 61 +++---------------- Octokit/Http/ApiConnection.cs | 55 +++-------------- 2 files changed, 14 insertions(+), 102 deletions(-) diff --git a/Octokit.Reactive/Helpers/ConnectionExtensions.cs b/Octokit.Reactive/Helpers/ConnectionExtensions.cs index 63f8eb72..becbf01c 100644 --- a/Octokit.Reactive/Helpers/ConnectionExtensions.cs +++ b/Octokit.Reactive/Helpers/ConnectionExtensions.cs @@ -18,18 +18,7 @@ namespace Octokit.Reactive.Internal { return GetPagesWithOptions(url, options, (pageUrl, o) => { - var parameters = new Dictionary(); - - if (options.PageSize.HasValue) - { - parameters.Add("per_page", options.PageSize.Value.ToString(CultureInfo.InvariantCulture)); - } - - if (options.StartPage.HasValue) - { - parameters.Add("page", options.StartPage.Value.ToString(CultureInfo.InvariantCulture)); - } - + var parameters = Pagination.Setup(new Dictionary(), options); return connection.Get>(pageUrl, parameters, null).ToObservable(); }); } @@ -65,52 +54,16 @@ namespace Octokit.Reactive.Internal { var nextPageUri = resp.HttpResponse.ApiInfo.GetNextPageUrl(); - if (nextPageUri == null) - { - return Observable.Empty>>(); - } + var shouldContinue = Pagination.ShouldContinue( + nextPageUri, + options); - if (nextPageUri.Query.Contains("page=") && options.PageCount.HasValue) - { - var allValues = ToQueryStringDictionary(nextPageUri); - - string pageValue; - if (allValues.TryGetValue("page", out pageValue)) - { - var startPage = options.StartPage ?? 1; - var pageCount = options.PageCount.Value; - - var endPage = startPage + pageCount; - if (pageValue.Equals(endPage.ToString(CultureInfo.InvariantCulture), StringComparison.OrdinalIgnoreCase)) - { - return Observable.Empty>>(); - } - } - } - - return Observable.Defer(() => getPageFunc(nextPageUri, null)); + return shouldContinue + ? Observable.Defer(() => getPageFunc(nextPageUri, null)) + : Observable.Empty>>(); }) .Where(resp => resp != null) .SelectMany(resp => resp.Body); } - - static Dictionary ToQueryStringDictionary(Uri uri) - { - return uri.Query.Split('&') - .Select(keyValue => - { - var indexOf = keyValue.IndexOf('='); - if (indexOf > 0) - { - var key = keyValue.Substring(0, indexOf); - var value = keyValue.Substring(indexOf + 1); - return new KeyValuePair(key, value); - } - - //just a plain old value, return it - return new KeyValuePair(keyValue, null); - }) - .ToDictionary(x => x.Key, x => x.Value); - } } } diff --git a/Octokit/Http/ApiConnection.cs b/Octokit/Http/ApiConnection.cs index 179d898d..818cd941 100644 --- a/Octokit/Http/ApiConnection.cs +++ b/Octokit/Http/ApiConnection.cs @@ -182,17 +182,7 @@ namespace Octokit Ensure.ArgumentNotNull(uri, "uri"); Ensure.ArgumentNotNull(options, "options"); - parameters = parameters ?? new Dictionary(); - - if (options.PageSize.HasValue) - { - parameters.Add("per_page", options.PageSize.Value.ToString(CultureInfo.InvariantCulture)); - } - - if (options.StartPage.HasValue) - { - parameters.Add("page", options.StartPage.Value.ToString(CultureInfo.InvariantCulture)); - } + parameters = Pagination.Setup(parameters, options); return _pagination.GetAllPages(async () => await GetPage(uri, parameters, accepts, options) .ConfigureAwait(false), uri); @@ -549,45 +539,14 @@ namespace Octokit response, nextPageUri => { - if (nextPageUri.Query.Contains("page=") && options.PageCount.HasValue) - { - var allValues = ToQueryStringDictionary(nextPageUri); + var shouldContinue = Pagination.ShouldContinue( + nextPageUri, + options); - string pageValue; - if (allValues.TryGetValue("page", out pageValue)) - { - var startPage = options.StartPage ?? 1; - var pageCount = options.PageCount.Value; - - var endPage = startPage + pageCount; - if (pageValue.Equals(endPage.ToString(), StringComparison.OrdinalIgnoreCase)) - { - return null; - } - } - } - - return connection.Get>(nextPageUri, parameters, accepts); + return shouldContinue + ? connection.Get>(nextPageUri, parameters, accepts) + : null; }); } - - static Dictionary ToQueryStringDictionary(Uri uri) - { - return uri.Query.Split('&') - .Select(keyValue => - { - var indexOf = keyValue.IndexOf('='); - if (indexOf > 0) - { - var key = keyValue.Substring(0, indexOf); - var value = keyValue.Substring(indexOf + 1); - return new KeyValuePair(key, value); - } - - //just a plain old value, return it - return new KeyValuePair(keyValue, null); - }) - .ToDictionary(x => x.Key, x => x.Value); - } } } From e27b58d043bd10e5d1ea6844a8b64dca6cb2d3f7 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Wed, 17 Feb 2016 11:14:39 +1100 Subject: [PATCH 13/77] a bit of cleanup --- Octokit.Tests.Conventions/PaginationTests.cs | 2 +- Octokit.Tests/Clients/ReleasesClientTests.cs | 2 +- Octokit/Http/ApiConnection.cs | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Octokit.Tests.Conventions/PaginationTests.cs b/Octokit.Tests.Conventions/PaginationTests.cs index fcd76b63..3c2565e7 100644 --- a/Octokit.Tests.Conventions/PaginationTests.cs +++ b/Octokit.Tests.Conventions/PaginationTests.cs @@ -8,7 +8,7 @@ namespace Octokit.Tests.Conventions { public class PaginationTests { - [Theory(Skip = "Disable this to run it and find all the places where things break")] + [Theory(Skip = "Enable this to run it and find all the places where things break")] [MemberData("GetClientInterfaces")] public void CheckObservableClients(Type clientInterface) { diff --git a/Octokit.Tests/Clients/ReleasesClientTests.cs b/Octokit.Tests/Clients/ReleasesClientTests.cs index bb0ef316..d82c0707 100644 --- a/Octokit.Tests/Clients/ReleasesClientTests.cs +++ b/Octokit.Tests/Clients/ReleasesClientTests.cs @@ -20,7 +20,7 @@ namespace Octokit.Tests.Clients client.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/releases"), null, - AcceptHeaders.StableVersion, + "application/vnd.github.v3", Args.ApiOptions); } diff --git a/Octokit/Http/ApiConnection.cs b/Octokit/Http/ApiConnection.cs index 818cd941..2805ff29 100644 --- a/Octokit/Http/ApiConnection.cs +++ b/Octokit/Http/ApiConnection.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Globalization; -using System.Linq; using System.Net; using System.Threading; using System.Threading.Tasks; From b036bb931b291ab72a9b84bb557a5e20b132477d Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Thu, 18 Feb 2016 14:03:48 +1100 Subject: [PATCH 14/77] corrected this test to be 1-based (and trigger null) --- Octokit.Tests/Models/ReadOnlyPagedCollectionTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Octokit.Tests/Models/ReadOnlyPagedCollectionTests.cs b/Octokit.Tests/Models/ReadOnlyPagedCollectionTests.cs index 6b690a63..908ff7e7 100644 --- a/Octokit.Tests/Models/ReadOnlyPagedCollectionTests.cs +++ b/Octokit.Tests/Models/ReadOnlyPagedCollectionTests.cs @@ -77,7 +77,7 @@ namespace Octokit.Tests.Models connection.Get>(nextPageUrl, null, null).Returns(nextPageResponse); - var pageCount = 0; + var pageCount = 1; var pagedCollection = new ReadOnlyPagedCollection( response, @@ -95,7 +95,7 @@ namespace Octokit.Tests.Models var second = await pagedCollection.GetNextPage(); Assert.NotNull(first); - Assert.NotNull(second); + Assert.Null(second); } } } From e93dc53e8c234f0c4f44b35bbc9f7de0648b5346 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Thu, 18 Feb 2016 14:04:51 +1100 Subject: [PATCH 15/77] less nulls in your life --- Octokit.Tests/Clients/AuthorizationsClientTests.cs | 2 +- Octokit/Clients/AuthorizationsClient.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Octokit.Tests/Clients/AuthorizationsClientTests.cs b/Octokit.Tests/Clients/AuthorizationsClientTests.cs index 1a05b4f4..5aad42ef 100644 --- a/Octokit.Tests/Clients/AuthorizationsClientTests.cs +++ b/Octokit.Tests/Clients/AuthorizationsClientTests.cs @@ -35,7 +35,7 @@ namespace Octokit.Tests.Clients client.Received().GetAll( Arg.Is(u => u.ToString() == "authorizations"), - Arg.Is>(d => d == null)); + Args.ApiOptions); } } diff --git a/Octokit/Clients/AuthorizationsClient.cs b/Octokit/Clients/AuthorizationsClient.cs index e7fd862e..84b41b78 100644 --- a/Octokit/Clients/AuthorizationsClient.cs +++ b/Octokit/Clients/AuthorizationsClient.cs @@ -36,7 +36,7 @@ namespace Octokit /// A list of s. public Task> GetAll() { - return ApiConnection.GetAll(ApiUrls.Authorizations(), (IDictionary)null); + return ApiConnection.GetAll(ApiUrls.Authorizations(), ApiOptions.None); } /// From 03a5542fe6f281ae991a6fdd818b24d2eb80c74a Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Wed, 24 Feb 2016 11:35:10 +1100 Subject: [PATCH 16/77] :lipstick: renaming --- .../Exception/ApiOptionsMissingException.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Octokit.Tests.Conventions/Exception/ApiOptionsMissingException.cs b/Octokit.Tests.Conventions/Exception/ApiOptionsMissingException.cs index f913ab94..61d1111f 100644 --- a/Octokit.Tests.Conventions/Exception/ApiOptionsMissingException.cs +++ b/Octokit.Tests.Conventions/Exception/ApiOptionsMissingException.cs @@ -21,10 +21,10 @@ namespace Octokit.Tests.Conventions static string FormatMethod(MethodInfo m) { - var parametersFormatteds = m.GetParameters() + var formattedParameters = m.GetParameters() .Select(p => string.Format("{0} {1}", p.ParameterType.Name, p.Name)); - var parameterList = string.Join(", ", parametersFormatteds); + var parameterList = string.Join(", ", formattedParameters); return string.Format(" - {0}({1})", m.Name, parameterList); } From 3618236be3ecb3593beafb1653d9b157310a635f Mon Sep 17 00:00:00 2001 From: Devesh Khandelwal Date: Mon, 14 Mar 2016 11:06:22 +0530 Subject: [PATCH 17/77] Add overloads for ApiOptions in Assignees API. --- Octokit.Tests/Clients/AssigneesClientTests.cs | 2 +- Octokit/Clients/AssigneesClient.cs | 18 ++++++++++++++++++ Octokit/Clients/IAssigneesClient.cs | 9 +++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Octokit.Tests/Clients/AssigneesClientTests.cs b/Octokit.Tests/Clients/AssigneesClientTests.cs index 12615271..e067c688 100644 --- a/Octokit.Tests/Clients/AssigneesClientTests.cs +++ b/Octokit.Tests/Clients/AssigneesClientTests.cs @@ -21,7 +21,7 @@ namespace Octokit.Tests.Clients client.GetAllForRepository("fake", "repo"); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/assignees")); + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/assignees"), null, AcceptHeaders.StableVersion, Args.ApiOptions); } [Fact] diff --git a/Octokit/Clients/AssigneesClient.cs b/Octokit/Clients/AssigneesClient.cs index f66b5dc1..16036c08 100644 --- a/Octokit/Clients/AssigneesClient.cs +++ b/Octokit/Clients/AssigneesClient.cs @@ -33,6 +33,24 @@ namespace Octokit return ApiConnection.GetAll(ApiUrls.Assignees(owner, name)); } + /// + /// Gets all the available assignees (owner + collaborators) to which issues may be assigned. + /// + /// The owner of the repository + /// The name of the repository + /// The options to change API's response. + /// + public Task> GetAllForRepository(string owner, string name, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNull(options, "options"); + + var endpoint = ApiUrls.Assignees(owner, name); + + return ApiConnection.GetAll(endpoint, null, options); + } + /// /// Checks to see if a user is an assignee for a repository. /// diff --git a/Octokit/Clients/IAssigneesClient.cs b/Octokit/Clients/IAssigneesClient.cs index 2a1e0cdf..f3bc5b79 100644 --- a/Octokit/Clients/IAssigneesClient.cs +++ b/Octokit/Clients/IAssigneesClient.cs @@ -19,6 +19,15 @@ namespace Octokit /// Task> GetAllForRepository(string owner, string name); + /// + /// Gets all the available assignees (owner + collaborators) to which issues may be assigned. + /// + /// The owner of the repository + /// The name of the repository + /// The options to chagne API's response. + /// + Task> GetAllForRepository(string owner, string name, ApiOptions options); + /// /// Checks to see if a user is an assignee for a repository. /// From 829ba2c5609b6f1ab40b9dd89cab529aecd91c79 Mon Sep 17 00:00:00 2001 From: Devesh Khandelwal Date: Mon, 14 Mar 2016 11:25:29 +0530 Subject: [PATCH 18/77] Add reactive overloads for ApiOptions in Assignees API. --- .../Clients/IObservableAssigneesClient.cs | 9 ++ .../Clients/ObservableAssigneesClient.cs | 15 ++++ .../Octokit.Tests.Integration.csproj | 1 + .../ObservableAssigneesClientTests.cs | 88 +++++++++++++++++++ 4 files changed, 113 insertions(+) create mode 100644 Octokit.Tests.Integration/Reactive/ObservableAssigneesClientTests.cs diff --git a/Octokit.Reactive/Clients/IObservableAssigneesClient.cs b/Octokit.Reactive/Clients/IObservableAssigneesClient.cs index b4be296d..b47ad18e 100644 --- a/Octokit.Reactive/Clients/IObservableAssigneesClient.cs +++ b/Octokit.Reactive/Clients/IObservableAssigneesClient.cs @@ -12,6 +12,15 @@ namespace Octokit.Reactive /// IObservable GetAllForRepository(string owner, string name); + /// + /// Gets all the available assignees (owner + collaborators) to which issues may be assigned. + /// + /// The owner of the repository + /// The name of the repository + /// The options to change API's behaviour. + /// + IObservable GetAllForRepository(string owner, string name, ApiOptions options); + /// /// Checks to see if a user is an assignee for a repository. /// diff --git a/Octokit.Reactive/Clients/ObservableAssigneesClient.cs b/Octokit.Reactive/Clients/ObservableAssigneesClient.cs index 63fe37d7..814d158d 100644 --- a/Octokit.Reactive/Clients/ObservableAssigneesClient.cs +++ b/Octokit.Reactive/Clients/ObservableAssigneesClient.cs @@ -31,6 +31,21 @@ namespace Octokit.Reactive return _connection.GetAndFlattenAllPages(ApiUrls.Assignees(owner, name)); } + /// + /// Gets all the available assignees (owner + collaborators) to which issues may be assigned. + /// + /// The owner of the repository + /// The name of the repository + /// + public IObservable GetAllForRepository(string owner, string name, ApiOptions options) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNull(options, "options"); + + return _connection.GetAndFlattenAllPages(ApiUrls.Assignees(owner, name), options); + } + /// /// Checks to see if a user is an assignee for a repository. /// diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index 5b843b6e..0a5c12a3 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -137,6 +137,7 @@ + diff --git a/Octokit.Tests.Integration/Reactive/ObservableAssigneesClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableAssigneesClientTests.cs new file mode 100644 index 00000000..a85f326b --- /dev/null +++ b/Octokit.Tests.Integration/Reactive/ObservableAssigneesClientTests.cs @@ -0,0 +1,88 @@ +using System.Reactive.Linq; +using System.Threading.Tasks; +using Octokit.Reactive; +using Xunit; + +namespace Octokit.Tests.Integration.Reactive +{ + public class ObservableAssigneesClientTests + { + public class TheGetAllMethod + { + readonly ObservableAssigneesClient _assigneesClient; + const string owner = "octokit"; + const string name = "octokit.net"; + + public TheGetAllMethod() + { + var github = Helper.GetAuthenticatedClient(); + + _assigneesClient = new ObservableAssigneesClient(github); + } + + [IntegrationTest] + public async Task ReturnsAssignees() + { + var assignees = await _assigneesClient.GetAllForRepository(owner, name).ToList(); + + Assert.NotEmpty(assignees); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfAssigneesWithoutStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var assignees = await _assigneesClient.GetAllForRepository(owner, name, options).ToList(); + + Assert.Equal(5, assignees.Count); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfAssigneesWithStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var releases = await _assigneesClient.GetAllForRepository(owner, name, options).ToList(); + + Assert.Equal(5, releases.Count); + } + + [IntegrationTest] + public async Task ReturnsDistinctResultsBasedOnStartPage() + { + var startOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var firstPage = await _assigneesClient.GetAllForRepository(owner, name, startOptions).ToList(); + + var skipStartOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var secondPage = await _assigneesClient.GetAllForRepository(owner, name, skipStartOptions).ToList(); + + Assert.NotEqual(firstPage[0].Id, secondPage[0].Id); + Assert.NotEqual(firstPage[1].Id, secondPage[1].Id); + Assert.NotEqual(firstPage[2].Id, secondPage[2].Id); + Assert.NotEqual(firstPage[3].Id, secondPage[3].Id); + Assert.NotEqual(firstPage[4].Id, secondPage[4].Id); + } + } + } +} \ No newline at end of file From 692a4cb165c08bc663d11fe782ceb27a1f80c88d Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Mon, 14 Mar 2016 18:56:31 +1100 Subject: [PATCH 19/77] extract OVERVIEW.md document which introduces the overall Octokit codebase --- CONTRIBUTING.md | 36 ++---------------------------------- OVERVIEW.md | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 34 deletions(-) create mode 100644 OVERVIEW.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 22a32416..29930996 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -25,40 +25,7 @@ easiest way to do this. You can then clone down your fork instead: After doing that, run the `.\build.cmd` script at the root of the repository to ensure all the tests pass. -### How is the codebase organised? - -The two main projects are the `Octokit` and `Octokit.Reactive` projects. - -The `Octokit.Reactive` library is a thin wrapper over the `Octokit` -library - for those who want to use Reactive Extensions (Rx) instead of tasks. - -The namespaces are organised so that the relevant components are easy to discover: - - - **Authentication** - everything related to authenticating requests - - **Clients** - the logic for interacting with various parts of the GitHub API - - **Exceptions** - types which represent exceptional behaviour from the API - - **Helpers** - assorted extensions and helpers to keep the code neat and tidy - - **Http** - the internal networking components which Octokit requires - - **Models** - types which represent request/response objects - -Unless you're modifying some core behaviour, the **Clients** and **Models** namespaces -are likely to be the most interesting areas. - -The clients within a project are organized similarly to the endpoints in the -[GitHub API documentation](http://developer.github.com/v3/) - -Some clients are "sub-clients". For example, when you navigate to the -[Issues API](http://developer.github.com/v3/issues/) you'll notice there's an -endpoint for issues. But in the right navbar, there are other APIs such as -[Assignees](http://developer.github.com/v3/issues/assignees/) and -[Milestones](http://developer.github.com/v3/issues/milestones/). - -We've tried to mirror this structure. So the `IObservableMilestoneClient` isn't -a direct property of `IObservableGitHubClient`. Instead, it's a property of the -`IObservableIssuesClient`. And thus you can get to it by going to -`client.Issues.Milestones`. - -### What needs to be done? +### How can I get involved? We have a [`easy-fix`](https://github.com/octokit/octokit.net/issues?labels=easy-fix&state=open) tag on our issue tracker to indicate tasks which contributors can pick up. @@ -141,4 +108,5 @@ Some things that will increase the chance that your pull request is accepted. # Additional Resources +* [Octokit Codebase Overview](https://github.com/octokit/octokit.net/blob/master/OVERVIEW.md) * [General GitHub documentation](http://help.github.com/) diff --git a/OVERVIEW.md b/OVERVIEW.md new file mode 100644 index 00000000..8276639b --- /dev/null +++ b/OVERVIEW.md @@ -0,0 +1,32 @@ +### How is the codebase organised? + +The two main projects are the `Octokit` and `Octokit.Reactive` projects. + +The `Octokit.Reactive` library is a thin wrapper over the `Octokit` +library - for those who want to use Reactive Extensions (Rx) instead of tasks. + +The namespaces are organised so that the relevant components are easy to discover: + + - **Authentication** - everything related to authenticating requests + - **Clients** - the logic for interacting with various parts of the GitHub API + - **Exceptions** - types which represent exceptional behaviour from the API + - **Helpers** - assorted extensions and helpers to keep the code neat and tidy + - **Http** - the internal networking components which Octokit requires + - **Models** - types which represent request/response objects + +Unless you're modifying some core behaviour, the **Clients** and **Models** namespaces +are likely to be the most interesting areas. + +The clients within a project are organized similarly to the endpoints in the +[GitHub API documentation](http://developer.github.com/v3/) + +Some clients are "sub-clients". For example, when you navigate to the +[Issues API](http://developer.github.com/v3/issues/) you'll notice there's an +endpoint for issues. But in the right navbar, there are other APIs such as +[Assignees](http://developer.github.com/v3/issues/assignees/) and +[Milestones](http://developer.github.com/v3/issues/milestones/). + +We've tried to mirror this structure. So the `IObservableMilestoneClient` isn't +a direct property of `IObservableGitHubClient`. Instead, it's a property of the +`IObservableIssuesClient`. And thus you can get to it by going to +`client.Issues.Milestones`. From 16175ecd869baa74528b6f69dc0041f0959af3f8 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Mon, 14 Mar 2016 18:56:53 +1100 Subject: [PATCH 20/77] refresh the CONTRIBUTING.md document --- CONTRIBUTING.md | 141 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 98 insertions(+), 43 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 29930996..64a9bb71 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,33 +1,35 @@ # How to Contribute -We love Pull Requests! Your contributions help make Octokit great. +Contributions take many forms from submitting issues, writing docs, to making +code changes - we welcome it all! ## Getting Started -So you want to contribute to Octokit. Great! Contributions take many forms -from submitting issues, writing docs, to making code changes. We welcome -it all. Don't forget to sign up for a [GitHub account](https://github.com/signup/free), -if you haven't already. +If you don't have a GitHub account, you can [sign up](https://github.com/signup/free) +as it will help you to participate with the project. -## Getting Started +If you are looking to contribute to the codebase, please ensure you have Visual +Studio 2015 installed - you can download the Community edition from +[here](https://www.visualstudio.com/en-us/downloads/download-visual-studio-vs.aspx) -You can clone this repository locally from GitHub using the "Clone in Desktop" -button from the main project site, or run this command in the Git Shell: +If you are running GitHub Desktop, you can clone this repository locally from +GitHub using the "Clone in Desktop" button from the Octokit.net project page, +or run this command in your Git-enabled shell: -`git clone git@github.com:octokit/Octokit.net.git Octokit` +`git clone https://github.com/octokit/Octokit.net.git Octokit` -If you want to make contributions to the project, -[forking the project](https://help.github.com/articles/fork-a-repo) is the +If you want to make contributions to the project, +[forking the project](https://help.github.com/articles/fork-a-repo) is the easiest way to do this. You can then clone down your fork instead: -`git clone git@github.com:MY-USERNAME-HERE/Octokit.net.git Octokit` +`git clone https://github.com/MY-USERNAME-HERE/Octokit.net.git Octokit` -After doing that, run the `.\build.cmd` script at the root of the repository -to ensure all the tests pass. +After doing that, run the `.\build` script at the root of the repository +to ensure everything builds and the tests pass. -### How can I get involved? +## How can I get involved? -We have a [`easy-fix`](https://github.com/octokit/octokit.net/issues?labels=easy-fix&state=open) +We have an [`up-for-grabs`](https://github.com/octokit/octokit.net/issues/labels/up-for-grabs) tag on our issue tracker to indicate tasks which contributors can pick up. If you've found something you'd like to contribute to, leave a comment in the issue @@ -39,28 +41,63 @@ for ways to improve the API to make it easy to work with the GitHub API. ## Making Changes -When you're ready to make a change, -[create a branch](https://help.github.com/articles/fork-a-repo#create-branches) -off the `master` branch. We use `master` as the default branch for the -repository, and it holds the most recent contributions, so any changes you make -in master might cause conflicts down the track. +When you're ready to make a change, create a branch off the `master` branch: + +``` +git checkout master +git pull origin master +git checkout -b SOME-BRANCH-NAME +``` + +We use `master` as the default branch for the repository, and it holds the most +recent contributions. By working in a branch away from `master` you can handle +potential conflicts that may occur in the future. If you make focused commits (instead of one monolithic commit) and have descriptive commit messages, this will help speed up the review process. -If you're adding new files to the Octokit project, we have a helper script to -synchronize these changes with the Mono* projects in the solution. +### Adding New files -Just run this command: `.\build FixProjects` +To ensure new files are available in the various projects, we have a helper script +to synchronize these changes across all the projects in the solution. + +If you need to create new files: + + - add the file to the main `Octokit` project + - build the project (to ensure the `csproj` change is saved) + - run this command: `.\build FixProjects` + +At any time you can build the project with `.\build BuildApp` - this will also +run FxCop analysis. + +### Running Tests Octokit.net also has a suite of tests which you can run to ensure existing -behaviour is unchanged. If you're adding new features, please add some -tests alongside so the maintainers can sleep at night, knowing their +behaviour is not affected. If you're adding new features, please add some +tests alongside so the maintainers can sleep at night, knowing their safety blanket is nice and green! -Run this command to confirm all the tests pass: `.\build` +The test suite is arranged into fast and slow tests. -### Running integration tests +#### Fast Tests + +**Unit Tests:** `.\build UnitTests` + +These tests verify specific behaviour while being isolated from the rest of the +library. If you are not familiar with unit testing, have a look at the existing +examples - they should be easy to apply to your work. + +**Convention Tests:** `.\build ConventionTests` + +These tests verify conventions and structure across the entire codebase - +ensuring everything is consistent and predictable. When writing new features, +these tests may fail and should help indicate where the changes have violated +the conventions, so feel free to run them locally while you're working on new +features. + +#### Slow Tests + +**Integration Tests** Octokit has integration tests that access the GitHub API, but they require a bit of setup to run. The tests make use of a set of test accounts accessed via @@ -71,9 +108,23 @@ variables: `.\script\configure-integration-tests.ps1` -Once these are set, the integration tests will be executed both when -running the IntegrationTests build target, or when running the -Octokit.Tests.Integration assembly in the Visual Studio test runner. +After running this, ensure any existing instances of Visual Studio are restarted +so they pick up the new environment variables are detected. + +With these variables set, you can run the integration tests locally using +`.\build IntegrationTests` or by running the `Octokit.Tests.Integration` +assembly in the Visual Studio test runner. + +**Note:** as the integration tests rely on using the actual GitHub API, you may +encounter issues if running the tests too frequently. Please use a test account +so that you're not impacted in the unlikely scenario of your account being +flagged as a spammer. + +### Testing Documentation + +If you are making changes to the documentation for Octokit, you can test these +changes locally using the [guide](https://github.com/shiftkey/octokit.net/blob/rewrite-contributing/docs/contributing.md) +under the `docs` folder. ### Submitting Changes @@ -83,27 +134,31 @@ the Git Shell: `git push origin MY-BRANCH-NAME` Once your changes are ready to be reviewed, publish the branch to GitHub and -[open a pull request](https://help.github.com/articles/using-pull-requests) +[open a pull request](https://help.github.com/articles/using-pull-requests) against it. -A few little tips with pull requests: +A few suggestions when opening a pull request: + + - if you are addressing a particular issue, reference it like this: + +> Fixes #1145 - prefix the title with `[WIP]` to indicate this is a work-in-progress. It's - always good to get feedback early, so don't be afraid to open the PR before it's "done". - - use [checklists](https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments) - to indicate the tasks which need to be done, so everyone knows how close you are to done. - - add comments to the PR about things that are unclear or you would like suggestions on + always good to get feedback early, so don't be afraid to open the PR before + it's "done". + - use [checklists](https://github.com/blog/1375-task-lists-in-gfm-issues-pulls-comments) + to indicate the tasks which need to be done, so everyone knows how close you + are to done. + - add comments to the PR about things that are unclear or you would like + suggestions on -Don't forget to mention in the pull request description which issue/issues are -being addressed. - -Some things that will increase the chance that your pull request is accepted. +Some things that will increase the chance that your pull request is accepted: * Follow existing code conventions. Most of what we do follows [standard .NET conventions](https://github.com/dotnet/corefx/blob/master/Documentation/coding-guidelines/coding-style.md) except in a few places. We include a ReSharper team settings file. -* Include unit tests that would otherwise fail without your code, but pass with +* Include unit tests that would otherwise fail without your code, but pass with it. -* Update the documentation, the surrounding one, examples elsewhere, guides, +* Update the documentation, the surrounding one, examples elsewhere, guides, whatever is affected by your contribution # Additional Resources From abc4eb9269a75c5bf40fd9bad79f03cdbbeda1f3 Mon Sep 17 00:00:00 2001 From: Devesh Khandelwal Date: Tue, 15 Mar 2016 15:27:19 +0530 Subject: [PATCH 21/77] Oops. Forgot to actually call the overload I added. --- Octokit.Reactive/Clients/ObservableAssigneesClient.cs | 1 + Octokit.Tests/Clients/AssigneesClientTests.cs | 6 +++++- Octokit/Clients/AssigneesClient.cs | 4 ++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Octokit.Reactive/Clients/ObservableAssigneesClient.cs b/Octokit.Reactive/Clients/ObservableAssigneesClient.cs index 814d158d..28717934 100644 --- a/Octokit.Reactive/Clients/ObservableAssigneesClient.cs +++ b/Octokit.Reactive/Clients/ObservableAssigneesClient.cs @@ -36,6 +36,7 @@ namespace Octokit.Reactive /// /// The owner of the repository /// The name of the repository + /// The options to change API's behaviour /// public IObservable GetAllForRepository(string owner, string name, ApiOptions options) { diff --git a/Octokit.Tests/Clients/AssigneesClientTests.cs b/Octokit.Tests/Clients/AssigneesClientTests.cs index e067c688..ac4a7bc0 100644 --- a/Octokit.Tests/Clients/AssigneesClientTests.cs +++ b/Octokit.Tests/Clients/AssigneesClientTests.cs @@ -21,7 +21,11 @@ namespace Octokit.Tests.Clients client.GetAllForRepository("fake", "repo"); - connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/assignees"), null, AcceptHeaders.StableVersion, Args.ApiOptions); + connection.Received().GetAll( + Arg.Is(u => u.ToString() == "repos/fake/repo/assignees"), + null, + AcceptHeaders.StableVersion, + Args.ApiOptions); } [Fact] diff --git a/Octokit/Clients/AssigneesClient.cs b/Octokit/Clients/AssigneesClient.cs index 16036c08..58ca8666 100644 --- a/Octokit/Clients/AssigneesClient.cs +++ b/Octokit/Clients/AssigneesClient.cs @@ -30,7 +30,7 @@ namespace Octokit Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(name, "name"); - return ApiConnection.GetAll(ApiUrls.Assignees(owner, name)); + return GetAllForRepository(owner, name, ApiOptions.None); } /// @@ -48,7 +48,7 @@ namespace Octokit var endpoint = ApiUrls.Assignees(owner, name); - return ApiConnection.GetAll(endpoint, null, options); + return ApiConnection.GetAll(endpoint, null, AcceptHeaders.StableVersion, options); } /// From b157c452a24cae8cd08bedaff79cc64c54647a64 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 15 Mar 2016 17:10:08 +0700 Subject: [PATCH 22/77] Class ApiOptionsSingleton was implemented in order to support proper unit tests. Now ApiOptionsSingleton.Instance is used as ApiOptions.None static member instead of creation of new ApiOptions class each time when ApiOptions.None is invoked. Singleton pattern will allow write proper tests for methods that use ApiOptions.None as their parameter For instance, now "Arg.Is(options => options == ApiOptions.None)" construction can be used. Also, usage of sigleton has some posititve performance impact. --- Octokit/Models/Request/ApiOptions.cs | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Octokit/Models/Request/ApiOptions.cs b/Octokit/Models/Request/ApiOptions.cs index ef149633..764dd45f 100644 --- a/Octokit/Models/Request/ApiOptions.cs +++ b/Octokit/Models/Request/ApiOptions.cs @@ -7,9 +7,32 @@ namespace Octokit [DebuggerDisplay("{DebuggerDisplay,nq}")] public class ApiOptions { + private class ApiOptionsSingleton + { + private static readonly ApiOptions _instance = new ApiOptions(); + + // Explicit static constructor to tell C# compiler + // not to mark type as beforefieldinit + static ApiOptionsSingleton() + { + } + + private ApiOptionsSingleton() + { + } + + public static ApiOptions Instance + { + get + { + return _instance; + } + } + } + public static ApiOptions None { - get { return new ApiOptions(); } + get { return ApiOptionsSingleton.Instance; } } /// From ec5de110ad201b7599a445c4141c404819ff5bad Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 15 Mar 2016 17:15:04 +0700 Subject: [PATCH 23/77] The overloaded version of needed methods for IUserEmailsClient interface was added and impelemented. Base methods: Task> GetAll() Overload methods: Task> GetAll(ApiOptions options); --- Octokit/Clients/IUserEmailsClient.cs | 11 +++++++++++ Octokit/Clients/UserEmailsClient.cs | 16 +++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/Octokit/Clients/IUserEmailsClient.cs b/Octokit/Clients/IUserEmailsClient.cs index b653d218..4fb9fb12 100644 --- a/Octokit/Clients/IUserEmailsClient.cs +++ b/Octokit/Clients/IUserEmailsClient.cs @@ -22,6 +22,17 @@ namespace Octokit [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] Task> GetAll(); + /// + /// Gets all email addresses for the authenticated user. + /// + /// + /// http://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user + /// + /// Options for changing the API response + /// The es for the authenticated user. + [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] + Task> GetAll(ApiOptions options); + /// /// Adds email addresses for the authenticated user. /// diff --git a/Octokit/Clients/UserEmailsClient.cs b/Octokit/Clients/UserEmailsClient.cs index d503e853..fc638cd0 100644 --- a/Octokit/Clients/UserEmailsClient.cs +++ b/Octokit/Clients/UserEmailsClient.cs @@ -30,7 +30,21 @@ namespace Octokit /// The es for the authenticated user. public Task> GetAll() { - return ApiConnection.GetAll(ApiUrls.Emails()); + return GetAll(ApiOptions.None); + } + + /// + /// Gets all email addresses for the authenticated user. + /// + /// + /// http://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user + /// + /// The es for the authenticated user. + public Task> GetAll(ApiOptions options) + { + Ensure.ArgumentNotNull(options, "options"); + + return ApiConnection.GetAll(ApiUrls.Emails(), options); } /// From b920bcdfcec241705505710666eaec5fafabde02 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 15 Mar 2016 17:17:33 +0700 Subject: [PATCH 24/77] A bunch of unit and integration tests for overloaded version of needed methods for IUserEmailsClient interface were added and impelemented. Base methods: Task> GetAll() Overload methods: Task> GetAll(ApiOptions options); --- .../Clients/UserEmailsClientTests.cs | 8 +++++++ .../Clients/UserEmailsClientTests.cs | 23 +++++++++++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs b/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs index f0af752c..9b54fb76 100644 --- a/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs @@ -15,6 +15,14 @@ namespace Octokit.Tests.Integration.Clients Assert.NotEmpty(emails); } + [IntegrationTest] + public async Task CanGetEmailWithApiOptions() + { + var github = Helper.GetAuthenticatedClient(); + var emails = await github.User.Email.GetAll(ApiOptions.None); + Assert.NotEmpty(emails); + } + const string testEmailAddress = "hahaha-not-a-real-email@foo.com"; [IntegrationTest(Skip = "this isn't passing in CI - i hate past me right now")] diff --git a/Octokit.Tests/Clients/UserEmailsClientTests.cs b/Octokit.Tests/Clients/UserEmailsClientTests.cs index b3564796..d2642c12 100644 --- a/Octokit.Tests/Clients/UserEmailsClientTests.cs +++ b/Octokit.Tests/Clients/UserEmailsClientTests.cs @@ -8,7 +8,7 @@ namespace Octokit.Tests.Clients { public class UserEmailsClientTests { - public class TheGetAllMethod + public class TheGetAllMethods { [Fact] public void GetsCorrectUrl() @@ -19,7 +19,26 @@ namespace Octokit.Tests.Clients client.GetAll(); connection.Received(1) - .GetAll(Arg.Is(u => u.ToString() == "user/emails")); + .GetAll(Arg.Is(u => u.ToString() == "user/emails"), + Arg.Is(ApiOptions.None)); + } + + [Fact] + public void GetsCorrectUrlWithApiOptions() + { + var options = new ApiOptions + { + StartPage = 1, + PageCount = 1 + }; + + var connection = Substitute.For(); + var client = new UserEmailsClient(connection); + + client.GetAll(options); + + connection.Received(1) + .GetAll(Arg.Is(u => u.ToString() == "user/emails"), Arg.Is(apiOptions => apiOptions == options)); } } From 9d4f0077b9b7979d1e2a21cf37b0469514e84582 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 15 Mar 2016 17:40:22 +0700 Subject: [PATCH 25/77] ApiOptionsSingleton implementation was changed in order to pass FoxCop analysis. --- Octokit/Models/Request/ApiOptions.cs | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/Octokit/Models/Request/ApiOptions.cs b/Octokit/Models/Request/ApiOptions.cs index 764dd45f..e7ed1c40 100644 --- a/Octokit/Models/Request/ApiOptions.cs +++ b/Octokit/Models/Request/ApiOptions.cs @@ -7,29 +7,21 @@ namespace Octokit [DebuggerDisplay("{DebuggerDisplay,nq}")] public class ApiOptions { - private class ApiOptionsSingleton + private sealed class ApiOptionsSingleton { - private static readonly ApiOptions _instance = new ApiOptions(); + private static readonly Lazy _lazy = + new Lazy(() => new ApiOptions()); - // Explicit static constructor to tell C# compiler - // not to mark type as beforefieldinit - static ApiOptionsSingleton() + public static ApiOptions Instance { + get { return _lazy.Value; } } private ApiOptionsSingleton() { } - - public static ApiOptions Instance - { - get - { - return _instance; - } - } } - + public static ApiOptions None { get { return ApiOptionsSingleton.Instance; } @@ -81,5 +73,4 @@ namespace Octokit } } } - } From bc3dc18045db183fbd45cec4518a4257c02193a2 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 15 Mar 2016 18:56:06 +0700 Subject: [PATCH 26/77] Add new overloaded extension method Task> GetResponse(this IConnection connection, Uri uri, Dictionary parameters) to work with IConnection. --- Octokit/Helpers/ApiExtensions.cs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/Octokit/Helpers/ApiExtensions.cs b/Octokit/Helpers/ApiExtensions.cs index 81b1ab8e..d25027e0 100644 --- a/Octokit/Helpers/ApiExtensions.cs +++ b/Octokit/Helpers/ApiExtensions.cs @@ -74,6 +74,23 @@ namespace Octokit return connection.Get(uri, null, null); } + /// + /// Gets the API resource at the specified URI. + /// + /// Type of the API resource to get. + /// The connection to use + /// URI of the API resource to get + /// Querystring parameters for the request + /// The API resource. + /// Thrown when an API error occurs. + public static Task> GetResponse(this IConnection connection, Uri uri, Dictionary parameters) + { + Ensure.ArgumentNotNull(connection, "connection"); + Ensure.ArgumentNotNull(uri, "uri"); + + return connection.Get(uri, parameters, null); + } + [Obsolete("Octokit's HTTP library now follows redirects by default - this API will be removed in a future release")] public static Task> GetRedirect(this IConnection connection, Uri uri) { From 7a01f22ee9ba539e0c9ca5133400358df3f45453 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 15 Mar 2016 18:58:10 +0700 Subject: [PATCH 27/77] New overloaded method IObservable GetAll(ApiOptions options) has been added and implemented on IObservableUserEmailsClient/ObservableUserEmailsClient. --- .../Clients/IObservableUserEmailsClient.cs | 11 +++++++++++ .../Clients/ObservableUserEmailsClient.cs | 17 ++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Octokit.Reactive/Clients/IObservableUserEmailsClient.cs b/Octokit.Reactive/Clients/IObservableUserEmailsClient.cs index 5198ef1a..dd1c99c1 100644 --- a/Octokit.Reactive/Clients/IObservableUserEmailsClient.cs +++ b/Octokit.Reactive/Clients/IObservableUserEmailsClient.cs @@ -22,6 +22,17 @@ namespace Octokit.Reactive [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] IObservable GetAll(); + /// + /// Gets all email addresses for the authenticated user. + /// + /// + /// http://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user + /// + /// Options for changing the API response + /// The es for the authenticated user. + [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] + IObservable GetAll(ApiOptions options); + /// /// Adds email addresses for the authenticated user. /// diff --git a/Octokit.Reactive/Clients/ObservableUserEmailsClient.cs b/Octokit.Reactive/Clients/ObservableUserEmailsClient.cs index 2a2d1071..96076c30 100644 --- a/Octokit.Reactive/Clients/ObservableUserEmailsClient.cs +++ b/Octokit.Reactive/Clients/ObservableUserEmailsClient.cs @@ -34,7 +34,22 @@ namespace Octokit.Reactive /// The es for the authenticated user. public IObservable GetAll() { - return _connection.GetAndFlattenAllPages(ApiUrls.Emails()); + return GetAll(ApiOptions.None); + } + + /// + /// Gets all email addresses for the authenticated user. + /// + /// + /// http://developer.github.com/v3/users/emails/#list-email-addresses-for-a-user + /// + /// Options for changing the API response + /// The es for the authenticated user. + public IObservable GetAll(ApiOptions options) + { + Ensure.ArgumentNotNull(options, "options"); + + return _connection.GetAndFlattenAllPages(ApiUrls.Emails(), options); } /// From dd969f24368f0eab5ecc0254015a62409063e52d Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 15 Mar 2016 18:58:57 +0700 Subject: [PATCH 28/77] New unit and integration tests were added in order to test IObservable GetAll(ApiOptions options) method. --- .../ObservableUserEmailsClientTests.cs | 11 ++++++ .../ObservableUserEmailsClientTests.cs | 34 ++++++++++++++----- 2 files changed, 36 insertions(+), 9 deletions(-) diff --git a/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs index f3cd8b81..a1fa327f 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs @@ -17,5 +17,16 @@ namespace Octokit.Tests.Integration var email = await client.GetAll(); Assert.NotNull(email); } + + [IntegrationTest] + public async Task CanGetEmailWithApiOptions() + { + var github = Helper.GetAuthenticatedClient(); + + var client = new ObservableUserEmailsClient(github); + + var email = await client.GetAll(ApiOptions.None); + Assert.NotNull(email); + } } } diff --git a/Octokit.Tests/Reactive/ObservableUserEmailsClientTests.cs b/Octokit.Tests/Reactive/ObservableUserEmailsClientTests.cs index 1e62a86b..22a03e57 100644 --- a/Octokit.Tests/Reactive/ObservableUserEmailsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableUserEmailsClientTests.cs @@ -1,7 +1,7 @@ -using NSubstitute; -using Octokit.Reactive; -using System; +using System; using System.Collections.Generic; +using NSubstitute; +using Octokit.Reactive; using Xunit; namespace Octokit.Tests @@ -18,25 +18,41 @@ namespace Octokit.Tests public class TheGetAllMethod { + private static readonly Uri _expectedUri = new Uri("user/emails", UriKind.Relative); + [Fact] public void GetsCorrectUrl() { - var expectedUri = new Uri("user/emails", UriKind.Relative); var github = Substitute.For(); var client = new ObservableUserEmailsClient(github); client.GetAll(); - github.Connection.Received(1).GetResponse>(expectedUri); + github.Connection.Received(1).GetResponse>(_expectedUri, + Arg.Is>(dictionary => dictionary.Count == 0)); + } + + [Fact] + public void GetsCorrectUrlWithApiOption() + { + var github = Substitute.For(); + var client = new ObservableUserEmailsClient(github); + + var options = new ApiOptions + { + StartPage = 1, + PageCount = 1 + }; + + client.GetAll(options); + + github.Connection.Received(1).GetResponse>(_expectedUri, + Arg.Is>(dictionary => dictionary.Count == 1)); } } public class TheAddMethod { - public IGitHubClient GitHubClient; - - public ObservableUserEmailsClient Client; - [Fact] public void CallsAddOnClient() { From 531792ebe2e991fb2fc52c460701a6d5cf3e85a0 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 15 Mar 2016 19:02:11 +0700 Subject: [PATCH 29/77] Some minor changes in logic of GetsCorrectUrlWithApiOptions test. Use ApiOptions.None instead of setted up class. --- Octokit.Tests/Clients/UserEmailsClientTests.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Octokit.Tests/Clients/UserEmailsClientTests.cs b/Octokit.Tests/Clients/UserEmailsClientTests.cs index d2642c12..5f3f6b24 100644 --- a/Octokit.Tests/Clients/UserEmailsClientTests.cs +++ b/Octokit.Tests/Clients/UserEmailsClientTests.cs @@ -26,19 +26,13 @@ namespace Octokit.Tests.Clients [Fact] public void GetsCorrectUrlWithApiOptions() { - var options = new ApiOptions - { - StartPage = 1, - PageCount = 1 - }; - var connection = Substitute.For(); var client = new UserEmailsClient(connection); - client.GetAll(options); + client.GetAll(ApiOptions.None); connection.Received(1) - .GetAll(Arg.Is(u => u.ToString() == "user/emails"), Arg.Is(apiOptions => apiOptions == options)); + .GetAll(Arg.Is(u => u.ToString() == "user/emails"), Arg.Is(apiOptions => apiOptions == ApiOptions.None)); } } From 9fd3c9b730fffe4281fdcc027ba1d02707a6f3e7 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 15 Mar 2016 19:05:03 +0700 Subject: [PATCH 30/77] Some minor changes in ObservableUserEmailsClientTests.GetsCorrectUrlWithApiOption. Now ApiOptions.None is used instead of pre-configured class. --- .../Reactive/ObservableUserEmailsClientTests.cs | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Octokit.Tests/Reactive/ObservableUserEmailsClientTests.cs b/Octokit.Tests/Reactive/ObservableUserEmailsClientTests.cs index 22a03e57..267f3029 100644 --- a/Octokit.Tests/Reactive/ObservableUserEmailsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableUserEmailsClientTests.cs @@ -38,16 +38,10 @@ namespace Octokit.Tests var github = Substitute.For(); var client = new ObservableUserEmailsClient(github); - var options = new ApiOptions - { - StartPage = 1, - PageCount = 1 - }; - - client.GetAll(options); + client.GetAll(ApiOptions.None); github.Connection.Received(1).GetResponse>(_expectedUri, - Arg.Is>(dictionary => dictionary.Count == 1)); + Arg.Is>(dictionary => dictionary.Count == 0)); } } From f16b20d28d1cc5479f6e0d8192794d8f60a10f4d Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 15 Mar 2016 19:32:42 +0700 Subject: [PATCH 31/77] Some new integration tests were added in order to test Pagination Support on IUserEmailsClient and IObservableUserEmailsClient. --- .../Clients/UserEmailsClientTests.cs | 60 +++++++++++++++++ .../ObservableUserEmailsClientTests.cs | 65 ++++++++++++++++--- 2 files changed, 117 insertions(+), 8 deletions(-) diff --git a/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs b/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs index 9b54fb76..0a1c5888 100644 --- a/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs @@ -6,6 +6,14 @@ namespace Octokit.Tests.Integration.Clients { public class UserEmailsClientTests { + private readonly IUserEmailsClient _emailClient; + + public UserEmailsClientTests() + { + var github = Helper.GetAuthenticatedClient(); + _emailClient = github.User.Email; + } + [IntegrationTest] public async Task CanGetEmail() { @@ -23,6 +31,58 @@ namespace Octokit.Tests.Integration.Clients Assert.NotEmpty(emails); } + [IntegrationTest] + public async Task ReturnsCorrectCountOfEmailsWithoutStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var emails = await _emailClient.GetAll(options); + + Assert.Equal(1, emails.Count); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfEmailsWithStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var emails = await _emailClient.GetAll(options); + + Assert.Equal(0, emails.Count); + } + + //[IntegrationTest] + //public async Task ReturnsDistinctResultsBasedOnStartPage() + //{ + // var startOptions = new ApiOptions + // { + // PageSize = 5, + // PageCount = 1 + // }; + + // var firstPage = await _emailClient.GetAll(startOptions); + + // var skipStartOptions = new ApiOptions + // { + // PageSize = 5, + // PageCount = 1, + // StartPage = 2 + // }; + + // var secondPage = await _emailClient.GetAll(skipStartOptions); + + // Assert.Equal(firstPage[0].Email, secondPage[0].Email); + //} + const string testEmailAddress = "hahaha-not-a-real-email@foo.com"; [IntegrationTest(Skip = "this isn't passing in CI - i hate past me right now")] diff --git a/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs index a1fa327f..66811c52 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs @@ -7,12 +7,13 @@ namespace Octokit.Tests.Integration { public class ObservableUserEmailsClientTests { + private readonly ObservableUserEmailsClient _emailClient + = new ObservableUserEmailsClient(Helper.GetAuthenticatedClient()); + [IntegrationTest] public async Task CanGetEmail() { - var github = Helper.GetAuthenticatedClient(); - - var client = new ObservableUserEmailsClient(github); + var client = new ObservableUserEmailsClient(Helper.GetAuthenticatedClient()); var email = await client.GetAll(); Assert.NotNull(email); @@ -21,12 +22,60 @@ namespace Octokit.Tests.Integration [IntegrationTest] public async Task CanGetEmailWithApiOptions() { - var github = Helper.GetAuthenticatedClient(); - - var client = new ObservableUserEmailsClient(github); - - var email = await client.GetAll(ApiOptions.None); + var email = await _emailClient.GetAll(ApiOptions.None); Assert.NotNull(email); } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfEmailsWithoutStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var emails = await _emailClient.GetAll(options).ToList(); + + Assert.Equal(1, emails.Count); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfEmailsWithStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var emails = await _emailClient.GetAll(options).ToList(); + + Assert.Equal(0, emails.Count); + } + + //[IntegrationTest] + //public async Task ReturnsDistinctResultsBasedOnStartPage() + //{ + // var startOptions = new ApiOptions + // { + // PageSize = 5, + // PageCount = 1 + // }; + + // var firstPage = await _emailClient.GetAll(startOptions); + + // var skipStartOptions = new ApiOptions + // { + // PageSize = 5, + // PageCount = 1, + // StartPage = 2 + // }; + + // var secondPage = await _emailClient.GetAll(skipStartOptions); + + // Assert.Equal(firstPage[0].Email, secondPage[0].Email); + //} } } From ad3b7823be91954e520201094a6514668182605d Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 15 Mar 2016 19:42:12 +0700 Subject: [PATCH 32/77] Replace usage Arg.Is with lambda to Arg.Any. --- Octokit.Tests/Clients/UserEmailsClientTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Octokit.Tests/Clients/UserEmailsClientTests.cs b/Octokit.Tests/Clients/UserEmailsClientTests.cs index 5f3f6b24..dc38ba1b 100644 --- a/Octokit.Tests/Clients/UserEmailsClientTests.cs +++ b/Octokit.Tests/Clients/UserEmailsClientTests.cs @@ -32,7 +32,7 @@ namespace Octokit.Tests.Clients client.GetAll(ApiOptions.None); connection.Received(1) - .GetAll(Arg.Is(u => u.ToString() == "user/emails"), Arg.Is(apiOptions => apiOptions == ApiOptions.None)); + .GetAll(Arg.Is(u => u.ToString() == "user/emails"), Arg.Any()); } } From 6760aca2b7a8ddee256269a855654d3322bca029 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 15 Mar 2016 23:56:49 +0700 Subject: [PATCH 33/77] Cosmetic changes UserEmailsClientTests. Changed Arg.Any to Args.ApiOptions. --- Octokit.Tests/Clients/UserEmailsClientTests.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Octokit.Tests/Clients/UserEmailsClientTests.cs b/Octokit.Tests/Clients/UserEmailsClientTests.cs index dc38ba1b..462852cc 100644 --- a/Octokit.Tests/Clients/UserEmailsClientTests.cs +++ b/Octokit.Tests/Clients/UserEmailsClientTests.cs @@ -1,7 +1,7 @@ -using NSubstitute; -using System; +using System; using System.Collections.Generic; using System.Threading.Tasks; +using NSubstitute; using Xunit; namespace Octokit.Tests.Clients @@ -19,8 +19,8 @@ namespace Octokit.Tests.Clients client.GetAll(); connection.Received(1) - .GetAll(Arg.Is(u => u.ToString() == "user/emails"), - Arg.Is(ApiOptions.None)); + .GetAll(Arg.Is(u => u.ToString() == "user/emails"), + Arg.Is(ApiOptions.None)); } [Fact] @@ -32,7 +32,7 @@ namespace Octokit.Tests.Clients client.GetAll(ApiOptions.None); connection.Received(1) - .GetAll(Arg.Is(u => u.ToString() == "user/emails"), Arg.Any()); + .GetAll(Arg.Is(u => u.ToString() == "user/emails"), Args.ApiOptions); } } From effecdf4b491f7df6a33bfd977bae4c6c482e6bf Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Wed, 16 Mar 2016 10:45:25 +1100 Subject: [PATCH 34/77] quiet nuget.exe when loading pre-requisities --- build.cmd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/build.cmd b/build.cmd index d5ac4da4..393b128f 100644 --- a/build.cmd +++ b/build.cmd @@ -1,9 +1,9 @@ @echo off -"tools\nuget\nuget.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.1.0" -"tools\nuget\nuget.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" -"tools\nuget\nuget.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" -"tools\nuget\nuget.exe" "install" "Octokit.CodeFormatter" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.0.0-preview" -Pre +"tools\nuget\nuget.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.1.0" -verbosity quiet +"tools\nuget\nuget.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" -verbosity quiet +"tools\nuget\nuget.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" -verbosity quiet +"tools\nuget\nuget.exe" "install" "Octokit.CodeFormatter" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.0.0-preview" -Pre -verbosity quiet :Build cls From 07b7fc4985b778a17e32976dd2d00eadf0ef165f Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Wed, 16 Mar 2016 12:55:21 +1100 Subject: [PATCH 35/77] quiet build output for other environment --- build.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/build.sh b/build.sh index 907b1b01..5706630d 100755 --- a/build.sh +++ b/build.sh @@ -3,16 +3,16 @@ if test "$OS" = "Windows_NT" then # use .Net -"./tools/nuget/nuget.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.0.0" -"./tools/nuget/nuget.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" -"./tools/nuget/nuget.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" -packages/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx +"./tools/nuget/nuget.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.0.0" -verbosity quiet +"./tools/nuget/nuget.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" -verbosity quiet +"./tools/nuget/nuget.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" -verbosity quiet +packages/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx else # use mono -mono "./tools/nuget/NuGet.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.0.0" -mono "./tools/nuget/NuGet.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" -mono "./tools/nuget/NuGet.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" -mono "./tools/nuget/NuGet.exe" "install" "System.Net.Http" "-OutputDirectory" "tools" -mono "./tools/nuget/NuGet.exe" "install" "Microsoft.Net.Http" "-OutputDirectory" "tools" -mono ./tools/FAKE.Core/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx +mono "./tools/nuget/NuGet.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.0.0" -verbosity quiet +mono "./tools/nuget/NuGet.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" -verbosity quiet +mono "./tools/nuget/NuGet.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" -verbosity quiet +mono "./tools/nuget/NuGet.exe" "install" "System.Net.Http" "-OutputDirectory" "tools" -verbosity quiet +mono "./tools/nuget/NuGet.exe" "install" "Microsoft.Net.Http" "-OutputDirectory" "tools" -verbosity quiet +mono ./tools/FAKE.Core/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx fi From f3f7656492f24431e10ae61b1b2b5c4ba9c12f23 Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Wed, 16 Mar 2016 12:56:18 +1100 Subject: [PATCH 36/77] make CodeFormatter available when running script as well --- build.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build.sh b/build.sh index 5706630d..f6294bc4 100755 --- a/build.sh +++ b/build.sh @@ -6,12 +6,14 @@ then "./tools/nuget/nuget.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.0.0" -verbosity quiet "./tools/nuget/nuget.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" -verbosity quiet "./tools/nuget/nuget.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" -verbosity quiet +"./tools/nuget/nuget.exe" "install" "Octokit.CodeFormatter" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.0.0-preview" -Pre -verbosity quiet packages/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx else # use mono mono "./tools/nuget/NuGet.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.0.0" -verbosity quiet mono "./tools/nuget/NuGet.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" -verbosity quiet mono "./tools/nuget/NuGet.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" -verbosity quiet +mono "./tools/nuget/NuGet.exe" "install" "Octokit.CodeFormatter" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.0.0-preview" -Pre -verbosity quiet mono "./tools/nuget/NuGet.exe" "install" "System.Net.Http" "-OutputDirectory" "tools" -verbosity quiet mono "./tools/nuget/NuGet.exe" "install" "Microsoft.Net.Http" "-OutputDirectory" "tools" -verbosity quiet mono ./tools/FAKE.Core/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx From 7c4185af8ea3b39422957d3b21f2e7e02a2cc9c6 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Wed, 16 Mar 2016 12:13:47 +0700 Subject: [PATCH 37/77] Now GetsCorrectUrl test accept any ApiOptions as valid. --- Octokit.Tests/Clients/UserEmailsClientTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Octokit.Tests/Clients/UserEmailsClientTests.cs b/Octokit.Tests/Clients/UserEmailsClientTests.cs index 462852cc..a66d5983 100644 --- a/Octokit.Tests/Clients/UserEmailsClientTests.cs +++ b/Octokit.Tests/Clients/UserEmailsClientTests.cs @@ -20,7 +20,7 @@ namespace Octokit.Tests.Clients connection.Received(1) .GetAll(Arg.Is(u => u.ToString() == "user/emails"), - Arg.Is(ApiOptions.None)); + Args.ApiOptions); } [Fact] From 8c03c90bfc80e2f1137cd9cea9c84128280c658e Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Wed, 16 Mar 2016 12:17:53 +0700 Subject: [PATCH 38/77] Tests have been rewritten in order to support "Received" check with ApiOptions parameter. --- Octokit.Tests/Reactive/ObservableUserEmailsClientTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Octokit.Tests/Reactive/ObservableUserEmailsClientTests.cs b/Octokit.Tests/Reactive/ObservableUserEmailsClientTests.cs index 267f3029..ea7dc688 100644 --- a/Octokit.Tests/Reactive/ObservableUserEmailsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableUserEmailsClientTests.cs @@ -28,8 +28,8 @@ namespace Octokit.Tests client.GetAll(); - github.Connection.Received(1).GetResponse>(_expectedUri, - Arg.Is>(dictionary => dictionary.Count == 0)); + github.Connection.Received(1).Get>(_expectedUri, + Arg.Is>(dictionary => dictionary.Count == 0), null); } [Fact] @@ -40,8 +40,8 @@ namespace Octokit.Tests client.GetAll(ApiOptions.None); - github.Connection.Received(1).GetResponse>(_expectedUri, - Arg.Is>(dictionary => dictionary.Count == 0)); + github.Connection.Received(1).Get>(_expectedUri, + Arg.Is>(dictionary => dictionary.Count == 0), null); } } From 833767cde41081e635c7177187d95af069f7b3c1 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Wed, 16 Mar 2016 12:19:23 +0700 Subject: [PATCH 39/77] An ApiExtensions.GetResponse overload has been removed. --- Octokit/Helpers/ApiExtensions.cs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Octokit/Helpers/ApiExtensions.cs b/Octokit/Helpers/ApiExtensions.cs index d25027e0..81b1ab8e 100644 --- a/Octokit/Helpers/ApiExtensions.cs +++ b/Octokit/Helpers/ApiExtensions.cs @@ -74,23 +74,6 @@ namespace Octokit return connection.Get(uri, null, null); } - /// - /// Gets the API resource at the specified URI. - /// - /// Type of the API resource to get. - /// The connection to use - /// URI of the API resource to get - /// Querystring parameters for the request - /// The API resource. - /// Thrown when an API error occurs. - public static Task> GetResponse(this IConnection connection, Uri uri, Dictionary parameters) - { - Ensure.ArgumentNotNull(connection, "connection"); - Ensure.ArgumentNotNull(uri, "uri"); - - return connection.Get(uri, parameters, null); - } - [Obsolete("Octokit's HTTP library now follows redirects by default - this API will be removed in a future release")] public static Task> GetRedirect(this IConnection connection, Uri uri) { From a1341c99bed07f15ad3adf319b03d11bda6ec9b0 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Wed, 16 Mar 2016 12:20:01 +0700 Subject: [PATCH 40/77] Unused commented test has been removed. --- .../ObservableUserEmailsClientTests.cs | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs index 66811c52..352fce92 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs @@ -54,28 +54,5 @@ namespace Octokit.Tests.Integration Assert.Equal(0, emails.Count); } - - //[IntegrationTest] - //public async Task ReturnsDistinctResultsBasedOnStartPage() - //{ - // var startOptions = new ApiOptions - // { - // PageSize = 5, - // PageCount = 1 - // }; - - // var firstPage = await _emailClient.GetAll(startOptions); - - // var skipStartOptions = new ApiOptions - // { - // PageSize = 5, - // PageCount = 1, - // StartPage = 2 - // }; - - // var secondPage = await _emailClient.GetAll(skipStartOptions); - - // Assert.Equal(firstPage[0].Email, secondPage[0].Email); - //} } } From 0fd34d9edc1dc00d622495dcdbacc0db2aaab03f Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Wed, 16 Mar 2016 12:23:38 +0700 Subject: [PATCH 41/77] Singleton ApiOptions instance has been removed. --- Octokit/Models/Request/ApiOptions.cs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/Octokit/Models/Request/ApiOptions.cs b/Octokit/Models/Request/ApiOptions.cs index e7ed1c40..af369d10 100644 --- a/Octokit/Models/Request/ApiOptions.cs +++ b/Octokit/Models/Request/ApiOptions.cs @@ -5,26 +5,11 @@ using System.Diagnostics; namespace Octokit { [DebuggerDisplay("{DebuggerDisplay,nq}")] - public class ApiOptions + public class ApiOptions { - private sealed class ApiOptionsSingleton - { - private static readonly Lazy _lazy = - new Lazy(() => new ApiOptions()); - - public static ApiOptions Instance - { - get { return _lazy.Value; } - } - - private ApiOptionsSingleton() - { - } - } - public static ApiOptions None { - get { return ApiOptionsSingleton.Instance; } + get { return new ApiOptions(); } } /// From e2cb829f2639eb5fd5e709416c0e9174c318282a Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Wed, 16 Mar 2016 12:24:30 +0700 Subject: [PATCH 42/77] Unused commented code has been removed. Minor changes. --- .../Clients/UserEmailsClientTests.cs | 30 ++----------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs b/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs index 0a1c5888..03c03f67 100644 --- a/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs @@ -17,17 +17,14 @@ namespace Octokit.Tests.Integration.Clients [IntegrationTest] public async Task CanGetEmail() { - var github = Helper.GetAuthenticatedClient(); - - var emails = await github.User.Email.GetAll(); + var emails = await _emailClient.GetAll(); Assert.NotEmpty(emails); } [IntegrationTest] public async Task CanGetEmailWithApiOptions() { - var github = Helper.GetAuthenticatedClient(); - var emails = await github.User.Email.GetAll(ApiOptions.None); + var emails = await _emailClient.GetAll(ApiOptions.None); Assert.NotEmpty(emails); } @@ -60,29 +57,6 @@ namespace Octokit.Tests.Integration.Clients Assert.Equal(0, emails.Count); } - //[IntegrationTest] - //public async Task ReturnsDistinctResultsBasedOnStartPage() - //{ - // var startOptions = new ApiOptions - // { - // PageSize = 5, - // PageCount = 1 - // }; - - // var firstPage = await _emailClient.GetAll(startOptions); - - // var skipStartOptions = new ApiOptions - // { - // PageSize = 5, - // PageCount = 1, - // StartPage = 2 - // }; - - // var secondPage = await _emailClient.GetAll(skipStartOptions); - - // Assert.Equal(firstPage[0].Email, secondPage[0].Email); - //} - const string testEmailAddress = "hahaha-not-a-real-email@foo.com"; [IntegrationTest(Skip = "this isn't passing in CI - i hate past me right now")] From 4c9057b00968fe5b68cbc7db03ded6dd0594874f Mon Sep 17 00:00:00 2001 From: Brendan Forster Date: Wed, 16 Mar 2016 13:08:06 +1100 Subject: [PATCH 43/77] bump FAKE to latest version --- build.cmd | 2 +- build.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build.cmd b/build.cmd index 393b128f..3e500ca4 100644 --- a/build.cmd +++ b/build.cmd @@ -1,7 +1,7 @@ @echo off "tools\nuget\nuget.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.1.0" -verbosity quiet -"tools\nuget\nuget.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" -verbosity quiet +"tools\nuget\nuget.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.22.2" -verbosity quiet "tools\nuget\nuget.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" -verbosity quiet "tools\nuget\nuget.exe" "install" "Octokit.CodeFormatter" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.0.0-preview" -Pre -verbosity quiet diff --git a/build.sh b/build.sh index f6294bc4..3c455fb4 100755 --- a/build.sh +++ b/build.sh @@ -4,14 +4,14 @@ then # use .Net "./tools/nuget/nuget.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.0.0" -verbosity quiet -"./tools/nuget/nuget.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" -verbosity quiet +"./tools/nuget/nuget.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.22.2" -verbosity quiet "./tools/nuget/nuget.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" -verbosity quiet "./tools/nuget/nuget.exe" "install" "Octokit.CodeFormatter" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.0.0-preview" -Pre -verbosity quiet packages/FAKE/tools/FAKE.exe $@ --fsiargs -d:MONO build.fsx else # use mono mono "./tools/nuget/NuGet.exe" "install" "xunit.runner.console" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "2.0.0" -verbosity quiet -mono "./tools/nuget/NuGet.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.4.2" -verbosity quiet +mono "./tools/nuget/NuGet.exe" "install" "FAKE.Core" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "4.22.2" -verbosity quiet mono "./tools/nuget/NuGet.exe" "install" "SourceLink.Fake" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.1.0" -verbosity quiet mono "./tools/nuget/NuGet.exe" "install" "Octokit.CodeFormatter" "-OutputDirectory" "tools" "-ExcludeVersion" "-version" "1.0.0-preview" -Pre -verbosity quiet mono "./tools/nuget/NuGet.exe" "install" "System.Net.Http" "-OutputDirectory" "tools" -verbosity quiet From 632dd6218bec026c1fb07cd974c957611eae2d63 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Wed, 16 Mar 2016 13:07:22 +0700 Subject: [PATCH 44/77] Some tests have been rewritten according to @shiftkey remarks. --- .../Clients/UserEmailsClientTests.cs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) diff --git a/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs b/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs index 03c03f67..12ac23e4 100644 --- a/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/UserEmailsClientTests.cs @@ -39,24 +39,9 @@ namespace Octokit.Tests.Integration.Clients var emails = await _emailClient.GetAll(options); - Assert.Equal(1, emails.Count); + Assert.NotEmpty(emails); } - - [IntegrationTest] - public async Task ReturnsCorrectCountOfEmailsWithStart() - { - var options = new ApiOptions - { - PageSize = 5, - PageCount = 1, - StartPage = 2 - }; - - var emails = await _emailClient.GetAll(options); - - Assert.Equal(0, emails.Count); - } - + const string testEmailAddress = "hahaha-not-a-real-email@foo.com"; [IntegrationTest(Skip = "this isn't passing in CI - i hate past me right now")] From fdcd0f95ec73ace5c4edb2201315e688e269be07 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Wed, 16 Mar 2016 13:08:57 +0700 Subject: [PATCH 45/77] Some integration tests have been rewritten according to @shiftkey remarks. --- .../Reactive/ObservableUserEmailsClientTests.cs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs index 352fce92..98a4cef4 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs @@ -37,22 +37,7 @@ namespace Octokit.Tests.Integration var emails = await _emailClient.GetAll(options).ToList(); - Assert.Equal(1, emails.Count); - } - - [IntegrationTest] - public async Task ReturnsCorrectCountOfEmailsWithStart() - { - var options = new ApiOptions - { - PageSize = 5, - PageCount = 1, - StartPage = 2 - }; - - var emails = await _emailClient.GetAll(options).ToList(); - - Assert.Equal(0, emails.Count); + Assert.NotEmpty(emails); } } } From 2ae5c1d6aa4fbaf07fa4bb93f8d80c4e72093070 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Wed, 16 Mar 2016 20:15:07 +0700 Subject: [PATCH 46/77] Name of test class have been changed in order to support naming conventions. --- Octokit.Tests/Clients/UserEmailsClientTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Octokit.Tests/Clients/UserEmailsClientTests.cs b/Octokit.Tests/Clients/UserEmailsClientTests.cs index a66d5983..34d31106 100644 --- a/Octokit.Tests/Clients/UserEmailsClientTests.cs +++ b/Octokit.Tests/Clients/UserEmailsClientTests.cs @@ -8,7 +8,7 @@ namespace Octokit.Tests.Clients { public class UserEmailsClientTests { - public class TheGetAllMethods + public class TheGetAllMethod { [Fact] public void GetsCorrectUrl() From 4b2f52f89b33c9ebf98ec4e310fb2f52bc7f80a9 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Wed, 16 Mar 2016 20:16:03 +0700 Subject: [PATCH 47/77] Extra whitespace have been removed. --- Octokit/Models/Request/ApiOptions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Octokit/Models/Request/ApiOptions.cs b/Octokit/Models/Request/ApiOptions.cs index af369d10..cdc3cbf3 100644 --- a/Octokit/Models/Request/ApiOptions.cs +++ b/Octokit/Models/Request/ApiOptions.cs @@ -5,7 +5,7 @@ using System.Diagnostics; namespace Octokit { [DebuggerDisplay("{DebuggerDisplay,nq}")] - public class ApiOptions + public class ApiOptions { public static ApiOptions None { From 5c835574b018e8c095264b117a9523abdbd2a41b Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Wed, 16 Mar 2016 20:23:21 +0700 Subject: [PATCH 48/77] ObservableUserEmailsClientTests have been rewritten in order to support project coding styles. --- .../Reactive/ObservableUserEmailsClientTests.cs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs index 98a4cef4..9e746299 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableUserEmailsClientTests.cs @@ -7,15 +7,19 @@ namespace Octokit.Tests.Integration { public class ObservableUserEmailsClientTests { - private readonly ObservableUserEmailsClient _emailClient - = new ObservableUserEmailsClient(Helper.GetAuthenticatedClient()); + readonly ObservableUserEmailsClient _emailClient; + + public ObservableUserEmailsClientTests() + { + var github = Helper.GetAuthenticatedClient(); + + _emailClient = new ObservableUserEmailsClient(github); + } [IntegrationTest] public async Task CanGetEmail() { - var client = new ObservableUserEmailsClient(Helper.GetAuthenticatedClient()); - - var email = await client.GetAll(); + var email = await _emailClient.GetAll(); Assert.NotNull(email); } @@ -36,7 +40,6 @@ namespace Octokit.Tests.Integration }; var emails = await _emailClient.GetAll(options).ToList(); - Assert.NotEmpty(emails); } } From 5dfe1968da206b85eef37fea588edd78bd819a57 Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Wed, 16 Mar 2016 21:59:33 +0000 Subject: [PATCH 49/77] Get the SHA-1 of a commit reference Updated RepositoryCommitsClients and unit/integration tests --- .../Clients/RepositoryCommitsClientTests.cs | 8 +++++ .../Clients/RepositoriesClientTests.cs | 30 +++++++++++++++++++ Octokit/Clients/IRepositoryCommitsClient.cs | 9 ++++++ Octokit/Clients/RepositoryCommitsClient.cs | 16 ++++++++++ 4 files changed, 63 insertions(+) diff --git a/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs index 95464917..7724e443 100644 --- a/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs @@ -87,6 +87,14 @@ public class RepositoryCommitsClientTests .Where(file => file.Status == "renamed") .All(file => string.IsNullOrEmpty(file.PreviousFileName) == false)); } + + [IntegrationTest] + public async Task CanGetSha1() + { + var sha1 = await _fixture.Sha1("octokit", "octokit.net", "master"); + + Assert.NotNull(sha1); + } } public class TestsWithNewRepository : IDisposable diff --git a/Octokit.Tests/Clients/RepositoriesClientTests.cs b/Octokit.Tests/Clients/RepositoriesClientTests.cs index e74cc97b..e1130eac 100644 --- a/Octokit.Tests/Clients/RepositoriesClientTests.cs +++ b/Octokit.Tests/Clients/RepositoriesClientTests.cs @@ -790,5 +790,35 @@ namespace Octokit.Tests.Clients await Assert.ThrowsAsync(() => client.EditBranch("owner", "repo", "", update)); } } + + public class TheSha1Method + { + [Fact] + public async Task EnsureNonNullArguments() + { + var client = new RepositoryCommitsClient(Substitute.For()); + + await Assert.ThrowsAsync(() => client.Sha1(null, "name", "reference")); + await Assert.ThrowsAsync(() => client.Sha1("", "name", "reference")); + + await Assert.ThrowsAsync(() => client.Sha1("owner", null, "reference")); + await Assert.ThrowsAsync(() => client.Sha1("owner", "", "reference")); + + await Assert.ThrowsAsync(() => client.Sha1("owner", "name", null)); + await Assert.ThrowsAsync(() => client.Sha1("owner", "name", "")); + } + + [Fact] + public void GetsCorrectUrl() + { + var connection = Substitute.For(); + var client = new RepositoryCommitsClient(connection); + + client.Sha1("owner", "name", "reference"); + + connection.Received() + .Get(Arg.Is(u => u.ToString() == "repos/owner/name/commits/reference"), null, AcceptHeaders.CommitReferenceSha1Preview); + } + } } } diff --git a/Octokit/Clients/IRepositoryCommitsClient.cs b/Octokit/Clients/IRepositoryCommitsClient.cs index f2b09f2b..27b846cb 100644 --- a/Octokit/Clients/IRepositoryCommitsClient.cs +++ b/Octokit/Clients/IRepositoryCommitsClient.cs @@ -50,5 +50,14 @@ namespace Octokit /// Used to filter list of commits returned /// Task> GetAll(string owner, string name, CommitRequest request); + + /// + /// Get the SHA-1 of a commit reference + /// + /// The owner of the repository + /// The name of the repository + /// The repository reference + /// + Task Sha1(string owner, string name, string reference); } } diff --git a/Octokit/Clients/RepositoryCommitsClient.cs b/Octokit/Clients/RepositoryCommitsClient.cs index 0e8ad1b2..c328cfb6 100644 --- a/Octokit/Clients/RepositoryCommitsClient.cs +++ b/Octokit/Clients/RepositoryCommitsClient.cs @@ -79,5 +79,21 @@ namespace Octokit return _apiConnection.GetAll(ApiUrls.RepositoryCommits(owner, name), request.ToParametersDictionary()); } + + /// + /// Get the SHA-1 of a commit reference + /// + /// The owner of the repository + /// The name of the repository + /// The repository reference + /// + public Task Sha1(string owner, string name, string reference) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNullOrEmptyString(reference, "reference"); + + return _apiConnection.Get(ApiUrls.RepositoryCommit(owner, name, reference), null, AcceptHeaders.CommitReferenceSha1Preview); + } } } \ No newline at end of file From 5270b3783e47ef73be9d4bbeb00f9d84b483dd4f Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Wed, 16 Mar 2016 22:01:45 +0000 Subject: [PATCH 50/77] Get the SHA-1 of a commit reference Added implementation for Reactive framework --- .../IObservableRepositoryCommitsClients.cs | 9 +++++++++ .../ObservableRepositoryCommitsClients.cs | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/Octokit.Reactive/Clients/IObservableRepositoryCommitsClients.cs b/Octokit.Reactive/Clients/IObservableRepositoryCommitsClients.cs index 927b34c0..aee95278 100644 --- a/Octokit.Reactive/Clients/IObservableRepositoryCommitsClients.cs +++ b/Octokit.Reactive/Clients/IObservableRepositoryCommitsClients.cs @@ -43,5 +43,14 @@ namespace Octokit.Reactive /// Used to filter list of commits returned /// IObservable GetAll(string owner, string name, CommitRequest request); + + /// + /// Get the SHA-1 of a commit reference + /// + /// The owner of the repository + /// The name of the repository + /// The repository reference + /// + IObservable Sha1(string owner, string name, string reference); } } diff --git a/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs b/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs index 7982485e..9aa5d2a6 100644 --- a/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs +++ b/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs @@ -73,5 +73,21 @@ namespace Octokit.Reactive return _connection.GetAndFlattenAllPages(ApiUrls.RepositoryCommits(owner, name), request.ToParametersDictionary()); } + + /// + /// Get the SHA-1 of a commit reference + /// + /// The owner of the repository + /// The name of the repository + /// The repository reference + /// + public IObservable Sha1(string owner, string name, string reference) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(name, "name"); + Ensure.ArgumentNotNullOrEmptyString(reference, "reference"); + + return _commit.Sha1(owner, name, reference).ToObservable(); + } } } From faa19af7485c01ff4d5517de8619e5c72768aed3 Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Wed, 16 Mar 2016 22:05:50 +0000 Subject: [PATCH 51/77] added sha preview header --- Octokit/Helpers/AcceptHeaders.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Octokit/Helpers/AcceptHeaders.cs b/Octokit/Helpers/AcceptHeaders.cs index d94e7e15..21c0047e 100644 --- a/Octokit/Helpers/AcceptHeaders.cs +++ b/Octokit/Helpers/AcceptHeaders.cs @@ -13,5 +13,7 @@ public const string ProtectedBranchesApiPreview = "application/vnd.github.loki-preview+json"; public const string StarCreationTimestamps = "application/vnd.github.v3.star+json"; + + public const string CommitReferenceSha1Preview = "application/vnd.github.chitauri-preview+sha"; } } From d9fd0b7e2ccbf9c65df1e3d2f123404ca805eacf Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Wed, 16 Mar 2016 23:30:41 +0000 Subject: [PATCH 52/77] Added verb to Sha1 method --- .../Clients/IObservableRepositoryCommitsClients.cs | 2 +- .../Clients/ObservableRepositoryCommitsClients.cs | 4 ++-- .../Clients/RepositoryCommitsClientTests.cs | 2 +- Octokit.Tests/Clients/RepositoriesClientTests.cs | 14 +++++++------- Octokit/Clients/IRepositoryCommitsClient.cs | 2 +- Octokit/Clients/RepositoryCommitsClient.cs | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Octokit.Reactive/Clients/IObservableRepositoryCommitsClients.cs b/Octokit.Reactive/Clients/IObservableRepositoryCommitsClients.cs index aee95278..29d4d55e 100644 --- a/Octokit.Reactive/Clients/IObservableRepositoryCommitsClients.cs +++ b/Octokit.Reactive/Clients/IObservableRepositoryCommitsClients.cs @@ -51,6 +51,6 @@ namespace Octokit.Reactive /// The name of the repository /// The repository reference /// - IObservable Sha1(string owner, string name, string reference); + IObservable GetSha1(string owner, string name, string reference); } } diff --git a/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs b/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs index 9aa5d2a6..629142d7 100644 --- a/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs +++ b/Octokit.Reactive/Clients/ObservableRepositoryCommitsClients.cs @@ -81,13 +81,13 @@ namespace Octokit.Reactive /// The name of the repository /// The repository reference /// - public IObservable Sha1(string owner, string name, string reference) + public IObservable GetSha1(string owner, string name, string reference) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(reference, "reference"); - return _commit.Sha1(owner, name, reference).ToObservable(); + return _commit.GetSha1(owner, name, reference).ToObservable(); } } } diff --git a/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs index 7724e443..1acbaa8c 100644 --- a/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs @@ -91,7 +91,7 @@ public class RepositoryCommitsClientTests [IntegrationTest] public async Task CanGetSha1() { - var sha1 = await _fixture.Sha1("octokit", "octokit.net", "master"); + var sha1 = await _fixture.GetSha1("octokit", "octokit.net", "master"); Assert.NotNull(sha1); } diff --git a/Octokit.Tests/Clients/RepositoriesClientTests.cs b/Octokit.Tests/Clients/RepositoriesClientTests.cs index e1130eac..52e325c7 100644 --- a/Octokit.Tests/Clients/RepositoriesClientTests.cs +++ b/Octokit.Tests/Clients/RepositoriesClientTests.cs @@ -798,14 +798,14 @@ namespace Octokit.Tests.Clients { var client = new RepositoryCommitsClient(Substitute.For()); - await Assert.ThrowsAsync(() => client.Sha1(null, "name", "reference")); - await Assert.ThrowsAsync(() => client.Sha1("", "name", "reference")); + await Assert.ThrowsAsync(() => client.GetSha1(null, "name", "reference")); + await Assert.ThrowsAsync(() => client.GetSha1("", "name", "reference")); - await Assert.ThrowsAsync(() => client.Sha1("owner", null, "reference")); - await Assert.ThrowsAsync(() => client.Sha1("owner", "", "reference")); + await Assert.ThrowsAsync(() => client.GetSha1("owner", null, "reference")); + await Assert.ThrowsAsync(() => client.GetSha1("owner", "", "reference")); - await Assert.ThrowsAsync(() => client.Sha1("owner", "name", null)); - await Assert.ThrowsAsync(() => client.Sha1("owner", "name", "")); + await Assert.ThrowsAsync(() => client.GetSha1("owner", "name", null)); + await Assert.ThrowsAsync(() => client.GetSha1("owner", "name", "")); } [Fact] @@ -814,7 +814,7 @@ namespace Octokit.Tests.Clients var connection = Substitute.For(); var client = new RepositoryCommitsClient(connection); - client.Sha1("owner", "name", "reference"); + client.GetSha1("owner", "name", "reference"); connection.Received() .Get(Arg.Is(u => u.ToString() == "repos/owner/name/commits/reference"), null, AcceptHeaders.CommitReferenceSha1Preview); diff --git a/Octokit/Clients/IRepositoryCommitsClient.cs b/Octokit/Clients/IRepositoryCommitsClient.cs index 27b846cb..bd486192 100644 --- a/Octokit/Clients/IRepositoryCommitsClient.cs +++ b/Octokit/Clients/IRepositoryCommitsClient.cs @@ -58,6 +58,6 @@ namespace Octokit /// The name of the repository /// The repository reference /// - Task Sha1(string owner, string name, string reference); + Task GetSha1(string owner, string name, string reference); } } diff --git a/Octokit/Clients/RepositoryCommitsClient.cs b/Octokit/Clients/RepositoryCommitsClient.cs index c328cfb6..e5fa9613 100644 --- a/Octokit/Clients/RepositoryCommitsClient.cs +++ b/Octokit/Clients/RepositoryCommitsClient.cs @@ -87,7 +87,7 @@ namespace Octokit /// The name of the repository /// The repository reference /// - public Task Sha1(string owner, string name, string reference) + public Task GetSha1(string owner, string name, string reference) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(name, "name"); From 64cea23bb78026dce03479a7046b6c803d93e6f3 Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Thu, 17 Mar 2016 07:43:12 +0000 Subject: [PATCH 53/77] Added integration test to verify a new repository - Create repository - Call GetSha1 - Call it a second time - Verify the two responses are equal --- .../Clients/RepositoryCommitsClientTests.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs index 1acbaa8c..349b83c8 100644 --- a/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs @@ -166,6 +166,17 @@ public class RepositoryCommitsClientTests Assert.Equal(0, result.BehindBy); } + [IntegrationTest] + public async Task GetShaFromRepository() + { + await CreateTheWorld(); + + var firstSha1 = await _fixture.GetSha1(Helper.UserName, _context.RepositoryName, "master"); + var secondSha1 = await _fixture.GetSha1(Helper.UserName, _context.RepositoryName, "master"); + + Assert.Equal(firstSha1, secondSha1); + } + async Task CreateTheWorld() { var master = await _github.Git.Reference.Get(Helper.UserName, _context.RepositoryName, "heads/master"); From 705b93913ec9845c65844bc8379110fe90d654aa Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Thu, 17 Mar 2016 07:48:33 +0000 Subject: [PATCH 54/77] Fixed wording & split out unit tests - One unit test for NonNullArguments - Another unit test for NonEMptyArguments --- .../Clients/RepositoriesClientTests.cs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Octokit.Tests/Clients/RepositoriesClientTests.cs b/Octokit.Tests/Clients/RepositoriesClientTests.cs index 52e325c7..417c3a56 100644 --- a/Octokit.Tests/Clients/RepositoriesClientTests.cs +++ b/Octokit.Tests/Clients/RepositoriesClientTests.cs @@ -794,18 +794,24 @@ namespace Octokit.Tests.Clients public class TheSha1Method { [Fact] - public async Task EnsureNonNullArguments() + public async void EnsuresNonNullArguments() + { + var client = new RepositoryCommitsClient(Substitute.For()); + + await Assert.ThrowsAsync(() => client.GetSha1("", "name", "reference")); + await Assert.ThrowsAsync(() => client.GetSha1("owner", "", "reference")); + await Assert.ThrowsAsync(() => client.GetSha1("owner", "name", "")); + + } + + [Fact] + public async Task EnsuresNonEmptyArguments() { var client = new RepositoryCommitsClient(Substitute.For()); await Assert.ThrowsAsync(() => client.GetSha1(null, "name", "reference")); - await Assert.ThrowsAsync(() => client.GetSha1("", "name", "reference")); - await Assert.ThrowsAsync(() => client.GetSha1("owner", null, "reference")); - await Assert.ThrowsAsync(() => client.GetSha1("owner", "", "reference")); - await Assert.ThrowsAsync(() => client.GetSha1("owner", "name", null)); - await Assert.ThrowsAsync(() => client.GetSha1("owner", "name", "")); } [Fact] From 0fa9966fa77350b1939ff80648c4a278f5e0f30c Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Thu, 17 Mar 2016 07:52:19 +0000 Subject: [PATCH 55/77] Changed integration test name --- .../Clients/RepositoryCommitsClientTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs index 349b83c8..bac6865b 100644 --- a/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs @@ -167,7 +167,7 @@ public class RepositoryCommitsClientTests } [IntegrationTest] - public async Task GetShaFromRepository() + public async Task GetSha1FromRepository() { await CreateTheWorld(); From 8f548254f1fcd9b7369f70b289113006710f6f3b Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Thu, 17 Mar 2016 15:34:01 +0700 Subject: [PATCH 56/77] New overloaded method Task> GetAll(ApiOptions options) has been added on IAuthorizationsClient and implemented on AuthorizationsClient. --- Octokit/Clients/AuthorizationsClient.cs | 22 +++++++++++++++++++++- Octokit/Clients/IAuthorizationsClient.cs | 17 +++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/Octokit/Clients/AuthorizationsClient.cs b/Octokit/Clients/AuthorizationsClient.cs index 84b41b78..09b8bf5a 100644 --- a/Octokit/Clients/AuthorizationsClient.cs +++ b/Octokit/Clients/AuthorizationsClient.cs @@ -36,7 +36,27 @@ namespace Octokit /// A list of s. public Task> GetAll() { - return ApiConnection.GetAll(ApiUrls.Authorizations(), ApiOptions.None); + return GetAll(ApiOptions.None); + } + + /// + /// Gets all s for the authenticated user. + /// + /// + /// This method requires authentication. + /// See the API documentation for more information. + /// + /// Options for changing the API response + /// + /// Thrown when the current user does not have permission to make the request. + /// + /// Thrown when a general API error occurs. + /// A list of s. + public Task> GetAll(ApiOptions options) + { + Ensure.ArgumentNotNull(options, "options"); + + return ApiConnection.GetAll(ApiUrls.Authorizations(), options); } /// diff --git a/Octokit/Clients/IAuthorizationsClient.cs b/Octokit/Clients/IAuthorizationsClient.cs index 81b8db48..72406ad3 100644 --- a/Octokit/Clients/IAuthorizationsClient.cs +++ b/Octokit/Clients/IAuthorizationsClient.cs @@ -31,6 +31,23 @@ namespace Octokit Justification = "It's an API call, so it's not a property.")] Task> GetAll(); + /// + /// Gets all s for the authenticated user. + /// + /// + /// This method requires authentication. + /// See the API documentation for more information. + /// + /// Options for changing the API response + /// + /// Thrown when the current user does not have permission to make the request. + /// + /// Thrown when a general API error occurs. + /// A list of s. + [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", + Justification = "It's an API call, so it's not a property.")] + Task> GetAll(ApiOptions options); + /// /// Gets a specific for the authenticated user. /// From 5b166ebc4269aac07d6c1e4b6bc7486a8b691b6e Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Thu, 17 Mar 2016 15:34:36 +0700 Subject: [PATCH 57/77] New overloaded method IObservable GetAll(ApiOptions options) has been added on IObservableAuthorizationsClient and implemented on ObservableAuthorizationsClient. --- .../Clients/IObservableAuthorizationsClient.cs | 13 +++++++++++++ .../Clients/ObservableAuthorizationsClient.cs | 18 +++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/Octokit.Reactive/Clients/IObservableAuthorizationsClient.cs b/Octokit.Reactive/Clients/IObservableAuthorizationsClient.cs index c72986fd..88382ccc 100644 --- a/Octokit.Reactive/Clients/IObservableAuthorizationsClient.cs +++ b/Octokit.Reactive/Clients/IObservableAuthorizationsClient.cs @@ -18,6 +18,19 @@ namespace Octokit.Reactive Justification = "It's an API call, so it's not a property.")] IObservable GetAll(); + /// + /// Get all s for the authenticated user. This method requires basic auth. + /// + /// + /// See API documentation for more + /// details. + /// + /// Options for changing the API response + /// An + [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", + Justification = "It's an API call, so it's not a property.")] + IObservable GetAll(ApiOptions options); + /// /// Get a specific for the authenticated user. This method requires basic auth. /// diff --git a/Octokit.Reactive/Clients/ObservableAuthorizationsClient.cs b/Octokit.Reactive/Clients/ObservableAuthorizationsClient.cs index 9d5127b7..c6d4de6a 100644 --- a/Octokit.Reactive/Clients/ObservableAuthorizationsClient.cs +++ b/Octokit.Reactive/Clients/ObservableAuthorizationsClient.cs @@ -28,7 +28,23 @@ namespace Octokit.Reactive /// An public IObservable GetAll() { - return _connection.GetAndFlattenAllPages(ApiUrls.Authorizations()); + return GetAll(ApiOptions.None); + } + + /// + /// Get all s for the authenticated user. This method requires basic auth. + /// + /// + /// See API documentation for more + /// details. + /// + /// Options for changing the API response + /// An + public IObservable GetAll(ApiOptions options) + { + Ensure.ArgumentNotNull(options, "options"); + + return _connection.GetAndFlattenAllPages(ApiUrls.Authorizations(), options); } /// From 6d1634c843df9e2853e12b32d6b3b888b500d173 Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Thu, 17 Mar 2016 08:35:39 +0000 Subject: [PATCH 58/77] Updated test to compare sha1 from reference with the GetSha1 method - CreateTheWorld now returns a Task - This reference is compared with client.GetSha1 --- .../Clients/RepositoryCommitsClientTests.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs index bac6865b..74c4e43e 100644 --- a/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/RepositoryCommitsClientTests.cs @@ -169,15 +169,14 @@ public class RepositoryCommitsClientTests [IntegrationTest] public async Task GetSha1FromRepository() { - await CreateTheWorld(); + var reference = await CreateTheWorld(); - var firstSha1 = await _fixture.GetSha1(Helper.UserName, _context.RepositoryName, "master"); - var secondSha1 = await _fixture.GetSha1(Helper.UserName, _context.RepositoryName, "master"); + var sha1 = await _fixture.GetSha1(Helper.UserName, _context.RepositoryName, "master"); - Assert.Equal(firstSha1, secondSha1); + Assert.Equal(reference.Object.Sha, sha1); } - async Task CreateTheWorld() + async Task CreateTheWorld() { var master = await _github.Git.Reference.Get(Helper.UserName, _context.RepositoryName, "heads/master"); @@ -193,7 +192,7 @@ public class RepositoryCommitsClientTests var newFeature = await CreateCommit("this is the commit to merge into the pull request", featureBranchTree.Sha, newMaster.Sha); // create branch - await _github.Git.Reference.Create(Helper.UserName, _context.RepositoryName, new NewReference("refs/heads/my-branch", newFeature.Sha)); + return await _github.Git.Reference.Create(Helper.UserName, _context.RepositoryName, new NewReference("refs/heads/my-branch", newFeature.Sha)); } async Task CreateTree(IDictionary treeContents) From fb8acd3d1aced612e005b53bc81c6c1c08863c3f Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Thu, 17 Mar 2016 15:37:01 +0700 Subject: [PATCH 59/77] New unit tests have been added to check AuthorizationsClient implementation. --- Octokit.Tests/Clients/AuthorizationsClientTests.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Octokit.Tests/Clients/AuthorizationsClientTests.cs b/Octokit.Tests/Clients/AuthorizationsClientTests.cs index 5aad42ef..6a508582 100644 --- a/Octokit.Tests/Clients/AuthorizationsClientTests.cs +++ b/Octokit.Tests/Clients/AuthorizationsClientTests.cs @@ -37,6 +37,19 @@ namespace Octokit.Tests.Clients Arg.Is(u => u.ToString() == "authorizations"), Args.ApiOptions); } + + [Fact] + public void GetsAListOfAuthorizationsWithApiOptions() + { + var client = Substitute.For(); + var authEndpoint = new AuthorizationsClient(client); + + authEndpoint.GetAll(ApiOptions.None); + + client.Received().GetAll( + Arg.Is(u => u.ToString() == "authorizations"), + Args.ApiOptions); + } } public class TheGetMethod From f8c776485636efb77fb48d060fa39ce18efdb679 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Thu, 17 Mar 2016 15:37:23 +0700 Subject: [PATCH 60/77] New unit tests have been added to check ObservableAuthorizationsClient implementation. --- Octokit.Tests/Octokit.Tests.csproj | 1 + .../ObservableAuthorizationsClientTests.cs | 48 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 Octokit.Tests/Reactive/ObservableAuthorizationsClientTests.cs diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj index 5c6484c3..cb994ec6 100644 --- a/Octokit.Tests/Octokit.Tests.csproj +++ b/Octokit.Tests/Octokit.Tests.csproj @@ -198,6 +198,7 @@ + diff --git a/Octokit.Tests/Reactive/ObservableAuthorizationsClientTests.cs b/Octokit.Tests/Reactive/ObservableAuthorizationsClientTests.cs new file mode 100644 index 00000000..5aa84daf --- /dev/null +++ b/Octokit.Tests/Reactive/ObservableAuthorizationsClientTests.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using NSubstitute; +using Octokit.Reactive; +using Xunit; + +namespace Octokit.Tests.Reactive +{ + public class ObservableAuthorizationsClientTests + { + public class TheGetAllMethod + { + [Fact] + public void GetsCorrectUrl() + { + var client = Substitute.For(); + var authEndpoint = new ObservableAuthorizationsClient(client); + + authEndpoint.GetAll(); + + client.Connection.Received(1).Get>(Arg.Is(u => u.ToString() == "authorizations"), + Arg.Is>(dictionary => dictionary.Count == 0), null); + } + + [Fact] + public void GetsCorrectUrlWithApiOption() + { + var client = Substitute.For(); + var authEndpoint = new ObservableAuthorizationsClient(client); + + authEndpoint.GetAll(ApiOptions.None); + + client.Connection.Received(1).Get>(Arg.Is(u => u.ToString() == "authorizations"), + Arg.Is>(dictionary => dictionary.Count == 0), null); + } + } + + public class TheCtor + { + [Fact] + public void EnsuresNonNullArguments() + { + Assert.Throws( + () => new ObservableAuthorizationsClient(null)); + } + } + } +} From ebf2792c25df19c59724c1d9061d1cbd1d02e8b0 Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Thu, 17 Mar 2016 08:47:06 +0000 Subject: [PATCH 61/77] Remove async from void --- Octokit.Tests/Clients/RepositoriesClientTests.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Octokit.Tests/Clients/RepositoriesClientTests.cs b/Octokit.Tests/Clients/RepositoriesClientTests.cs index 417c3a56..583db072 100644 --- a/Octokit.Tests/Clients/RepositoriesClientTests.cs +++ b/Octokit.Tests/Clients/RepositoriesClientTests.cs @@ -794,14 +794,13 @@ namespace Octokit.Tests.Clients public class TheSha1Method { [Fact] - public async void EnsuresNonNullArguments() + public void EnsuresNonNullArguments() { var client = new RepositoryCommitsClient(Substitute.For()); - await Assert.ThrowsAsync(() => client.GetSha1("", "name", "reference")); - await Assert.ThrowsAsync(() => client.GetSha1("owner", "", "reference")); - await Assert.ThrowsAsync(() => client.GetSha1("owner", "name", "")); - + Assert.ThrowsAsync(() => client.GetSha1("", "name", "reference")); + Assert.ThrowsAsync(() => client.GetSha1("owner", "", "reference")); + Assert.ThrowsAsync(() => client.GetSha1("owner", "name", "")); } [Fact] From 5be778b0f01b21a424b1e622d2e5cefe4596c476 Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Thu, 17 Mar 2016 08:53:12 +0000 Subject: [PATCH 62/77] Modified the test class name to reflect the method under test --- Octokit.Tests/Clients/RepositoriesClientTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Octokit.Tests/Clients/RepositoriesClientTests.cs b/Octokit.Tests/Clients/RepositoriesClientTests.cs index 583db072..dab4474d 100644 --- a/Octokit.Tests/Clients/RepositoriesClientTests.cs +++ b/Octokit.Tests/Clients/RepositoriesClientTests.cs @@ -791,7 +791,7 @@ namespace Octokit.Tests.Clients } } - public class TheSha1Method + public class TheGetSha1Method { [Fact] public void EnsuresNonNullArguments() From 6009cc9720ba902431e6380e741d199f4b308a03 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Thu, 17 Mar 2016 17:06:17 +0700 Subject: [PATCH 63/77] Documentation of methods have been updated. --- Octokit.Reactive/Clients/IObservableAuthorizationsClient.cs | 4 ++-- Octokit.Reactive/Clients/ObservableAuthorizationsClient.cs | 4 ++-- Octokit/Clients/AuthorizationsClient.cs | 4 ++-- Octokit/Clients/IAuthorizationsClient.cs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Octokit.Reactive/Clients/IObservableAuthorizationsClient.cs b/Octokit.Reactive/Clients/IObservableAuthorizationsClient.cs index 88382ccc..0e5083fd 100644 --- a/Octokit.Reactive/Clients/IObservableAuthorizationsClient.cs +++ b/Octokit.Reactive/Clients/IObservableAuthorizationsClient.cs @@ -13,7 +13,7 @@ namespace Octokit.Reactive /// See API documentation for more /// details. /// - /// An + /// A list of s for the authenticated user. [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "It's an API call, so it's not a property.")] IObservable GetAll(); @@ -26,7 +26,7 @@ namespace Octokit.Reactive /// details. /// /// Options for changing the API response - /// An + /// A list of s for the authenticated user. [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "It's an API call, so it's not a property.")] IObservable GetAll(ApiOptions options); diff --git a/Octokit.Reactive/Clients/ObservableAuthorizationsClient.cs b/Octokit.Reactive/Clients/ObservableAuthorizationsClient.cs index c6d4de6a..d5cd1989 100644 --- a/Octokit.Reactive/Clients/ObservableAuthorizationsClient.cs +++ b/Octokit.Reactive/Clients/ObservableAuthorizationsClient.cs @@ -25,7 +25,7 @@ namespace Octokit.Reactive /// See API documentation for more /// details. /// - /// An + /// A list of s for the authenticated user. public IObservable GetAll() { return GetAll(ApiOptions.None); @@ -39,7 +39,7 @@ namespace Octokit.Reactive /// details. /// /// Options for changing the API response - /// An + /// A list of s for the authenticated user. public IObservable GetAll(ApiOptions options) { Ensure.ArgumentNotNull(options, "options"); diff --git a/Octokit/Clients/AuthorizationsClient.cs b/Octokit/Clients/AuthorizationsClient.cs index 09b8bf5a..92a4cf4b 100644 --- a/Octokit/Clients/AuthorizationsClient.cs +++ b/Octokit/Clients/AuthorizationsClient.cs @@ -33,7 +33,7 @@ namespace Octokit /// Thrown when the current user does not have permission to make the request. /// /// Thrown when a general API error occurs. - /// A list of s. + /// A list of s for the authenticated user. public Task> GetAll() { return GetAll(ApiOptions.None); @@ -51,7 +51,7 @@ namespace Octokit /// Thrown when the current user does not have permission to make the request. /// /// Thrown when a general API error occurs. - /// A list of s. + /// A list of s for the authenticated user. public Task> GetAll(ApiOptions options) { Ensure.ArgumentNotNull(options, "options"); diff --git a/Octokit/Clients/IAuthorizationsClient.cs b/Octokit/Clients/IAuthorizationsClient.cs index 72406ad3..c78a048d 100644 --- a/Octokit/Clients/IAuthorizationsClient.cs +++ b/Octokit/Clients/IAuthorizationsClient.cs @@ -26,7 +26,7 @@ namespace Octokit /// Thrown when the current user does not have permission to make the request. /// /// Thrown when a general API error occurs. - /// A list of s. + /// A list of s for the authenticated user. [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "It's an API call, so it's not a property.")] Task> GetAll(); @@ -43,7 +43,7 @@ namespace Octokit /// Thrown when the current user does not have permission to make the request. /// /// Thrown when a general API error occurs. - /// A list of s. + /// A list of s for the authenticated user. [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate", Justification = "It's an API call, so it's not a property.")] Task> GetAll(ApiOptions options); From db8738b6750967e2d0894259fcc2e6b5d620b58c Mon Sep 17 00:00:00 2001 From: Prayank Mathur Date: Thu, 17 Mar 2016 11:55:44 +0530 Subject: [PATCH 64/77] Corrected TheUpdateMethod.EnsureArgumentsNotNull() --- .../Enterprise/IObservableEnterpriseLdapClient.cs | 2 +- .../Enterprise/ObservableEnterpriseLdapClient.cs | 2 +- .../Enterprise/EnterpriseLdapClientTests.cs | 2 +- .../Clients/RepositoriesClientTests.cs | 2 +- .../Clients/UserAdministrationClientTests.cs | 4 ++-- Octokit.Tests.Integration/EnterpriseHelper.cs | 8 ++++---- .../ObservableEnterpriseLdapClientTests.cs | 4 ++-- .../Reactive/ObservableUserKeysClientTests.cs | 2 +- .../EnterpriseOrganizationClientTests.cs | 2 +- Octokit.Tests/Clients/RepositoriesClientTests.cs | 1 - .../Clients/RepositoryContentsClientTests.cs | 2 +- .../Clients/UserAdministrationClientTests.cs | 8 ++++---- .../ObservableEnterpriseLdapClientTests.cs | 14 +++++++------- .../ObservableEnterpriseOrganizationClientTests.cs | 6 +++--- ...bservableEnterpriseSearchIndexingClientTests.cs | 2 +- .../Reactive/ObservableIssuesClientTests.cs | 10 +++++----- .../ObservableUserAdministrationClientTests.cs | 2 +- Octokit/Clients/Enterprise/EnterpriseLdapClient.cs | 6 +++--- .../Enterprise/EnterpriseSearchIndexingClient.cs | 2 +- Octokit/Clients/UserAdministrationClient.cs | 2 +- Octokit/Http/IApiConnection.cs | 2 +- Octokit/Models/Request/CreateFileRequest.cs | 2 +- SolutionInfo.cs | 6 ++++-- 23 files changed, 47 insertions(+), 46 deletions(-) diff --git a/Octokit.Reactive/Clients/Enterprise/IObservableEnterpriseLdapClient.cs b/Octokit.Reactive/Clients/Enterprise/IObservableEnterpriseLdapClient.cs index d5f4bd1f..1791d57e 100644 --- a/Octokit.Reactive/Clients/Enterprise/IObservableEnterpriseLdapClient.cs +++ b/Octokit.Reactive/Clients/Enterprise/IObservableEnterpriseLdapClient.cs @@ -33,7 +33,7 @@ namespace Octokit.Reactive /// The username to sync LDAP mapping /// The of the queue request. IObservable QueueSyncUserMapping(string userName); - + /// /// Update the LDAP mapping for a team on a GitHub Enterprise appliance (must be Site Admin user). /// diff --git a/Octokit.Reactive/Clients/Enterprise/ObservableEnterpriseLdapClient.cs b/Octokit.Reactive/Clients/Enterprise/ObservableEnterpriseLdapClient.cs index f096e496..0a037406 100644 --- a/Octokit.Reactive/Clients/Enterprise/ObservableEnterpriseLdapClient.cs +++ b/Octokit.Reactive/Clients/Enterprise/ObservableEnterpriseLdapClient.cs @@ -49,7 +49,7 @@ namespace Octokit.Reactive { return _client.QueueSyncUserMapping(userName).ToObservable(); } - + /// /// Update the LDAP mapping for a team on a GitHub Enterprise appliance (must be Site Admin user). /// diff --git a/Octokit.Tests.Integration/Clients/Enterprise/EnterpriseLdapClientTests.cs b/Octokit.Tests.Integration/Clients/Enterprise/EnterpriseLdapClientTests.cs index edbca496..5fbac372 100644 --- a/Octokit.Tests.Integration/Clients/Enterprise/EnterpriseLdapClientTests.cs +++ b/Octokit.Tests.Integration/Clients/Enterprise/EnterpriseLdapClientTests.cs @@ -19,7 +19,7 @@ public class EnterpriseLdapClientTests : IDisposable public EnterpriseLdapClientTests() { _github = EnterpriseHelper.GetAuthenticatedClient(); - + NewTeam newTeam = new NewTeam(Helper.MakeNameWithTimestamp("test-team")) { Description = "Test Team" }; _context = _github.CreateEnterpriseTeamContext(EnterpriseHelper.Organization, newTeam).Result; } diff --git a/Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs index 78247ebc..ebd29eb2 100644 --- a/Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs +++ b/Octokit.Tests.Integration/Clients/RepositoriesClientTests.cs @@ -447,7 +447,7 @@ public class RepositoriesClientTests var repoName = Helper.MakeNameWithTimestamp("repo-to-delete"); await github.Repository.Create(new NewRepository(repoName)); - + await github.Repository.Delete(Helper.UserName, repoName); } } diff --git a/Octokit.Tests.Integration/Clients/UserAdministrationClientTests.cs b/Octokit.Tests.Integration/Clients/UserAdministrationClientTests.cs index 321017ac..b9c049ab 100644 --- a/Octokit.Tests.Integration/Clients/UserAdministrationClientTests.cs +++ b/Octokit.Tests.Integration/Clients/UserAdministrationClientTests.cs @@ -95,7 +95,7 @@ namespace Octokit.Tests.Integration.Clients Assert.NotNull(token); Assert.True( - token.Scopes.Count() == 1 && + token.Scopes.Count() == 1 && token.Scopes.All(s => s == "public_repo")); // Delete Impersonation token @@ -187,7 +187,7 @@ namespace Octokit.Tests.Integration.Clients { // Ensure user has a key //var key = await _github.User.Keys.Create(new NewPublicKey("title", "key")); - + // Delete key //await _github.User.Administration.DeletePublicKey(key.Id); } diff --git a/Octokit.Tests.Integration/EnterpriseHelper.cs b/Octokit.Tests.Integration/EnterpriseHelper.cs index 7e03a604..baf16c9a 100644 --- a/Octokit.Tests.Integration/EnterpriseHelper.cs +++ b/Octokit.Tests.Integration/EnterpriseHelper.cs @@ -55,7 +55,7 @@ namespace Octokit.Tests.Integration string enabled = Environment.GetEnvironmentVariable("OCTOKIT_GHE_ENABLED"); return !String.IsNullOrWhiteSpace(enabled); }); - + static readonly Lazy _gitHubEnterpriseUrl = new Lazy(() => { string uri = Environment.GetEnvironmentVariable("OCTOKIT_GHE_URL"); @@ -76,7 +76,7 @@ namespace Octokit.Tests.Integration public static string UserName { get; private set; } public static string Organization { get; private set; } - + /// /// These credentials should be set to a test GitHub account using the powershell script configure-integration-tests.ps1 /// @@ -88,8 +88,8 @@ namespace Octokit.Tests.Integration public static bool IsGitHubEnterpriseEnabled { get { return _gitHubEnterpriseEnabled.Value; } } - public static Uri GitHubEnterpriseUrl { get { return _gitHubEnterpriseUrl.Value; } } - + public static Uri GitHubEnterpriseUrl { get { return _gitHubEnterpriseUrl.Value; } } + public static bool IsUsingToken { get diff --git a/Octokit.Tests.Integration/Reactive/Enterprise/ObservableEnterpriseLdapClientTests.cs b/Octokit.Tests.Integration/Reactive/Enterprise/ObservableEnterpriseLdapClientTests.cs index dde932d8..948a52a6 100644 --- a/Octokit.Tests.Integration/Reactive/Enterprise/ObservableEnterpriseLdapClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/Enterprise/ObservableEnterpriseLdapClientTests.cs @@ -14,10 +14,10 @@ namespace Octokit.Tests.Integration readonly string _testUser = "test-user"; readonly string _distinguishedNameUser = "uid=test-user,ou=users,dc=company,dc=com"; - + readonly EnterpriseTeamContext _context; readonly string _distinguishedNameTeam = "cn=test-team,ou=groups,dc=company,dc=com"; - + public ObservableEnterpriseLdapClientTests() { _github = new ObservableGitHubClient(EnterpriseHelper.GetAuthenticatedClient()); diff --git a/Octokit.Tests.Integration/Reactive/ObservableUserKeysClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableUserKeysClientTests.cs index cf56317b..4e48c55f 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableUserKeysClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableUserKeysClientTests.cs @@ -68,7 +68,7 @@ namespace Octokit.Tests.Integration.Clients // Create a key string keyTitle = "title"; string keyData = "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAjo4DqFKg8dOxiz/yjypmN1A4itU5QOStyYrfOFuTinesU/2zm9hqxJ5BctIhgtSHJ5foxkhsiBji0qrUg73Q25BThgNg8YFE8njr4EwjmqSqW13akx/zLV0GFFU0SdJ2F6rBldhi93lMnl0ex9swBqa3eLTY8C+HQGBI6MQUMw+BKp0oFkz87Kv+Pfp6lt/Uo32ejSxML1PT5hTH5n+fyl0ied+sRmPGZWmWoHB5Bc9mox7lB6I6A/ZgjtBqbEEn4HQ2/6vp4ojKfSgA4Mm7XMu0bZzX0itKjH1QWD9Lr5apV1cmZsj49Xf8SHucTtH+bq98hb8OOXEGFzplwsX2MQ=="; - + var observable = _github.User.Keys.Create(new NewPublicKey(keyTitle, keyData)); var key = await observable; diff --git a/Octokit.Tests/Clients/Enterprise/EnterpriseOrganizationClientTests.cs b/Octokit.Tests/Clients/Enterprise/EnterpriseOrganizationClientTests.cs index 4b078b12..b3c815b5 100644 --- a/Octokit.Tests/Clients/Enterprise/EnterpriseOrganizationClientTests.cs +++ b/Octokit.Tests/Clients/Enterprise/EnterpriseOrganizationClientTests.cs @@ -17,7 +17,7 @@ namespace Octokit.Tests.Clients string expectedUri = "admin/organizations"; client.Create(new NewOrganization("org", "admin", "org name")); - + connection.Received().Post(Arg.Is(u => u.ToString() == expectedUri), Arg.Any()); } diff --git a/Octokit.Tests/Clients/RepositoriesClientTests.cs b/Octokit.Tests/Clients/RepositoriesClientTests.cs index e74cc97b..0dadb511 100644 --- a/Octokit.Tests/Clients/RepositoriesClientTests.cs +++ b/Octokit.Tests/Clients/RepositoriesClientTests.cs @@ -404,7 +404,6 @@ namespace Octokit.Tests.Clients var request = new RepositoryRequest { - Affiliation = RepositoryAffiliation.Owner, Sort = RepositorySort.FullName }; diff --git a/Octokit.Tests/Clients/RepositoryContentsClientTests.cs b/Octokit.Tests/Clients/RepositoryContentsClientTests.cs index 0e59b533..5dea73d8 100644 --- a/Octokit.Tests/Clients/RepositoryContentsClientTests.cs +++ b/Octokit.Tests/Clients/RepositoryContentsClientTests.cs @@ -100,7 +100,7 @@ namespace Octokit.Tests.Clients string expectedUri = "repos/org/repo/contents/path/to/file"; client.CreateFile("org", "repo", "path/to/file", new CreateFileRequest("message", "myfilecontents", "mybranch")); - + connection.Received().Put(Arg.Is(u => u.ToString() == expectedUri), Arg.Any()); } diff --git a/Octokit.Tests/Clients/UserAdministrationClientTests.cs b/Octokit.Tests/Clients/UserAdministrationClientTests.cs index 4174b06b..4712b24b 100644 --- a/Octokit.Tests/Clients/UserAdministrationClientTests.cs +++ b/Octokit.Tests/Clients/UserAdministrationClientTests.cs @@ -29,7 +29,7 @@ namespace Octokit.Tests.Clients client.Create(new NewUser("name", "email@company.com")); connection.Received().Post( - Arg.Is(u => u.ToString() == expectedUri), + Arg.Is(u => u.ToString() == expectedUri), Arg.Any()); } @@ -38,13 +38,13 @@ namespace Octokit.Tests.Clients { var connection = Substitute.For(); var client = new UserAdministrationClient(connection); - + client.Create(new NewUser("name", "email@company.com")); connection.Received().Post( - Arg.Any(), + Arg.Any(), Arg.Is(a => - a.Login == "name" && + a.Login == "name" && a.Email == "email@company.com")); } } diff --git a/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseLdapClientTests.cs b/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseLdapClientTests.cs index a1fc9769..ec8de495 100644 --- a/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseLdapClientTests.cs +++ b/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseLdapClientTests.cs @@ -10,7 +10,7 @@ namespace Octokit.Tests public class TheUpdateUserMappingMethod { readonly string _distinguishedName = "uid=test-user,ou=users,dc=company,dc=com"; - + [Fact] public void CallsIntoClient() { @@ -20,11 +20,11 @@ namespace Octokit.Tests client.UpdateUserMapping("test-user", new NewLdapMapping(_distinguishedName)); github.Enterprise.Ldap.Received(1).UpdateUserMapping( Arg.Is(a => a == "test-user"), - Arg.Is(a => + Arg.Is(a => a.LdapDistinguishedName == _distinguishedName)); } } - + public class TheQueueSyncUserMappingMethod { [Fact] @@ -38,11 +38,11 @@ namespace Octokit.Tests Arg.Is(a => a == "test-user")); } } - + public class TheUpdateTeamMappingMethod { readonly string _distinguishedName = "cn=test-team,ou=groups,dc=company,dc=com"; - + [Fact] public void CallsIntoClient() { @@ -52,11 +52,11 @@ namespace Octokit.Tests client.UpdateTeamMapping(1, new NewLdapMapping(_distinguishedName)); github.Enterprise.Ldap.Received(1).UpdateTeamMapping( Arg.Is(a => a == 1), - Arg.Is(a => + Arg.Is(a => a.LdapDistinguishedName == _distinguishedName)); } } - + public class TheQueueSyncTeamMappingMethod { [Fact] diff --git a/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseOrganizationClientTests.cs b/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseOrganizationClientTests.cs index 47046e05..5e849d84 100644 --- a/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseOrganizationClientTests.cs +++ b/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseOrganizationClientTests.cs @@ -17,9 +17,9 @@ namespace Octokit.Tests client.Create(new NewOrganization("org", "admin", "org name")); github.Enterprise.Organization.Received(1).Create( - Arg.Is(a => - a.Login == "org" - && a.Admin == "admin" + Arg.Is(a => + a.Login == "org" + && a.Admin == "admin" && a.ProfileName == "org name")); } } diff --git a/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseSearchIndexingClientTests.cs b/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseSearchIndexingClientTests.cs index 491acbfc..e185081f 100644 --- a/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseSearchIndexingClientTests.cs +++ b/Octokit.Tests/Reactive/Enterprise/ObservableEnterpriseSearchIndexingClientTests.cs @@ -17,7 +17,7 @@ namespace Octokit.Tests client.Queue("org"); github.Enterprise.SearchIndexing.Received(1). - Queue(Arg.Is( "org" )); + Queue(Arg.Is("org")); client.Queue("org", "repo"); github.Enterprise.SearchIndexing.Received(1). diff --git a/Octokit.Tests/Reactive/ObservableIssuesClientTests.cs b/Octokit.Tests/Reactive/ObservableIssuesClientTests.cs index aa23f958..b09a498a 100644 --- a/Octokit.Tests/Reactive/ObservableIssuesClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableIssuesClientTests.cs @@ -329,11 +329,11 @@ public class ObservableIssuesClientTests var gitHubClient = Substitute.For(); var client = new ObservableIssuesClient(gitHubClient); - Assert.Throws(() => client.Create(null, "name", new NewIssue("title"))); - Assert.Throws(() => client.Create("", "name", new NewIssue("x"))); - Assert.Throws(() => client.Create("owner", null, new NewIssue("x"))); - Assert.Throws(() => client.Create("owner", "", new NewIssue("x"))); - Assert.Throws(() => client.Create("owner", "name", null)); + Assert.Throws(() => client.Update(null, "name", 42, new IssueUpdate())); + Assert.Throws(() => client.Update("", "name", 42, new IssueUpdate())); + Assert.Throws(() => client.Update("owner", null, 42, new IssueUpdate())); + Assert.Throws(() => client.Update("owner", "", 42, new IssueUpdate())); + Assert.Throws(() => client.Update("owner", "name", 42, null)); } } diff --git a/Octokit.Tests/Reactive/ObservableUserAdministrationClientTests.cs b/Octokit.Tests/Reactive/ObservableUserAdministrationClientTests.cs index d247ddb3..682a09b6 100644 --- a/Octokit.Tests/Reactive/ObservableUserAdministrationClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableUserAdministrationClientTests.cs @@ -19,7 +19,7 @@ namespace Octokit.Tests.Reactive client.Create(new NewUser("auser", "email@company.com")); gitHubClient.User.Administration.Received().Create( - Arg.Is(a => + Arg.Is(a => a.Login == "auser" && a.Email == "email@company.com")); } diff --git a/Octokit/Clients/Enterprise/EnterpriseLdapClient.cs b/Octokit/Clients/Enterprise/EnterpriseLdapClient.cs index 6357da50..1980dc6f 100644 --- a/Octokit/Clients/Enterprise/EnterpriseLdapClient.cs +++ b/Octokit/Clients/Enterprise/EnterpriseLdapClient.cs @@ -45,7 +45,7 @@ namespace Octokit public async Task QueueSyncUserMapping(string userName) { Ensure.ArgumentNotNull(userName, "userName"); - + var endpoint = ApiUrls.EnterpriseLdapUserSync(userName); var response = await Connection.Post(endpoint); @@ -56,7 +56,7 @@ namespace Octokit return response.Body; } - + /// /// Update the LDAP mapping for a team on a GitHub Enterprise appliance (must be Site Admin user). /// @@ -87,7 +87,7 @@ namespace Octokit public async Task QueueSyncTeamMapping(int teamId) { Ensure.ArgumentNotNull(teamId, "teamId"); - + var endpoint = ApiUrls.EnterpriseLdapTeamSync(teamId); var response = await Connection.Post(endpoint); diff --git a/Octokit/Clients/Enterprise/EnterpriseSearchIndexingClient.cs b/Octokit/Clients/Enterprise/EnterpriseSearchIndexingClient.cs index 7e157bfb..2351a2f1 100644 --- a/Octokit/Clients/Enterprise/EnterpriseSearchIndexingClient.cs +++ b/Octokit/Clients/Enterprise/EnterpriseSearchIndexingClient.cs @@ -146,7 +146,7 @@ namespace Octokit public async Task QueueAllCode(string owner) { Ensure.ArgumentNotNull(owner, "owner"); - + var endpoint = ApiUrls.EnterpriseSearchIndexing(); var target = new SearchIndexTarget(string.Format(CultureInfo.InvariantCulture, "{0}/*/code", owner)); diff --git a/Octokit/Clients/UserAdministrationClient.cs b/Octokit/Clients/UserAdministrationClient.cs index a39fcb8d..1b7a15e6 100644 --- a/Octokit/Clients/UserAdministrationClient.cs +++ b/Octokit/Clients/UserAdministrationClient.cs @@ -218,7 +218,7 @@ namespace Octokit { Ensure.ArgumentNotNull(keyId, "keyId"); var endpoint = ApiUrls.UserAdministrationPublicKeys(keyId); - + var response = ((HttpStatusCode)await Connection.Delete(endpoint)); if (response != HttpStatusCode.NoContent) { diff --git a/Octokit/Http/IApiConnection.cs b/Octokit/Http/IApiConnection.cs index 4984870b..81966a10 100644 --- a/Octokit/Http/IApiConnection.cs +++ b/Octokit/Http/IApiConnection.cs @@ -141,7 +141,7 @@ namespace Octokit /// The created API resource. /// Thrown when an API error occurs. Task Post(Uri uri); - + /// /// Creates a new API resource in the list at the specified URI. /// diff --git a/Octokit/Models/Request/CreateFileRequest.cs b/Octokit/Models/Request/CreateFileRequest.cs index b9529e3b..7104b364 100644 --- a/Octokit/Models/Request/CreateFileRequest.cs +++ b/Octokit/Models/Request/CreateFileRequest.cs @@ -26,7 +26,7 @@ namespace Octokit /// /// The message. /// The branch the request is for. - protected ContentRequest(string message, string branch): this(message) + protected ContentRequest(string message, string branch) : this(message) { Ensure.ArgumentNotNullOrEmptyString(branch, "branch"); diff --git a/SolutionInfo.cs b/SolutionInfo.cs index a52961be..22509412 100644 --- a/SolutionInfo.cs +++ b/SolutionInfo.cs @@ -6,8 +6,10 @@ using System.Runtime.InteropServices; [assembly: AssemblyVersionAttribute("0.19.0")] [assembly: AssemblyFileVersionAttribute("0.19.0")] [assembly: ComVisibleAttribute(false)] -namespace System { - internal static class AssemblyVersionInformation { +namespace System +{ + internal static class AssemblyVersionInformation + { internal const string Version = "0.19.0"; } } From a00d08149e021d3cab2d8fa7b33851e7833d5a68 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Fri, 18 Mar 2016 13:49:54 +0700 Subject: [PATCH 65/77] The names of unit tests has been corrected in order to fit IReleaseClient unit test name convention (Gets prefix -> Requests prefix). --- Octokit.Tests/Clients/AuthorizationsClientTests.cs | 4 ++-- Octokit.Tests/Reactive/ObservableAuthorizationsClientTests.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Octokit.Tests/Clients/AuthorizationsClientTests.cs b/Octokit.Tests/Clients/AuthorizationsClientTests.cs index 6a508582..0b0b855e 100644 --- a/Octokit.Tests/Clients/AuthorizationsClientTests.cs +++ b/Octokit.Tests/Clients/AuthorizationsClientTests.cs @@ -26,7 +26,7 @@ namespace Octokit.Tests.Clients public class TheGetAllMethod { [Fact] - public void GetsAListOfAuthorizations() + public void RequestsCorrectUrl() { var client = Substitute.For(); var authEndpoint = new AuthorizationsClient(client); @@ -39,7 +39,7 @@ namespace Octokit.Tests.Clients } [Fact] - public void GetsAListOfAuthorizationsWithApiOptions() + public void RequestsCorrectUrlWithApiOptions() { var client = Substitute.For(); var authEndpoint = new AuthorizationsClient(client); diff --git a/Octokit.Tests/Reactive/ObservableAuthorizationsClientTests.cs b/Octokit.Tests/Reactive/ObservableAuthorizationsClientTests.cs index 5aa84daf..241950bb 100644 --- a/Octokit.Tests/Reactive/ObservableAuthorizationsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableAuthorizationsClientTests.cs @@ -11,7 +11,7 @@ namespace Octokit.Tests.Reactive public class TheGetAllMethod { [Fact] - public void GetsCorrectUrl() + public void RequestsCorrectUrl() { var client = Substitute.For(); var authEndpoint = new ObservableAuthorizationsClient(client); @@ -23,7 +23,7 @@ namespace Octokit.Tests.Reactive } [Fact] - public void GetsCorrectUrlWithApiOption() + public void RequestsCorrectUrlWithApiOption() { var client = Substitute.For(); var authEndpoint = new ObservableAuthorizationsClient(client); From 63b58527c6ba1c7596030674d4223a2615006d16 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Fri, 18 Mar 2016 13:50:59 +0700 Subject: [PATCH 66/77] New integration tests for IAuthorizationsClient and IObservableAuthorizationsClient have been added. --- .../Clients/AuthorizationClientTests.cs | 40 ++++++++++++++-- .../Octokit.Tests.Integration.csproj | 1 + .../ObservableAuthorizationsClientTests.cs | 46 +++++++++++++++++++ 3 files changed, 83 insertions(+), 4 deletions(-) create mode 100644 Octokit.Tests.Integration/Reactive/ObservableAuthorizationsClientTests.cs diff --git a/Octokit.Tests.Integration/Clients/AuthorizationClientTests.cs b/Octokit.Tests.Integration/Clients/AuthorizationClientTests.cs index 3108c42b..994c29b5 100644 --- a/Octokit.Tests.Integration/Clients/AuthorizationClientTests.cs +++ b/Octokit.Tests.Integration/Clients/AuthorizationClientTests.cs @@ -1,5 +1,4 @@ -using System; -using System.Threading.Tasks; +using System.Threading.Tasks; using Xunit; namespace Octokit.Tests.Integration.Clients @@ -13,7 +12,7 @@ namespace Octokit.Tests.Integration.Clients var note = Helper.MakeNameWithTimestamp("Testing authentication"); var newAuthorization = new NewAuthorization( note, - new string[] { "user" }); + new[] { "user" }); var created = await github.Authorization.Create(newAuthorization); @@ -27,6 +26,39 @@ namespace Octokit.Tests.Integration.Clients Assert.Equal(created.Note, get.Note); } + [IntegrationTest] + public async Task CanGetAuthorization() + { + var github = Helper.GetBasicAuthClient(); + + var authorizations = await github.Authorization.GetAll(); + Assert.NotEmpty(authorizations); + } + + [IntegrationTest] + public async Task CanGetAuthorizationWithApiOptions() + { + var github = Helper.GetBasicAuthClient(); + + var authorizations = await github.Authorization.GetAll(ApiOptions.None); + Assert.NotEmpty(authorizations); + } + + [IntegrationTest] + public async Task ReturnsNotEmptyAuthorizationsWithoutStart() + { + var github = Helper.GetBasicAuthClient(); + + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var authorizations = await github.Authorization.GetAll(options); + Assert.NotEmpty(authorizations); + } + [IntegrationTest] public async Task CannotCreatePersonalTokenWhenUsingOauthTokenCredentials() { @@ -34,7 +66,7 @@ namespace Octokit.Tests.Integration.Clients var note = Helper.MakeNameWithTimestamp("Testing authentication"); var newAuthorization = new NewAuthorization( note, - new string[] { "user" }); + new[] { "user" }); var error = Assert.ThrowsAsync(() => github.Authorization.Create(newAuthorization)); Assert.True(error.Result.Message.Contains("username and password Basic Auth")); diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index 0a5c12a3..4181ab35 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -138,6 +138,7 @@ + diff --git a/Octokit.Tests.Integration/Reactive/ObservableAuthorizationsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableAuthorizationsClientTests.cs new file mode 100644 index 00000000..348eb774 --- /dev/null +++ b/Octokit.Tests.Integration/Reactive/ObservableAuthorizationsClientTests.cs @@ -0,0 +1,46 @@ +using System.Reactive.Linq; +using System.Threading.Tasks; +using Octokit.Reactive; +using Xunit; + +namespace Octokit.Tests.Integration.Reactive +{ + public class ObservableAuthorizationsClientTests + { + readonly ObservableAuthorizationsClient _authorizationsClient; + + public ObservableAuthorizationsClientTests() + { + var github = Helper.GetBasicAuthClient(); + + _authorizationsClient = new ObservableAuthorizationsClient(github); + } + + [IntegrationTest] + public async Task CanGetAuthorization() + { + var authorization = await _authorizationsClient.GetAll(); + Assert.NotNull(authorization); + } + + [IntegrationTest] + public async Task CanGetAuthorizationWithApiOptions() + { + var authorization = await _authorizationsClient.GetAll(ApiOptions.None); + Assert.NotNull(authorization); + } + + [IntegrationTest] + public async Task ReturnsNotEmptyAuthorizationsWithoutStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var authorizations = await _authorizationsClient.GetAll(options).ToList(); + Assert.NotEmpty(authorizations); + } + } +} From e72c7c5d3cf1741fc6e4b9d913d5856d69408708 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Fri, 18 Mar 2016 19:09:28 +0700 Subject: [PATCH 67/77] Some code inconsistency has been fixed in GistsClientTests. --- Octokit.Tests/Clients/GistsClientTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Octokit.Tests/Clients/GistsClientTests.cs b/Octokit.Tests/Clients/GistsClientTests.cs index a78efd70..56c31186 100644 --- a/Octokit.Tests/Clients/GistsClientTests.cs +++ b/Octokit.Tests/Clients/GistsClientTests.cs @@ -1,7 +1,6 @@ using NSubstitute; using Octokit; using Octokit.Internal; -using Octokit.Tests.Helpers; using System; using System.Collections.Generic; using System.Net; @@ -24,7 +23,7 @@ public class GistsClientTests } } - public class TheGetAllMethods + public class TheGetAllMethod { [Fact] public void RequestsCorrectGetAllUrl() @@ -42,6 +41,7 @@ public class GistsClientTests { var connection = Substitute.For(); var client = new GistsClient(connection); + DateTimeOffset since = DateTimeOffset.Now; client.GetAll(since); From 1a5658d31f4241a899222cb1db44499949093c28 Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Mon, 21 Mar 2016 23:25:54 +0700 Subject: [PATCH 68/77] Add some new tests for overloaded methods. --- .../Clients/ObservableAssigneesClient.cs | 5 +--- Octokit.Tests/Clients/AssigneesClientTests.cs | 26 +++++++++++++++++-- .../Clients/AuthorizationsClientTests.cs | 22 +++++++++++++--- Octokit.Tests/Clients/ReleasesClientTests.cs | 22 ++++++++++++++++ .../Clients/UserEmailsClientTests.cs | 24 ++++++++++++++--- .../ObservableAuthorizationsClientTests.cs | 13 +++++++++- 6 files changed, 98 insertions(+), 14 deletions(-) diff --git a/Octokit.Reactive/Clients/ObservableAssigneesClient.cs b/Octokit.Reactive/Clients/ObservableAssigneesClient.cs index 28717934..beabc06d 100644 --- a/Octokit.Reactive/Clients/ObservableAssigneesClient.cs +++ b/Octokit.Reactive/Clients/ObservableAssigneesClient.cs @@ -25,10 +25,7 @@ namespace Octokit.Reactive /// public IObservable GetAllForRepository(string owner, string name) { - Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); - Ensure.ArgumentNotNullOrEmptyString(name, "name"); - - return _connection.GetAndFlattenAllPages(ApiUrls.Assignees(owner, name)); + return GetAllForRepository(owner, name, ApiOptions.None); } /// diff --git a/Octokit.Tests/Clients/AssigneesClientTests.cs b/Octokit.Tests/Clients/AssigneesClientTests.cs index ac4a7bc0..e5c56018 100644 --- a/Octokit.Tests/Clients/AssigneesClientTests.cs +++ b/Octokit.Tests/Clients/AssigneesClientTests.cs @@ -4,14 +4,13 @@ using System.Net; using System.Threading.Tasks; using NSubstitute; using Octokit.Internal; -using Octokit.Tests.Helpers; using Xunit; namespace Octokit.Tests.Clients { public class AssigneesClientTests { - public class TheGetForRepositoryMethod + public class TheGetAllMethod { [Fact] public void RequestsCorrectUrl() @@ -28,6 +27,28 @@ namespace Octokit.Tests.Clients Args.ApiOptions); } + [Fact] + public void RequestsCorrectUrlWithApiOptions() + { + var connection = Substitute.For(); + var client = new AssigneesClient(connection); + + var options = new ApiOptions + { + PageCount = 1, + PageSize = 1, + StartPage = 1 + }; + + client.GetAllForRepository("fake", "repo", options); + + connection.Received().GetAll( + Arg.Is(u => u.ToString() == "repos/fake/repo/assignees"), + null, + AcceptHeaders.StableVersion, + options); + } + [Fact] public async Task EnsuresNonNullArguments() { @@ -37,6 +58,7 @@ namespace Octokit.Tests.Clients await Assert.ThrowsAsync(() => client.GetAllForRepository(null, "")); await Assert.ThrowsAsync(() => client.GetAllForRepository("owner", null)); await Assert.ThrowsAsync(() => client.GetAllForRepository("", null)); + await Assert.ThrowsAsync(() => client.GetAllForRepository("owner", "name", null)); } } diff --git a/Octokit.Tests/Clients/AuthorizationsClientTests.cs b/Octokit.Tests/Clients/AuthorizationsClientTests.cs index 0b0b855e..0724d76b 100644 --- a/Octokit.Tests/Clients/AuthorizationsClientTests.cs +++ b/Octokit.Tests/Clients/AuthorizationsClientTests.cs @@ -43,12 +43,28 @@ namespace Octokit.Tests.Clients { var client = Substitute.For(); var authEndpoint = new AuthorizationsClient(client); - - authEndpoint.GetAll(ApiOptions.None); + + var options = new ApiOptions + { + StartPage = 1, + PageSize = 1, + PageCount = 1 + }; + + authEndpoint.GetAll(options); client.Received().GetAll( Arg.Is(u => u.ToString() == "authorizations"), - Args.ApiOptions); + options); + } + + [Fact] + public async Task EnsuresArgumentsNotNull() + { + var client = Substitute.For(); + var authEndpoint = new AuthorizationsClient(client); + + await Assert.ThrowsAsync(() => authEndpoint.GetAll(null)); } } diff --git a/Octokit.Tests/Clients/ReleasesClientTests.cs b/Octokit.Tests/Clients/ReleasesClientTests.cs index d82c0707..10ce49a8 100644 --- a/Octokit.Tests/Clients/ReleasesClientTests.cs +++ b/Octokit.Tests/Clients/ReleasesClientTests.cs @@ -24,6 +24,27 @@ namespace Octokit.Tests.Clients Args.ApiOptions); } + [Fact] + public void RequestsCorrectUrlWithApiOptions() + { + var client = Substitute.For(); + var releasesClient = new ReleasesClient(client); + + var options = new ApiOptions + { + PageSize = 1, + PageCount = 1, + StartPage = 1 + }; + + releasesClient.GetAll("fake", "repo", options); + + client.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/releases"), + null, + "application/vnd.github.v3", + options); + } + [Fact] public async Task EnsuresNonNullArguments() { @@ -31,6 +52,7 @@ namespace Octokit.Tests.Clients await Assert.ThrowsAsync(() => releasesClient.GetAll(null, "name")); await Assert.ThrowsAsync(() => releasesClient.GetAll("owner", null)); + await Assert.ThrowsAsync(() => releasesClient.GetAll("owner", "name", null)); } } diff --git a/Octokit.Tests/Clients/UserEmailsClientTests.cs b/Octokit.Tests/Clients/UserEmailsClientTests.cs index 34d31106..9ea83029 100644 --- a/Octokit.Tests/Clients/UserEmailsClientTests.cs +++ b/Octokit.Tests/Clients/UserEmailsClientTests.cs @@ -11,7 +11,7 @@ namespace Octokit.Tests.Clients public class TheGetAllMethod { [Fact] - public void GetsCorrectUrl() + public void RequestsCorrectUrl() { var connection = Substitute.For(); var client = new UserEmailsClient(connection); @@ -24,15 +24,31 @@ namespace Octokit.Tests.Clients } [Fact] - public void GetsCorrectUrlWithApiOptions() + public void RequestsCorrectUrlWithApiOptions() { var connection = Substitute.For(); var client = new UserEmailsClient(connection); - client.GetAll(ApiOptions.None); + var options = new ApiOptions + { + PageCount = 1, + PageSize = 1, + StartPage = 1 + }; + + client.GetAll(options); connection.Received(1) - .GetAll(Arg.Is(u => u.ToString() == "user/emails"), Args.ApiOptions); + .GetAll(Arg.Is(u => u.ToString() == "user/emails"), + options); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var releasesClient = new UserEmailsClient(Substitute.For()); + + await Assert.ThrowsAsync(() => releasesClient.GetAll(null)); } } diff --git a/Octokit.Tests/Reactive/ObservableAuthorizationsClientTests.cs b/Octokit.Tests/Reactive/ObservableAuthorizationsClientTests.cs index 241950bb..7fe3bea0 100644 --- a/Octokit.Tests/Reactive/ObservableAuthorizationsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableAuthorizationsClientTests.cs @@ -1,5 +1,7 @@ using System; using System.Collections.Generic; +using System.Reactive.Threading.Tasks; +using System.Threading.Tasks; using NSubstitute; using Octokit.Reactive; using Xunit; @@ -27,12 +29,21 @@ namespace Octokit.Tests.Reactive { var client = Substitute.For(); var authEndpoint = new ObservableAuthorizationsClient(client); - + authEndpoint.GetAll(ApiOptions.None); client.Connection.Received(1).Get>(Arg.Is(u => u.ToString() == "authorizations"), Arg.Is>(dictionary => dictionary.Count == 0), null); } + + [Fact] + public async Task EnsuresArgumentsNotNull() + { + var client = Substitute.For(); + var authEndpoint = new ObservableAuthorizationsClient(client); + + await Assert.ThrowsAsync(() => authEndpoint.GetAll(null).ToTask()); + } } public class TheCtor From 04ec997cfa57a138c50bd7d173303e235dd4af44 Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Mon, 21 Mar 2016 19:13:15 +0000 Subject: [PATCH 69/77] Created ObservableRepositoryCommitsClientTests Added tests for GetSha1 --- Octokit.Tests/Octokit.Tests.csproj | 1 + .../ObservableRepositoryCommitsClientTests.cs | 50 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 Octokit.Tests/Reactive/ObservableRepositoryCommitsClientTests.cs diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj index 5c6484c3..9f226d4e 100644 --- a/Octokit.Tests/Octokit.Tests.csproj +++ b/Octokit.Tests/Octokit.Tests.csproj @@ -212,6 +212,7 @@ + diff --git a/Octokit.Tests/Reactive/ObservableRepositoryCommitsClientTests.cs b/Octokit.Tests/Reactive/ObservableRepositoryCommitsClientTests.cs new file mode 100644 index 00000000..a99938b4 --- /dev/null +++ b/Octokit.Tests/Reactive/ObservableRepositoryCommitsClientTests.cs @@ -0,0 +1,50 @@ +using System; +using System.Reactive.Threading.Tasks; +using System.Threading.Tasks; +using NSubstitute; +using Octokit.Reactive; +using Xunit; + +namespace Octokit.Tests.Reactive +{ + public class ObservableRepositoryCommitsClientTests + { + public class TheGetSha1Method + { + [Fact] + public void EnsuresNonNullArguments() + { + var client = new ObservableRepositoryCommitsClient(Substitute.For()); + + Assert.ThrowsAsync(() => client.GetSha1("", "name", "reference").ToTask()); + Assert.ThrowsAsync(() => client.GetSha1("owner", "", "reference").ToTask()); + Assert.ThrowsAsync(() => client.GetSha1("owner", "name", "").ToTask()); + } + + [Fact] + public async Task EnsuresNonEmptyArguments() + { + var client = new ObservableRepositoryCommitsClient(Substitute.For()); + + await Assert.ThrowsAsync(() => client.GetSha1(null, "name", "reference").ToTask()); + await Assert.ThrowsAsync(() => client.GetSha1("owner", null, "reference").ToTask()); + await Assert.ThrowsAsync(() => client.GetSha1("owner", "name", null).ToTask()); + } + + [Fact] + public void GetsCorrectUrl() + { + var gitHubClient = Substitute.For(); + var client = new ObservableRepositoryCommitsClient(gitHubClient); + + client.GetSha1("owner", "name", "reference"); + + gitHubClient + .Received() + .Repository + .Commit + .GetSha1("owner", "name", "reference"); + } + } + } +} From c34d904f1ab50972a7fe8d02dd762144033c5155 Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Mon, 21 Mar 2016 19:23:18 +0000 Subject: [PATCH 70/77] Created ObservableRepositoryCommitsClientTests Added integration test for GetSha1 for observableclient --- .../Octokit.Tests.Integration.csproj | 1 + .../ObservableRepositoryCommitsClientTests.cs | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 Octokit.Tests.Integration/Reactive/ObservableRepositoryCommitsClientTests.cs diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index 0a5c12a3..d5581fe8 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -147,6 +147,7 @@ + diff --git a/Octokit.Tests.Integration/Reactive/ObservableRepositoryCommitsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableRepositoryCommitsClientTests.cs new file mode 100644 index 00000000..8906a3c0 --- /dev/null +++ b/Octokit.Tests.Integration/Reactive/ObservableRepositoryCommitsClientTests.cs @@ -0,0 +1,29 @@ +using System.Reactive.Linq; +using System.Threading.Tasks; +using Octokit.Reactive; +using Xunit; + +namespace Octokit.Tests.Integration.Reactive +{ + public class ObservableRepositoryCommitsClientTests + { + readonly IObservableRepositoryCommitsClient _fixture; + + public ObservableRepositoryCommitsClientTests() + { + var github = Helper.GetAuthenticatedClient(); + + _fixture = new ObservableRepositoryCommitsClient(github); + } + + [IntegrationTest] + public async Task CanGetSha1() + { + var observable = _fixture.GetSha1("octokit", "octokit.net", "master"); + + var sha1 = await observable; + + Assert.NotNull(sha1); + } + } +} From e57dfa33e2a8e645d0aa37851fa0c125564943d1 Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Mon, 21 Mar 2016 19:27:13 +0000 Subject: [PATCH 71/77] Added constructor test Check the ctor for a null IGitHubClient --- .../Reactive/ObservableRepositoryCommitsClientTests.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Octokit.Tests/Reactive/ObservableRepositoryCommitsClientTests.cs b/Octokit.Tests/Reactive/ObservableRepositoryCommitsClientTests.cs index a99938b4..44154d1b 100644 --- a/Octokit.Tests/Reactive/ObservableRepositoryCommitsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableRepositoryCommitsClientTests.cs @@ -9,6 +9,15 @@ namespace Octokit.Tests.Reactive { public class ObservableRepositoryCommitsClientTests { + public class TheCtor + { + [Fact] + public void EnsuresArgument() + { + Assert.Throws(() => new ObservableRepositoryCommitsClient(null)); + } + } + public class TheGetSha1Method { [Fact] From 71e7cc2055a3697ca69f4bc9f49fd4b53da3b81d Mon Sep 17 00:00:00 2001 From: Devesh Khandelwal Date: Tue, 22 Mar 2016 12:04:32 +0530 Subject: [PATCH 72/77] Correct spelling: docmentation -> documentation --- .../Clients/IObservableRepositoriesClient.cs | 2 +- .../Clients/ObservableRepositoriesClient.cs | 2 +- Octokit/Clients/IRepositoriesClient.cs | 2 +- Octokit/Clients/RepositoriesClient.cs | 2 +- Octokit/GitHubClient.cs | 36 +++++++++---------- Octokit/IGitHubClient.cs | 32 ++++++++--------- 6 files changed, 38 insertions(+), 38 deletions(-) diff --git a/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs b/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs index 493e90b8..123860bc 100644 --- a/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs +++ b/Octokit.Reactive/Clients/IObservableRepositoriesClient.cs @@ -328,7 +328,7 @@ namespace Octokit.Reactive /// Access GitHub's Releases API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/repos/releases/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/repos/releases/ /// IObservableReleasesClient Release { get; } diff --git a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs index 1495afb7..005270bb 100644 --- a/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs +++ b/Octokit.Reactive/Clients/ObservableRepositoriesClient.cs @@ -475,7 +475,7 @@ namespace Octokit.Reactive /// Access GitHub's Releases API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/repos/releases/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/repos/releases/ /// public IObservableReleasesClient Release { get; private set; } diff --git a/Octokit/Clients/IRepositoriesClient.cs b/Octokit/Clients/IRepositoriesClient.cs index d88480a6..b5db4ad6 100644 --- a/Octokit/Clients/IRepositoriesClient.cs +++ b/Octokit/Clients/IRepositoriesClient.cs @@ -274,7 +274,7 @@ namespace Octokit /// Access GitHub's Releases API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/repos/releases/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/repos/releases/ /// IReleasesClient Release { get; } diff --git a/Octokit/Clients/RepositoriesClient.cs b/Octokit/Clients/RepositoriesClient.cs index 0b034fe4..590637d0 100644 --- a/Octokit/Clients/RepositoriesClient.cs +++ b/Octokit/Clients/RepositoriesClient.cs @@ -396,7 +396,7 @@ namespace Octokit /// Access GitHub's Releases API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/repos/releases/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/repos/releases/ /// public IReleasesClient Release { get; private set; } diff --git a/Octokit/GitHubClient.cs b/Octokit/GitHubClient.cs index 105a7da1..69577776 100644 --- a/Octokit/GitHubClient.cs +++ b/Octokit/GitHubClient.cs @@ -147,7 +147,7 @@ namespace Octokit /// Access GitHub's Authorization API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/oauth_authorizations/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/oauth_authorizations/ /// public IAuthorizationsClient Authorization { get; private set; } @@ -155,7 +155,7 @@ namespace Octokit /// Access GitHub's Activity API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/activity/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/activity/ /// public IActivitiesClient Activity { get; private set; } @@ -163,7 +163,7 @@ namespace Octokit /// Access GitHub's Issue API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/issues/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/issues/ /// public IIssuesClient Issue { get; private set; } @@ -171,7 +171,7 @@ namespace Octokit /// Access GitHub's Miscellaneous API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/misc/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/misc/ /// public IMiscellaneousClient Miscellaneous { get; private set; } @@ -179,7 +179,7 @@ namespace Octokit /// Access GitHub's OAuth API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/oauth/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/oauth/ /// public IOauthClient Oauth { get; private set; } @@ -187,7 +187,7 @@ namespace Octokit /// Access GitHub's Organizations API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/orgs/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/orgs/ /// public IOrganizationsClient Organization { get; private set; } @@ -195,7 +195,7 @@ namespace Octokit /// Access GitHub's Pull Requests API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/pulls/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/pulls/ /// public IPullRequestsClient PullRequest { get; private set; } @@ -203,7 +203,7 @@ namespace Octokit /// Access GitHub's Repositories API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/repos/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/repos/ /// public IRepositoriesClient Repository { get; private set; } @@ -211,7 +211,7 @@ namespace Octokit /// Access GitHub's Gists API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/gists/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/gists/ /// public IGistsClient Gist { get; private set; } @@ -219,7 +219,7 @@ namespace Octokit /// Access GitHub's Releases API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/repos/releases/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/repos/releases/ /// [Obsolete("Use Repository.Release instead")] public IReleasesClient Release @@ -233,7 +233,7 @@ namespace Octokit /// Access GitHub's Public Keys API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/users/keys/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/users/keys/ /// public ISshKeysClient SshKey { get; private set; } @@ -241,7 +241,7 @@ namespace Octokit /// Access GitHub's Users API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/users/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/users/ /// public IUsersClient User { get; private set; } @@ -250,7 +250,7 @@ namespace Octokit /// Access GitHub's Notifications API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/activity/notifications/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/activity/notifications/ /// public INotificationsClient Notification { get; private set; } @@ -258,7 +258,7 @@ namespace Octokit /// Access GitHub's Git Data API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/git/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/git/ /// [Obsolete("Use Git instead")] public IGitDatabaseClient GitDatabase { get { return Git; } } @@ -267,7 +267,7 @@ namespace Octokit /// Access GitHub's Git Data API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/git/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/git/ /// public IGitDatabaseClient Git { get; private set; } @@ -275,7 +275,7 @@ namespace Octokit /// Access GitHub's Search API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/search/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/search/ /// public ISearchClient Search { get; private set; } @@ -284,7 +284,7 @@ namespace Octokit /// Access GitHub's Deployments API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/repos/deployments/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/repos/deployments/ /// public IDeploymentsClient Deployment { get; private set; } @@ -292,7 +292,7 @@ namespace Octokit /// Access GitHub's Enterprise API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/enterprise/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/enterprise/ /// public IEnterpriseClient Enterprise { get; private set; } diff --git a/Octokit/IGitHubClient.cs b/Octokit/IGitHubClient.cs index f6a996c9..d39eeb03 100644 --- a/Octokit/IGitHubClient.cs +++ b/Octokit/IGitHubClient.cs @@ -16,7 +16,7 @@ namespace Octokit /// Access GitHub's Authorization API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/oauth_authorizations/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/oauth_authorizations/ /// IAuthorizationsClient Authorization { get; } @@ -24,7 +24,7 @@ namespace Octokit /// Access GitHub's Activity API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/activity/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/activity/ /// IActivitiesClient Activity { get; } @@ -32,7 +32,7 @@ namespace Octokit /// Access GitHub's Issue API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/issues/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/issues/ /// IIssuesClient Issue { get; } @@ -40,7 +40,7 @@ namespace Octokit /// Access GitHub's Miscellaneous API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/misc/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/misc/ /// IMiscellaneousClient Miscellaneous { get; } @@ -48,7 +48,7 @@ namespace Octokit /// Access GitHub's OAuth API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/oauth/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/oauth/ /// IOauthClient Oauth { get; } @@ -56,7 +56,7 @@ namespace Octokit /// Access GitHub's Organizations API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/orgs/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/orgs/ /// IOrganizationsClient Organization { get; } @@ -64,7 +64,7 @@ namespace Octokit /// Access GitHub's Pull Requests API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/pulls/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/pulls/ /// IPullRequestsClient PullRequest { get; } @@ -72,7 +72,7 @@ namespace Octokit /// Access GitHub's Repositories API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/repos/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/repos/ /// IRepositoriesClient Repository { get; } @@ -80,7 +80,7 @@ namespace Octokit /// Access GitHub's Gists API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/gists/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/gists/ /// IGistsClient Gist { get; } @@ -89,7 +89,7 @@ namespace Octokit /// Access GitHub's Releases API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/repos/releases/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/repos/releases/ /// [Obsolete("Use Repository.Release instead")] IReleasesClient Release { get; } @@ -100,7 +100,7 @@ namespace Octokit /// Access GitHub's Public Keys API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/users/keys/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/users/keys/ /// ISshKeysClient SshKey { get; } @@ -108,7 +108,7 @@ namespace Octokit /// Access GitHub's Users API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/users/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/users/ /// IUsersClient User { get; } @@ -117,7 +117,7 @@ namespace Octokit /// Access GitHub's Notifications API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/activity/notifications/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/activity/notifications/ /// [System.Obsolete("Notifications are now available under the Activities client. This will be removed in a future update.")] INotificationsClient Notification { get; } @@ -126,7 +126,7 @@ namespace Octokit /// Access GitHub's Git Data API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/git/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/git/ /// [Obsolete("Use Git instead")] IGitDatabaseClient GitDatabase { get; } @@ -135,7 +135,7 @@ namespace Octokit /// Access GitHub's Git Data API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/git/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/git/ /// IGitDatabaseClient Git { get; } @@ -143,7 +143,7 @@ namespace Octokit /// Access GitHub's Search API. /// /// - /// Refer to the API docmentation for more information: https://developer.github.com/v3/search/ + /// Refer to the API documentation for more information: https://developer.github.com/v3/search/ /// ISearchClient Search { get; } From dc8ef18c25d1652b999968edd9b2581303b0091a Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Tue, 22 Mar 2016 09:00:51 +0000 Subject: [PATCH 73/77] Removing integration test --- .../Octokit.Tests.Integration.csproj | 1 - .../ObservableRepositoryCommitsClientTests.cs | 29 ------------------- 2 files changed, 30 deletions(-) delete mode 100644 Octokit.Tests.Integration/Reactive/ObservableRepositoryCommitsClientTests.cs diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index d5581fe8..0a5c12a3 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -147,7 +147,6 @@ - diff --git a/Octokit.Tests.Integration/Reactive/ObservableRepositoryCommitsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableRepositoryCommitsClientTests.cs deleted file mode 100644 index 8906a3c0..00000000 --- a/Octokit.Tests.Integration/Reactive/ObservableRepositoryCommitsClientTests.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Reactive.Linq; -using System.Threading.Tasks; -using Octokit.Reactive; -using Xunit; - -namespace Octokit.Tests.Integration.Reactive -{ - public class ObservableRepositoryCommitsClientTests - { - readonly IObservableRepositoryCommitsClient _fixture; - - public ObservableRepositoryCommitsClientTests() - { - var github = Helper.GetAuthenticatedClient(); - - _fixture = new ObservableRepositoryCommitsClient(github); - } - - [IntegrationTest] - public async Task CanGetSha1() - { - var observable = _fixture.GetSha1("octokit", "octokit.net", "master"); - - var sha1 = await observable; - - Assert.NotNull(sha1); - } - } -} From dd63d1bffad336b82f145c1a7b2ae1ff41596177 Mon Sep 17 00:00:00 2001 From: Roger Tinsley Date: Tue, 22 Mar 2016 09:02:45 +0000 Subject: [PATCH 74/77] Correcting method names NoNull needs to test null strings and NonEmpty tests empty strings --- .../Reactive/ObservableRepositoryCommitsClientTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Octokit.Tests/Reactive/ObservableRepositoryCommitsClientTests.cs b/Octokit.Tests/Reactive/ObservableRepositoryCommitsClientTests.cs index 44154d1b..bcd91f37 100644 --- a/Octokit.Tests/Reactive/ObservableRepositoryCommitsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableRepositoryCommitsClientTests.cs @@ -21,7 +21,7 @@ namespace Octokit.Tests.Reactive public class TheGetSha1Method { [Fact] - public void EnsuresNonNullArguments() + public void EnsuresNonEmptyArguments() { var client = new ObservableRepositoryCommitsClient(Substitute.For()); @@ -31,7 +31,7 @@ namespace Octokit.Tests.Reactive } [Fact] - public async Task EnsuresNonEmptyArguments() + public async Task EnsuresNonNullArguments() { var client = new ObservableRepositoryCommitsClient(Substitute.For()); From 509036c2196ac269b2424ea2b2bb785e0d924e0e Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 22 Mar 2016 18:37:43 +0700 Subject: [PATCH 75/77] Redundant this. qaulifier was removed. --- Octokit/Http/ApiInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Octokit/Http/ApiInfo.cs b/Octokit/Http/ApiInfo.cs index 0c6c7705..ce6ef0c2 100644 --- a/Octokit/Http/ApiInfo.cs +++ b/Octokit/Http/ApiInfo.cs @@ -66,7 +66,7 @@ namespace Octokit return new ApiInfo(Links.Clone(), OauthScopes.Clone(), AcceptedOauthScopes.Clone(), - new string(this.Etag.ToCharArray()), + new string(Etag.ToCharArray()), RateLimit.Clone()); } } From 56a0970d15de44c9432ffff859149bd496a0fb7a Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 22 Mar 2016 18:57:12 +0700 Subject: [PATCH 76/77] Redundant string.Format() call was removed. --- Octokit.Tests/Reactive/ObservablePullRequestsClientTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Octokit.Tests/Reactive/ObservablePullRequestsClientTests.cs b/Octokit.Tests/Reactive/ObservablePullRequestsClientTests.cs index 929ed17f..f9d7eec1 100644 --- a/Octokit.Tests/Reactive/ObservablePullRequestsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservablePullRequestsClientTests.cs @@ -281,7 +281,7 @@ namespace Octokit.Tests.Reactive public async Task FetchesAllCommitsForPullRequest() { var commit = new PullRequestCommit(null, null, null, null, null, Enumerable.Empty(), null, null); - var expectedUrl = string.Format("repos/fake/repo/pulls/42/commits"); + var expectedUrl = "repos/fake/repo/pulls/42/commits"; var gitHubClient = Substitute.For(); var connection = Substitute.For(); IApiResponse> response = new ApiResponse> @@ -320,7 +320,7 @@ namespace Octokit.Tests.Reactive public async Task FetchesAllFilesForPullRequest() { var file = new PullRequestFile(null, null, null, 0, 0, 0, null, null, null, null); - var expectedUrl = string.Format("repos/fake/repo/pulls/42/files"); + var expectedUrl = "repos/fake/repo/pulls/42/files"; var gitHubClient = Substitute.For(); var connection = Substitute.For(); IApiResponse> response = new ApiResponse> From 6133210b979375888af0857a547fa6713febe4ae Mon Sep 17 00:00:00 2001 From: "aedampir@gmail.com" Date: Tue, 22 Mar 2016 19:13:24 +0700 Subject: [PATCH 77/77] Inconsistent modifiers declaration order was fixed. --- Octokit.Tests/Http/RedirectHandlerTests.cs | 2 +- Octokit/Http/Credentials.cs | 2 +- Octokit/Http/HttpClientAdapter.cs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Octokit.Tests/Http/RedirectHandlerTests.cs b/Octokit.Tests/Http/RedirectHandlerTests.cs index 8f5b65d3..845067e2 100644 --- a/Octokit.Tests/Http/RedirectHandlerTests.cs +++ b/Octokit.Tests/Http/RedirectHandlerTests.cs @@ -189,7 +189,7 @@ namespace Octokit.Tests.Http _response2 = response2; } - protected async override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { if (!_Response1Sent) { diff --git a/Octokit/Http/Credentials.cs b/Octokit/Http/Credentials.cs index 37261bac..f62efa63 100644 --- a/Octokit/Http/Credentials.cs +++ b/Octokit/Http/Credentials.cs @@ -6,7 +6,7 @@ namespace Octokit { [SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes" , Justification = "Credentials is immutable")] - public readonly static Credentials Anonymous = new Credentials(); + public static readonly Credentials Anonymous = new Credentials(); private Credentials() { diff --git a/Octokit/Http/HttpClientAdapter.cs b/Octokit/Http/HttpClientAdapter.cs index 8f4f6d83..1c6a65a5 100644 --- a/Octokit/Http/HttpClientAdapter.cs +++ b/Octokit/Http/HttpClientAdapter.cs @@ -64,7 +64,7 @@ namespace Octokit.Internal return cancellationTokenForRequest; } - protected async virtual Task BuildResponse(HttpResponseMessage responseMessage) + protected virtual async Task BuildResponse(HttpResponseMessage responseMessage) { Ensure.ArgumentNotNull(responseMessage, "responseMessage");