diff --git a/Octokit.Reactive/Clients/IObservableMilestonesClient.cs b/Octokit.Reactive/Clients/IObservableMilestonesClient.cs
new file mode 100644
index 0000000000..321790a128
--- /dev/null
+++ b/Octokit.Reactive/Clients/IObservableMilestonesClient.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using System.Reactive;
+
+namespace Octokit
+{
+ public interface IObservableMilestonesClient
+ {
+ ///
+ /// Gets a single Milestone by number.
+ ///
+ ///
+ /// http://developer.github.com/v3/issues/milestones/#get-a-single-milestone
+ ///
+ ///
+ [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get",
+ Justification = "Method makes a network request")]
+ IObservable Get(string owner, string name, int number);
+
+ ///
+ /// Gets all open milestones for the repository.
+ ///
+ ///
+ /// http://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ ///
+ IObservable GetForRepository(string owner, string name);
+
+ ///
+ /// Gets all open milestones for the repository.
+ ///
+ ///
+ /// http://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ /// Used to filter and sort the list of Milestones returned
+ ///
+ IObservable GetForRepository(string owner, string name, MilestoneRequest request);
+
+ ///
+ /// Creates a milestone for the specified repository. Any user with pull access to a repository can create an
+ /// Milestone.
+ ///
+ /// http://developer.github.com/v3/issues/milestones/#create-a-milestone
+ /// The owner of the repository
+ /// The name of the repository
+ /// A instance describing the new Milestone to create
+ ///
+ IObservable Create(string owner, string name, NewMilestone newMilestone);
+
+ ///
+ /// Creates a milestone for the specified repository. Any user with pull access to a repository can create an
+ /// Milestone.
+ ///
+ /// http://developer.github.com/v3/issues/milestones/#update-a-milestone
+ /// The owner of the repository
+ /// The name of the repository
+ /// The Milestone number
+ /// An instance describing the changes to make to the Milestone
+ ///
+ ///
+ IObservable Update(string owner, string name, int number, MilestoneUpdate milestoneUpdate);
+
+ ///
+ /// Deletes a milestone for the specified repository. Any user with pull access to a repository can create an
+ /// Milestone.
+ ///
+ /// http://developer.github.com/v3/issues/milestones/#delete-a-milestone
+ /// The owner of the repository
+ /// The name of the repository
+ /// The milestone number
+ ///
+ IObservable Delete(string owner, string name, int number);
+ }
+}
diff --git a/Octokit.Reactive/Clients/ObservableMilestonesClient.cs b/Octokit.Reactive/Clients/ObservableMilestonesClient.cs
new file mode 100644
index 0000000000..bd33ad53eb
--- /dev/null
+++ b/Octokit.Reactive/Clients/ObservableMilestonesClient.cs
@@ -0,0 +1,125 @@
+using System;
+using System.Reactive;
+using System.Reactive.Threading.Tasks;
+using Octokit.Reactive.Internal;
+
+namespace Octokit.Reactive.Clients
+{
+ public class ObservableMilestonesClient : IObservableMilestonesClient
+ {
+ readonly IMilestonesClient _client;
+ readonly IConnection _connection;
+
+ public ObservableMilestonesClient(IGitHubClient client)
+ {
+ Ensure.ArgumentNotNull(client, "client");
+
+ _client = client.Issue.Milestone;
+ _connection = client.Connection;
+ }
+
+ ///
+ /// Gets a single Milestone by number.
+ ///
+ ///
+ /// http://developer.github.com/v3/issues/milestones/#get-a-single-milestone
+ ///
+ ///
+ public IObservable Get(string owner, string name, int number)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+
+ return _client.Get(owner, name, number).ToObservable();
+ }
+
+ ///
+ /// Gets all open milestones for the repository.
+ ///
+ ///
+ /// http://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ ///
+ public IObservable GetForRepository(string owner, string name)
+ {
+ return _connection.GetAndFlattenAllPages(ApiUrls.Milestones(owner, name));
+ }
+
+ ///
+ /// Gets all open milestones for the repository.
+ ///
+ ///
+ /// http://developer.github.com/v3/issues/milestones/#list-milestones-for-a-repository
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ /// Used to filter and sort the list of Milestones returned
+ ///
+ public IObservable GetForRepository(string owner, string name, MilestoneRequest request)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+ Ensure.ArgumentNotNull(request, "request");
+
+ return _connection.GetAndFlattenAllPages(ApiUrls.Milestones(owner, name),
+ request.ToParametersDictionary());
+ }
+
+ ///
+ /// Creates an Milestone for the specified repository. Any user with pull access to a repository can create an
+ /// Milestone.
+ ///
+ /// http://developer.github.com/v3/issues/milestones/#create-a-milestone
+ /// The owner of the repository
+ /// The name of the repository
+ /// A instance describing the new Milestone to create
+ ///
+ public IObservable Create(string owner, string name, NewMilestone newMilestone)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+ Ensure.ArgumentNotNull(newMilestone, "newMilestone");
+
+ return _client.Create(owner, name, newMilestone).ToObservable();
+ }
+
+ ///
+ /// Creates an Milestone for the specified repository. Any user with pull access to a repository can create an
+ /// Milestone.
+ ///
+ /// http://developer.github.com/v3/issues/milestones/#create-a-milestone
+ /// The owner of the repository
+ /// The name of the repository
+ /// The Milestone number
+ /// An instance describing the changes to make to the Milestone
+ ///
+ ///
+ public IObservable Update(string owner, string name, int number, MilestoneUpdate milestoneUpdate)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+ Ensure.ArgumentNotNull(milestoneUpdate, "milestoneUpdate");
+
+ return _client.Update(owner, name, number, milestoneUpdate).ToObservable();
+ }
+
+ ///
+ /// Deletes a milestone for the specified repository. Any user with pull access to a repository can create an
+ /// Milestone.
+ ///
+ /// http://developer.github.com/v3/issues/milestones/#delete-a-milestone
+ /// The owner of the repository
+ /// The name of the repository
+ /// The milestone number
+ ///
+ public IObservable Delete(string owner, string name, int number)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+
+ return _client.Delete(owner, name, number).ToObservable();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Octokit.Reactive/Helpers/ConnectionExtensions.cs b/Octokit.Reactive/Helpers/ConnectionExtensions.cs
index 91d6b30c1d..2a0fa79c85 100644
--- a/Octokit.Reactive/Helpers/ConnectionExtensions.cs
+++ b/Octokit.Reactive/Helpers/ConnectionExtensions.cs
@@ -7,20 +7,20 @@ namespace Octokit.Reactive.Internal
{
internal static class ConnectionExtensions
{
- public static IObservable GetAndFlattenAllPages(this IConnection connection, Uri url)
+ public static IObservable GetAndFlattenAllPages(this IConnection connection, Uri url, IDictionary parameters = null, string accepts = null)
{
- return GetPages(url, nextPageUrl => connection.GetAsync>(nextPageUrl).ToObservable());
+ return GetPages(url, parameters, (pageUrl, pageParams) => connection.GetAsync>(pageUrl, pageParams, accepts).ToObservable());
}
- static IObservable GetPages(Uri uri,
- Func>>> getPageFunc)
+ static IObservable GetPages(Uri uri, IDictionary parameters,
+ Func, IObservable>>> getPageFunc)
{
- return getPageFunc(uri).Expand(resp =>
+ return getPageFunc(uri, parameters).Expand(resp =>
{
var nextPageUrl = resp.ApiInfo.GetNextPageUrl();
return nextPageUrl == null
? Observable.Empty>>()
- : Observable.Defer(() => getPageFunc(nextPageUrl));
+ : Observable.Defer(() => getPageFunc(nextPageUrl, null));
})
.Where(resp => resp != null)
.SelectMany(resp => resp.BodyAsObject);
diff --git a/Octokit.Reactive/Octokit.Reactive.csproj b/Octokit.Reactive/Octokit.Reactive.csproj
index bfe5da0a47..7a0e66084d 100644
--- a/Octokit.Reactive/Octokit.Reactive.csproj
+++ b/Octokit.Reactive/Octokit.Reactive.csproj
@@ -71,6 +71,8 @@
Properties\SolutionInfo.cs
+
+
diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
index c0b63d6777..51a5a58f31 100644
--- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
+++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
@@ -61,6 +61,7 @@
+
diff --git a/Octokit.Tests.Integration/Reactive/ObservableMilestonesClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableMilestonesClientTests.cs
new file mode 100644
index 0000000000..2b28cd6fdc
--- /dev/null
+++ b/Octokit.Tests.Integration/Reactive/ObservableMilestonesClientTests.cs
@@ -0,0 +1,45 @@
+using System.Linq;
+using System.Net.Http.Headers;
+using System.Reactive.Linq;
+using System.Threading.Tasks;
+using Octokit.Reactive.Clients;
+using Xunit;
+
+namespace Octokit.Tests.Integration
+{
+ public class ObservableMilestonesClientTests
+ {
+ public class TheGetMethod
+ {
+ [IntegrationTest]
+ public async Task ReturnsSpecifiedMilestone()
+ {
+ var github = new GitHubClient(new ProductHeaderValue("OctokitTests"))
+ {
+ Credentials = Helper.Credentials
+ };
+ var client = new ObservableMilestonesClient(github);
+ var observable = client.Get("libgit2", "libgit2sharp", 1);
+ var milestone = await observable;
+
+ Assert.Equal(1, milestone.Number);
+ Assert.Equal("v0.4.0", milestone.Title);
+ Assert.Equal(7, milestone.ClosedIssues);
+ }
+
+ [IntegrationTest]
+ public void ReturnsAllMilestones()
+ {
+ var github = new GitHubClient(new ProductHeaderValue("OctokitTests"))
+ {
+ Credentials = Helper.Credentials
+ };
+ var client = new ObservableMilestonesClient(github);
+ var milestones = client.GetForRepository("libgit2", "libgit2sharp", new MilestoneRequest { State = ItemState.Closed }).ToList().Wait();
+
+ Assert.NotEmpty(milestones);
+ Assert.True(milestones.All(m => m.State == ItemState.Closed));
+ }
+ }
+ }
+}
diff --git a/Octokit.Tests/Clients/AssigneesClientTests.cs b/Octokit.Tests/Clients/AssigneesClientTests.cs
index d571ea5e65..443a059b3f 100644
--- a/Octokit.Tests/Clients/AssigneesClientTests.cs
+++ b/Octokit.Tests/Clients/AssigneesClientTests.cs
@@ -9,89 +9,92 @@
using Xunit;
using Xunit.Extensions;
-public class AssignessClientTests
+namespace Octokit.Tests.Clients
{
- public class TheGetForRepositoryMethod
+ public class AssignessClientTests
{
- [Fact]
- public void RequestsCorrectUrl()
+ public class TheGetForRepositoryMethod
{
- var connection = Substitute.For();
- var client = new AssigneesClient(connection);
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new AssigneesClient(connection);
- client.GetForRepository("fake", "repo");
+ client.GetForRepository("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"));
+ }
- [Fact]
- public async Task EnsuresNonNullArguments()
- {
- var client = new AssigneesClient(Substitute.For());
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new AssigneesClient(Substitute.For());
- await AssertEx.Throws(async () => await client.GetForRepository(null, "name"));
- await AssertEx.Throws(async () => await client.GetForRepository(null, ""));
- await AssertEx.Throws(async () => await client.GetForRepository("owner", null));
- await AssertEx.Throws(async () => await client.GetForRepository("", null));
+ await AssertEx.Throws(async () => await client.GetForRepository(null, "name"));
+ await AssertEx.Throws(async () => await client.GetForRepository(null, ""));
+ await AssertEx.Throws(async () => await client.GetForRepository("owner", null));
+ await AssertEx.Throws(async () => await client.GetForRepository("", null));
+ }
}
- }
- public class TheCheckAssigneeMethod
- {
- [Theory]
- [InlineData(HttpStatusCode.NoContent, true)]
- [InlineData(HttpStatusCode.NotFound, false)]
- public async Task RequestsCorrectValueForStatusCode(HttpStatusCode status, bool expected)
+ public class TheCheckAssigneeMethod
{
- var response = Task.Factory.StartNew>(() =>
- new ApiResponse