mirror of
https://github.com/zoriya/octokit.net.git
synced 2026-06-03 11:05:56 +00:00
Merge pull request #160 from brlinton/observable-issues
Observable Issues Client
This commit is contained in:
@@ -69,3 +69,4 @@ nunit-*.xml
|
||||
*.userprefs
|
||||
packaging/
|
||||
tools/FAKE.Core
|
||||
*.ncrunch*
|
||||
@@ -0,0 +1,140 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Octokit.Reactive
|
||||
{
|
||||
public interface IObservableIssuesClient
|
||||
{
|
||||
IObservableAssigneesClient Assignee { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Client for managing milestones.
|
||||
/// </summary>
|
||||
IObservableMilestonesClient Milestone { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a single Issue by number.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#get-a-single-issue
|
||||
/// </remarks>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <param name="number">The issue number</param>
|
||||
/// <returns></returns>
|
||||
[SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get",
|
||||
Justification = "Method makes a network request")]
|
||||
IObservable<Issue> Get(string owner, string name, int number);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all open issues assigned to the authenticated user across all the authenticated user’s visible
|
||||
/// repositories including owned repositories, member repositories, and organization repositories.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Issues are sorted by the create date descending.
|
||||
/// http://developer.github.com/v3/issues/#list-issues
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
IObservable<Issue> GetAllForCurrent();
|
||||
|
||||
/// <summary>
|
||||
/// Gets all issues across all the authenticated user’s visible repositories including owned repositories,
|
||||
/// member repositories, and organization repositories.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#list-issues
|
||||
/// </remarks>
|
||||
/// <param name="request">Used to filter and sort the list of issues returned</param>
|
||||
/// <returns></returns>
|
||||
IObservable<Issue> GetAllForCurrent(IssueRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all open issues assigned to the authenticated user across owned and member repositories for the
|
||||
/// authenticated user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Issues are sorted by the create date descending.
|
||||
/// http://developer.github.com/v3/issues/#list-issues
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
IObservable<Issue> GetAllForOwnedAndMemberRepositories();
|
||||
|
||||
/// <summary>
|
||||
/// Gets all issues across owned and member repositories for the authenticated user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#list-issues
|
||||
/// </remarks>
|
||||
/// <param name="request">Used to filter and sort the list of issues returned</param>
|
||||
/// <returns></returns>
|
||||
IObservable<Issue> GetAllForOwnedAndMemberRepositories(IssueRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all open issues assigned to the authenticated user for a given organization for the authenticated user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#list-issues
|
||||
/// </remarks>
|
||||
/// <param name="organization">The name of the organization</param>
|
||||
/// <returns></returns>
|
||||
IObservable<Issue> GetAllForOrganization(string organization);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all issues for a given organization for the authenticated user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#list-issues
|
||||
/// </remarks>
|
||||
/// <param name="organization">The name of the organization</param>
|
||||
/// <param name="request">Used to filter and sort the list of issues returned</param>
|
||||
/// <returns></returns>
|
||||
IObservable<Issue> GetAllForOrganization(string organization, IssueRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all open issues assigned to the authenticated user for the repository.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#list-issues-for-a-repository
|
||||
/// </remarks>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <returns></returns>
|
||||
IObservable<Issue> GetForRepository(string owner, string name);
|
||||
|
||||
/// <summary>
|
||||
/// Gets issues for a repository.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#list-issues-for-a-repository
|
||||
/// </remarks>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <param name="request">Used to filter and sort the list of issues returned</param>
|
||||
/// <returns></returns>
|
||||
IObservable<Issue> GetForRepository(string owner, string name, RepositoryIssueRequest request);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an issue for the specified repository. Any user with pull access to a repository can create an
|
||||
/// issue.
|
||||
/// </summary>
|
||||
/// <remarks>http://developer.github.com/v3/issues/#create-an-issue</remarks>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <param name="newIssue">A <see cref="NewIssue"/> instance describing the new issue to create</param>
|
||||
/// <returns></returns>
|
||||
IObservable<Issue> Create(string owner, string name, NewIssue newIssue);
|
||||
|
||||
/// <summary>
|
||||
/// Creates an issue for the specified repository. Any user with pull access to a repository can create an
|
||||
/// issue.
|
||||
/// </summary>
|
||||
/// <remarks>http://developer.github.com/v3/issues/#create-an-issue</remarks>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <param name="number">The issue number</param>
|
||||
/// <param name="issueUpdate">An <see cref="IssueUpdate"/> instance describing the changes to make to the issue
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
IObservable<Issue> Update(string owner, string name, int number, IssueUpdate issueUpdate);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reactive.Threading.Tasks;
|
||||
using Octokit.Reactive.Clients;
|
||||
using Octokit.Reactive.Internal;
|
||||
|
||||
namespace Octokit.Reactive
|
||||
{
|
||||
public class ObservableIssuesClient : IObservableIssuesClient
|
||||
{
|
||||
readonly IIssuesClient _client;
|
||||
readonly IConnection _connection;
|
||||
|
||||
public IObservableAssigneesClient Assignee { get; private set; }
|
||||
public IObservableMilestonesClient Milestone { get; private set; }
|
||||
|
||||
public ObservableIssuesClient(IGitHubClient client)
|
||||
{
|
||||
Ensure.ArgumentNotNull(client, "client");
|
||||
|
||||
_client = client.Issue;
|
||||
_connection = client.Connection;
|
||||
Assignee = new ObservableAssigneesClient(client);
|
||||
Milestone = new ObservableMilestonesClient(client);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a single Issue by number./// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#get-a-single-issue
|
||||
/// </remarks>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <param name="number">The issue number</param>
|
||||
/// <returns></returns>
|
||||
public IObservable<Issue> Get(string owner, string name, int number)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
|
||||
Ensure.ArgumentNotNullOrEmptyString(name, "name");
|
||||
|
||||
return _client.Get(owner, name, number).ToObservable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all open issues assigned to the authenticated user across all the authenticated user’s visible
|
||||
/// repositories including owned repositories, member repositories, and organization repositories.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Issues are sorted by the create date descending.
|
||||
/// http://developer.github.com/v3/issues/#list-issues
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
public IObservable<Issue> GetAllForCurrent()
|
||||
{
|
||||
return GetAllForCurrent(new IssueRequest());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all issues across all the authenticated user’s visible repositories including owned repositories,
|
||||
/// member repositories, and organization repositories.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#list-issues
|
||||
/// </remarks>
|
||||
/// <param name="request">Used to filter and sort the list of issues returned</param>
|
||||
/// <returns></returns>
|
||||
public IObservable<Issue> GetAllForCurrent(IssueRequest request)
|
||||
{
|
||||
Ensure.ArgumentNotNull(request, "request");
|
||||
|
||||
return _connection.GetAndFlattenAllPages<Issue>(ApiUrls.Issues(), request.ToParametersDictionary());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all open issues assigned to the authenticated user across owned and member repositories for the
|
||||
/// authenticated user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Issues are sorted by the create date descending.
|
||||
/// http://developer.github.com/v3/issues/#list-issues
|
||||
/// </remarks>
|
||||
/// <returns></returns>
|
||||
public IObservable<Issue> GetAllForOwnedAndMemberRepositories()
|
||||
{
|
||||
return GetAllForOwnedAndMemberRepositories(new IssueRequest());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all issues across owned and member repositories for the authenticated user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#list-issues
|
||||
/// </remarks>
|
||||
/// <param name="request">Used to filter and sort the list of issues returned</param>
|
||||
/// <returns></returns>
|
||||
public IObservable<Issue> GetAllForOwnedAndMemberRepositories(IssueRequest request)
|
||||
{
|
||||
Ensure.ArgumentNotNull(request, "request");
|
||||
|
||||
return _connection.GetAndFlattenAllPages<Issue>(ApiUrls.IssuesForOwnedAndMember(), request.ToParametersDictionary());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all open issues assigned to the authenticated user for a given organization for the authenticated user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#list-issues
|
||||
/// </remarks>
|
||||
/// <param name="organization">The name of the organization</param>
|
||||
/// <returns></returns>
|
||||
public IObservable<Issue> GetAllForOrganization(string organization)
|
||||
{
|
||||
return GetAllForOrganization(organization, new IssueRequest());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all issues for a given organization for the authenticated user.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#list-issues
|
||||
/// </remarks>
|
||||
/// <param name="organization">The name of the organization</param>
|
||||
/// <param name="request">Used to filter and sort the list of issues returned</param>
|
||||
/// <returns></returns>
|
||||
public IObservable<Issue> GetAllForOrganization(string organization, IssueRequest request)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(organization, "organization");
|
||||
Ensure.ArgumentNotNull(request, "request");
|
||||
|
||||
return _connection.GetAndFlattenAllPages<Issue>(ApiUrls.Issues(organization), request.ToParametersDictionary());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all open issues assigned to the authenticated user for the repository.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#list-issues-for-a-repository
|
||||
/// </remarks>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <returns></returns>
|
||||
public IObservable<Issue> GetForRepository(string owner, string name)
|
||||
{
|
||||
return GetForRepository(owner, name, new RepositoryIssueRequest());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets issues for a repository.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// http://developer.github.com/v3/issues/#list-issues-for-a-repository
|
||||
/// </remarks>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <param name="request">Used to filter and sort the list of issues returned</param>
|
||||
/// <returns></returns>
|
||||
public IObservable<Issue> GetForRepository(string owner, string name, RepositoryIssueRequest request)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
|
||||
Ensure.ArgumentNotNullOrEmptyString(name, "name");
|
||||
Ensure.ArgumentNotNull(request, "request");
|
||||
|
||||
return _connection.GetAndFlattenAllPages<Issue>(ApiUrls.Issues(owner, name), request.ToParametersDictionary());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an issue for the specified repository. Any user with pull access to a repository can create an
|
||||
/// issue.
|
||||
/// </summary>
|
||||
/// <remarks>http://developer.github.com/v3/issues/#create-an-issue</remarks>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <param name="newIssue">A <see cref="NewIssue"/> instance describing the new issue to create</param>
|
||||
/// <returns></returns>
|
||||
public IObservable<Issue> Create(string owner, string name, NewIssue newIssue)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
|
||||
Ensure.ArgumentNotNullOrEmptyString(name, "name");
|
||||
Ensure.ArgumentNotNull(newIssue, "newIssue");
|
||||
|
||||
return _client.Create(owner, name, newIssue).ToObservable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an issue for the specified repository. Any user with pull access to a repository can create an
|
||||
/// issue.
|
||||
/// </summary>
|
||||
/// <remarks>http://developer.github.com/v3/issues/#create-an-issue</remarks>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <param name="number">The issue number</param>
|
||||
/// <param name="issueUpdate">An <see cref="IssueUpdate"/> instance describing the changes to make to the issue
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
public IObservable<Issue> Update(string owner, string name, int number, IssueUpdate issueUpdate)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
|
||||
Ensure.ArgumentNotNullOrEmptyString(name, "name");
|
||||
Ensure.ArgumentNotNull(issueUpdate, "issueUpdate");
|
||||
|
||||
return _client.Update(owner, name, number, issueUpdate).ToObservable();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,9 @@
|
||||
<Compile Include="..\SolutionInfo.cs">
|
||||
<Link>Properties\SolutionInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Clients\IObservableIssuesClient.cs" />
|
||||
<Compile Include="Clients\IObservableMilestonesClient.cs" />
|
||||
<Compile Include="Clients\ObservableIssuesClient.cs" />
|
||||
<Compile Include="Clients\ObservableMilestonesClient.cs" />
|
||||
<Compile Include="Clients\ObservableAssigneesClient.cs" />
|
||||
<Compile Include="Clients\IObservableCommitStatusClient.cs" />
|
||||
@@ -123,4 +125,4 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -63,6 +63,7 @@
|
||||
<Compile Include="IntegrationTestAttribute.cs" />
|
||||
<Compile Include="IssuesClientTests.cs" />
|
||||
<Compile Include="MiscellaneousClientTests.cs" />
|
||||
<Compile Include="Reactive\ObservableIssuesClientTests.cs" />
|
||||
<Compile Include="Reactive\ObservableMilestonesClientTests.cs" />
|
||||
<Compile Include="Reactive\ObservableRepositoriesClientTests.cs" />
|
||||
<Compile Include="ReleasesClientTests.cs" />
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
using Octokit.Reactive;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Octokit.Tests.Integration
|
||||
{
|
||||
public class ObservableIssuesClientTests : IDisposable
|
||||
{
|
||||
readonly ObservableIssuesClient client;
|
||||
readonly string repoName;
|
||||
readonly Repository createdRepository;
|
||||
|
||||
public ObservableIssuesClientTests()
|
||||
{
|
||||
var github = new GitHubClient(new ProductHeaderValue("OctokitTests"))
|
||||
{
|
||||
Credentials = Helper.Credentials
|
||||
};
|
||||
|
||||
client = new ObservableIssuesClient(github);
|
||||
repoName = Helper.MakeNameWithTimestamp("public-repo");
|
||||
var result = github.Repository.Create(new NewRepository { Name = repoName }).Result;
|
||||
createdRepository = result;
|
||||
}
|
||||
|
||||
[IntegrationTest]
|
||||
public async Task ReturnsSpecifiedIssue()
|
||||
{
|
||||
var observable = client.Get("libgit2", "libgit2sharp", 1);
|
||||
var issue = await observable;
|
||||
|
||||
Assert.Equal(1, issue.Number);
|
||||
Assert.Equal("Change License ", issue.Title);
|
||||
}
|
||||
|
||||
[IntegrationTest]
|
||||
public void ReturnsAllIssuesForARepository()
|
||||
{
|
||||
var issues = client.GetForRepository("libgit2", "libgit2sharp").ToList().Wait();
|
||||
|
||||
Assert.NotEmpty(issues);
|
||||
}
|
||||
|
||||
[IntegrationTest]
|
||||
public async void ReturnsAllIssuesForCurrentUser()
|
||||
{
|
||||
var newIssue = new NewIssue("Integration test issue");
|
||||
var createResult = await client.Create(createdRepository.Owner.Name, repoName, newIssue);
|
||||
|
||||
var issues = client.GetAllForCurrent().ToList().Wait();
|
||||
|
||||
Assert.NotEmpty(issues);
|
||||
}
|
||||
|
||||
[IntegrationTest]
|
||||
public async void ReturnsAllIssuesForOwnedAndMemberRepositories()
|
||||
{
|
||||
var newIssue = new NewIssue("Integration test issue");
|
||||
var createResult = await client.Create(createdRepository.Owner.Name, repoName, newIssue);
|
||||
var result = client.GetAllForOwnedAndMemberRepositories().ToList().Wait();
|
||||
|
||||
Assert.NotEmpty(result);
|
||||
}
|
||||
|
||||
[IntegrationTest]
|
||||
public async void CanCreateAndUpdateIssues()
|
||||
{
|
||||
var newIssue = new NewIssue("Integration test issue");
|
||||
|
||||
var createResult = await client.Create(createdRepository.Owner.Name, repoName, newIssue);
|
||||
var updateResult = await client.Update(createdRepository.Owner.Name, repoName, createResult.Number, new IssueUpdate { Title = "Modified integration test issue" });
|
||||
|
||||
Assert.Equal("Modified integration test issue", updateResult.Title);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Helper.DeleteRepo(createdRepository);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,6 +106,7 @@
|
||||
<Compile Include="Helpers\StringExtensionsTests.cs" />
|
||||
<Compile Include="Clients\RepositoriesClientTests.cs" />
|
||||
<Compile Include="Reactive\AuthorizationExtensionsTests.cs" />
|
||||
<Compile Include="Reactive\ObservableIssuesClientTests.cs" />
|
||||
<Compile Include="Reactive\ObservableMilestonesClientTests.cs" />
|
||||
<Compile Include="Reactive\ObservableRepositoriesClientTests.cs" />
|
||||
<Compile Include="SimpleJsonSerializerTests.cs" />
|
||||
|
||||
@@ -0,0 +1,364 @@
|
||||
using NSubstitute;
|
||||
using Octokit.Internal;
|
||||
using Octokit.Reactive;
|
||||
using Octokit.Tests.Helpers;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Xunit;
|
||||
|
||||
namespace Octokit.Tests.Reactive
|
||||
{
|
||||
public class ObservableIssuesClientTests
|
||||
{
|
||||
public class TheGetMethod
|
||||
{
|
||||
[Fact]
|
||||
public void GetsFromClientIssueIssue()
|
||||
{
|
||||
var gitHubClient = Substitute.For<IGitHubClient>();
|
||||
var client = new ObservableIssuesClient(gitHubClient);
|
||||
|
||||
client.Get("fake", "repo", 42);
|
||||
|
||||
gitHubClient.Issue.Received().Get("fake", "repo", 42);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsuresNonNullArguments()
|
||||
{
|
||||
var client = new ObservableIssuesClient(Substitute.For<IGitHubClient>());
|
||||
|
||||
await AssertEx.Throws<ArgumentNullException>(async () => await client.Get(null, "name", 1));
|
||||
await AssertEx.Throws<ArgumentNullException>(async () => await client.Get("owner", null, 1));
|
||||
await AssertEx.Throws<ArgumentException>(async () => await client.Get(null, "", 1));
|
||||
await AssertEx.Throws<ArgumentException>(async () => await client.Get("", null, 1));
|
||||
}
|
||||
}
|
||||
|
||||
public class TheGetForRepositoryMethod
|
||||
{
|
||||
[Fact]
|
||||
public void ReturnsEveryPageOfIssues()
|
||||
{
|
||||
var firstPageUrl = new Uri("repos/fake/repo/issues", UriKind.Relative);
|
||||
var secondPageUrl = new Uri("https://example.com/page/2");
|
||||
var firstPageLinks = new Dictionary<string, Uri> { { "next", secondPageUrl } };
|
||||
var firstPageResponse = new ApiResponse<List<Issue>>
|
||||
{
|
||||
BodyAsObject = new List<Issue>
|
||||
{
|
||||
new Issue {Number = 1},
|
||||
new Issue {Number = 2},
|
||||
new Issue {Number = 3},
|
||||
},
|
||||
ApiInfo = CreateApiInfo(firstPageLinks)
|
||||
};
|
||||
var thirdPageUrl = new Uri("https://example.com/page/3");
|
||||
var secondPageLinks = new Dictionary<string, Uri> { { "next", thirdPageUrl } };
|
||||
var secondPageResponse = new ApiResponse<List<Issue>>
|
||||
{
|
||||
BodyAsObject = new List<Issue>
|
||||
{
|
||||
new Issue {Number = 4},
|
||||
new Issue {Number = 5},
|
||||
new Issue {Number = 6},
|
||||
},
|
||||
ApiInfo = CreateApiInfo(secondPageLinks)
|
||||
};
|
||||
var lastPageResponse = new ApiResponse<List<Issue>>
|
||||
{
|
||||
BodyAsObject = new List<Issue>
|
||||
{
|
||||
new Issue {Number = 7},
|
||||
},
|
||||
ApiInfo = CreateApiInfo(new Dictionary<string, Uri>())
|
||||
};
|
||||
var gitHubClient = Substitute.For<IGitHubClient>();
|
||||
gitHubClient.Connection.GetAsync<List<Issue>>(Arg.Is(firstPageUrl),
|
||||
Arg.Is<Dictionary<string, string>>(d => d.Count == 4
|
||||
&& d["direction"] == "desc"
|
||||
&& d["state"] == "open"
|
||||
&& d["sort"] == "created"
|
||||
&& d["filter"] == "assigned"), Arg.Any<string>())
|
||||
.Returns(Task.Factory.StartNew<IResponse<List<Issue>>>(() => firstPageResponse));
|
||||
gitHubClient.Connection.GetAsync<List<Issue>>(secondPageUrl, null, null)
|
||||
.Returns(Task.Factory.StartNew<IResponse<List<Issue>>>(() => secondPageResponse));
|
||||
gitHubClient.Connection.GetAsync<List<Issue>>(thirdPageUrl, null, null)
|
||||
.Returns(Task.Factory.StartNew<IResponse<List<Issue>>>(() => lastPageResponse));
|
||||
var client = new ObservableIssuesClient(gitHubClient);
|
||||
|
||||
var results = client.GetForRepository("fake", "repo").ToArray().Wait();
|
||||
|
||||
Assert.Equal(7, results.Length);
|
||||
Assert.Equal(firstPageResponse.BodyAsObject[0].Number, results[0].Number);
|
||||
Assert.Equal(secondPageResponse.BodyAsObject[1].Number, results[4].Number);
|
||||
Assert.Equal(lastPageResponse.BodyAsObject[0].Number, results[6].Number);
|
||||
}
|
||||
}
|
||||
|
||||
public class TheGetAllForOwnedAndMemberRepositoriesMethod
|
||||
{
|
||||
[Fact]
|
||||
public void ReturnsEveryPageOfIssues()
|
||||
{
|
||||
var firstPageUrl = new Uri("user/issues", UriKind.Relative);
|
||||
var secondPageUrl = new Uri("https://example.com/page/2");
|
||||
var firstPageLinks = new Dictionary<string, Uri> { { "next", secondPageUrl } };
|
||||
var firstPageResponse = new ApiResponse<List<Issue>>
|
||||
{
|
||||
BodyAsObject = new List<Issue>
|
||||
{
|
||||
new Issue {Number = 1},
|
||||
new Issue {Number = 2},
|
||||
new Issue {Number = 3},
|
||||
},
|
||||
ApiInfo = CreateApiInfo(firstPageLinks)
|
||||
};
|
||||
var thirdPageUrl = new Uri("https://example.com/page/3");
|
||||
var secondPageLinks = new Dictionary<string, Uri> { { "next", thirdPageUrl } };
|
||||
var secondPageResponse = new ApiResponse<List<Issue>>
|
||||
{
|
||||
BodyAsObject = new List<Issue>
|
||||
{
|
||||
new Issue {Number = 4},
|
||||
new Issue {Number = 5},
|
||||
new Issue {Number = 6},
|
||||
},
|
||||
ApiInfo = CreateApiInfo(secondPageLinks)
|
||||
};
|
||||
var lastPageResponse = new ApiResponse<List<Issue>>
|
||||
{
|
||||
BodyAsObject = new List<Issue>
|
||||
{
|
||||
new Issue {Number = 7},
|
||||
},
|
||||
ApiInfo = CreateApiInfo(new Dictionary<string, Uri>())
|
||||
};
|
||||
var gitHubClient = Substitute.For<IGitHubClient>();
|
||||
gitHubClient.Connection.GetAsync<List<Issue>>(Arg.Is(firstPageUrl),
|
||||
Arg.Is<Dictionary<string, string>>(d => d.Count == 4
|
||||
&& d["direction"] == "desc"
|
||||
&& d["state"] == "open"
|
||||
&& d["sort"] == "created"
|
||||
&& d["filter"] == "assigned"), Arg.Any<string>())
|
||||
.Returns(Task.Factory.StartNew<IResponse<List<Issue>>>(() => firstPageResponse));
|
||||
gitHubClient.Connection.GetAsync<List<Issue>>(secondPageUrl, null, null)
|
||||
.Returns(Task.Factory.StartNew<IResponse<List<Issue>>>(() => secondPageResponse));
|
||||
gitHubClient.Connection.GetAsync<List<Issue>>(thirdPageUrl, null, null)
|
||||
.Returns(Task.Factory.StartNew<IResponse<List<Issue>>>(() => lastPageResponse));
|
||||
var client = new ObservableIssuesClient(gitHubClient);
|
||||
|
||||
var results = client.GetAllForOwnedAndMemberRepositories().ToArray().Wait();
|
||||
|
||||
Assert.Equal(7, results.Length);
|
||||
Assert.Equal(firstPageResponse.BodyAsObject[0].Number, results[0].Number);
|
||||
Assert.Equal(secondPageResponse.BodyAsObject[1].Number, results[4].Number);
|
||||
Assert.Equal(lastPageResponse.BodyAsObject[0].Number, results[6].Number);
|
||||
}
|
||||
}
|
||||
|
||||
public class TheGetAllForOrganizationMethod
|
||||
{
|
||||
[Fact]
|
||||
public void ReturnsEveryPageOfIssues()
|
||||
{
|
||||
var firstPageUrl = new Uri("orgs/test/issues", UriKind.Relative);
|
||||
var secondPageUrl = new Uri("https://example.com/page/2");
|
||||
var firstPageLinks = new Dictionary<string, Uri> { { "next", secondPageUrl } };
|
||||
var firstPageResponse = new ApiResponse<List<Issue>>
|
||||
{
|
||||
BodyAsObject = new List<Issue>
|
||||
{
|
||||
new Issue {Number = 1},
|
||||
new Issue {Number = 2},
|
||||
new Issue {Number = 3},
|
||||
},
|
||||
ApiInfo = CreateApiInfo(firstPageLinks)
|
||||
};
|
||||
var thirdPageUrl = new Uri("https://example.com/page/3");
|
||||
var secondPageLinks = new Dictionary<string, Uri> { { "next", thirdPageUrl } };
|
||||
var secondPageResponse = new ApiResponse<List<Issue>>
|
||||
{
|
||||
BodyAsObject = new List<Issue>
|
||||
{
|
||||
new Issue {Number = 4},
|
||||
new Issue {Number = 5},
|
||||
new Issue {Number = 6},
|
||||
},
|
||||
ApiInfo = CreateApiInfo(secondPageLinks)
|
||||
};
|
||||
var lastPageResponse = new ApiResponse<List<Issue>>
|
||||
{
|
||||
BodyAsObject = new List<Issue>
|
||||
{
|
||||
new Issue {Number = 7},
|
||||
},
|
||||
ApiInfo = CreateApiInfo(new Dictionary<string, Uri>())
|
||||
};
|
||||
var gitHubClient = Substitute.For<IGitHubClient>();
|
||||
gitHubClient.Connection.GetAsync<List<Issue>>(Arg.Is(firstPageUrl),
|
||||
Arg.Is<Dictionary<string, string>>(d => d.Count == 4
|
||||
&& d["direction"] == "desc"
|
||||
&& d["state"] == "open"
|
||||
&& d["sort"] == "created"
|
||||
&& d["filter"] == "assigned"), Arg.Any<string>())
|
||||
.Returns(Task.Factory.StartNew<IResponse<List<Issue>>>(() => firstPageResponse));
|
||||
gitHubClient.Connection.GetAsync<List<Issue>>(secondPageUrl, null, null)
|
||||
.Returns(Task.Factory.StartNew<IResponse<List<Issue>>>(() => secondPageResponse));
|
||||
gitHubClient.Connection.GetAsync<List<Issue>>(thirdPageUrl, null, null)
|
||||
.Returns(Task.Factory.StartNew<IResponse<List<Issue>>>(() => lastPageResponse));
|
||||
var client = new ObservableIssuesClient(gitHubClient);
|
||||
|
||||
var results = client.GetAllForOrganization("test").ToArray().Wait();
|
||||
|
||||
Assert.Equal(7, results.Length);
|
||||
Assert.Equal(firstPageResponse.BodyAsObject[0].Number, results[0].Number);
|
||||
Assert.Equal(secondPageResponse.BodyAsObject[1].Number, results[4].Number);
|
||||
Assert.Equal(lastPageResponse.BodyAsObject[0].Number, results[6].Number);
|
||||
}
|
||||
}
|
||||
|
||||
public class TheGetAllForCurrentMethod
|
||||
{
|
||||
[Fact]
|
||||
public void ReturnsEveryPageOfIssues()
|
||||
{
|
||||
var firstPageUrl = new Uri("issues", UriKind.Relative);
|
||||
var secondPageUrl = new Uri("https://example.com/page/2");
|
||||
var firstPageLinks = new Dictionary<string, Uri> { { "next", secondPageUrl } };
|
||||
var firstPageResponse = new ApiResponse<List<Issue>>
|
||||
{
|
||||
BodyAsObject = new List<Issue>
|
||||
{
|
||||
new Issue {Number = 1},
|
||||
new Issue {Number = 2},
|
||||
new Issue {Number = 3},
|
||||
},
|
||||
ApiInfo = CreateApiInfo(firstPageLinks)
|
||||
};
|
||||
var thirdPageUrl = new Uri("https://example.com/page/3");
|
||||
var secondPageLinks = new Dictionary<string, Uri> { { "next", thirdPageUrl } };
|
||||
var secondPageResponse = new ApiResponse<List<Issue>>
|
||||
{
|
||||
BodyAsObject = new List<Issue>
|
||||
{
|
||||
new Issue {Number = 4},
|
||||
new Issue {Number = 5},
|
||||
new Issue {Number = 6},
|
||||
},
|
||||
ApiInfo = CreateApiInfo(secondPageLinks)
|
||||
};
|
||||
var lastPageResponse = new ApiResponse<List<Issue>>
|
||||
{
|
||||
BodyAsObject = new List<Issue>
|
||||
{
|
||||
new Issue {Number = 7},
|
||||
},
|
||||
ApiInfo = CreateApiInfo(new Dictionary<string, Uri>())
|
||||
};
|
||||
var gitHubClient = Substitute.For<IGitHubClient>();
|
||||
gitHubClient.Connection.GetAsync<List<Issue>>(Arg.Is(firstPageUrl),
|
||||
Arg.Is<Dictionary<string, string>>(d => d.Count == 4
|
||||
&& d["direction"] == "desc"
|
||||
&& d["state"] == "open"
|
||||
&& d["sort"] == "created"
|
||||
&& d["filter"] == "assigned"), Arg.Any<string>())
|
||||
.Returns(Task.Factory.StartNew<IResponse<List<Issue>>>(() => firstPageResponse));
|
||||
gitHubClient.Connection.GetAsync<List<Issue>>(secondPageUrl, null, null)
|
||||
.Returns(Task.Factory.StartNew<IResponse<List<Issue>>>(() => secondPageResponse));
|
||||
gitHubClient.Connection.GetAsync<List<Issue>>(thirdPageUrl, null, null)
|
||||
.Returns(Task.Factory.StartNew<IResponse<List<Issue>>>(() => lastPageResponse));
|
||||
var client = new ObservableIssuesClient(gitHubClient);
|
||||
|
||||
var results = client.GetAllForCurrent().ToArray().Wait();
|
||||
|
||||
Assert.Equal(7, results.Length);
|
||||
Assert.Equal(firstPageResponse.BodyAsObject[0].Number, results[0].Number);
|
||||
Assert.Equal(secondPageResponse.BodyAsObject[1].Number, results[4].Number);
|
||||
Assert.Equal(lastPageResponse.BodyAsObject[0].Number, results[6].Number);
|
||||
}
|
||||
}
|
||||
|
||||
public class TheCreateMethod
|
||||
{
|
||||
[Fact]
|
||||
public void CreatesFromClientIssueIssue()
|
||||
{
|
||||
var newIssue = new NewIssue("some title");
|
||||
var gitHubClient = Substitute.For<IGitHubClient>();
|
||||
var client = new ObservableIssuesClient(gitHubClient);
|
||||
|
||||
client.Create("fake", "repo", newIssue);
|
||||
|
||||
gitHubClient.Issue.Received().Create("fake", "repo", newIssue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsuresArgumentsNotNull()
|
||||
{
|
||||
var gitHubClient = Substitute.For<IGitHubClient>();
|
||||
var client = new ObservableIssuesClient(gitHubClient);
|
||||
|
||||
AssertEx.Throws<ArgumentNullException>(async () => await
|
||||
client.Create(null, "name", new NewIssue("title")));
|
||||
AssertEx.Throws<ArgumentException>(async () => await
|
||||
client.Create("", "name", new NewIssue("x")));
|
||||
AssertEx.Throws<ArgumentNullException>(async () => await
|
||||
client.Create("owner", null, new NewIssue("x")));
|
||||
AssertEx.Throws<ArgumentException>(async () => await
|
||||
client.Create("owner", "", new NewIssue("x")));
|
||||
AssertEx.Throws<ArgumentNullException>(async () => await
|
||||
client.Create("owner", "name", null));
|
||||
}
|
||||
}
|
||||
|
||||
public class TheUpdateMethod
|
||||
{
|
||||
[Fact]
|
||||
public void UpdatesClientIssueIssue()
|
||||
{
|
||||
var IssueUpdate = new IssueUpdate();
|
||||
var gitHubClient = Substitute.For<IGitHubClient>();
|
||||
var client = new ObservableIssuesClient(gitHubClient);
|
||||
|
||||
client.Update("fake", "repo", 42, IssueUpdate);
|
||||
|
||||
gitHubClient.Issue.Received().Update("fake", "repo", 42, IssueUpdate);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsuresArgumentsNotNull()
|
||||
{
|
||||
var gitHubClient = Substitute.For<IGitHubClient>();
|
||||
var client = new ObservableIssuesClient(gitHubClient);
|
||||
|
||||
AssertEx.Throws<ArgumentNullException>(async () => await
|
||||
client.Create(null, "name", new NewIssue("title")));
|
||||
AssertEx.Throws<ArgumentException>(async () => await
|
||||
client.Create("", "name", new NewIssue("x")));
|
||||
AssertEx.Throws<ArgumentNullException>(async () => await
|
||||
client.Create("owner", null, new NewIssue("x")));
|
||||
AssertEx.Throws<ArgumentException>(async () => await
|
||||
client.Create("owner", "", new NewIssue("x")));
|
||||
AssertEx.Throws<ArgumentNullException>(async () => await
|
||||
client.Create("owner", "name", null));
|
||||
}
|
||||
}
|
||||
|
||||
public class TheCtor
|
||||
{
|
||||
[Fact]
|
||||
public void EnsuresArgument()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => new IssuesClient(null));
|
||||
}
|
||||
}
|
||||
|
||||
static ApiInfo CreateApiInfo(IDictionary<string, Uri> links)
|
||||
{
|
||||
return new ApiInfo(links, new List<string>(), new List<string>(), "etag", new RateLimit(new Dictionary<string, string>()));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user