mirror of
https://github.com/zoriya/octokit.net.git
synced 2025-12-06 07:16:09 +00:00
Implement AssigneesClient
Implement client to list and check available assignees for a repository
This commit is contained in:
24
Octokit.Reactive/IAssigneesClient.cs
Normal file
24
Octokit.Reactive/IAssigneesClient.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Octokit
|
||||
{
|
||||
public interface IAssigneesClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all the available assignees (owner + collaborators) to which issues may be assigned.
|
||||
/// </summary>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <returns></returns>
|
||||
Task<IReadOnlyList<User>> GetForRepository(string owner, string name);
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if a user is an assignee for a repository.
|
||||
/// </summary>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <param name="assignee">Username of the prospective assignee</param>
|
||||
/// <returns></returns>
|
||||
Task<bool> CheckAssignee(string owner, string name, string assignee);
|
||||
}
|
||||
}
|
||||
@@ -93,6 +93,7 @@
|
||||
<Compile Include="Clients\ObservableRepositoriesClient.cs" />
|
||||
<Compile Include="Clients\ObservableSshKeysClient.cs" />
|
||||
<Compile Include="Clients\ObservableUsersClient.cs" />
|
||||
<Compile Include="IAssigneesClient.cs" />
|
||||
<Compile Include="IObservableNotificationsClient.cs" />
|
||||
<Compile Include="Helpers\AuthorizationExtensions.cs" />
|
||||
<Compile Include="Helpers\ConnectionExtensions.cs" />
|
||||
|
||||
50
Octokit.Tests.Integration/AssigneesClientTests.cs
Normal file
50
Octokit.Tests.Integration/AssigneesClientTests.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Octokit;
|
||||
using Octokit.Tests.Integration;
|
||||
using Xunit;
|
||||
|
||||
public class AssigneesClientTests
|
||||
{
|
||||
readonly IGitHubClient _gitHubClient;
|
||||
readonly Repository _repository;
|
||||
readonly string _owner;
|
||||
|
||||
public AssigneesClientTests()
|
||||
{
|
||||
_gitHubClient = new GitHubClient("Test Runner User Agent")
|
||||
{
|
||||
Credentials = Helper.Credentials
|
||||
};
|
||||
var repoName = Helper.MakeNameWithTimestamp("public-repo");
|
||||
|
||||
_repository = _gitHubClient.Repository.Create(new NewRepository { Name = repoName }).Result;
|
||||
_owner = _repository.Owner.Login;
|
||||
}
|
||||
|
||||
[IntegrationTest]
|
||||
public async Task CanCheckAssignees()
|
||||
{
|
||||
var isAssigned = await
|
||||
_gitHubClient.Issue.Assignee.CheckAssignee(_owner, _repository.Name, "FakeHaacked");
|
||||
Assert.False(isAssigned);
|
||||
|
||||
// Repository owner is always an assignee
|
||||
isAssigned = await
|
||||
_gitHubClient.Issue.Assignee.CheckAssignee(_owner, _repository.Name, _owner);
|
||||
Assert.True(isAssigned);
|
||||
}
|
||||
|
||||
[IntegrationTest]
|
||||
public async Task CanListAssignees()
|
||||
{
|
||||
// Repository owner is always an assignee
|
||||
var assignees = await _gitHubClient.Issue.Assignee.GetForRepository(_owner, _repository.Name);
|
||||
Assert.True(assignees.Any(u => u.Login == Helper.Credentials.Login));
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Helper.DeleteRepo(_repository);
|
||||
}
|
||||
}
|
||||
@@ -55,6 +55,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AssigneesClientTests.cs" />
|
||||
<Compile Include="IntegrationTestAttribute.cs" />
|
||||
<Compile Include="IssuesClientTests.cs" />
|
||||
<Compile Include="MiscellaneousClientTests.cs" />
|
||||
|
||||
97
Octokit.Tests/Clients/AssigneesClientTests.cs
Normal file
97
Octokit.Tests/Clients/AssigneesClientTests.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using NSubstitute;
|
||||
using Octokit;
|
||||
using Octokit.Internal;
|
||||
using Octokit.Tests.Helpers;
|
||||
using Xunit;
|
||||
using Xunit.Extensions;
|
||||
|
||||
public class AssignessClientTests
|
||||
{
|
||||
public class TheGetForRepositoryMethod
|
||||
{
|
||||
[Fact]
|
||||
public void RequestsCorrectUrl()
|
||||
{
|
||||
var connection = Substitute.For<IApiConnection>();
|
||||
var client = new AssigneesClient(connection);
|
||||
|
||||
client.GetForRepository("fake", "repo");
|
||||
|
||||
connection.Received().GetAll<User>(Arg.Is<Uri>(u => u.ToString() == "/repos/fake/repo/assignees"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsuresNonNullArguments()
|
||||
{
|
||||
var client = new AssigneesClient(Substitute.For<IApiConnection>());
|
||||
|
||||
await AssertEx.Throws<ArgumentNullException>(async () => await client.GetForRepository(null, "name"));
|
||||
await AssertEx.Throws<ArgumentException>(async () => await client.GetForRepository(null, ""));
|
||||
await AssertEx.Throws<ArgumentNullException>(async () => await client.GetForRepository("owner", null));
|
||||
await AssertEx.Throws<ArgumentException>(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)
|
||||
{
|
||||
var response = Task.Factory.StartNew<IResponse<object>>(() =>
|
||||
new ApiResponse<object> { StatusCode = status });
|
||||
var connection = Substitute.For<IConnection>();
|
||||
connection.GetAsync<object>(Arg.Is<Uri>(u => u.ToString() == "/repos/foo/bar/assignees/cody"),
|
||||
null, null).Returns(response);
|
||||
var apiConnection = Substitute.For<IApiConnection>();
|
||||
apiConnection.Connection.Returns(connection);
|
||||
var client = new AssigneesClient(apiConnection);
|
||||
|
||||
var result = await client.CheckAssignee("foo", "bar", "cody");
|
||||
|
||||
Assert.Equal(expected, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ThrowsExceptionForInvalidStatusCode()
|
||||
{
|
||||
var response = Task.Factory.StartNew<IResponse<object>>(() =>
|
||||
new ApiResponse<object> { StatusCode = HttpStatusCode.Conflict });
|
||||
var connection = Substitute.For<IConnection>();
|
||||
connection.GetAsync<object>(Arg.Is<Uri>(u => u.ToString() == "/repos/foo/bar/assignees/cody"),
|
||||
null, null).Returns(response);
|
||||
var apiConnection = Substitute.For<IApiConnection>();
|
||||
apiConnection.Connection.Returns(connection);
|
||||
var client = new AssigneesClient(apiConnection);
|
||||
|
||||
AssertEx.Throws<ApiException>(async () => await client.CheckAssignee("foo", "bar", "cody"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task EnsuresNonNullArguments()
|
||||
{
|
||||
var client = new AssigneesClient(Substitute.For<IApiConnection>());
|
||||
|
||||
await AssertEx.Throws<ArgumentNullException>(async () => await client.CheckAssignee(null, "name", "tweety"));
|
||||
await AssertEx.Throws<ArgumentException>(async () => await client.CheckAssignee(null, "", "tweety"));
|
||||
await AssertEx.Throws<ArgumentNullException>(async () => await client.CheckAssignee("owner", null, "tweety"));
|
||||
await AssertEx.Throws<ArgumentException>(async () => await client.CheckAssignee("", null, "tweety"));
|
||||
await AssertEx.Throws<ArgumentNullException>(async () => await client.CheckAssignee("owner", "name", null));
|
||||
await AssertEx.Throws<ArgumentException>(async () => await client.CheckAssignee("owner", "name", ""));
|
||||
}
|
||||
}
|
||||
|
||||
public class TheCtor
|
||||
{
|
||||
[Fact]
|
||||
public void EnsuresArgument()
|
||||
{
|
||||
Assert.Throws<ArgumentNullException>(() => new AssigneesClient(null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,6 +60,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Authentication\CredentialsTests.cs" />
|
||||
<Compile Include="Clients\AssigneesClientTests.cs" />
|
||||
<Compile Include="Clients\IssuesClientTests.cs" />
|
||||
<Compile Include="Clients\NotificationsClientTests.cs" />
|
||||
<Compile Include="Clients\ReleasesClientTests.cs" />
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Authentication\CredentialsTests.cs" />
|
||||
<Compile Include="Clients\AssigneesClientTests.cs" />
|
||||
<Compile Include="Clients\IssuesClientTests.cs" />
|
||||
<Compile Include="Clients\MiscellaneousClientTests.cs" />
|
||||
<Compile Include="Clients\NotificationsClientTests.cs" />
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
Ensure.ArgumentNotNull(apiConnection, "apiConnection");
|
||||
|
||||
ApiConnection = apiConnection;
|
||||
Connection = apiConnection.Connection;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -23,5 +24,11 @@
|
||||
/// The API client's connection
|
||||
/// </value>
|
||||
protected IApiConnection ApiConnection {get; private set;}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the underlying <see cref="IConnection"/> used by the <see cref="IApiConnection"/>. This is useful
|
||||
/// for requests that need to access the HTTP response and not just the response model.
|
||||
/// </summary>
|
||||
protected IConnection Connection { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
55
Octokit/Clients/AssigneesClient.cs
Normal file
55
Octokit/Clients/AssigneesClient.cs
Normal file
@@ -0,0 +1,55 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Octokit
|
||||
{
|
||||
public class AssigneesClient : ApiClient, IAssigneesClient
|
||||
{
|
||||
public AssigneesClient(IApiConnection apiConnection) : base(apiConnection)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets all the available assignees (owner + collaborators) to which issues may be assigned.
|
||||
/// </summary>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <returns></returns>
|
||||
public async Task<IReadOnlyList<User>> GetForRepository(string owner, string name)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
|
||||
Ensure.ArgumentNotNullOrEmptyString(name, "name");
|
||||
|
||||
return await ApiConnection.GetAll<User>(ApiUrls.Assignees(owner, name));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if a user is an assignee for a repository.
|
||||
/// </summary>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <param name="assignee">Username of the prospective assignee</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> CheckAssignee(string owner, string name, string assignee)
|
||||
{
|
||||
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
|
||||
Ensure.ArgumentNotNullOrEmptyString(name, "name");
|
||||
Ensure.ArgumentNotNullOrEmptyString(assignee, "assignee");
|
||||
|
||||
try
|
||||
{
|
||||
var response = await Connection.GetAsync<object>(ApiUrls.CheckAssignee(owner, name, assignee), null, null);
|
||||
if (response.StatusCode != HttpStatusCode.NotFound && response.StatusCode != HttpStatusCode.NoContent)
|
||||
{
|
||||
throw new ApiException("Invalid Status Code returned. Expected a 204 or a 404", response.StatusCode);
|
||||
}
|
||||
return response.StatusCode == HttpStatusCode.NoContent;
|
||||
}
|
||||
catch (NotFoundException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,11 @@ namespace Octokit
|
||||
{
|
||||
public IssuesClient(IApiConnection apiConnection) : base(apiConnection)
|
||||
{
|
||||
Assignee = new AssigneesClient(apiConnection);
|
||||
}
|
||||
|
||||
public IAssigneesClient Assignee { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a single Issue by number./// </summary>
|
||||
/// <remarks>
|
||||
|
||||
@@ -34,15 +34,16 @@ namespace Octokit
|
||||
Ensure.ArgumentNotNull(connection, "connection");
|
||||
|
||||
Connection = connection;
|
||||
Authorization = new AuthorizationsClient(new ApiConnection(connection));
|
||||
Issue = new IssuesClient(new ApiConnection(connection));
|
||||
var apiConnection = new ApiConnection(connection);
|
||||
Authorization = new AuthorizationsClient(apiConnection);
|
||||
Issue = new IssuesClient(apiConnection);
|
||||
Miscellaneous = new MiscellaneousClient(connection);
|
||||
Notification = new NotificationsClient(new ApiConnection(connection));
|
||||
Organization = new OrganizationsClient(new ApiConnection(connection));
|
||||
Repository = new RepositoriesClient(new ApiConnection(connection));
|
||||
Release = new ReleasesClient(new ApiConnection(connection));
|
||||
User = new UsersClient(new ApiConnection(connection));
|
||||
SshKey = new SshKeysClient(new ApiConnection(connection));
|
||||
Notification = new NotificationsClient(apiConnection);
|
||||
Organization = new OrganizationsClient(apiConnection);
|
||||
Repository = new RepositoriesClient(apiConnection);
|
||||
Release = new ReleasesClient(apiConnection);
|
||||
User = new UsersClient(apiConnection);
|
||||
SshKey = new SshKeysClient(apiConnection);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -188,6 +188,28 @@ namespace Octokit
|
||||
return "/repos/{0}/{1}/issues/{2}".FormatUri(owner, name, number);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="Uri"/> that returns all of the assignees to which issues may be assigned.
|
||||
/// </summary>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <returns></returns>
|
||||
public static Uri Assignees(string owner, string name)
|
||||
{
|
||||
return "/repos/{0}/{1}/assignees".FormatUri(owner, name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the <see cref="Uri"/> that returns a 204 if the login belongs to an assignee of the repository.
|
||||
/// Otherwire returns a 404.
|
||||
/// </summary>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <param name="login">The login for the user</param>
|
||||
/// <returns></returns>
|
||||
public static Uri CheckAssignee(string owner, string name, string login)
|
||||
{
|
||||
return "/repos/{0}/{1}/assignees/{2}".FormatUri(owner, name, login);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Octokit
|
||||
/// <summary>
|
||||
/// Gets the connection for making HTTP requests.
|
||||
/// </summary>
|
||||
protected IConnection Connection { get; private set; }
|
||||
public IConnection Connection { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the API resource at the specified URI.
|
||||
|
||||
@@ -11,6 +11,11 @@ namespace Octokit
|
||||
/// </summary>
|
||||
public interface IApiConnection
|
||||
{
|
||||
/// <summary>
|
||||
/// The underlying connection.
|
||||
/// </summary>
|
||||
IConnection Connection { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the API resource at the specified URI.
|
||||
/// </summary>
|
||||
|
||||
25
Octokit/IAssigneesClient.cs
Normal file
25
Octokit/IAssigneesClient.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Octokit
|
||||
{
|
||||
public interface IAssigneesClient
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all the available assignees (owner + collaborators) to which issues may be assigned.
|
||||
/// </summary>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <returns></returns>
|
||||
Task<IReadOnlyList<User>> GetForRepository(string owner, string name);
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if a user is an assignee for a repository.
|
||||
/// </summary>
|
||||
/// <param name="owner">The owner of the repository</param>
|
||||
/// <param name="name">The name of the repository</param>
|
||||
/// <param name="assignee">Username of the prospective assignee</param>
|
||||
/// <returns></returns>
|
||||
Task<bool> CheckAssignee(string owner, string name, string assignee);
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,8 @@ namespace Octokit
|
||||
{
|
||||
public interface IIssuesClient
|
||||
{
|
||||
IAssigneesClient Assignee { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a single Issue by number.
|
||||
/// </summary>
|
||||
|
||||
@@ -81,8 +81,10 @@
|
||||
<Compile Include="..\SolutionInfo.cs">
|
||||
<Link>Properties\SolutionInfo.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Clients\AssigneesClient.cs" />
|
||||
<Compile Include="Clients\IssuesClient.cs" />
|
||||
<Compile Include="Exceptions\NotFoundException.cs" />
|
||||
<Compile Include="IAssigneesClient.cs" />
|
||||
<Compile Include="IIssuesClient.cs" />
|
||||
<Compile Include="Models\Issue.cs" />
|
||||
<Compile Include="Models\IssueRequest.cs" />
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
<Compile Include="Authentication\TokenAuthenticator.cs" />
|
||||
<Compile Include="Clients\ApiClient.cs" />
|
||||
<Compile Include="Clients\ApiPagination.cs" />
|
||||
<Compile Include="Clients\AssigneesClient.cs" />
|
||||
<Compile Include="Clients\AuthorizationsClient.cs" />
|
||||
<Compile Include="Clients\IssuesClient.cs" />
|
||||
<Compile Include="Clients\MiscellaneousClient.cs" />
|
||||
@@ -146,6 +147,7 @@
|
||||
<Compile Include="Http\RateLimit.cs" />
|
||||
<Compile Include="Http\ReadOnlyPagedCollection.cs" />
|
||||
<Compile Include="IApiPagination.cs" />
|
||||
<Compile Include="IAssigneesClient.cs" />
|
||||
<Compile Include="IAuthorizationsClient.cs" />
|
||||
<Compile Include="IGitHubClient.cs" />
|
||||
<Compile Include="IIssuesClient.cs" />
|
||||
|
||||
Reference in New Issue
Block a user