Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add repositoryId overloads to methods on I(Observable)IssueReactionsClient #1384

Merged
37 changes: 29 additions & 8 deletions Octokit.Reactive/Clients/IObservableIssueReactionsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,31 @@

namespace Octokit.Reactive
{
/// <summary>
/// A client for GitHub's Reactions API.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/reactions/">Reactions API documentation</a> for more information.
/// </remarks>
public interface IObservableIssueReactionsClient
{
/// <summary>
/// List reactions for a specified Issue.
/// </summary>
/// <remarks>https://developer.github.com/v3/reactions/#list-reactions-for-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 id</param>
IObservable<Reaction> GetAll(string owner, string name, int number);

/// <summary>
/// List reactions for a specified Issue.
/// </summary>
/// <remarks>https://developer.github.com/v3/reactions/#list-reactions-for-an-issue</remarks>
/// <param name="repositoryId">The ID of the repository</param>
/// <param name="number">The issue id</param>
IObservable<Reaction> GetAll(int repositoryId, int number);

/// <summary>
/// Creates a reaction for a specified Issue.
/// </summary>
Expand All @@ -12,17 +35,15 @@ public interface IObservableIssueReactionsClient
/// <param name="name">The name of the repository</param>
/// <param name="number">The issue id</param>
/// <param name="reaction">The reaction to create </param>
/// <returns></returns>
IObservable<Reaction> Create(string owner, string name, int number, NewReaction reaction);

/// <summary>
/// List reactions for a specified Issue.
/// Creates a reaction for a specified Issue.
/// </summary>
/// <remarks>https://developer.github.com/v3/reactions/#list-reactions-for-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 id</param>
/// <returns></returns>
IObservable<Reaction> GetAll(string owner, string name, int number);
/// <remarks>https://developer.github.com/v3/reactions/#create-reaction-for-an-issue</remarks>
/// <param name="repositoryId">The ID of the repository</param>
/// <param name="number">The issue id</param>
/// <param name="reaction">The reaction to create </param>
IObservable<Reaction> Create(int repositoryId, int number, NewReaction reaction);
}
}
55 changes: 42 additions & 13 deletions Octokit.Reactive/Clients/ObservableIssueReactionsClient.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
using Octokit.Reactive.Internal;
using System;
using System;
using System.Reactive.Threading.Tasks;
using Octokit.Reactive.Internal;

namespace Octokit.Reactive
{
/// <summary>
/// A client for GitHub's Reactions API.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/reactions/">Reactions API documentation</a> for more information.
/// </remarks>
public class ObservableIssueReactionsClient : IObservableIssueReactionsClient
{
readonly IIssueReactionsClient _client;
Expand All @@ -17,6 +23,32 @@ public ObservableIssueReactionsClient(IGitHubClient client)
_connection = client.Connection;
}

/// <summary>
/// List reactions for a specified Issue
/// </summary>
/// <remarks>https://developer.github.com/v3/reactions/#list-reactions-for-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 id</param>
public IObservable<Reaction> GetAll(string owner, string name, int number)
{
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Ensure.ArgumentNotNullOrEmptyString(name, "name");

return _connection.GetAndFlattenAllPages<Reaction>(ApiUrls.IssueReactions(owner, name, number), null, AcceptHeaders.ReactionsPreview);
}

/// <summary>
/// List reactions for a specified Issue.
/// </summary>
/// <remarks>https://developer.github.com/v3/reactions/#list-reactions-for-an-issue</remarks>
/// <param name="repositoryId">The ID of the repository</param>
/// <param name="number">The issue id</param>
public IObservable<Reaction> GetAll(int repositoryId, int number)
{
return _connection.GetAndFlattenAllPages<Reaction>(ApiUrls.IssueReactions(repositoryId, number), null, AcceptHeaders.ReactionsPreview);
}

/// <summary>
/// Creates a reaction for a specified Issue
/// </summary>
Expand All @@ -25,7 +57,6 @@ public ObservableIssueReactionsClient(IGitHubClient client)
/// <param name="name">The name of the repository</param>
/// <param name="number">The issue id</param>
/// <param name="reaction">The reaction to create</param>
/// <returns></returns>
public IObservable<Reaction> Create(string owner, string name, int number, NewReaction reaction)
{
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Expand All @@ -36,19 +67,17 @@ public IObservable<Reaction> Create(string owner, string name, int number, NewRe
}

/// <summary>
/// List reactions for a specified Issue
/// Creates a reaction for a specified Issue.
/// </summary>
/// <remarks>https://developer.github.com/v3/reactions/#list-reactions-for-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 id</param>
/// <returns></returns>
public IObservable<Reaction> GetAll(string owner, string name, int number)
/// <remarks>https://developer.github.com/v3/reactions/#create-reaction-for-an-issue</remarks>
/// <param name="repositoryId">The ID of the repository</param>
/// <param name="number">The issue id</param>
/// <param name="reaction">The reaction to create </param>
public IObservable<Reaction> Create(int repositoryId, int number, NewReaction reaction)
{
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Ensure.ArgumentNotNullOrEmptyString(name, "name");
Ensure.ArgumentNotNull(reaction, "reaction");

return _connection.GetAndFlattenAllPages<Reaction>(ApiUrls.IssueReactions(owner, name, number), null, AcceptHeaders.ReactionsPreview);
return _client.Create(repositoryId, number, reaction).ToObservable();
}
}
}
66 changes: 61 additions & 5 deletions Octokit.Tests.Integration/Clients/IssueReactionsClientTests.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
using Octokit;
using System;
using System.Threading.Tasks;
using Octokit;
using Octokit.Tests.Integration;
using Octokit.Tests.Integration.Helpers;
using System;
using System.Threading.Tasks;
using Xunit;

public class IssueReactionsClientTests
Expand All @@ -16,11 +16,49 @@ public class TheCreateReactionMethod : IDisposable
public TheCreateReactionMethod()
{
_github = Helper.GetAuthenticatedClient();
var repoName = Helper.MakeNameWithTimestamp("public-repo");

_issuesClient = _github.Issue;

var repoName = Helper.MakeNameWithTimestamp("public-repo");
_context = _github.CreateRepositoryContext(new NewRepository(repoName)).Result;
}

[IntegrationTest]
public async Task CanListReactions()
{
var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" };
var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue);

Assert.NotNull(issue);

var issueReaction = await _github.Reaction.Issue.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, new NewReaction(ReactionType.Heart));

var issueReactions = await _github.Reaction.Issue.GetAll(_context.RepositoryOwner, _context.RepositoryName, issue.Number);

Assert.NotEmpty(issueReactions);

Assert.Equal(issueReaction.Id, issueReactions[0].Id);
Assert.Equal(issueReaction.Content, issueReactions[0].Content);
}

[IntegrationTest]
public async Task CanListReactionsWithRepositoryId()
{
var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" };
var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue);

Assert.NotNull(issue);

var issueReaction = await _github.Reaction.Issue.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, new NewReaction(ReactionType.Heart));

var issueReactions = await _github.Reaction.Issue.GetAll(_context.Repository.Id, issue.Number);

Assert.NotEmpty(issueReactions);

Assert.Equal(issueReaction.Id, issueReactions[0].Id);
Assert.Equal(issueReaction.Content, issueReactions[0].Content);
}

[IntegrationTest]
public async Task CanCreateReaction()
{
Expand All @@ -40,10 +78,28 @@ public async Task CanCreateReaction()
Assert.Equal(issue.User.Id, issueReaction.User.Id);
}

[IntegrationTest]
public async Task CanCreateReactionWithRepositoryId()
{
var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" };
var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue);

Assert.NotNull(issue);

var issueReaction = await _github.Reaction.Issue.Create(_context.Repository.Id, issue.Number, new NewReaction(ReactionType.Heart));

Assert.NotNull(issueReaction);

Assert.IsType<Reaction>(issueReaction);

Assert.Equal(ReactionType.Heart, issueReaction.Content);

Assert.Equal(issue.User.Id, issueReaction.User.Id);
}

public void Dispose()
{
_context.Dispose();
}
}
}

64 changes: 52 additions & 12 deletions Octokit.Tests/Clients/IssueReactionsClientTests.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using NSubstitute;
using System;
using System;
using System.Threading.Tasks;
using NSubstitute;
using Xunit;

namespace Octokit.Tests.Clients
Expand All @@ -22,24 +22,35 @@ public class TheGetAllMethod
public async Task RequestsCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new ReactionsClient(connection);
var client = new IssueReactionsClient(connection);

client.Issue.GetAll("fake", "repo", 42);
await client.GetAll("fake", "repo", 42);

connection.Received().GetAll<Reaction>(Arg.Is<Uri>(u => u.ToString() == "repos/fake/repo/issues/42/reactions"), "application/vnd.github.squirrel-girl-preview");
}

[Fact]
public async Task EnsuresArgumentsNotNull()
public async Task RequestsCorrectUrlWithRepositoryId()
{
var connection = Substitute.For<IApiConnection>();
var client = new IssueReactionsClient(connection);

await client.GetAll(1, 42);

connection.Received().GetAll<Reaction>(Arg.Is<Uri>(u => u.ToString() == "repositories/1/issues/42/reactions"), "application/vnd.github.squirrel-girl-preview");
}

[Fact]
public async Task EnsuresNonNullArguments()
{
var connection = Substitute.For<IApiConnection>();
var client = new ReactionsClient(connection);

await Assert.ThrowsAsync<ArgumentNullException>(() => client.Issue.Create(null, "name", 1, new NewReaction(ReactionType.Heart)));
await Assert.ThrowsAsync<ArgumentException>(() => client.Issue.Create("", "name", 1, new NewReaction(ReactionType.Heart)));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Issue.Create("owner", null, 1, new NewReaction(ReactionType.Heart)));
await Assert.ThrowsAsync<ArgumentException>(() => client.Issue.Create("owner", "", 1, new NewReaction(ReactionType.Heart)));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Issue.Create("owner", "name", 1, null));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Issue.GetAll(null, "name", 1));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Issue.GetAll("owner", null, 1));

await Assert.ThrowsAsync<ArgumentException>(() => client.Issue.GetAll("", "name", 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.Issue.GetAll("owner", "", 1));
}
}

Expand All @@ -50,12 +61,41 @@ public void RequestsCorrectUrl()
{
NewReaction newReaction = new NewReaction(ReactionType.Heart);

var connection = Substitute.For<IApiConnection>();
var client = new IssueReactionsClient(connection);

client.Create("fake", "repo", 1, newReaction);

connection.Received().Post<Reaction>(Arg.Is<Uri>(u => u.ToString() == "repos/fake/repo/issues/1/reactions"), newReaction, "application/vnd.github.squirrel-girl-preview");
}

[Fact]
public void RequestsCorrectUrlWithRepositoryId()
{
NewReaction newReaction = new NewReaction(ReactionType.Heart);

var connection = Substitute.For<IApiConnection>();
var client = new IssueReactionsClient(connection);

client.Create(1, 1, newReaction);

connection.Received().Post<Reaction>(Arg.Is<Uri>(u => u.ToString() == "repositories/1/issues/1/reactions"), newReaction, "application/vnd.github.squirrel-girl-preview");
}

[Fact]
public async Task EnsuresNonNullArguments()
{
var connection = Substitute.For<IApiConnection>();
var client = new ReactionsClient(connection);

client.Issue.Create("fake", "repo", 1, newReaction);
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Issue.Create(null, "name", 1, new NewReaction(ReactionType.Heart)));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Issue.Create("owner", null, 1, new NewReaction(ReactionType.Heart)));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Issue.Create("owner", "name", 1, null));

await Assert.ThrowsAsync<ArgumentNullException>(() => client.Issue.Create(1, 1, null));

connection.Received().Post<Reaction>(Arg.Is<Uri>(u => u.ToString() == "repos/fake/repo/issues/1/reactions"), Arg.Any<object>(), "application/vnd.github.squirrel-girl-preview");
await Assert.ThrowsAsync<ArgumentException>(() => client.Issue.Create("", "name", 1, new NewReaction(ReactionType.Heart)));
await Assert.ThrowsAsync<ArgumentException>(() => client.Issue.Create("owner", "", 1, new NewReaction(ReactionType.Heart)));
}
}
}
Expand Down
Loading