diff --git a/Octokit.Reactive/Clients/IObservableIssueCommentsClient.cs b/Octokit.Reactive/Clients/IObservableIssueCommentsClient.cs index 906a8814..4d387dae 100644 --- a/Octokit.Reactive/Clients/IObservableIssueCommentsClient.cs +++ b/Octokit.Reactive/Clients/IObservableIssueCommentsClient.cs @@ -4,6 +4,12 @@ using System.Reactive; namespace Octokit.Reactive { + /// + /// A client for GitHub's Issue Comments API. + /// + /// + /// See the Issue Comments API documentation for more information. + /// public interface IObservableIssueCommentsClient { /// @@ -13,20 +19,35 @@ namespace Octokit.Reactive /// The owner of the repository /// The name of the repository /// The issue comment id - /// The s for the specified Issue Comment. [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", Justification = "Method makes a network request")] IObservable Get(string owner, string name, int id); + /// + /// Gets a single Issue Comment by id. + /// + /// http://developer.github.com/v3/issues/comments/#get-a-single-comment + /// The ID of the repository + /// The issue comment id + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", + Justification = "Method makes a network request")] + IObservable Get(int repositoryId, int id); + /// /// Gets Issue Comments for a repository. /// /// http://developer.github.com/v3/issues/comments/#list-comments-in-a-repository /// The owner of the repository /// The name of the repository - /// The list of s for the specified Repository. IObservable GetAllForRepository(string owner, string name); + /// + /// Gets Issue Comments for a repository. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-in-a-repository + /// The ID of the repository + IObservable GetAllForRepository(int repositoryId); + /// /// Gets Issue Comments for a repository. /// @@ -34,9 +55,16 @@ namespace Octokit.Reactive /// The owner of the repository /// The name of the repository /// Options for changing the API response - /// The list of s for the specified Repository. IObservable GetAllForRepository(string owner, string name, ApiOptions options); + /// + /// Gets Issue Comments for a repository. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-in-a-repository + /// The ID of the repository + /// Options for changing the API response + IObservable GetAllForRepository(int repositoryId, ApiOptions options); + /// /// Gets Issue Comments for a specified Issue. /// @@ -44,9 +72,16 @@ namespace Octokit.Reactive /// The owner of the repository /// The name of the repository /// The issue number - /// The list of s for the specified Issue. IObservable GetAllForIssue(string owner, string name, int number); + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The ID of the repository + /// The issue number + IObservable GetAllForIssue(int repositoryId, int number); + /// /// Gets Issue Comments for a specified Issue. /// @@ -55,9 +90,17 @@ namespace Octokit.Reactive /// The name of the repository /// The issue number /// Options for changing the API response - /// The list of s for the specified Issue. IObservable GetAllForIssue(string owner, string name, int number, ApiOptions options); + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The ID of the repository + /// The issue number + /// Options for changing the API response + IObservable GetAllForIssue(int repositoryId, int number, ApiOptions options); + /// /// Creates a new Issue Comment for a specified Issue. /// @@ -66,9 +109,17 @@ namespace Octokit.Reactive /// The name of the repository /// The number of the issue /// The text of the new comment - /// The that was just created. IObservable Create(string owner, string name, int number, string newComment); + /// + /// Creates a new Issue Comment for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#create-a-comment + /// The ID of the repository + /// The number of the issue + /// The text of the new comment + IObservable Create(int repositoryId, int number, string newComment); + /// /// Updates a specified Issue Comment. /// @@ -77,9 +128,17 @@ namespace Octokit.Reactive /// The name of the repository /// The comment id /// The modified comment - /// The that was just updated. IObservable Update(string owner, string name, int id, string commentUpdate); + /// + /// Updates a specified Issue Comment. + /// + /// http://developer.github.com/v3/issues/comments/#edit-a-comment + /// The ID of the repository + /// The comment id + /// The modified comment + IObservable Update(int repositoryId, int id, string commentUpdate); + /// /// Deletes the specified Issue Comment /// @@ -87,7 +146,14 @@ namespace Octokit.Reactive /// The owner of the repository /// The name of the repository /// The comment id - /// IObservable Delete(string owner, string name, int id); + + /// + /// Deletes the specified Issue Comment + /// + /// http://developer.github.com/v3/issues/comments/#delete-a-comment + /// The ID of the repository + /// The comment id + IObservable Delete(int repositoryId, int id); } } diff --git a/Octokit.Reactive/Clients/ObservableIssueCommentsClient.cs b/Octokit.Reactive/Clients/ObservableIssueCommentsClient.cs index f0011cf2..37b42c67 100644 --- a/Octokit.Reactive/Clients/ObservableIssueCommentsClient.cs +++ b/Octokit.Reactive/Clients/ObservableIssueCommentsClient.cs @@ -5,6 +5,12 @@ using Octokit.Reactive.Internal; namespace Octokit.Reactive { + /// + /// A client for GitHub's Issue Comments API. + /// + /// + /// See the Issue Comments API documentation for more information. + /// public class ObservableIssueCommentsClient : IObservableIssueCommentsClient { readonly IIssueCommentsClient _client; @@ -25,7 +31,6 @@ namespace Octokit.Reactive /// The owner of the repository /// The name of the repository /// The issue comment id - /// The s for the specified Issue Comment. public IObservable Get(string owner, string name, int id) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -34,13 +39,23 @@ namespace Octokit.Reactive return _client.Get(owner, name, id).ToObservable(); } + /// + /// Gets a single Issue Comment by id. + /// + /// http://developer.github.com/v3/issues/comments/#get-a-single-comment + /// The ID of the repository + /// The issue comment id + public IObservable Get(int repositoryId, int id) + { + return _client.Get(repositoryId, id).ToObservable(); + } + /// /// Gets Issue Comments for a repository. /// /// http://developer.github.com/v3/issues/comments/#list-comments-in-a-repository /// The owner of the repository /// The name of the repository - /// The list of s for the specified Repository. public IObservable GetAllForRepository(string owner, string name) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -49,6 +64,16 @@ namespace Octokit.Reactive return GetAllForRepository(owner, name, ApiOptions.None); } + /// + /// Gets Issue Comments for a repository. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-in-a-repository + /// The ID of the repository + public IObservable GetAllForRepository(int repositoryId) + { + return GetAllForRepository(repositoryId, ApiOptions.None); + } + /// /// Gets Issue Comments for a repository. /// @@ -56,7 +81,6 @@ namespace Octokit.Reactive /// The owner of the repository /// The name of the repository /// Options for changing the API response - /// The list of s for the specified Repository. public IObservable GetAllForRepository(string owner, string name, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -66,6 +90,19 @@ namespace Octokit.Reactive return _connection.GetAndFlattenAllPages(ApiUrls.IssueComments(owner, name), null, AcceptHeaders.ReactionsPreview, options); } + /// + /// Gets Issue Comments for a repository. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-in-a-repository + /// The ID of the repository + /// Options for changing the API response + public IObservable GetAllForRepository(int repositoryId, ApiOptions options) + { + Ensure.ArgumentNotNull(options, "options"); + + return _connection.GetAndFlattenAllPages(ApiUrls.IssueComments(repositoryId), options); + } + /// /// Gets Issue Comments for a specified Issue. /// @@ -73,7 +110,6 @@ namespace Octokit.Reactive /// The owner of the repository /// The name of the repository /// The issue number - /// The list of s for the specified Issue. public IObservable GetAllForIssue(string owner, string name, int number) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -82,6 +118,17 @@ namespace Octokit.Reactive return GetAllForIssue(owner, name, number, ApiOptions.None); } + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The ID of the repository + /// The issue number + public IObservable GetAllForIssue(int repositoryId, int number) + { + return GetAllForIssue(repositoryId, number, ApiOptions.None); + } + /// /// Gets Issue Comments for a specified Issue. /// @@ -90,7 +137,6 @@ namespace Octokit.Reactive /// The name of the repository /// The issue number /// Options for changing the API response - /// The list of s for the specified Issue. public IObservable GetAllForIssue(string owner, string name, int number, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -100,6 +146,20 @@ namespace Octokit.Reactive return _connection.GetAndFlattenAllPages(ApiUrls.IssueComments(owner, name, number), null, AcceptHeaders.ReactionsPreview, options); } + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The ID of the repository + /// The issue number + /// Options for changing the API response + public IObservable GetAllForIssue(int repositoryId, int number, ApiOptions options) + { + Ensure.ArgumentNotNull(options, "options"); + + return _connection.GetAndFlattenAllPages(ApiUrls.IssueComments(repositoryId, number), options); + } + /// /// Creates a new Issue Comment for a specified Issue. /// @@ -108,7 +168,6 @@ namespace Octokit.Reactive /// The name of the repository /// The number of the issue /// The text of the new comment - /// The that was just created. public IObservable Create(string owner, string name, int number, string newComment) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -118,6 +177,20 @@ namespace Octokit.Reactive return _client.Create(owner, name, number, newComment).ToObservable(); } + /// + /// Creates a new Issue Comment for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#create-a-comment + /// The ID of the repository + /// The number of the issue + /// The text of the new comment + public IObservable Create(int repositoryId, int number, string newComment) + { + Ensure.ArgumentNotNull(newComment, "newComment"); + + return _client.Create(repositoryId, number, newComment).ToObservable(); + } + /// /// Updates a specified Issue Comment. /// @@ -126,7 +199,6 @@ namespace Octokit.Reactive /// The name of the repository /// The comment id /// The modified comment - /// The that was just updated. public IObservable Update(string owner, string name, int id, string commentUpdate) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -136,6 +208,20 @@ namespace Octokit.Reactive return _client.Update(owner, name, id, commentUpdate).ToObservable(); } + /// + /// Updates a specified Issue Comment. + /// + /// http://developer.github.com/v3/issues/comments/#edit-a-comment + /// The ID of the repository + /// The comment id + /// The modified comment + public IObservable Update(int repositoryId, int id, string commentUpdate) + { + Ensure.ArgumentNotNull(commentUpdate, "commentUpdate"); + + return _client.Update(repositoryId, id, commentUpdate).ToObservable(); + } + /// /// Deletes the specified Issue Comment /// @@ -143,7 +229,6 @@ namespace Octokit.Reactive /// The owner of the repository /// The name of the repository /// The comment id - /// public IObservable Delete(string owner, string name, int id) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -151,5 +236,16 @@ namespace Octokit.Reactive return _client.Delete(owner, name, id).ToObservable(); } + + /// + /// Deletes the specified Issue Comment + /// + /// http://developer.github.com/v3/issues/comments/#delete-a-comment + /// The ID of the repository + /// The comment id + public IObservable Delete(int repositoryId, int id) + { + return _client.Delete(repositoryId, id).ToObservable(); + } } -} +} \ No newline at end of file diff --git a/Octokit.Tests.Integration/Clients/IssueCommentsClientTests.cs b/Octokit.Tests.Integration/Clients/IssueCommentsClientTests.cs index ceb375a0..071a841e 100644 --- a/Octokit.Tests.Integration/Clients/IssueCommentsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/IssueCommentsClientTests.cs @@ -1,53 +1,475 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Threading.Tasks; using Octokit; using Octokit.Tests.Integration; +using Octokit.Tests.Integration.Helpers; using Xunit; public class IssueCommentsClientTests { - private readonly IIssueCommentsClient _issueCommentsClient; - - public IssueCommentsClientTests() + public class TheGetMethod { - var github = Helper.GetAuthenticatedClient(); - _issueCommentsClient = github.Issue.Comment; + readonly IIssueCommentsClient _issueCommentsClient; + + const string owner = "octokit"; + const string name = "octokit.net"; + const int id = 12067722; + const int repositoryId = 7528679; + + public TheGetMethod() + { + var github = Helper.GetAuthenticatedClient(); + + _issueCommentsClient = github.Issue.Comment; + } + + [IntegrationTest] + public async Task ReturnsIssueComment() + { + var comment = await _issueCommentsClient.Get(owner, name, id); + + Assert.NotNull(comment); + } + + [IntegrationTest] + public async Task ReturnsIssueCommentWithRepositoryId() + { + var comment = await _issueCommentsClient.Get(repositoryId, id); + + Assert.NotNull(comment); + } } - [IntegrationTest] - public async Task CanDeserializeIssueCommentWhenGettingAllForRepository() + public class TheGetAllForRepositoryMethod { - var comments = await _issueCommentsClient.GetAllForRepository("alfhenrik-test", "repo-with-issue-comment-reactions"); + readonly IIssueCommentsClient _issueCommentsClient; - Assert.NotEmpty(comments); - var comment = comments[0]; - Assert.NotNull(comment.Reactions); - Assert.Equal(3, comment.Reactions.TotalCount); - Assert.Equal(1, comment.Reactions.Plus1); - Assert.Equal(1, comment.Reactions.Hooray); - Assert.Equal(1, comment.Reactions.Heart); - Assert.Equal(0, comment.Reactions.Laugh); - Assert.Equal(0, comment.Reactions.Confused); - Assert.Equal(0, comment.Reactions.Minus1); + const string owner = "octokit"; + const string name = "octokit.net"; + const int repositoryId = 7528679; + + public TheGetAllForRepositoryMethod() + { + var github = Helper.GetAuthenticatedClient(); + + _issueCommentsClient = github.Issue.Comment; + } + + [IntegrationTest] + public async Task ReturnsIssueComments() + { + var issueComments = await _issueCommentsClient.GetAllForRepository(owner, name); + + Assert.NotEmpty(issueComments); + } + + [IntegrationTest] + public async Task ReturnsIssueCommentsWithRepositoryId() + { + var issueComments = await _issueCommentsClient.GetAllForRepository(repositoryId); + + Assert.NotEmpty(issueComments); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfIssueCommentsWithoutStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var issueComments = await _issueCommentsClient.GetAllForRepository(owner, name, options); + + Assert.Equal(5, issueComments.Count); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfIssueCommentsWithRepositoryIdWithoutStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var issueComments = await _issueCommentsClient.GetAllForRepository(repositoryId, options); + + Assert.Equal(5, issueComments.Count); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfIssueCommentsWithStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var issueComments = await _issueCommentsClient.GetAllForRepository(owner, name, options); + + Assert.Equal(5, issueComments.Count); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfIssueCommentsWithRepositoryIdWithStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var issueComments = await _issueCommentsClient.GetAllForRepository(repositoryId, options); + + Assert.Equal(5, issueComments.Count); + } + + [IntegrationTest] + public async Task ReturnsDistinctResultsBasedOnStartPage() + { + var startOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var firstPageIssueComments = await _issueCommentsClient.GetAllForRepository(owner, name, startOptions); + + var skipStartOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var secondPageIssueComments = await _issueCommentsClient.GetAllForRepository(owner, name, skipStartOptions); + + Assert.NotEqual(firstPageIssueComments[0].Id, secondPageIssueComments[0].Id); + Assert.NotEqual(firstPageIssueComments[1].Id, secondPageIssueComments[1].Id); + Assert.NotEqual(firstPageIssueComments[2].Id, secondPageIssueComments[2].Id); + Assert.NotEqual(firstPageIssueComments[3].Id, secondPageIssueComments[3].Id); + Assert.NotEqual(firstPageIssueComments[4].Id, secondPageIssueComments[4].Id); + } + + [IntegrationTest] + public async Task ReturnsDistinctResultsBasedOnStartPageWithRepositoryId() + { + var startOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var firstPageIssueComments = await _issueCommentsClient.GetAllForRepository(repositoryId, startOptions); + + var skipStartOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var secondPageIssueComments = await _issueCommentsClient.GetAllForRepository(repositoryId, skipStartOptions); + + Assert.NotEqual(firstPageIssueComments[0].Id, secondPageIssueComments[0].Id); + Assert.NotEqual(firstPageIssueComments[1].Id, secondPageIssueComments[1].Id); + Assert.NotEqual(firstPageIssueComments[2].Id, secondPageIssueComments[2].Id); + Assert.NotEqual(firstPageIssueComments[3].Id, secondPageIssueComments[3].Id); + Assert.NotEqual(firstPageIssueComments[4].Id, secondPageIssueComments[4].Id); + } } - [IntegrationTest] - public async Task CanDeserializeIssueComment() + public class TheGetAllForIssueMethod { - var comments = await _issueCommentsClient.GetAllForIssue("alfhenrik-test", "repo-with-issue-comment-reactions", 1); + readonly IIssueCommentsClient _issueCommentsClient; - Assert.NotEmpty(comments); - var comment = comments[0]; - Assert.NotNull(comment.Reactions); - Assert.Equal(3, comment.Reactions.TotalCount); - Assert.Equal(1, comment.Reactions.Plus1); - Assert.Equal(1, comment.Reactions.Hooray); - Assert.Equal(1, comment.Reactions.Heart); - Assert.Equal(0, comment.Reactions.Laugh); - Assert.Equal(0, comment.Reactions.Confused); - Assert.Equal(0, comment.Reactions.Minus1); + const string owner = "octokit"; + const string name = "octokit.net"; + const int number = 1115; + const int repositoryId = 7528679; + + public TheGetAllForIssueMethod() + { + var github = Helper.GetAuthenticatedClient(); + + _issueCommentsClient = github.Issue.Comment; + } + + [IntegrationTest] + public async Task ReturnsIssueComments() + { + var issueComments = await _issueCommentsClient.GetAllForIssue(owner, name, number); + + Assert.NotEmpty(issueComments); + } + + [IntegrationTest] + public async Task ReturnsIssueCommentsWithRepositoryId() + { + var issueComments = await _issueCommentsClient.GetAllForIssue(repositoryId, number); + + Assert.NotEmpty(issueComments); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfIssueCommentsWithoutStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var issueComments = await _issueCommentsClient.GetAllForIssue(owner, name, number, options); + + Assert.Equal(5, issueComments.Count); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfIssueCommentsWithRepositoryIdWithoutStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var issueComments = await _issueCommentsClient.GetAllForIssue(repositoryId, number, options); + + Assert.Equal(5, issueComments.Count); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfIssueCommentsWithStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var issueComments = await _issueCommentsClient.GetAllForIssue(owner, name, number, options); + + Assert.Equal(5, issueComments.Count); + } + + [IntegrationTest] + public async Task ReturnsCorrectCountOfIssueCommentsWithRepositoryIdWithStart() + { + var options = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var issueComments = await _issueCommentsClient.GetAllForIssue(repositoryId, number, options); + + Assert.Equal(5, issueComments.Count); + } + + [IntegrationTest] + public async Task ReturnsDistinctResultsBasedOnStartPage() + { + var startOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var firstPageIssueComments = await _issueCommentsClient.GetAllForIssue(owner, name, number, startOptions); + + var skipStartOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var secondPageIssueComments = await _issueCommentsClient.GetAllForIssue(owner, name, number, skipStartOptions); + + Assert.NotEqual(firstPageIssueComments[0].Id, secondPageIssueComments[0].Id); + Assert.NotEqual(firstPageIssueComments[1].Id, secondPageIssueComments[1].Id); + Assert.NotEqual(firstPageIssueComments[2].Id, secondPageIssueComments[2].Id); + Assert.NotEqual(firstPageIssueComments[3].Id, secondPageIssueComments[3].Id); + Assert.NotEqual(firstPageIssueComments[4].Id, secondPageIssueComments[4].Id); + } + + [IntegrationTest] + public async Task ReturnsDistinctResultsBasedOnStartPageWithRepositoryId() + { + var startOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1 + }; + + var firstPageIssueComments = await _issueCommentsClient.GetAllForIssue(repositoryId, number, startOptions); + + var skipStartOptions = new ApiOptions + { + PageSize = 5, + PageCount = 1, + StartPage = 2 + }; + + var secondPageIssueComments = await _issueCommentsClient.GetAllForIssue(repositoryId, number, skipStartOptions); + + Assert.NotEqual(firstPageIssueComments[0].Id, secondPageIssueComments[0].Id); + Assert.NotEqual(firstPageIssueComments[1].Id, secondPageIssueComments[1].Id); + Assert.NotEqual(firstPageIssueComments[2].Id, secondPageIssueComments[2].Id); + Assert.NotEqual(firstPageIssueComments[3].Id, secondPageIssueComments[3].Id); + Assert.NotEqual(firstPageIssueComments[4].Id, secondPageIssueComments[4].Id); + } + } + + public class TheCreateMethod + { + readonly IIssueCommentsClient _issueCommentsClient; + readonly RepositoryContext _context; + readonly IIssuesClient _issuesClient; + + public TheCreateMethod() + { + var gitHubClient = Helper.GetAuthenticatedClient(); + + var repoName = Helper.MakeNameWithTimestamp("public-repo"); + + _context = gitHubClient.CreateRepositoryContext(new NewRepository(repoName)).Result; + + _issuesClient = gitHubClient.Issue; + _issueCommentsClient = gitHubClient.Issue.Comment; + } + + [IntegrationTest] + public async Task ReturnsIssueComment() + { + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, new NewIssue("Super Issue 1")); + + var comment = await _issueCommentsClient.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, "test comment 1"); + + var loadedComment = await _issueCommentsClient.Get(_context.RepositoryOwner, _context.RepositoryName, comment.Id); + + Assert.Equal(comment.Id, loadedComment.Id); + Assert.Equal(comment.Body, loadedComment.Body); + } + + [IntegrationTest] + public async Task ReturnsIssueCommentWithRepositoryId() + { + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, new NewIssue("Super Issue 2")); + + var comment = await _issueCommentsClient.Create(_context.Repository.Id, issue.Number, "test comment 2"); + + var loadedComment = await _issueCommentsClient.Get(_context.Repository.Id, comment.Id); + + Assert.Equal(comment.Id, loadedComment.Id); + Assert.Equal(comment.Body, loadedComment.Body); + } + } + + public class TheUpdateMethod + { + readonly IIssueCommentsClient _issueCommentsClient; + readonly RepositoryContext _context; + readonly IIssuesClient _issuesClient; + + public TheUpdateMethod() + { + var gitHubClient = Helper.GetAuthenticatedClient(); + + var repoName = Helper.MakeNameWithTimestamp("public-repo"); + + _context = gitHubClient.CreateRepositoryContext(new NewRepository(repoName)).Result; + + _issuesClient = gitHubClient.Issue; + _issueCommentsClient = gitHubClient.Issue.Comment; + } + + [IntegrationTest] + public async Task UpdateIssueComment() + { + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, new NewIssue("Super Issue 1")); + + var comment = await _issueCommentsClient.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, "test comment 1"); + var commentId = comment.Id; + + var beforeComment = await _issueCommentsClient.Get(_context.RepositoryOwner, _context.RepositoryName, commentId); + + await _issueCommentsClient.Update(_context.RepositoryOwner, _context.RepositoryName, commentId, "test comment 2"); + + var afterComment = await _issueCommentsClient.Get(_context.RepositoryOwner, _context.RepositoryName, commentId); + + Assert.Equal(beforeComment.Id, afterComment.Id); + Assert.NotEqual(beforeComment.Body, afterComment.Body); + Assert.Equal("test comment 2", afterComment.Body); + } + + [IntegrationTest] + public async Task UpdateIssueWithRepositoryId() + { + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, new NewIssue("Super Issue 1")); + + var comment = await _issueCommentsClient.Create(_context.Repository.Id, issue.Number, "test comment 1"); + var commentId = comment.Id; + + var beforeComment = await _issueCommentsClient.Get(_context.Repository.Id, commentId); + + await _issueCommentsClient.Update(_context.Repository.Id, commentId, "test comment 2"); + + var afterComment = await _issueCommentsClient.Get(_context.Repository.Id, commentId); + + Assert.Equal(beforeComment.Id, afterComment.Id); + Assert.NotEqual(beforeComment.Body, afterComment.Body); + Assert.Equal("test comment 2", afterComment.Body); + } + } + + public class TheDeleteMethod + { + readonly IIssueCommentsClient _issueCommentsClient; + readonly RepositoryContext _context; + readonly IIssuesClient _issuesClient; + + public TheDeleteMethod() + { + var gitHubClient = Helper.GetAuthenticatedClient(); + + var repoName = Helper.MakeNameWithTimestamp("public-repo"); + + _context = gitHubClient.CreateRepositoryContext(new NewRepository(repoName)).Result; + + _issuesClient = gitHubClient.Issue; + _issueCommentsClient = gitHubClient.Issue.Comment; + } + + [IntegrationTest] + public async Task DeleteIssueComment() + { + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, new NewIssue("Super Issue 1")); + + var comment = await _issueCommentsClient.Create(_context.RepositoryOwner, _context.RepositoryName, issue.Number, "test comment 1"); + + await _issueCommentsClient.Delete(_context.RepositoryOwner, _context.RepositoryName, comment.Id); + + await Assert.ThrowsAsync(() => _issueCommentsClient.Get(_context.RepositoryOwner, _context.RepositoryName, comment.Id)); + } + + [IntegrationTest] + public async Task DeleteIssueWithRepositoryId() + { + var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, new NewIssue("Super Issue 1")); + + var comment = await _issueCommentsClient.Create(_context.Repository.Id, issue.Number, "test comment 1"); + + await _issueCommentsClient.Delete(_context.Repository.Id, comment.Id); + + await Assert.ThrowsAsync(() => _issueCommentsClient.Get(_context.Repository.Id, comment.Id)); + } } } diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index aa34483d..3b51a013 100644 --- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj +++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj @@ -151,7 +151,6 @@ - diff --git a/Octokit.Tests.Integration/Reactive/ObservableIssueCommentsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableIssueCommentsClientTests.cs deleted file mode 100644 index 11c8b845..00000000 --- a/Octokit.Tests.Integration/Reactive/ObservableIssueCommentsClientTests.cs +++ /dev/null @@ -1,126 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reactive.Linq; -using System.Text; -using System.Threading.Tasks; -using Octokit.Reactive; -using Xunit; - -namespace Octokit.Tests.Integration.Reactive -{ - public class ObservableIssueCommentsClientTests - { - public class TheGetAllForRepositoryMethod - { - readonly ObservableIssueCommentsClient _issueCommentsClient; - const string owner = "octokit"; - const string name = "octokit.net"; - - public TheGetAllForRepositoryMethod() - { - var github = Helper.GetAuthenticatedClient(); - - _issueCommentsClient = new ObservableIssueCommentsClient(github); - } - - [IntegrationTest] - public async Task ReturnsIssueComments() - { - var issueComments = await _issueCommentsClient.GetAllForRepository(owner, name).ToList(); - - Assert.NotEmpty(issueComments); - } - - [IntegrationTest] - public async Task ReturnsCorrectCountOfIssueCommentsWithoutStart() - { - var options = new ApiOptions - { - PageSize = 5, - PageCount = 1 - }; - - var issueComments = await _issueCommentsClient.GetAllForRepository(owner, name, options).ToList(); - - Assert.Equal(5, issueComments.Count); - } - - [IntegrationTest] - public async Task ReturnsCorrectCountOfIssueCommentsWithStart() - { - var options = new ApiOptions - { - PageSize = 5, - PageCount = 1, - StartPage = 2 - }; - - var issueComments = await _issueCommentsClient.GetAllForRepository(owner, name, options).ToList(); - - Assert.Equal(5, issueComments.Count); - } - - [IntegrationTest] - public async Task ReturnsDistinctResultsBasedOnStartPage() - { - var startOptions = new ApiOptions - { - PageSize = 5, - PageCount = 1 - }; - - var firstPageIssueComments = await _issueCommentsClient.GetAllForRepository(owner, name, startOptions).ToList(); - - var skipStartOptions = new ApiOptions - { - PageSize = 5, - PageCount = 1, - StartPage = 2 - }; - - var secondPageIssueComments = await _issueCommentsClient.GetAllForRepository(owner, name, skipStartOptions).ToList(); - - Assert.NotEqual(firstPageIssueComments[0].Id, secondPageIssueComments[0].Id); - Assert.NotEqual(firstPageIssueComments[1].Id, secondPageIssueComments[1].Id); - Assert.NotEqual(firstPageIssueComments[2].Id, secondPageIssueComments[2].Id); - Assert.NotEqual(firstPageIssueComments[3].Id, secondPageIssueComments[3].Id); - Assert.NotEqual(firstPageIssueComments[4].Id, secondPageIssueComments[4].Id); - } - - [IntegrationTest] - public async Task ReturnsAllIssueCommentsWithReactions() - { - var comments = await _issueCommentsClient.GetAllForRepository("alfhenrik-test", "repo-with-issue-comment-reactions").ToList(); - - Assert.NotEmpty(comments); - var comment = comments[0]; - Assert.NotNull(comment.Reactions); - Assert.Equal(3, comment.Reactions.TotalCount); - Assert.Equal(1, comment.Reactions.Plus1); - Assert.Equal(1, comment.Reactions.Hooray); - Assert.Equal(1, comment.Reactions.Heart); - Assert.Equal(0, comment.Reactions.Laugh); - Assert.Equal(0, comment.Reactions.Confused); - Assert.Equal(0, comment.Reactions.Minus1); - } - - [IntegrationTest] - public async Task ReturnsIssueCommentWithReactions() - { - var comments = await _issueCommentsClient.GetAllForIssue("alfhenrik-test", "repo-with-issue-comment-reactions", 1).ToList(); - - Assert.NotEmpty(comments); - var comment = comments[0]; - Assert.NotNull(comment.Reactions); - Assert.Equal(3, comment.Reactions.TotalCount); - Assert.Equal(1, comment.Reactions.Plus1); - Assert.Equal(1, comment.Reactions.Hooray); - Assert.Equal(1, comment.Reactions.Heart); - Assert.Equal(0, comment.Reactions.Laugh); - Assert.Equal(0, comment.Reactions.Confused); - Assert.Equal(0, comment.Reactions.Minus1); - } - } - } -} diff --git a/Octokit.Tests/Clients/IssueCommentsClientTests.cs b/Octokit.Tests/Clients/IssueCommentsClientTests.cs index 629cf80f..2354e780 100644 --- a/Octokit.Tests/Clients/IssueCommentsClientTests.cs +++ b/Octokit.Tests/Clients/IssueCommentsClientTests.cs @@ -13,12 +13,12 @@ namespace Octokit.Tests.Clients public class TheGetMethod { [Fact] - public void RequestsCorrectUrl() + public async Task RequestsCorrectUrl() { var connection = Substitute.For(); var client = new IssueCommentsClient(connection); - client.Get("fake", "repo", 42); + await client.Get("fake", "repo", 42); connection.Received().Get( Arg.Is(u => u.ToString() == "repos/fake/repo/issues/comments/42"), @@ -26,14 +26,26 @@ namespace Octokit.Tests.Clients Arg.Is(s => s == "application/vnd.github.squirrel-girl-preview")); } + [Fact] + public async Task RequestsCorrectUrlWithRepositoryId() + { + var connection = Substitute.For(); + var client = new IssueCommentsClient(connection); + + await client.Get(1, 42); + + connection.Received().Get(Arg.Is(u => u.ToString() == "repositories/1/issues/comments/42")); + } + [Fact] public async Task EnsuresNonNullArguments() { var client = new IssueCommentsClient(Substitute.For()); await Assert.ThrowsAsync(() => client.Get(null, "name", 1)); - await Assert.ThrowsAsync(() => client.Get("", "name", 1)); await Assert.ThrowsAsync(() => client.Get("owner", null, 1)); + + await Assert.ThrowsAsync(() => client.Get("", "name", 1)); await Assert.ThrowsAsync(() => client.Get("owner", "", 1)); } } @@ -41,12 +53,12 @@ namespace Octokit.Tests.Clients public class TheGetForRepositoryMethod { [Fact] - public void RequestsCorrectUrl() + public async Task RequestsCorrectUrl() { var connection = Substitute.For(); var client = new IssueCommentsClient(connection); - client.GetAllForRepository("fake", "repo"); + await client.GetAllForRepository("fake", "repo"); connection.Received().GetAll( Arg.Is(u => u.ToString() == "repos/fake/repo/issues/comments"), @@ -56,7 +68,18 @@ namespace Octokit.Tests.Clients } [Fact] - public void RequestsCorrectUrlWithApiOptions() + public async Task RequestsCorrectUrlWithRepositoryId() + { + var connection = Substitute.For(); + var client = new IssueCommentsClient(connection); + + await client.GetAllForRepository(1); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/issues/comments"), Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlWithApiOptions() { var connection = Substitute.For(); var client = new IssueCommentsClient(connection); @@ -67,7 +90,8 @@ namespace Octokit.Tests.Clients PageSize = 1, StartPage = 1 }; - client.GetAllForRepository("fake", "repo", options); + + await client.GetAllForRepository("fake", "repo", options); connection.Received().GetAll( Arg.Is(u => u.ToString() == "repos/fake/repo/issues/comments"), @@ -77,16 +101,39 @@ namespace Octokit.Tests.Clients } [Fact] - public async Task EnsuresArgumentsNotNull() + public async Task RequestsCorrectUrlWithRepositoryIdWithApiOptions() + { + var connection = Substitute.For(); + var client = new IssueCommentsClient(connection); + + var options = new ApiOptions + { + PageCount = 1, + PageSize = 1, + StartPage = 1 + }; + + await client.GetAllForRepository(1, options); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/issues/comments"), options); + } + + [Fact] + public async Task EnsuresNonNullArguments() { var connection = Substitute.For(); var client = new IssueCommentsClient(connection); await Assert.ThrowsAsync(() => client.GetAllForRepository(null, "name")); - await Assert.ThrowsAsync(() => client.GetAllForRepository("", "name")); await Assert.ThrowsAsync(() => client.GetAllForRepository("owner", null)); - await Assert.ThrowsAsync(() => client.GetAllForRepository("owner", "")); + await Assert.ThrowsAsync(() => client.GetAllForRepository(null, "name", ApiOptions.None)); + await Assert.ThrowsAsync(() => client.GetAllForRepository("owner", null, ApiOptions.None)); await Assert.ThrowsAsync(() => client.GetAllForRepository("owner", "name", null)); + + await Assert.ThrowsAsync(() => client.GetAllForRepository(1, null)); + + await Assert.ThrowsAsync(() => client.GetAllForRepository("", "name")); + await Assert.ThrowsAsync(() => client.GetAllForRepository("owner", "")); await Assert.ThrowsAsync(() => client.GetAllForRepository("owner", "", ApiOptions.None)); await Assert.ThrowsAsync(() => client.GetAllForRepository("", "name", ApiOptions.None)); } @@ -95,12 +142,12 @@ namespace Octokit.Tests.Clients public class TheGetForIssueMethod { [Fact] - public void RequestsCorrectUrl() + public async Task RequestsCorrectUrl() { var connection = Substitute.For(); var client = new IssueCommentsClient(connection); - client.GetAllForIssue("fake", "repo", 3); + await client.GetAllForIssue("fake", "repo", 3); connection.Received().GetAll( Arg.Is(u => u.ToString() == "repos/fake/repo/issues/3/comments"), @@ -110,7 +157,18 @@ namespace Octokit.Tests.Clients } [Fact] - public void RequestsCorrectUrlWithApiOptions() + public async Task RequestsCorrectUrlWithRepositoryId() + { + var connection = Substitute.For(); + var client = new IssueCommentsClient(connection); + + await client.GetAllForIssue(1, 3); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/issues/3/comments"), Args.ApiOptions); + } + + [Fact] + public async Task RequestsCorrectUrlWithApiOptions() { var connection = Substitute.For(); var client = new IssueCommentsClient(connection); @@ -121,7 +179,8 @@ namespace Octokit.Tests.Clients PageSize = 1, PageCount = 1 }; - client.GetAllForIssue("fake", "repo", 3, options); + + await client.GetAllForIssue("fake", "repo", 3, options); connection.Received().GetAll( Arg.Is(u => u.ToString() == "repos/fake/repo/issues/3/comments"), @@ -131,16 +190,39 @@ namespace Octokit.Tests.Clients } [Fact] - public async Task EnsuresArgumentsNotNull() + public async Task RequestsCorrectUrlWithRepositoryIdWithApiOptions() + { + var connection = Substitute.For(); + var client = new IssueCommentsClient(connection); + + var options = new ApiOptions + { + StartPage = 1, + PageSize = 1, + PageCount = 1 + }; + + await client.GetAllForIssue(1, 3, options); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "repositories/1/issues/3/comments"), options); + } + + [Fact] + public async Task EnsuresNonNullArguments() { var connection = Substitute.For(); var client = new IssueCommentsClient(connection); await Assert.ThrowsAsync(() => client.GetAllForIssue(null, "name", 1)); - await Assert.ThrowsAsync(() => client.GetAllForIssue("", "name", 1)); await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", null, 1)); - await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", "", 1)); + await Assert.ThrowsAsync(() => client.GetAllForIssue(null, "name", 1, ApiOptions.None)); + await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", null, 1, ApiOptions.None)); await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", "name", 1, null)); + + await Assert.ThrowsAsync(() => client.GetAllForIssue(1, 1, null)); + + await Assert.ThrowsAsync(() => client.GetAllForIssue("", "name", 1)); + await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", "", 1)); await Assert.ThrowsAsync(() => client.GetAllForIssue("", "name", 1, ApiOptions.None)); await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", "", 1, ApiOptions.None)); } @@ -161,16 +243,31 @@ namespace Octokit.Tests.Clients } [Fact] - public async Task EnsuresArgumentsNotNull() + public void PostsToCorrectUrlWithRepositoryId() + { + const string newComment = "some title"; + var connection = Substitute.For(); + var client = new IssueCommentsClient(connection); + + client.Create(1, 1, newComment); + + connection.Received().Post(Arg.Is(u => u.ToString() == "repositories/1/issues/1/comments"), Arg.Any()); + } + + [Fact] + public async Task EnsuresNonNullArguments() { var connection = Substitute.For(); var client = new IssueCommentsClient(connection); - await Assert.ThrowsAsync(() => client.Create(null, "name", 1, "title")); - await Assert.ThrowsAsync(() => client.Create("", "name", 1, "x")); + await Assert.ThrowsAsync(() => client.Create(null, "name", 1, "x")); await Assert.ThrowsAsync(() => client.Create("owner", null, 1, "x")); - await Assert.ThrowsAsync(() => client.Create("owner", "", 1, "x")); await Assert.ThrowsAsync(() => client.Create("owner", "name", 1, null)); + + await Assert.ThrowsAsync(() => client.Create(1, 1, null)); + + await Assert.ThrowsAsync(() => client.Create("", "name", 1, "x")); + await Assert.ThrowsAsync(() => client.Create("owner", "", 1, "x")); } } @@ -189,16 +286,31 @@ namespace Octokit.Tests.Clients } [Fact] - public async Task EnsuresArgumentsNotNull() + public void PostsToCorrectUrlWithRepositoryId() + { + const string issueCommentUpdate = "Worthwhile update"; + var connection = Substitute.For(); + var client = new IssueCommentsClient(connection); + + client.Update(1, 42, issueCommentUpdate); + + connection.Received().Patch(Arg.Is(u => u.ToString() == "repositories/1/issues/comments/42"), Arg.Any()); + } + + [Fact] + public async Task EnsuresNonNullArguments() { var connection = Substitute.For(); var client = new IssueCommentsClient(connection); - await Assert.ThrowsAsync(() => client.Update(null, "name", 42, "title")); - await Assert.ThrowsAsync(() => client.Update("", "name", 42, "x")); + await Assert.ThrowsAsync(() => client.Update(null, "name", 42, "x")); await Assert.ThrowsAsync(() => client.Update("owner", null, 42, "x")); - await Assert.ThrowsAsync(() => client.Update("owner", "", 42, "x")); await Assert.ThrowsAsync(() => client.Update("owner", "name", 42, null)); + + await Assert.ThrowsAsync(() => client.Update(1, 42, null)); + + await Assert.ThrowsAsync(() => client.Update("", "name", 42, "x")); + await Assert.ThrowsAsync(() => client.Update("owner", "", 42, "x")); } } @@ -215,6 +327,17 @@ namespace Octokit.Tests.Clients connection.Received().Delete(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/comments/42")); } + [Fact] + public void DeletesCorrectUrlWithRepositoryId() + { + var connection = Substitute.For(); + var client = new IssueCommentsClient(connection); + + client.Delete(1, 42); + + connection.Received().Delete(Arg.Is(u => u.ToString() == "repositories/1/issues/comments/42")); + } + [Fact] public async Task EnsuresArgumentsNotNullOrEmpty() { @@ -222,20 +345,21 @@ namespace Octokit.Tests.Clients var client = new IssueCommentsClient(connection); await Assert.ThrowsAsync(() => client.Delete(null, "name", 42)); - await Assert.ThrowsAsync(() => client.Delete("", "name", 42)); await Assert.ThrowsAsync(() => client.Delete("owner", null, 42)); + + await Assert.ThrowsAsync(() => client.Delete("", "name", 42)); await Assert.ThrowsAsync(() => client.Delete("owner", "", 42)); } } - public class TheCtor - { - [Fact] - public void EnsuresNonNullArguments() + public class TheCtor { - Assert.Throws(() => new IssueCommentsClient(null)); + [Fact] + public void EnsuresNonNullArguments() + { + Assert.Throws(() => new IssueCommentsClient(null)); + } } - } [Fact] public void CanDeserializeIssueComment() diff --git a/Octokit.Tests/Reactive/ObservableIssueCommentsClientTests.cs b/Octokit.Tests/Reactive/ObservableIssueCommentsClientTests.cs index 34dda0cd..422379ec 100644 --- a/Octokit.Tests/Reactive/ObservableIssueCommentsClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableIssueCommentsClientTests.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Reactive.Threading.Tasks; using System.Threading.Tasks; using NSubstitute; using Octokit.Reactive; @@ -13,7 +12,7 @@ namespace Octokit.Tests.Reactive public class TheGetMethod { [Fact] - public void GetsFromClientIssueComment() + public void RequestsCorrectUrl() { var gitHubClient = Substitute.For(); var client = new ObservableIssueCommentsClient(gitHubClient); @@ -23,15 +22,27 @@ namespace Octokit.Tests.Reactive gitHubClient.Issue.Comment.Received().Get("fake", "repo", 42); } + [Fact] + public void RequestsCorrectUrlWithRepositoryId() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentsClient(gitHubClient); + + client.Get(1, 42); + + gitHubClient.Issue.Comment.Received().Get(1, 42); + } + [Fact] public async Task EnsuresNonNullArguments() { var client = new ObservableIssueCommentsClient(Substitute.For()); - await Assert.ThrowsAsync(() => client.Get(null, "name", 1).ToTask()); - await Assert.ThrowsAsync(() => client.Get("", "name", 1).ToTask()); - await Assert.ThrowsAsync(() => client.Get("owner", null, 1).ToTask()); - await Assert.ThrowsAsync(() => client.Get("owner", "", 1).ToTask()); + Assert.Throws(() => client.Get(null, "name", 1)); + Assert.Throws(() => client.Get("owner", null, 1)); + + Assert.Throws(() => client.Get("", "name", 1)); + Assert.Throws(() => client.Get("owner", "", 1)); } } @@ -51,18 +62,31 @@ namespace Octokit.Tests.Reactive "application/vnd.github.squirrel-girl-preview"); } + [Fact] + public void RequestsCorrectUrlWithRepositoryId() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentsClient(gitHubClient); + + client.GetAllForRepository(1); + + gitHubClient.Connection.Received(1).Get>( + new Uri("repositories/1/issues/comments", UriKind.Relative), Args.EmptyDictionary, null); + } + [Fact] public void RequestsCorrectUrlWithApiOptions() { var gitHubClient = Substitute.For(); var client = new ObservableIssueCommentsClient(gitHubClient); - var options=new ApiOptions + var options = new ApiOptions { StartPage = 1, PageSize = 1, PageCount = 1 }; + client.GetAllForRepository("fake", "repo", options); gitHubClient.Connection.Received(1).Get>( @@ -72,18 +96,42 @@ namespace Octokit.Tests.Reactive } [Fact] - public async Task EnsuresArgumentsNotNull() + public void RequestsCorrectUrlWithRepositoryIdWithApiOptions() { var gitHubClient = Substitute.For(); var client = new ObservableIssueCommentsClient(gitHubClient); - await Assert.ThrowsAsync(() => client.GetAllForRepository(null, "name").ToTask()); - await Assert.ThrowsAsync(() => client.GetAllForRepository("", "name").ToTask()); - await Assert.ThrowsAsync(() => client.GetAllForRepository("owner", null).ToTask()); - await Assert.ThrowsAsync(() => client.GetAllForRepository("owner", "").ToTask()); - await Assert.ThrowsAsync(() => client.GetAllForRepository("owner", "name", null).ToTask()); - await Assert.ThrowsAsync(() => client.GetAllForRepository("", "name", ApiOptions.None).ToTask()); - await Assert.ThrowsAsync(() => client.GetAllForRepository("owner", "", ApiOptions.None).ToTask()); + var options = new ApiOptions + { + StartPage = 1, + PageSize = 1, + PageCount = 1 + }; + + client.GetAllForRepository(1, options); + + gitHubClient.Connection.Received(1).Get>( + new Uri("repositories/1/issues/comments", UriKind.Relative), Arg.Is>(d => d.Count == 2), null); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentsClient(gitHubClient); + + Assert.Throws(() => client.GetAllForRepository(null, "name")); + Assert.Throws(() => client.GetAllForRepository("owner", null)); + Assert.Throws(() => client.GetAllForRepository(null, "name", ApiOptions.None)); + Assert.Throws(() => client.GetAllForRepository("owner", null, ApiOptions.None)); + Assert.Throws(() => client.GetAllForRepository("owner", "name", null)); + + Assert.Throws(() => client.GetAllForRepository(1, null)); + + Assert.Throws(() => client.GetAllForRepository("", "name")); + Assert.Throws(() => client.GetAllForRepository("owner", "")); + Assert.Throws(() => client.GetAllForRepository("", "name", ApiOptions.None)); + Assert.Throws(() => client.GetAllForRepository("owner", "", ApiOptions.None)); } } @@ -103,39 +151,74 @@ namespace Octokit.Tests.Reactive "application/vnd.github.squirrel-girl-preview"); } + [Fact] + public void RequestsCorrectUrlWithRepositoryId() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentsClient(gitHubClient); + + client.GetAllForIssue(1, 3); + + gitHubClient.Connection.Received(1).Get>( + new Uri("repositories/1/issues/3/comments", UriKind.Relative), Args.EmptyDictionary, null); + } + [Fact] public void RequestsCorrectUrlWithApiOptions() { var gitHubClient = Substitute.For(); var client = new ObservableIssueCommentsClient(gitHubClient); - var options=new ApiOptions + var options = new ApiOptions { StartPage = 1, PageSize = 1, PageCount = 1 }; + client.GetAllForIssue("fake", "repo", 3, options); gitHubClient.Connection.Received(1).Get>( - new Uri("repos/fake/repo/issues/3/comments", UriKind.Relative), - Arg.Any>(), - "application/vnd.github.squirrel-girl-preview"); + new Uri("repos/fake/repo/issues/3/comments", UriKind.Relative), Arg.Is>(d => d.Count == 2), "application/vnd.github.squirrel-girl-preview"); } [Fact] - public async Task EnsuresArgumentsNotNull() + public void RequestsCorrectUrlWithRepositoryIdWithApiOptions() { var gitHubClient = Substitute.For(); var client = new ObservableIssueCommentsClient(gitHubClient); - await Assert.ThrowsAsync(() => client.GetAllForIssue(null, "name", 1).ToTask()); - await Assert.ThrowsAsync(() => client.GetAllForIssue("", "name", 1).ToTask()); - await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", null, 1).ToTask()); - await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", "", 1).ToTask()); - await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", "name", 1, null).ToTask()); - await Assert.ThrowsAsync(() => client.GetAllForIssue("", "name", 1, ApiOptions.None).ToTask()); - await Assert.ThrowsAsync(() => client.GetAllForIssue("owner", "", 1, ApiOptions.None).ToTask()); + var options = new ApiOptions + { + StartPage = 1, + PageSize = 1, + PageCount = 1 + }; + + client.GetAllForIssue(1, 3, options); + + gitHubClient.Connection.Received(1).Get>( + new Uri("repositories/1/issues/3/comments", UriKind.Relative), Arg.Is>(d => d.Count == 2), null); + } + + [Fact] + public async Task EnsuresNonNullArguments() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentsClient(gitHubClient); + + Assert.Throws(() => client.GetAllForIssue(null, "name", 1)); + Assert.Throws(() => client.GetAllForIssue("owner", null, 1)); + Assert.Throws(() => client.GetAllForIssue(null, "name", 1, ApiOptions.None)); + Assert.Throws(() => client.GetAllForIssue("owner", null, 1, ApiOptions.None)); + Assert.Throws(() => client.GetAllForIssue("owner", "name", 1, null)); + + Assert.Throws(() => client.GetAllForIssue(1, 1, null)); + + Assert.Throws(() => client.GetAllForIssue("", "name", 1)); + Assert.Throws(() => client.GetAllForIssue("owner", "", 1)); + Assert.Throws(() => client.GetAllForIssue("", "name", 1, ApiOptions.None)); + Assert.Throws(() => client.GetAllForIssue("owner", "", 1, ApiOptions.None)); } } @@ -154,16 +237,31 @@ namespace Octokit.Tests.Reactive } [Fact] - public async Task EnsuresArgumentsNotNull() + public void PostsToCorrectUrlWithRepositoryId() + { + const string newComment = "some title"; + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentsClient(gitHubClient); + + client.Create(1, 1, newComment); + + gitHubClient.Issue.Comment.Received().Create(1, 1, newComment); + } + + [Fact] + public async Task EnsuresNonNullArguments() { var gitHubClient = Substitute.For(); var client = new ObservableIssueCommentsClient(gitHubClient); - await Assert.ThrowsAsync(() => client.Create(null, "name", 1, "title").ToTask()); - await Assert.ThrowsAsync(() => client.Create("", "name", 1, "x").ToTask()); - await Assert.ThrowsAsync(() => client.Create("owner", null, 1, "x").ToTask()); - await Assert.ThrowsAsync(() => client.Create("owner", "", 1, "x").ToTask()); - await Assert.ThrowsAsync(() => client.Create("owner", "name", 1, null).ToTask()); + Assert.Throws(() => client.Create(null, "name", 1, "x")); + Assert.Throws(() => client.Create("owner", null, 1, "x")); + Assert.Throws(() => client.Create("owner", "name", 1, null)); + + Assert.Throws(() => client.Create(1, 1, null)); + + Assert.Throws(() => client.Create("", "name", 1, "x")); + Assert.Throws(() => client.Create("owner", "", 1, "x")); } } @@ -182,16 +280,69 @@ namespace Octokit.Tests.Reactive } [Fact] - public async Task EnsuresArgumentsNotNull() + public void PostsToCorrectUrlWithRepositoryId() + { + const string issueCommentUpdate = "Worthwhile update"; + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentsClient(gitHubClient); + + client.Update(1, 42, issueCommentUpdate); + + gitHubClient.Issue.Comment.Received().Update(1, 42, issueCommentUpdate); + } + + [Fact] + public async Task EnsuresNonNullArguments() { var gitHubClient = Substitute.For(); var client = new ObservableIssueCommentsClient(gitHubClient); - await Assert.ThrowsAsync(() => client.Update(null, "name", 42, "title").ToTask()); - await Assert.ThrowsAsync(() => client.Update("", "name", 42, "x").ToTask()); - await Assert.ThrowsAsync(() => client.Update("owner", null, 42, "x").ToTask()); - await Assert.ThrowsAsync(() => client.Update("owner", "", 42, "x").ToTask()); - await Assert.ThrowsAsync(() => client.Update("owner", "name", 42, null).ToTask()); + Assert.Throws(() => client.Update(null, "name", 42, "title")); + Assert.Throws(() => client.Update("owner", null, 42, "x")); + Assert.Throws(() => client.Update("owner", "name", 42, null)); + + Assert.Throws(() => client.Update(1, 42, null)); + + Assert.Throws(() => client.Update("", "name", 42, "x")); + Assert.Throws(() => client.Update("owner", "", 42, "x")); + } + } + + public class TheDeleteMethod + { + [Fact] + public void DeletesCorrectUrl() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentsClient(gitHubClient); + + client.Delete("fake", "repo", 42); + + gitHubClient.Issue.Comment.Received().Delete("fake", "repo", 42); + } + + [Fact] + public void DeletesCorrectUrlWithRepositoryId() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentsClient(gitHubClient); + + client.Delete(1, 42); + + gitHubClient.Issue.Comment.Received().Delete(1, 42); + } + + [Fact] + public async Task EnsuresArgumentsNotNullOrEmpty() + { + var gitHubClient = Substitute.For(); + var client = new ObservableIssueCommentsClient(gitHubClient); + + Assert.Throws(() => client.Delete(null, "name", 42)); + Assert.Throws(() => client.Delete("owner", null, 42)); + + Assert.Throws(() => client.Delete("", "name", 42)); + Assert.Throws(() => client.Delete("owner", "", 42)); } } diff --git a/Octokit/Clients/IIssueCommentsClient.cs b/Octokit/Clients/IIssueCommentsClient.cs index 147c3b84..b4e1c48e 100644 --- a/Octokit/Clients/IIssueCommentsClient.cs +++ b/Octokit/Clients/IIssueCommentsClient.cs @@ -19,20 +19,35 @@ namespace Octokit /// The owner of the repository /// The name of the repository /// The issue comment id - /// [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", - Justification = "Method makes a network request")] + Justification = "Method makes a network request")] Task Get(string owner, string name, int id); + /// + /// Gets a single Issue Comment by id. + /// + /// http://developer.github.com/v3/issues/comments/#get-a-single-comment + /// The ID of the repository + /// The issue comment id + [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get", + Justification = "Method makes a network request")] + Task Get(int repositoryId, int id); + /// /// Gets Issue Comments for a repository. /// /// http://developer.github.com/v3/issues/comments/#list-comments-in-a-repository /// The owner of the repository /// The name of the repository - /// Task> GetAllForRepository(string owner, string name); + /// + /// Gets Issue Comments for a repository. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-in-a-repository + /// The ID of the repository + Task> GetAllForRepository(int repositoryId); + /// /// Gets Issue Comments for a repository. /// @@ -40,9 +55,16 @@ namespace Octokit /// The owner of the repository /// The name of the repository /// Options for changing the API response - /// Task> GetAllForRepository(string owner, string name, ApiOptions options); + /// + /// Gets Issue Comments for a repository. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-in-a-repository + /// The ID of the repository + /// Options for changing the API response + Task> GetAllForRepository(int repositoryId, ApiOptions options); + /// /// Gets Issue Comments for a specified Issue. /// @@ -50,9 +72,16 @@ namespace Octokit /// The owner of the repository /// The name of the repository /// The issue number - /// Task> GetAllForIssue(string owner, string name, int number); + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The ID of the repository + /// The issue number + Task> GetAllForIssue(int repositoryId, int number); + /// /// Gets Issue Comments for a specified Issue. /// @@ -61,9 +90,17 @@ namespace Octokit /// The name of the repository /// The issue number /// Options for changing the API response - /// Task> GetAllForIssue(string owner, string name, int number, ApiOptions options); + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The ID of the repository + /// The issue number + /// Options for changing the API response + Task> GetAllForIssue(int repositoryId, int number, ApiOptions options); + /// /// Creates a new Issue Comment for a specified Issue. /// @@ -72,9 +109,17 @@ namespace Octokit /// The name of the repository /// The number of the issue /// The new comment to add to the issue - /// Task Create(string owner, string name, int number, string newComment); + /// + /// Creates a new Issue Comment for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#create-a-comment + /// The ID of the repository + /// The number of the issue + /// The new comment to add to the issue + Task Create(int repositoryId, int number, string newComment); + /// /// Updates a specified Issue Comment. /// @@ -83,9 +128,17 @@ namespace Octokit /// The name of the repository /// The comment id /// The modified comment - /// Task Update(string owner, string name, int id, string commentUpdate); + /// + /// Updates a specified Issue Comment. + /// + /// http://developer.github.com/v3/issues/comments/#edit-a-comment + /// The ID of the repository + /// The comment id + /// The modified comment + Task Update(int repositoryId, int id, string commentUpdate); + /// /// Deletes the specified Issue Comment /// @@ -93,7 +146,14 @@ namespace Octokit /// The owner of the repository /// The name of the repository /// The comment id - /// Task Delete(string owner, string name, int id); + + /// + /// Deletes the specified Issue Comment + /// + /// http://developer.github.com/v3/issues/comments/#delete-a-comment + /// The ID of the repository + /// The comment id + Task Delete(int repositoryId, int id); } } diff --git a/Octokit/Clients/IssueCommentsClient.cs b/Octokit/Clients/IssueCommentsClient.cs index 2bb32b32..87e9dd7c 100644 --- a/Octokit/Clients/IssueCommentsClient.cs +++ b/Octokit/Clients/IssueCommentsClient.cs @@ -26,7 +26,6 @@ namespace Octokit /// The owner of the repository /// The name of the repository /// The issue comment id - /// public Task Get(string owner, string name, int id) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -35,13 +34,23 @@ namespace Octokit return ApiConnection.Get(ApiUrls.IssueComment(owner, name, id), null, AcceptHeaders.ReactionsPreview); } + /// + /// Gets a single Issue Comment by id. + /// + /// http://developer.github.com/v3/issues/comments/#get-a-single-comment + /// The ID of the repository + /// The issue comment id + public Task Get(int repositoryId, int id) + { + return ApiConnection.Get(ApiUrls.IssueComment(repositoryId, id)); + } + /// /// Gets Issue Comments for a repository. /// /// http://developer.github.com/v3/issues/comments/#list-comments-in-a-repository /// The owner of the repository /// The name of the repository - /// public Task> GetAllForRepository(string owner, string name) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -50,6 +59,16 @@ namespace Octokit return GetAllForRepository(owner, name, ApiOptions.None); } + /// + /// Gets Issue Comments for a repository. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-in-a-repository + /// The ID of the repository + public Task> GetAllForRepository(int repositoryId) + { + return GetAllForRepository(repositoryId, ApiOptions.None); + } + /// /// Gets Issue Comments for a repository. /// @@ -57,7 +76,6 @@ namespace Octokit /// The owner of the repository /// The name of the repository /// Options for changing the API response - /// public Task> GetAllForRepository(string owner, string name, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -67,6 +85,19 @@ namespace Octokit return ApiConnection.GetAll(ApiUrls.IssueComments(owner, name), null, AcceptHeaders.ReactionsPreview, options); } + /// + /// Gets Issue Comments for a repository. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-in-a-repository + /// The ID of the repository + /// Options for changing the API response + public Task> GetAllForRepository(int repositoryId, ApiOptions options) + { + Ensure.ArgumentNotNull(options, "options"); + + return ApiConnection.GetAll(ApiUrls.IssueComments(repositoryId), options); + } + /// /// Gets Issue Comments for a specified Issue. /// @@ -74,7 +105,6 @@ namespace Octokit /// The owner of the repository /// The name of the repository /// The issue number - /// public Task> GetAllForIssue(string owner, string name, int number) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -82,6 +112,18 @@ namespace Octokit return GetAllForIssue(owner, name, number, ApiOptions.None); } + + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The ID of the repository + /// The issue number + public Task> GetAllForIssue(int repositoryId, int number) + { + return GetAllForIssue(repositoryId, number, ApiOptions.None); + } + /// /// Gets Issue Comments for a specified Issue. /// @@ -90,7 +132,6 @@ namespace Octokit /// The name of the repository /// The issue number /// Options for changing the API response - /// public Task> GetAllForIssue(string owner, string name, int number, ApiOptions options) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -100,6 +141,20 @@ namespace Octokit return ApiConnection.GetAll(ApiUrls.IssueComments(owner, name, number), null, AcceptHeaders.ReactionsPreview, options); } + /// + /// Gets Issue Comments for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#list-comments-on-an-issue + /// The ID of the repository + /// The issue number + /// Options for changing the API response + public Task> GetAllForIssue(int repositoryId, int number, ApiOptions options) + { + Ensure.ArgumentNotNull(options, "options"); + + return ApiConnection.GetAll(ApiUrls.IssueComments(repositoryId, number), options); + } + /// /// Creates a new Issue Comment for a specified Issue. /// @@ -108,7 +163,6 @@ namespace Octokit /// The name of the repository /// The number of the issue /// The new comment to add to the issue - /// public Task Create(string owner, string name, int number, string newComment) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -118,6 +172,20 @@ namespace Octokit return ApiConnection.Post(ApiUrls.IssueComments(owner, name, number), new BodyWrapper(newComment)); } + /// + /// Creates a new Issue Comment for a specified Issue. + /// + /// http://developer.github.com/v3/issues/comments/#create-a-comment + /// The ID of the repository + /// The number of the issue + /// The new comment to add to the issue + public Task Create(int repositoryId, int number, string newComment) + { + Ensure.ArgumentNotNull(newComment, "newComment"); + + return ApiConnection.Post(ApiUrls.IssueComments(repositoryId, number), new BodyWrapper(newComment)); + } + /// /// Updates a specified Issue Comment. /// @@ -126,7 +194,6 @@ namespace Octokit /// The name of the repository /// The comment id /// The modified comment - /// public Task Update(string owner, string name, int id, string commentUpdate) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -136,6 +203,20 @@ namespace Octokit return ApiConnection.Patch(ApiUrls.IssueComment(owner, name, id), new BodyWrapper(commentUpdate)); } + /// + /// Updates a specified Issue Comment. + /// + /// http://developer.github.com/v3/issues/comments/#edit-a-comment + /// The ID of the repository + /// The comment id + /// The modified comment + public Task Update(int repositoryId, int id, string commentUpdate) + { + Ensure.ArgumentNotNull(commentUpdate, "commentUpdate"); + + return ApiConnection.Patch(ApiUrls.IssueComment(repositoryId, id), new BodyWrapper(commentUpdate)); + } + /// /// Deletes the specified Issue Comment /// @@ -143,7 +224,6 @@ namespace Octokit /// The owner of the repository /// The name of the repository /// The comment id - /// public Task Delete(string owner, string name, int id) { Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); @@ -151,5 +231,16 @@ namespace Octokit return ApiConnection.Delete(ApiUrls.IssueComment(owner, name, id)); } + + /// + /// Deletes the specified Issue Comment + /// + /// http://developer.github.com/v3/issues/comments/#delete-a-comment + /// The ID of the repository + /// The comment id + public Task Delete(int repositoryId, int id) + { + return ApiConnection.Delete(ApiUrls.IssueComment(repositoryId, id)); + } } }