diff --git a/Octokit.Reactive/Clients/IObservablePullRequestReviewCommentsClient.cs b/Octokit.Reactive/Clients/IObservablePullRequestReviewCommentsClient.cs
new file mode 100644
index 00000000..89526242
--- /dev/null
+++ b/Octokit.Reactive/Clients/IObservablePullRequestReviewCommentsClient.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Reactive;
+
+namespace Octokit.Reactive
+{
+ public interface IObservablePullRequestReviewCommentsClient
+ {
+ ///
+ /// Gets review comments for a specified pull request.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#list-comments-on-a-pull-request
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request number
+ /// The list of s for the specified pull request
+ IObservable GetForPullRequest(string owner, string name, int number);
+
+ ///
+ /// Gets a list of the pull request review comments in a specified repository.
+ ///
+ /// http://developer.github.com/v3/pulls/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 GetForRepository(string owner, string name);
+
+ ///
+ /// Gets a list of the pull request review comments in a specified repository.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#list-comments-in-a-repository
+ /// The owner of the repository
+ /// The name of the repository
+ /// The sorting parameters
+ /// The list of s for the specified repository
+ IObservable GetForRepository(string owner, string name, PullRequestReviewCommentRequest request);
+
+ ///
+ /// Gets a single pull request review comment by number.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#get-a-single-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request review comment number
+ /// The
+ IObservable GetComment(string owner, string name, int number);
+
+ ///
+ /// Creates a comment on a pull request review.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#create-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The Pull Request number
+ /// The comment
+ /// The created
+ IObservable Create(string owner, string name, int number, PullRequestReviewCommentCreate comment);
+
+ ///
+ /// Creates a comment on a pull request review as a reply to another comment.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#create-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request number
+ /// The comment
+ /// The created
+ IObservable CreateReply(string owner, string name, int number, PullRequestReviewCommentReplyCreate comment);
+
+ ///
+ /// Edits a comment on a pull request review.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#edit-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request review comment number
+ /// The edited comment
+ /// The edited
+ IObservable Edit(string owner, string name, int number, PullRequestReviewCommentEdit comment);
+
+ ///
+ /// Deletes a comment on a pull request review.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#delete-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request review comment number
+ ///
+ IObservable Delete(string owner, string name, int number);
+ }
+}
diff --git a/Octokit.Reactive/Clients/IObservablePullRequestsClient.cs b/Octokit.Reactive/Clients/IObservablePullRequestsClient.cs
index 739793c8..7fd79c95 100644
--- a/Octokit.Reactive/Clients/IObservablePullRequestsClient.cs
+++ b/Octokit.Reactive/Clients/IObservablePullRequestsClient.cs
@@ -5,6 +5,11 @@ namespace Octokit.Reactive
{
public interface IObservablePullRequestsClient
{
+ ///
+ /// Client for managing comments.
+ ///
+ IObservablePullRequestReviewCommentsClient Comment { get; }
+
///
/// Gets a single Pull Request by number.
///
diff --git a/Octokit.Reactive/Clients/ObservablePullRequestReviewCommentsClient.cs b/Octokit.Reactive/Clients/ObservablePullRequestReviewCommentsClient.cs
new file mode 100644
index 00000000..6c33ae3d
--- /dev/null
+++ b/Octokit.Reactive/Clients/ObservablePullRequestReviewCommentsClient.cs
@@ -0,0 +1,152 @@
+using System;
+using System.Reactive;
+using System.Reactive.Threading.Tasks;
+using Octokit.Reactive.Internal;
+
+namespace Octokit.Reactive
+{
+ public class ObservablePullRequestReviewCommentsClient : IObservablePullRequestReviewCommentsClient
+ {
+ readonly IPullRequestReviewCommentsClient _client;
+ readonly IConnection _connection;
+
+ public ObservablePullRequestReviewCommentsClient(IGitHubClient client)
+ {
+ Ensure.ArgumentNotNull(client, "client");
+
+ _client = client.PullRequest.Comment;
+ _connection = client.Connection;
+ }
+
+ ///
+ /// Gets review comments for a specified pull request.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#list-comments-on-a-pull-request
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request number
+ /// The list of s for the specified pull request
+ public IObservable GetForPullRequest(string owner, string name, int number)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+
+ return _connection.GetAndFlattenAllPages(ApiUrls.PullRequestReviewComments(owner, name, number));
+ }
+
+ ///
+ /// Gets a list of the pull request review comments in a specified repository.
+ ///
+ /// http://developer.github.com/v3/pulls/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 GetForRepository(string owner, string name)
+ {
+ return GetForRepository(owner, name, new PullRequestReviewCommentRequest());
+ }
+
+ ///
+ /// Gets a list of the pull request review comments in a specified repository.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#list-comments-in-a-repository
+ /// The owner of the repository
+ /// The name of the repository
+ /// The sorting parameters
+ /// The list of s for the specified repository
+ public IObservable GetForRepository(string owner, string name, PullRequestReviewCommentRequest request)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+ Ensure.ArgumentNotNull(request, "request");
+
+ return _connection.GetAndFlattenAllPages(ApiUrls.PullRequestReviewCommentsRepository(owner, name), request.ToParametersDictionary());
+ }
+
+ ///
+ /// Gets a single pull request review comment by number.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#get-a-single-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request review comment number
+ /// The
+ public IObservable GetComment(string owner, string name, int number)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+
+ return _client.GetComment(owner, name, number).ToObservable();
+ }
+
+ ///
+ /// Creates a comment on a pull request review.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#create-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The Pull Request number
+ /// The comment
+ /// The created
+ public IObservable Create(string owner, string name, int number, PullRequestReviewCommentCreate comment)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+ Ensure.ArgumentNotNull(comment, "comment");
+
+ return _client.Create(owner, name, number, comment).ToObservable();
+ }
+
+ ///
+ /// Creates a comment on a pull request review as a reply to another comment.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#create-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request number
+ /// The comment
+ /// The created
+ public IObservable CreateReply(string owner, string name, int number, PullRequestReviewCommentReplyCreate comment)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+ Ensure.ArgumentNotNull(comment, "comment");
+
+ return _client.CreateReply(owner, name, number, comment).ToObservable();
+ }
+
+ ///
+ /// Edits a comment on a pull request review.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#edit-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request review comment number
+ /// The edited comment
+ /// The edited
+ public IObservable Edit(string owner, string name, int number, PullRequestReviewCommentEdit comment)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+ Ensure.ArgumentNotNull(comment, "comment");
+
+ return _client.Edit(owner, name, number, comment).ToObservable();
+ }
+
+ ///
+ /// Deletes a comment on a pull request review.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#delete-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request review comment number
+ ///
+ public IObservable Delete(string owner, string name, int number)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+
+ return _client.Delete(owner, name, number).ToObservable();
+ }
+ }
+}
diff --git a/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs b/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs
index 33f749b2..ca8cd05d 100644
--- a/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs
+++ b/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs
@@ -9,12 +9,18 @@ namespace Octokit.Reactive
readonly IPullRequestsClient _client;
readonly IConnection _connection;
+ ///
+ /// Client for managing comments.
+ ///
+ public IObservablePullRequestReviewCommentsClient Comment { get; private set; }
+
public ObservablePullRequestsClient(IGitHubClient client)
{
Ensure.ArgumentNotNull(client, "client");
_client = client.Repository.PullRequest;
_connection = client.Connection;
+ Comment = new ObservablePullRequestReviewCommentsClient(client);
}
///
diff --git a/Octokit.Reactive/IObservableGitHubClient.cs b/Octokit.Reactive/IObservableGitHubClient.cs
index c8983ff8..e6374a0c 100644
--- a/Octokit.Reactive/IObservableGitHubClient.cs
+++ b/Octokit.Reactive/IObservableGitHubClient.cs
@@ -10,6 +10,7 @@
IObservableMiscellaneousClient Miscellaneous { get; }
IObservableOauthClient Oauth { get; }
IObservableOrganizationsClient Organization { get; }
+ IObservablePullRequestsClient PullRequest { get; }
IObservableRepositoriesClient Repository { get; }
IObservableGistsClient Gist { get; }
IObservableReleasesClient Release { get; }
diff --git a/Octokit.Reactive/ObservableGitHubClient.cs b/Octokit.Reactive/ObservableGitHubClient.cs
index cba117f2..dc5c3d03 100644
--- a/Octokit.Reactive/ObservableGitHubClient.cs
+++ b/Octokit.Reactive/ObservableGitHubClient.cs
@@ -38,6 +38,7 @@ namespace Octokit.Reactive
Notification = new ObservableNotificationsClient(gitHubClient);
Oauth = new ObservableOauthClient(gitHubClient);
Organization = new ObservableOrganizationsClient(gitHubClient);
+ PullRequest = new ObservablePullRequestsClient(gitHubClient);
Repository = new ObservableRepositoriesClient(gitHubClient);
SshKey = new ObservableSshKeysClient(gitHubClient);
User = new ObservableUsersClient(gitHubClient);
@@ -58,6 +59,7 @@ namespace Octokit.Reactive
public IObservableMiscellaneousClient Miscellaneous { get; private set; }
public IObservableOauthClient Oauth { get; private set; }
public IObservableOrganizationsClient Organization { get; private set; }
+ public IObservablePullRequestsClient PullRequest { get; private set; }
public IObservableRepositoriesClient Repository { get; private set; }
public IObservableGistsClient Gist { get; private set; }
public IObservableReleasesClient Release { get; private set; }
diff --git a/Octokit.Reactive/Octokit.Reactive-Mono.csproj b/Octokit.Reactive/Octokit.Reactive-Mono.csproj
index e952a858..ee8075f0 100644
--- a/Octokit.Reactive/Octokit.Reactive-Mono.csproj
+++ b/Octokit.Reactive/Octokit.Reactive-Mono.csproj
@@ -107,6 +107,8 @@
+
+
diff --git a/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj b/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj
index 33dfb655..dcb18a1b 100644
--- a/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj
+++ b/Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj
@@ -116,6 +116,8 @@
+
+
diff --git a/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj b/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj
index 03e99810..fccfe7e1 100644
--- a/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj
+++ b/Octokit.Reactive/Octokit.Reactive-Monotouch.csproj
@@ -111,6 +111,8 @@
+
+
diff --git a/Octokit.Reactive/Octokit.Reactive.csproj b/Octokit.Reactive/Octokit.Reactive.csproj
index 18f89bee..43b5cbd0 100644
--- a/Octokit.Reactive/Octokit.Reactive.csproj
+++ b/Octokit.Reactive/Octokit.Reactive.csproj
@@ -108,6 +108,7 @@
+
@@ -136,6 +137,7 @@
+
diff --git a/Octokit.Tests.Integration/Clients/PullRequestReviewCommentsClientTests.cs b/Octokit.Tests.Integration/Clients/PullRequestReviewCommentsClientTests.cs
new file mode 100644
index 00000000..b3da09e9
--- /dev/null
+++ b/Octokit.Tests.Integration/Clients/PullRequestReviewCommentsClientTests.cs
@@ -0,0 +1,303 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Octokit;
+using Octokit.Tests.Integration;
+using Xunit;
+
+public class PullRequestReviewCommentsClientTests : IDisposable
+{
+ readonly IGitHubClient _gitHubClient;
+ readonly IPullRequestReviewCommentsClient _client;
+ readonly Repository _repository;
+
+ const string branchName = "heads/new-branch";
+ const string path = "CONTRIBUTING.md";
+
+ public PullRequestReviewCommentsClientTests()
+ {
+ _gitHubClient = new GitHubClient(new ProductHeaderValue("OctokitTests"))
+ {
+ Credentials = Helper.Credentials
+ };
+
+ _client = _gitHubClient.PullRequest.Comment;
+
+ // We'll create a pull request that can be used by most tests
+ var repoName = Helper.MakeNameWithTimestamp("test-repo");
+ _repository = CreateRepository(repoName).Result;
+ }
+
+ [IntegrationTest]
+ public async Task CanCreateAndRetrieveComment()
+ {
+ var pullRequest = await CreatePullRequest(_repository);
+
+ const string body = "A review comment message";
+ const int position = 1;
+
+ var createdComment = await CreateComment(body, position, pullRequest.Sha, pullRequest.Number);
+
+ var commentFromGitHub = await _client.GetComment(Helper.UserName, _repository.Name, createdComment.Id);
+
+ AssertComment(commentFromGitHub, body, position);
+ }
+
+ [IntegrationTest]
+ public async Task CanEditComment()
+ {
+ var pullRequest = await CreatePullRequest(_repository);
+
+ const string body = "A new review comment message";
+ const int position = 1;
+
+ var createdComment = await CreateComment(body, position, pullRequest.Sha, pullRequest.Number);
+
+ var edit = new PullRequestReviewCommentEdit("Edited Comment");
+
+ var editedComment = await _client.Edit(Helper.UserName, _repository.Name, createdComment.Id, edit);
+
+ var commentFromGitHub = await _client.GetComment(Helper.UserName, _repository.Name, editedComment.Id);
+
+ AssertComment(commentFromGitHub, edit.Body, position);
+ }
+
+ [IntegrationTest]
+ public async Task TimestampsAreUpdated()
+ {
+ var pullRequest = await CreatePullRequest(_repository);
+
+ const string body = "A new review comment message";
+ const int position = 1;
+
+ var createdComment = await CreateComment(body, position, pullRequest.Sha, pullRequest.Number);
+
+ Assert.Equal(createdComment.UpdatedAt, createdComment.CreatedAt);
+
+ await Task.Delay(TimeSpan.FromSeconds(2));
+
+ var edit = new PullRequestReviewCommentEdit("Edited Comment");
+
+ var editedComment = await _client.Edit(Helper.UserName, _repository.Name, createdComment.Id, edit);
+
+ Assert.NotEqual(editedComment.UpdatedAt, editedComment.CreatedAt);
+ }
+
+ [IntegrationTest]
+ public async Task CanDeleteComment()
+ {
+ var pullRequest = await CreatePullRequest(_repository);
+
+ const string body = "A new review comment message";
+ const int position = 1;
+
+ var createdComment = await CreateComment(body, position, pullRequest.Sha, pullRequest.Number);
+
+ Assert.DoesNotThrow(async () => { await _client.Delete(Helper.UserName, _repository.Name, createdComment.Id); });
+ }
+
+ [IntegrationTest]
+ public async Task CanCreateReply()
+ {
+ var pullRequest = await CreatePullRequest(_repository);
+
+ const string body = "Reply me!";
+ const int position = 1;
+
+ var createdComment = await CreateComment(body, position, pullRequest.Sha, pullRequest.Number);
+
+ var reply = new PullRequestReviewCommentReplyCreate("Replied", createdComment.Id);
+ var createdReply = await _client.CreateReply(Helper.UserName, _repository.Name, pullRequest.Number, reply);
+ var createdReplyFromGitHub = await _client.GetComment(Helper.UserName, _repository.Name, createdReply.Id);
+
+ AssertComment(createdReplyFromGitHub, reply.Body, position);
+ }
+
+ [IntegrationTest]
+ public async Task CanGetForPullRequest()
+ {
+ var pullRequest = await CreatePullRequest(_repository);
+
+ const int position = 1;
+ var commentsToCreate = new List { "Comment 1", "Comment 2", "Comment 3" };
+
+ await CreateComments(commentsToCreate, position, _repository.Name, pullRequest.Sha, pullRequest.Number);
+
+ var pullRequestComments = await _client.GetAll(Helper.UserName, _repository.Name, pullRequest.Number);
+
+ AssertComments(pullRequestComments, commentsToCreate, position);
+ }
+
+ [IntegrationTest]
+ public async Task CanGetForRepository()
+ {
+ var pullRequest = await CreatePullRequest(_repository);
+
+ const int position = 1;
+ var commentsToCreate = new List { "Comment One", "Comment Two" };
+
+ await CreateComments(commentsToCreate, position, _repository.Name, pullRequest.Sha, pullRequest.Number);
+
+ var pullRequestComments = await _client.GetForRepository(Helper.UserName, _repository.Name);
+
+ AssertComments(pullRequestComments, commentsToCreate, position);
+ }
+
+ [IntegrationTest]
+ public async Task CanGetForRepositoryAscendingSort()
+ {
+ var pullRequest = await CreatePullRequest(_repository);
+
+ const int position = 1;
+ var commentsToCreate = new [] { "Comment One", "Comment Two", "Comment Three" };
+
+ await CreateComments(commentsToCreate, position, _repository.Name, pullRequest.Sha, pullRequest.Number);
+
+ var pullRequestComments = await _client.GetForRepository(Helper.UserName, _repository.Name, new PullRequestReviewCommentRequest { Direction = SortDirection.Ascending });
+
+ Assert.Equal(pullRequestComments.Select(x => x.Body), commentsToCreate);
+ }
+
+ [IntegrationTest]
+ public async Task CanGetForRepositoryDescendingSort()
+ {
+ var pullRequest = await CreatePullRequest(_repository);
+
+ const int position = 1;
+ var commentsToCreate = new [] { "Comment One", "Comment Two", "Comment Three", "Comment Four" };
+
+ await CreateComments(commentsToCreate, position, _repository.Name, pullRequest.Sha, pullRequest.Number);
+
+ var pullRequestComments = await _client.GetForRepository(Helper.UserName, _repository.Name, new PullRequestReviewCommentRequest { Direction = SortDirection.Descending });
+
+ Assert.Equal(pullRequestComments.Select(x => x.Body), commentsToCreate.Reverse());
+ }
+
+ public void Dispose()
+ {
+ Helper.DeleteRepo(_repository);
+ }
+
+ async Task CreateComment(string body, int position, string commitId, int number)
+ {
+ return await CreateComment(body, position, _repository.Name, commitId, number);
+ }
+
+ async Task CreateComment(string body, int position, string repoName, string pullRequestCommitId, int pullRequestNumber)
+ {
+ var comment = new PullRequestReviewCommentCreate(body, pullRequestCommitId, path, position);
+
+ var createdComment = await _client.Create(Helper.UserName, repoName, pullRequestNumber, comment);
+
+ AssertComment(createdComment, body, position);
+
+ return createdComment;
+ }
+
+ async Task CreateComments(IEnumerable comments, int position, string repoName, string pullRequestCommitId, int pullRequestNumber)
+ {
+ foreach (var comment in comments)
+ {
+ await CreateComment(comment, position, repoName, pullRequestCommitId, pullRequestNumber);
+ await Task.Delay(TimeSpan.FromSeconds(2));
+ }
+ }
+
+ static void AssertComment(PullRequestReviewComment comment, string body, int position)
+ {
+ Assert.NotNull(comment);
+ Assert.Equal(body, comment.Body);
+ Assert.Equal(position, comment.Position);
+ }
+
+ static void AssertComments(IReadOnlyList comments, List bodies, int position)
+ {
+ Assert.Equal(bodies.Count, comments.Count);
+
+ for (var i = 0; i < bodies.Count; i = i + 1)
+ {
+ AssertComment(comments[i], bodies[i], position);
+ }
+ }
+
+ async Task CreateRepository(string repoName)
+ {
+ return await _gitHubClient.Repository.Create(new NewRepository { Name = repoName, AutoInit = true });
+ }
+
+ ///
+ /// Creates the base state for testing (creates a repo, a commit in master, a branch, a commit in the branch and a pull request)
+ ///
+ ///
+ async Task CreatePullRequest(Repository repository)
+ {
+ var repoName = repository.Name;
+
+ // Creating a commit in master
+
+ var createdCommitInMaster = await CreateCommit(repoName, "Hello World!", "README.md", "heads/master", "A master commit message");
+
+ // Creating a branch
+
+ var newBranch = new NewReference("refs/" + branchName, createdCommitInMaster.Sha);
+ await _gitHubClient.GitDatabase.Reference.Create(Helper.UserName, repoName, newBranch);
+
+ // Creating a commit in the branch
+
+ var createdCommitInBranch = await CreateCommit(repoName, "Hello from the fork!", path, branchName, "A branch commit message");
+
+ // Creating a pull request
+
+ var pullRequest = new NewPullRequest("Nice title for the pull request", branchName, "master");
+ var createdPullRequest = await _gitHubClient.PullRequest.Create(Helper.UserName, repoName, pullRequest);
+
+ var data = new PullRequestData
+ {
+ Sha = createdCommitInBranch.Sha,
+ Number = createdPullRequest.Number,
+ };
+
+ return data;
+ }
+
+ async Task CreateCommit(string repoName, string blobContent, string treePath, string reference, string commitMessage)
+ {
+ // Creating a blob
+ var blob = new NewBlob
+ {
+ Content = blobContent,
+ Encoding = EncodingType.Utf8
+ };
+
+ var createdBlob = await _gitHubClient.GitDatabase.Blob.Create(Helper.UserName, repoName, blob);
+
+ // Creating a tree
+ var newTree = new NewTree();
+ newTree.Tree.Add(new NewTreeItem
+ {
+ Type = TreeType.Blob,
+ Mode = FileMode.File,
+ Path = treePath,
+ Sha = createdBlob.Sha,
+ });
+
+ var createdTree = await _gitHubClient.GitDatabase.Tree.Create(Helper.UserName, repoName, newTree);
+ var treeSha = createdTree.Sha;
+
+ // Creating a commit
+ var parent = await _gitHubClient.GitDatabase.Reference.Get(Helper.UserName, repoName, reference);
+ var commit = new NewCommit(commitMessage, treeSha, parent.Object.Sha);
+
+ var createdCommit = await _gitHubClient.GitDatabase.Commit.Create(Helper.UserName, repoName, commit);
+ await _gitHubClient.GitDatabase.Reference.Update(Helper.UserName, repoName, reference, new ReferenceUpdate(createdCommit.Sha));
+
+ return createdCommit;
+ }
+
+ class PullRequestData
+ {
+ public int Number { get; set; }
+ public string Sha { get; set; }
+ }
+}
diff --git a/Octokit.Tests.Integration/Clients/RepositoryDeployKeysClientTests.cs b/Octokit.Tests.Integration/Clients/RepositoryDeployKeysClientTests.cs
index e52dd5c2..5a70ae4f 100644
--- a/Octokit.Tests.Integration/Clients/RepositoryDeployKeysClientTests.cs
+++ b/Octokit.Tests.Integration/Clients/RepositoryDeployKeysClientTests.cs
@@ -11,7 +11,6 @@ public class RepositoryDeployKeysClientTests : IDisposable
readonly IGitHubClient _client;
IRepositoryDeployKeysClient _fixture;
Repository _repository;
- DeployKey _deployKey;
string _owner;
public RepositoryDeployKeysClientTests()
diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
index 6ab0b6e6..824137cb 100644
--- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
+++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
@@ -82,6 +82,7 @@
+
diff --git a/Octokit.Tests.Integration/Reactive/ObservableRespositoryDeployKeysClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableRespositoryDeployKeysClientTests.cs
index 03fe1d56..eaf7e367 100644
--- a/Octokit.Tests.Integration/Reactive/ObservableRespositoryDeployKeysClientTests.cs
+++ b/Octokit.Tests.Integration/Reactive/ObservableRespositoryDeployKeysClientTests.cs
@@ -13,7 +13,6 @@ public class ObservableRespositoryDeployKeysClientTests : IDisposable
const string _keyTitle = "octokit@github";
ObservableRepositoryDeployKeysClient _client;
Repository _repository;
- DeployKey _deployKey;
string _owner;
public ObservableRespositoryDeployKeysClientTests()
diff --git a/Octokit.Tests/Clients/PullRequestReviewCommentsClientTests.cs b/Octokit.Tests/Clients/PullRequestReviewCommentsClientTests.cs
new file mode 100644
index 00000000..70d38c37
--- /dev/null
+++ b/Octokit.Tests/Clients/PullRequestReviewCommentsClientTests.cs
@@ -0,0 +1,329 @@
+using System;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using NSubstitute;
+using Octokit;
+using Octokit.Tests.Helpers;
+using Xunit;
+
+public class PullRequestReviewCommentsClientTests
+{
+ public class TheModelConstructors
+ {
+ [Fact]
+ public void PullRequestReviewCommentCreateEnsuresArgumentsValue()
+ {
+ string body = "body";
+ string commitId = "sha";
+ string path = "path";
+ int position = 1;
+
+ var comment = new PullRequestReviewCommentCreate(body, commitId, path, position);
+
+ Assert.Equal(body, comment.Body);
+ Assert.Equal(commitId, comment.CommitId);
+ Assert.Equal(path, comment.Path);
+ Assert.Equal(position, comment.Position);
+ }
+
+ [Fact]
+ public void PullRequestReviewCommentCreateEnsuresArgumentsNotNull()
+ {
+ string body = "body";
+ string commitId = "sha";
+ string path = "path";
+ int position = 1;
+
+ Assert.Throws(() => new PullRequestReviewCommentCreate(null, commitId, path, position));
+ Assert.Throws(() => new PullRequestReviewCommentCreate("", commitId, path, position));
+ Assert.Throws(() => new PullRequestReviewCommentCreate(body, null, path, position));
+ Assert.Throws(() => new PullRequestReviewCommentCreate(body, "", path, position));
+ Assert.Throws(() => new PullRequestReviewCommentCreate(body, commitId, null, position));
+ Assert.Throws(() => new PullRequestReviewCommentCreate(body, commitId, "", position));
+ }
+
+ [Fact]
+ public void PullRequestReviewCommentEditEnsuresArgumentsValue()
+ {
+ string body = "body";
+
+ var comment = new PullRequestReviewCommentEdit(body);
+
+ Assert.Equal(body, comment.Body);
+ }
+
+ [Fact]
+ public void PullRequestReviewCommentEditEnsuresArgumentsNotNull()
+ {
+ Assert.Throws(() => new PullRequestReviewCommentEdit(null));
+ Assert.Throws(() => new PullRequestReviewCommentEdit(""));
+ }
+
+ [Fact]
+ public void PullRequestReviewCommentReplyCreateEnsuresArgumentsValue()
+ {
+ string body = "body";
+ int inReplyTo = 1;
+
+ var comment = new PullRequestReviewCommentReplyCreate(body, inReplyTo);
+
+ Assert.Equal(body, comment.Body);
+ Assert.Equal(inReplyTo, comment.InReplyTo);
+ }
+
+ [Fact]
+ public void PullRequestReviewCommentReplyCreateEnsuresArgumentsNotNull()
+ {
+ int inReplyTo = 1;
+
+ Assert.Throws(() => new PullRequestReviewCommentReplyCreate(null, inReplyTo));
+ Assert.Throws(() => new PullRequestReviewCommentReplyCreate("", inReplyTo));
+ }
+ }
+
+ public class TheGetForPullRequestMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PullRequestReviewCommentsClient(connection);
+
+ client.GetAll("fakeOwner", "fakeRepoName", 7);
+
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fakeOwner/fakeRepoName/pulls/7/comments"));
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNotNull()
+ {
+ var connection = Substitute.For();
+ var client = new PullRequestReviewCommentsClient(connection);
+
+ await AssertEx.Throws(async () => await client.GetAll(null, "name", 1));
+ await AssertEx.Throws(async () => await client.GetAll("", "name", 1));
+ await AssertEx.Throws(async () => await client.GetAll("owner", null, 1));
+ await AssertEx.Throws(async () => await client.GetAll("owner", "", 1));
+ }
+ }
+
+ public class TheGetForRepositoryMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PullRequestReviewCommentsClient(connection);
+
+ var request = new PullRequestReviewCommentRequest
+ {
+ Direction = SortDirection.Descending,
+ Since = new DateTimeOffset(2013, 11, 15, 11, 43, 01, 00, new TimeSpan()),
+ Sort = PullRequestReviewCommentSort.Updated,
+ };
+
+ client.GetForRepository("fakeOwner", "fakeRepoName", request);
+
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fakeOwner/fakeRepoName/pulls/comments"),
+ Arg.Is>(d => d.Count == 3
+ && d["direction"] == "desc"
+ && d["since"] == "2013-11-15T11:43:01Z"
+ && d["sort"] == "updated"));
+ }
+
+ [Fact]
+ public void RequestsCorrectUrlWithoutSelectedSortingArguments()
+ {
+ var connection = Substitute.For();
+ var client = new PullRequestReviewCommentsClient(connection);
+
+ client.GetForRepository("fakeOwner", "fakeRepoName");
+
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fakeOwner/fakeRepoName/pulls/comments"),
+ Arg.Is>(d => d.Count == 2
+ && d["direction"] == "asc"
+ && d["sort"] == "created"));
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNotNull()
+ {
+ var client = new PullRequestReviewCommentsClient(Substitute.For());
+
+ var request = new PullRequestReviewCommentRequest();
+
+ await AssertEx.Throws(async () => await client.GetForRepository(null, "name", request));
+ await AssertEx.Throws(async () => await client.GetForRepository("", "name", request));
+ await AssertEx.Throws(async () => await client.GetForRepository("owner", null, request));
+ await AssertEx.Throws(async () => await client.GetForRepository("owner", "", request));
+ await AssertEx.Throws(async () => await client.GetForRepository("owner", "name", null));
+ }
+
+ [Fact]
+ public async Task EnsuresDefaultValues()
+ {
+ var request = new PullRequestReviewCommentRequest();
+
+ Assert.Equal(SortDirection.Ascending, request.Direction);
+ Assert.Null(request.Since);
+ Assert.Equal(PullRequestReviewCommentSort.Created, request.Sort);
+ }
+ }
+
+ public class TheGetCommentMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PullRequestReviewCommentsClient(connection);
+
+ client.GetComment("fakeOwner", "fakeRepoName", 53);
+
+ connection.Received().Get(Arg.Is(u => u.ToString() == "repos/fakeOwner/fakeRepoName/pulls/comments/53"),
+ null);
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNotNull()
+ {
+ var client = new PullRequestReviewCommentsClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.GetComment(null, "name", 1));
+ await AssertEx.Throws(async () => await client.GetComment("", "name", 1));
+ await AssertEx.Throws(async () => await client.GetComment("owner", null, 1));
+ await AssertEx.Throws(async () => await client.GetComment("owner", "", 1));
+ }
+ }
+
+ public class TheCreateMethod
+ {
+ [Fact]
+ public void PostsToCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PullRequestReviewCommentsClient(connection);
+
+ var comment = new PullRequestReviewCommentCreate("Comment content", "qe3dsdsf6", "file.css", 7);
+
+ client.Create("fakeOwner", "fakeRepoName", 13, comment);
+
+ connection.Connection.Received().Post(Arg.Is(u => u.ToString() == "repos/fakeOwner/fakeRepoName/pulls/13/comments"),
+ comment, null, null);
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNotNull()
+ {
+ var connection = Substitute.For();
+ var client = new PullRequestReviewCommentsClient(connection);
+
+ string body = "Comment content";
+ string commitId = "qe3dsdsf6";
+ string path = "file.css";
+ int position = 7;
+
+ var comment = new PullRequestReviewCommentCreate(body, commitId, path, position);
+
+ await AssertEx.Throws(async () => await client.Create(null, "fakeRepoName", 1, comment));
+ await AssertEx.Throws(async () => await client.Create("", "fakeRepoName", 1, comment));
+ await AssertEx.Throws(async () => await client.Create("fakeOwner", null, 1, comment));
+ await AssertEx.Throws(async () => await client.Create("fakeOwner", "", 1, comment));
+ await AssertEx.Throws(async () => await client.Create("fakeOwner", "fakeRepoName", 1, null));
+ }
+ }
+
+ public class TheCreateReplyMethod
+ {
+ [Fact]
+ public void PostsToCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PullRequestReviewCommentsClient(connection);
+
+ var comment = new PullRequestReviewCommentReplyCreate("Comment content", 5);
+
+ client.CreateReply("fakeOwner", "fakeRepoName", 13, comment);
+
+ connection.Connection.Received().Post(Arg.Is(u => u.ToString() == "repos/fakeOwner/fakeRepoName/pulls/13/comments"),
+ comment, null, null);
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNotNull()
+ {
+ var connection = Substitute.For();
+ var client = new PullRequestReviewCommentsClient(connection);
+
+ string body = "Comment content";
+ int inReplyTo = 7;
+
+ var comment = new PullRequestReviewCommentReplyCreate(body, inReplyTo);
+
+ await AssertEx.Throws(async () => await client.CreateReply(null, "fakeRepoName", 1, comment));
+ await AssertEx.Throws(async () => await client.CreateReply("", "fakeRepoName", 1, comment));
+ await AssertEx.Throws(async () => await client.CreateReply("fakeOwner", null, 1, comment));
+ await AssertEx.Throws(async () => await client.CreateReply("fakeOwner", "", 1, comment));
+ await AssertEx.Throws(async () => await client.CreateReply("fakeOwner", "fakeRepoName", 1, null));
+ }
+ }
+
+ public class TheEditMethod
+ {
+ [Fact]
+ public void PostsToCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PullRequestReviewCommentsClient(connection);
+
+ var comment = new PullRequestReviewCommentEdit("New comment content");
+
+ client.Edit("fakeOwner", "fakeRepoName", 13, comment);
+
+ connection.Received().Patch(Arg.Is(u => u.ToString() == "repos/fakeOwner/fakeRepoName/pulls/comments/13"), comment);
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNotNull()
+ {
+ var connection = Substitute.For();
+ var client = new PullRequestReviewCommentsClient(connection);
+
+ var body = "New comment content";
+
+ var comment = new PullRequestReviewCommentEdit(body);
+
+ await AssertEx.Throws(async () => await client.Edit(null, "fakeRepoName", 1, comment));
+ await AssertEx.Throws(async () => await client.Edit("", "fakeRepoName", 1, comment));
+ await AssertEx.Throws(async () => await client.Edit("fakeOwner", null, 1, comment));
+ await AssertEx.Throws(async () => await client.Edit("fakeOwner", "", 1, comment));
+ await AssertEx.Throws(async () => await client.Edit("fakeOwner", null, 1, null));
+ }
+ }
+
+ public class TheDeleteMethod
+ {
+ [Fact]
+ public void PostsToCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new PullRequestReviewCommentsClient(connection);
+
+ client.Delete("fakeOwner", "fakeRepoName", 13);
+
+ connection.Received().Delete(Arg.Is(u => u.ToString() == "repos/fakeOwner/fakeRepoName/pulls/comments/13"));
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNotNull()
+ {
+ var connection = Substitute.For();
+ var client = new PullRequestReviewCommentsClient(connection);
+
+ await AssertEx.Throws(async () => await client.Delete(null, "fakeRepoName", 1));
+ await AssertEx.Throws(async () => await client.Delete("", "fakeRepoName", 1));
+ await AssertEx.Throws(async () => await client.Delete("fakeOwner", null, 1));
+ await AssertEx.Throws(async () => await client.Delete("fakeOwner", "", 1));
+ }
+ }
+}
diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj
index effdec53..c3477890 100644
--- a/Octokit.Tests/Octokit.Tests.csproj
+++ b/Octokit.Tests/Octokit.Tests.csproj
@@ -80,6 +80,7 @@
+
@@ -158,6 +159,7 @@
+
diff --git a/Octokit.Tests/Reactive/ObservablePullRequestReviewCommentsClientTests.cs b/Octokit.Tests/Reactive/ObservablePullRequestReviewCommentsClientTests.cs
new file mode 100644
index 00000000..5c7f2d93
--- /dev/null
+++ b/Octokit.Tests/Reactive/ObservablePullRequestReviewCommentsClientTests.cs
@@ -0,0 +1,400 @@
+using System;
+using System.Collections.Generic;
+using System.Reactive.Linq;
+using System.Threading.Tasks;
+using NSubstitute;
+using Octokit.Internal;
+using Octokit.Reactive;
+using Octokit.Tests.Helpers;
+using Xunit;
+
+namespace Octokit.Tests.Reactive
+{
+ public class ObservablePullRequestReviewCommentsClientTests
+ {
+ static ApiInfo CreateApiInfo(IDictionary links)
+ {
+ return new ApiInfo(links, new List(), new List(), "etag", new RateLimit(new Dictionary()));
+ }
+
+ public class TheGetForPullRequestMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var firstPageUrl = new Uri("repos/fakeOwner/fakeRepoName/pulls/7/comments", UriKind.Relative);
+ var secondPageUrl = new Uri("https://example.com/page/2");
+ var firstPageLinks = new Dictionary { { "next", secondPageUrl } };
+ var firstPageResponse = new ApiResponse>
+ {
+ BodyAsObject = new List
+ {
+ new PullRequestReviewComment {Id = 1},
+ new PullRequestReviewComment {Id = 2},
+ new PullRequestReviewComment {Id = 3}
+ },
+ ApiInfo = CreateApiInfo(firstPageLinks)
+ };
+ var thirdPageUrl = new Uri("https://example.com/page/3");
+ var secondPageLinks = new Dictionary { { "next", thirdPageUrl } };
+ var secondPageResponse = new ApiResponse>
+ {
+ BodyAsObject = new List
+ {
+ new PullRequestReviewComment {Id = 4},
+ new PullRequestReviewComment {Id = 5},
+ new PullRequestReviewComment {Id = 6}
+ },
+ ApiInfo = CreateApiInfo(secondPageLinks)
+ };
+ var lastPageResponse = new ApiResponse>
+ {
+ BodyAsObject = new List
+ {
+ new PullRequestReviewComment {Id = 7}
+ },
+ ApiInfo = CreateApiInfo(new Dictionary())
+ };
+
+ var gitHubClient = Substitute.For();
+ gitHubClient.Connection.Get>(firstPageUrl, null, null)
+ .Returns(Task.Factory.StartNew>>(() => firstPageResponse));
+ gitHubClient.Connection.Get>(secondPageUrl, null, null)
+ .Returns(Task.Factory.StartNew>>(() => secondPageResponse));
+ gitHubClient.Connection.Get>(thirdPageUrl, null, null)
+ .Returns(Task.Factory.StartNew>>(() => lastPageResponse));
+
+ var client = new ObservablePullRequestReviewCommentsClient(gitHubClient);
+
+ var results = await client.GetForPullRequest("fakeOwner", "fakeRepoName", 7).ToArray();
+
+ Assert.Equal(7, results.Length);
+ gitHubClient.Connection.Received(1).Get>(firstPageUrl, null, null);
+ gitHubClient.Connection.Received(1).Get>(secondPageUrl, null, null);
+ gitHubClient.Connection.Received(1).Get>(thirdPageUrl, null, null);
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNotNull()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservablePullRequestReviewCommentsClient(gitHubClient);
+
+ await AssertEx.Throws(async () => await client.GetForPullRequest(null, "name", 1));
+ await AssertEx.Throws(async () => await client.GetForPullRequest("", "name", 1));
+ await AssertEx.Throws(async () => await client.GetForPullRequest("owner", null, 1));
+ await AssertEx.Throws(async () => await client.GetForPullRequest("owner", "", 1));
+ await AssertEx.Throws(async () => await client.GetForPullRequest(null, null, 1));
+ await AssertEx.Throws(async () => await client.GetForPullRequest("", "", 1));
+ }
+ }
+
+ public class TheGetForRepositoryMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var firstPageUrl = new Uri("repos/fakeOwner/fakeRepoName/pulls/comments", UriKind.Relative);
+ var secondPageUrl = new Uri("https://example.com/page/2");
+ var firstPageLinks = new Dictionary { { "next", secondPageUrl } };
+ var firstPageResponse = new ApiResponse>
+ {
+ BodyAsObject = new List
+ {
+ new PullRequestReviewComment {Id = 1},
+ new PullRequestReviewComment {Id = 2},
+ new PullRequestReviewComment {Id = 3}
+ },
+ ApiInfo = CreateApiInfo(firstPageLinks)
+ };
+ var thirdPageUrl = new Uri("https://example.com/page/3");
+ var secondPageLinks = new Dictionary { { "next", thirdPageUrl } };
+ var secondPageResponse = new ApiResponse>
+ {
+ BodyAsObject = new List
+ {
+ new PullRequestReviewComment {Id = 4},
+ new PullRequestReviewComment {Id = 5},
+ new PullRequestReviewComment {Id = 6}
+ },
+ ApiInfo = CreateApiInfo(secondPageLinks)
+ };
+ var lastPageResponse = new ApiResponse>
+ {
+ BodyAsObject = new List
+ {
+ new PullRequestReviewComment {Id = 7},
+ new PullRequestReviewComment {Id = 8},
+ },
+ ApiInfo = CreateApiInfo(new Dictionary())
+ };
+
+ var gitHubClient = Substitute.For();
+
+ gitHubClient.Connection.Get>(firstPageUrl,
+ Arg.Is>(d => d.Count == 3
+ && d["direction"] == "desc"
+ && d["since"] == "2013-11-15T11:43:01Z"
+ && d["sort"] == "updated"), null)
+ .Returns(Task.Factory.StartNew>>(() => firstPageResponse));
+ gitHubClient.Connection.Get>(secondPageUrl, null, null)
+ .Returns(Task.Factory.StartNew>>(() => secondPageResponse));
+ gitHubClient.Connection.Get>(thirdPageUrl, null, null)
+ .Returns(Task.Factory.StartNew>>(() => lastPageResponse));
+
+ var client = new ObservablePullRequestReviewCommentsClient(gitHubClient);
+
+ var request = new PullRequestReviewCommentRequest
+ {
+ Direction = SortDirection.Descending,
+ Since = new DateTimeOffset(2013, 11, 15, 11, 43, 01, 00, new TimeSpan()),
+ Sort = PullRequestReviewCommentSort.Updated,
+ };
+
+ var results = await client.GetForRepository("fakeOwner", "fakeRepoName", request).ToArray();
+
+ Assert.Equal(8, results.Length);
+ gitHubClient.Connection.Received(1).Get>(firstPageUrl,
+ Arg.Is>(d => d.Count == 3
+ && d["direction"] == "desc"
+ && d["since"] == "2013-11-15T11:43:01Z"
+ && d["sort"] == "updated"), null);
+ gitHubClient.Connection.Received(1).Get>(secondPageUrl, null, null);
+ gitHubClient.Connection.Received(1).Get>(thirdPageUrl, null, null);
+ }
+
+ [Fact]
+ public async Task RequestsCorrectUrlWithoutSelectedSortingArguments()
+ {
+ var firstPageUrl = new Uri("repos/fakeOwner/fakeRepoName/pulls/comments", UriKind.Relative);
+ var secondPageUrl = new Uri("https://example.com/page/2");
+ var firstPageLinks = new Dictionary { { "next", secondPageUrl } };
+ var firstPageResponse = new ApiResponse>
+ {
+ BodyAsObject = new List
+ {
+ new PullRequestReviewComment {Id = 1},
+ new PullRequestReviewComment {Id = 2},
+ new PullRequestReviewComment {Id = 3}
+ },
+ ApiInfo = CreateApiInfo(firstPageLinks)
+ };
+ var thirdPageUrl = new Uri("https://example.com/page/3");
+ var secondPageLinks = new Dictionary { { "next", thirdPageUrl } };
+ var secondPageResponse = new ApiResponse>
+ {
+ BodyAsObject = new List
+ {
+ new PullRequestReviewComment {Id = 4},
+ new PullRequestReviewComment {Id = 5},
+ new PullRequestReviewComment {Id = 6}
+ },
+ ApiInfo = CreateApiInfo(secondPageLinks)
+ };
+ var lastPageResponse = new ApiResponse>
+ {
+ BodyAsObject = new List
+ {
+ new PullRequestReviewComment {Id = 7},
+ new PullRequestReviewComment {Id = 8},
+ },
+ ApiInfo = CreateApiInfo(new Dictionary())
+ };
+
+ var gitHubClient = Substitute.For();
+
+ gitHubClient.Connection.Get>(firstPageUrl,
+ Arg.Is>(d => d.Count == 2
+ && d["direction"] == "asc"
+ && d["sort"] == "created"), null)
+ .Returns(Task.Factory.StartNew>>(() => firstPageResponse));
+ gitHubClient.Connection.Get>(secondPageUrl, null, null)
+ .Returns(Task.Factory.StartNew>>(() => secondPageResponse));
+ gitHubClient.Connection.Get>(thirdPageUrl, null, null)
+ .Returns(Task.Factory.StartNew>>(() => lastPageResponse));
+
+ var client = new ObservablePullRequestReviewCommentsClient(gitHubClient);
+
+ var results = await client.GetForRepository("fakeOwner", "fakeRepoName").ToArray();
+
+ Assert.Equal(8, results.Length);
+ gitHubClient.Connection.Received(1).Get>(firstPageUrl,
+ Arg.Is>(d => d.Count == 2
+ && d["direction"] == "asc"
+ && d["sort"] == "created"), null);
+ gitHubClient.Connection.Received(1).Get>(secondPageUrl, null, null);
+ gitHubClient.Connection.Received(1).Get>(thirdPageUrl, null, null);
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNotNull()
+ {
+ var client = new ObservablePullRequestReviewCommentsClient(Substitute.For());
+
+ var request = new PullRequestReviewCommentRequest();
+
+ await AssertEx.Throws(async () => await client.GetForRepository(null, "name", request));
+ await AssertEx.Throws(async () => await client.GetForRepository("", "name", request));
+ await AssertEx.Throws(async () => await client.GetForRepository("owner", null, request));
+ await AssertEx.Throws(async () => await client.GetForRepository("owner", "", request));
+ await AssertEx.Throws(async () => await client.GetForRepository("owner", "name", null));
+ }
+ }
+
+ public class TheGetCommentMethod
+ {
+ [Fact]
+ public void GetsFromClientPullRequestComment()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservablePullRequestReviewCommentsClient(gitHubClient);
+
+ client.GetComment("fakeOwner", "fakeRepoName", 53);
+
+ gitHubClient.PullRequest.Comment.Received().GetComment("fakeOwner", "fakeRepoName", 53);
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNonNull()
+ {
+ var client = new ObservablePullRequestReviewCommentsClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.GetComment(null, "name", 1));
+ await AssertEx.Throws(async () => await client.GetComment("", "name", 1));
+ await AssertEx.Throws(async () => await client.GetComment("owner", null, 1));
+ await AssertEx.Throws(async () => await client.GetComment("owner", "", 1));
+ await AssertEx.Throws(async () => await client.GetComment(null, null, 1));
+ await AssertEx.Throws(async () => await client.GetComment("", "", 1));
+ }
+ }
+
+ public class TheCreateMethod
+ {
+ [Fact]
+ public void PostsToCorrectUrl()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservablePullRequestReviewCommentsClient(gitHubClient);
+
+ var comment = new PullRequestReviewCommentCreate("Comment content", "qe3dsdsf6", "file.css", 7);
+
+ client.Create("fakeOwner", "fakeRepoName", 13, comment);
+
+ gitHubClient.PullRequest.Comment.Received().Create("fakeOwner", "fakeRepoName", 13, comment);
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNotNull()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservablePullRequestReviewCommentsClient(gitHubClient);
+
+ string body = "Comment content";
+ string commitId = "qe3dsdsf6";
+ string path = "file.css";
+ int position = 7;
+
+ var comment = new PullRequestReviewCommentCreate(body, commitId, path, position);
+
+ await AssertEx.Throws(async () => await client.Create(null, "name", 1, comment));
+ await AssertEx.Throws(async () => await client.Create("", "name", 1, comment));
+ await AssertEx.Throws(async () => await client.Create("owner", null, 1, comment));
+ await AssertEx.Throws(async () => await client.Create("owner", "", 1, comment));
+ await AssertEx.Throws(async () => await client.Create("owner", "name", 1, null));
+ }
+ }
+
+ public class TheCreateReplyMethod
+ {
+ [Fact]
+ public void PostsToCorrectUrl()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservablePullRequestReviewCommentsClient(gitHubClient);
+
+ var comment = new PullRequestReviewCommentReplyCreate("Comment content", 9);
+
+ client.CreateReply("fakeOwner", "fakeRepoName", 13, comment);
+
+ gitHubClient.PullRequest.Comment.Received().CreateReply("fakeOwner", "fakeRepoName", 13, comment);
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNotNull()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservablePullRequestReviewCommentsClient(gitHubClient);
+
+ string body = "Comment content";
+ int inReplyTo = 7;
+
+ var comment = new PullRequestReviewCommentReplyCreate(body, inReplyTo);
+
+ await AssertEx.Throws(async () => await client.CreateReply(null, "name", 1, comment));
+ await AssertEx.Throws(async () => await client.CreateReply("", "name", 1, comment));
+ await AssertEx.Throws(async () => await client.CreateReply("owner", null, 1, comment));
+ await AssertEx.Throws(async () => await client.CreateReply("owner", "", 1, comment));
+ await AssertEx.Throws(async () => await client.CreateReply("owner", "name", 1, null));
+ }
+ }
+
+ public class TheEditMethod
+ {
+ [Fact]
+ public void PostsToCorrectUrl()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservablePullRequestReviewCommentsClient(gitHubClient);
+
+ var comment = new PullRequestReviewCommentEdit("New comment content");
+
+ client.Edit("fakeOwner", "fakeRepoName", 13, comment);
+
+ gitHubClient.PullRequest.Comment.Received().Edit("fakeOwner", "fakeRepoName", 13, comment);
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNotNull()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservablePullRequestReviewCommentsClient(gitHubClient);
+
+ var body = "New comment content";
+
+ var comment = new PullRequestReviewCommentEdit(body);
+
+ await AssertEx.Throws(async () => await client.Edit(null, "name", 1, comment));
+ await AssertEx.Throws(async () => await client.Edit("", "name", 1, comment));
+ await AssertEx.Throws(async () => await client.Edit("owner", null, 1, comment));
+ await AssertEx.Throws(async () => await client.Edit("owner", "", 1, comment));
+ await AssertEx.Throws(async () => await client.Edit("owner", "name", 1, null));
+ }
+ }
+
+ public class TheDeleteMethod
+ {
+ [Fact]
+ public void PostsToCorrectUrl()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservablePullRequestReviewCommentsClient(gitHubClient);
+
+ client.Delete("fakeOwner", "fakeRepoName", 13);
+
+ gitHubClient.PullRequest.Comment.Received().Delete("fakeOwner", "fakeRepoName", 13);
+ }
+
+ [Fact]
+ public async Task EnsuresArgumentsNotNull()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservablePullRequestReviewCommentsClient(gitHubClient);
+
+ await AssertEx.Throws(async () => await client.Delete(null, "name", 1));
+ await AssertEx.Throws(async () => await client.Delete("", "name", 1));
+ await AssertEx.Throws(async () => await client.Delete("owner", null, 1));
+ await AssertEx.Throws(async () => await client.Delete("owner", "", 1));
+ }
+ }
+ }
+}
diff --git a/Octokit/Clients/IPullRequestReviewCommentsClient.cs b/Octokit/Clients/IPullRequestReviewCommentsClient.cs
new file mode 100644
index 00000000..e749effe
--- /dev/null
+++ b/Octokit/Clients/IPullRequestReviewCommentsClient.cs
@@ -0,0 +1,90 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace Octokit
+{
+ public interface IPullRequestReviewCommentsClient
+ {
+ ///
+ /// Gets review comments for a specified pull request.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#list-comments-on-a-pull-request
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request number
+ /// The list of s for the specified pull request
+ Task> GetAll(string owner, string name, int number);
+
+ ///
+ /// Gets a list of the pull request review comments in a specified repository.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#list-comments-in-a-repository
+ /// The owner of the repository
+ /// The name of the repository
+ /// The list of s for the specified repository
+ Task> GetForRepository(string owner, string name);
+
+ ///
+ /// Gets a list of the pull request review comments in a specified repository.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#list-comments-in-a-repository
+ /// The owner of the repository
+ /// The name of the repository
+ /// The sorting parameters
+ /// The list of s for the specified repository
+ Task> GetForRepository(string owner, string name, PullRequestReviewCommentRequest request);
+
+ ///
+ /// Gets a single pull request review comment by number.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#get-a-single-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request review comment number
+ /// The
+ Task GetComment(string owner, string name, int number);
+
+ ///
+ /// Creates a comment on a pull request review.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#create-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The Pull Request number
+ /// The comment
+ /// The created
+ Task Create(string owner, string name, int number, PullRequestReviewCommentCreate comment);
+
+ ///
+ /// Creates a comment on a pull request review as a reply to another comment.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#create-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request number
+ /// The comment
+ /// The created
+ Task CreateReply(string owner, string name, int number, PullRequestReviewCommentReplyCreate comment);
+
+ ///
+ /// Edits a comment on a pull request review.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#edit-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request review comment number
+ /// The edited comment
+ /// The edited
+ Task Edit(string owner, string name, int number, PullRequestReviewCommentEdit comment);
+
+ ///
+ /// Deletes a comment on a pull request review.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#delete-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request review comment number
+ ///
+ Task Delete(string owner, string name, int number);
+ }
+}
diff --git a/Octokit/Clients/IPullRequestsClient.cs b/Octokit/Clients/IPullRequestsClient.cs
index 0c0b5fc6..940db5c0 100644
--- a/Octokit/Clients/IPullRequestsClient.cs
+++ b/Octokit/Clients/IPullRequestsClient.cs
@@ -7,6 +7,10 @@ namespace Octokit
public interface IPullRequestsClient
{
///
+ /// Client for managing comments.
+ ///
+ IPullRequestReviewCommentsClient Comment { get; }
+
/// Get a pull request by number.
///
///
diff --git a/Octokit/Clients/PullRequestReviewCommentsClient.cs b/Octokit/Clients/PullRequestReviewCommentsClient.cs
new file mode 100644
index 00000000..fee2143c
--- /dev/null
+++ b/Octokit/Clients/PullRequestReviewCommentsClient.cs
@@ -0,0 +1,159 @@
+using System.Collections.Generic;
+using System.Net;
+using System.Threading.Tasks;
+
+namespace Octokit
+{
+ public class PullRequestReviewCommentsClient : ApiClient, IPullRequestReviewCommentsClient
+ {
+ public PullRequestReviewCommentsClient(IApiConnection apiConnection)
+ : base(apiConnection)
+ {
+ }
+
+ ///
+ /// Gets review comments for a specified pull request.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#list-comments-on-a-pull-request
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request number
+ /// The list of s for the specified pull request
+ public Task> GetAll(string owner, string name, int number)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+
+ return ApiConnection.GetAll(ApiUrls.PullRequestReviewComments(owner, name, number));
+ }
+
+ ///
+ /// Gets a list of the pull request review comments in a specified repository.
+ ///
+ /// http://developer.github.com/v3/pulls/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 Task> GetForRepository(string owner, string name)
+ {
+ return GetForRepository(owner, name, new PullRequestReviewCommentRequest());
+ }
+
+ ///
+ /// Gets a list of the pull request review comments in a specified repository.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#list-comments-in-a-repository
+ /// The owner of the repository
+ /// The name of the repository
+ /// The sorting parameters
+ /// The list of s for the specified repository
+ public Task> GetForRepository(string owner, string name, PullRequestReviewCommentRequest request)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+ Ensure.ArgumentNotNull(request, "request");
+
+ return ApiConnection.GetAll(ApiUrls.PullRequestReviewCommentsRepository(owner, name), request.ToParametersDictionary());
+ }
+
+ ///
+ /// Gets a single pull request review comment by number.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#get-a-single-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request review comment number
+ /// The
+ public Task GetComment(string owner, string name, int number)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+
+ return ApiConnection.Get(ApiUrls.PullRequestReviewComment(owner, name, number));
+ }
+
+ ///
+ /// Creates a comment on a pull request review.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#create-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The Pull Request number
+ /// The comment
+ /// The created
+ public async Task Create(string owner, string name, int number, PullRequestReviewCommentCreate comment)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+ Ensure.ArgumentNotNull(comment, "comment");
+
+ var response = await ApiConnection.Connection.Post(ApiUrls.PullRequestReviewComments(owner, name, number), comment, null, null).ConfigureAwait(false);
+
+ if (response.StatusCode != HttpStatusCode.Created)
+ {
+ throw new ApiException("Invalid Status Code returned. Expected a 201", response.StatusCode);
+ }
+
+ return response.BodyAsObject;
+ }
+
+ ///
+ /// Creates a comment on a pull request review as a reply to another comment.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#create-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request number
+ /// The comment
+ /// The created
+ public async Task CreateReply(string owner, string name, int number, PullRequestReviewCommentReplyCreate comment)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+ Ensure.ArgumentNotNull(comment, "comment");
+
+ var response = await ApiConnection.Connection.Post(ApiUrls.PullRequestReviewComments(owner, name, number), comment, null, null).ConfigureAwait(false);
+
+ if (response.StatusCode != HttpStatusCode.Created)
+ {
+ throw new ApiException("Invalid Status Code returned. Expected a 201", response.StatusCode);
+ }
+
+ return response.BodyAsObject;
+ }
+
+ ///
+ /// Edits a comment on a pull request review.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#edit-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request review comment number
+ /// The edited comment
+ /// The edited
+ public Task Edit(string owner, string name, int number, PullRequestReviewCommentEdit comment)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+ Ensure.ArgumentNotNull(comment, "comment");
+
+ return ApiConnection.Patch(ApiUrls.PullRequestReviewComment(owner, name, number), comment);
+ }
+
+ ///
+ /// Deletes a comment on a pull request review.
+ ///
+ /// http://developer.github.com/v3/pulls/comments/#delete-a-comment
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request review comment number
+ ///
+ public Task Delete(string owner, string name, int number)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
+ Ensure.ArgumentNotNullOrEmptyString(name, "name");
+
+ return ApiConnection.Delete(ApiUrls.PullRequestReviewComment(owner, name, number));
+ }
+ }
+}
diff --git a/Octokit/Clients/PullRequestsClient.cs b/Octokit/Clients/PullRequestsClient.cs
index 1c1919fb..bf2a026c 100644
--- a/Octokit/Clients/PullRequestsClient.cs
+++ b/Octokit/Clients/PullRequestsClient.cs
@@ -6,12 +6,16 @@ namespace Octokit
{
public class PullRequestsClient : ApiClient, IPullRequestsClient
{
- public PullRequestsClient(IApiConnection apiConnection)
- : base(apiConnection)
+ public PullRequestsClient(IApiConnection apiConnection) : base(apiConnection)
{
+ Comment = new PullRequestReviewCommentsClient(apiConnection);
}
///
+ /// Client for managing comments.
+ ///
+ public IPullRequestReviewCommentsClient Comment { get; private set; }
+
/// Get a pull request by number.
///
///
diff --git a/Octokit/GitHubClient.cs b/Octokit/GitHubClient.cs
index 97a663db..4580642a 100644
--- a/Octokit/GitHubClient.cs
+++ b/Octokit/GitHubClient.cs
@@ -86,6 +86,7 @@ namespace Octokit
Notification = new NotificationsClient(apiConnection);
Oauth = new OauthClient(connection);
Organization = new OrganizationsClient(apiConnection);
+ PullRequest = new PullRequestsClient(apiConnection);
Repository = new RepositoriesClient(apiConnection);
Gist = new GistsClient(apiConnection);
Release = new ReleasesClient(apiConnection);
@@ -136,6 +137,7 @@ namespace Octokit
public IMiscellaneousClient Miscellaneous { get; private set; }
public IOauthClient Oauth { get; private set; }
public IOrganizationsClient Organization { get; private set; }
+ public IPullRequestsClient PullRequest { get; private set; }
public IRepositoriesClient Repository { get; private set; }
public IGistsClient Gist { get; private set; }
public IReleasesClient Release { get; private set; }
diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs
index 44dc39e2..980dfe11 100644
--- a/Octokit/Helpers/ApiUrls.cs
+++ b/Octokit/Helpers/ApiUrls.cs
@@ -862,6 +862,41 @@ namespace Octokit
return "users/{0}/events/orgs/{1}".FormatUri(user, organization);
}
+ ///
+ /// Returns the for the comments of a specified pull request review.
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ /// The pull request number
+ /// The
+ public static Uri PullRequestReviewComments(string owner, string name, int number)
+ {
+ return "repos/{0}/{1}/pulls/{2}/comments".FormatUri(owner, name, number);
+ }
+
+ ///
+ /// Returns the for the specified pull request review comment.
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ /// The comment number
+ /// The
+ public static Uri PullRequestReviewComment(string owner, string name, int number)
+ {
+ return "repos/{0}/{1}/pulls/comments/{2}".FormatUri(owner, name, number);
+ }
+
+ ///
+ /// Returns the for the pull request review comments on a specified repository.
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ /// The
+ public static Uri PullRequestReviewCommentsRepository(string owner, string name)
+ {
+ return "repos/{0}/{1}/pulls/comments".FormatUri(owner, name);
+ }
+
///
/// Returns the for a specifc blob.
///
diff --git a/Octokit/IGitHubClient.cs b/Octokit/IGitHubClient.cs
index ba5da490..54472d5f 100644
--- a/Octokit/IGitHubClient.cs
+++ b/Octokit/IGitHubClient.cs
@@ -15,6 +15,7 @@ namespace Octokit
IMiscellaneousClient Miscellaneous { get; }
IOauthClient Oauth { get; }
IOrganizationsClient Organization { get; }
+ IPullRequestsClient PullRequest { get; }
IRepositoriesClient Repository { get; }
IGistsClient Gist { get; }
IReleasesClient Release { get; }
diff --git a/Octokit/Models/Request/PullRequestReviewCommentCreate.cs b/Octokit/Models/Request/PullRequestReviewCommentCreate.cs
new file mode 100644
index 00000000..d9ae04b8
--- /dev/null
+++ b/Octokit/Models/Request/PullRequestReviewCommentCreate.cs
@@ -0,0 +1,48 @@
+using System.Diagnostics;
+using Octokit.Internal;
+
+namespace Octokit
+{
+ [DebuggerDisplay("{DebuggerDisplay,nq}")]
+ public class PullRequestReviewCommentCreate : RequestParameters
+ {
+ ///
+ /// Creates a comment
+ ///
+ /// The text of the comment
+ /// The SHA of the commit to comment on
+ /// The relative path of the file to comment on
+ /// The line index in the diff to comment on
+ public PullRequestReviewCommentCreate(string body, string commitId, string path, int position)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(body, "body");
+ Ensure.ArgumentNotNullOrEmptyString(commitId, "commitId");
+ Ensure.ArgumentNotNullOrEmptyString(path, "path");
+
+ Body = body;
+ CommitId = commitId;
+ Path = path;
+ Position = position;
+ }
+
+ ///
+ /// The text of the comment.
+ ///
+ public string Body { get; private set; }
+
+ ///
+ /// The SHA of the commit to comment on.
+ ///
+ public string CommitId { get; private set; }
+
+ ///
+ /// The relative path of the file to comment on.
+ ///
+ public string Path { get; private set; }
+
+ ///
+ /// The line index in the diff to comment on.
+ ///
+ public int Position { get; private set; }
+ }
+}
diff --git a/Octokit/Models/Request/PullRequestReviewCommentEdit.cs b/Octokit/Models/Request/PullRequestReviewCommentEdit.cs
new file mode 100644
index 00000000..f8cc7ba1
--- /dev/null
+++ b/Octokit/Models/Request/PullRequestReviewCommentEdit.cs
@@ -0,0 +1,24 @@
+using System.Diagnostics;
+
+namespace Octokit
+{
+ [DebuggerDisplay("{DebuggerDisplay,nq}")]
+ public class PullRequestReviewCommentEdit : RequestParameters
+ {
+ ///
+ /// Creates an edit to a comment
+ ///
+ /// The text of the comment
+ public PullRequestReviewCommentEdit(string body)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(body, "body");
+
+ Body = body;
+ }
+
+ ///
+ /// The text of the comment.
+ ///
+ public string Body { get; private set; }
+ }
+}
diff --git a/Octokit/Models/Request/PullRequestReviewCommentReplyCreate.cs b/Octokit/Models/Request/PullRequestReviewCommentReplyCreate.cs
new file mode 100644
index 00000000..221ea677
--- /dev/null
+++ b/Octokit/Models/Request/PullRequestReviewCommentReplyCreate.cs
@@ -0,0 +1,32 @@
+using System.Diagnostics;
+using Octokit.Internal;
+
+namespace Octokit
+{
+ [DebuggerDisplay("{DebuggerDisplay,nq}")]
+ public class PullRequestReviewCommentReplyCreate : RequestParameters
+ {
+ ///
+ /// Creates a comment that is replying to another comment.
+ ///
+ /// The text of the comment
+ /// The comment Id to reply to
+ public PullRequestReviewCommentReplyCreate(string body, int inReplyTo)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(body, "body");
+
+ Body = body;
+ InReplyTo = inReplyTo;
+ }
+
+ ///
+ /// The text of the comment.
+ ///
+ public string Body { get; private set; }
+
+ ///
+ /// The comment Id to reply to.
+ ///
+ public int InReplyTo { get; private set; }
+ }
+}
diff --git a/Octokit/Models/Request/PullRequestReviewCommentRequest.cs b/Octokit/Models/Request/PullRequestReviewCommentRequest.cs
new file mode 100644
index 00000000..4bd22d0f
--- /dev/null
+++ b/Octokit/Models/Request/PullRequestReviewCommentRequest.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Diagnostics;
+
+namespace Octokit
+{
+ [DebuggerDisplay("{DebuggerDisplay,nq}")]
+ public class PullRequestReviewCommentRequest : RequestParameters
+ {
+ public PullRequestReviewCommentRequest()
+ {
+ // Default arguments
+ Sort = PullRequestReviewCommentSort.Created;
+ Direction = SortDirection.Ascending;
+ Since = null;
+ }
+
+ ///
+ /// Can be either created or updated. Default: created.
+ ///
+ public PullRequestReviewCommentSort Sort { get; set; }
+
+ ///
+ /// Can be either asc or desc. Default: asc.
+ ///
+ public SortDirection Direction { get; set; }
+
+ ///
+ /// Only comments updated at or after this time are returned. This is a timestamp in ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ.
+ ///
+ public DateTimeOffset? Since { get; set; }
+ }
+}
diff --git a/Octokit/Models/Response/PullRequestReviewComment.cs b/Octokit/Models/Response/PullRequestReviewComment.cs
new file mode 100644
index 00000000..03e6b418
--- /dev/null
+++ b/Octokit/Models/Response/PullRequestReviewComment.cs
@@ -0,0 +1,92 @@
+using System;
+using System.Diagnostics;
+
+namespace Octokit
+{
+ [DebuggerDisplay("{DebuggerDisplay,nq}")]
+ public class PullRequestReviewComment
+ {
+ ///
+ /// URL of the comment via the API.
+ ///
+ public Uri Url { get; set; }
+
+ ///
+ /// The comment Id.
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// The diff hunk the comment is about.
+ ///
+ public string DiffHunk { get; set; }
+
+ ///
+ /// The relative path of the file the comment is about.
+ ///
+ public string Path { get; set; }
+
+ ///
+ /// The line index in the diff.
+ ///
+ public int? Position { get; set; }
+
+ ///
+ /// The comment original position.
+ ///
+ public int? OriginalPosition { get; set; }
+
+ ///
+ /// The commit Id the comment is associated with.
+ ///
+ public string CommitId { get; set; }
+
+ ///
+ /// The original commit Id the comment is associated with.
+ ///
+ public string OriginalCommitId { get; set; }
+
+ ///
+ /// The user that created the comment.
+ ///
+ public User User { get; set; }
+
+ ///
+ /// The text of the comment.
+ ///
+ public string Body { get; set; }
+
+ ///
+ /// The date the comment was created.
+ ///
+ public DateTimeOffset CreatedAt { get; set; }
+
+ ///
+ /// The date the comment was last updated.
+ ///
+ public DateTimeOffset UpdatedAt { get; set; }
+
+ ///
+ /// The URL for this comment on Github.com
+ ///
+ public Uri HtmlUrl { get; set; }
+
+ ///
+ /// The URL for the pull request via the API.
+ ///
+ public Uri PullRequestUrl { get; set; }
+ }
+
+ public enum PullRequestReviewCommentSort
+ {
+ ///
+ /// Sort by create date (default)
+ ///
+ Created,
+
+ ///
+ /// Sort by the date of the last update
+ ///
+ Updated,
+ }
+}
diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj
index cf135ed5..f7483d98 100644
--- a/Octokit/Octokit-Mono.csproj
+++ b/Octokit/Octokit-Mono.csproj
@@ -154,6 +154,7 @@
+
@@ -261,6 +262,12 @@
+
+
+
+
+
+
diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj
index bb4b6d1f..7fd056f7 100644
--- a/Octokit/Octokit-MonoAndroid.csproj
+++ b/Octokit/Octokit-MonoAndroid.csproj
@@ -241,6 +241,13 @@
+
+
+
+
+
+
+
diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj
index 09c2666f..882e3807 100644
--- a/Octokit/Octokit-Monotouch.csproj
+++ b/Octokit/Octokit-Monotouch.csproj
@@ -236,6 +236,13 @@
+
+
+
+
+
+
+
diff --git a/Octokit/Octokit-Portable.csproj b/Octokit/Octokit-Portable.csproj
index 7cf66edd..69b78da2 100644
--- a/Octokit/Octokit-Portable.csproj
+++ b/Octokit/Octokit-Portable.csproj
@@ -317,6 +317,13 @@
+
+
+
+
+
+
+
diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj
index 8ab09384..acf45b5a 100644
--- a/Octokit/Octokit-netcore45.csproj
+++ b/Octokit/Octokit-netcore45.csproj
@@ -65,6 +65,10 @@
+
+
+
+
@@ -85,7 +89,6 @@
-
@@ -106,7 +109,6 @@
-
@@ -258,6 +260,11 @@
+
+
+
+
+
diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj
index 46051948..43853cc5 100644
--- a/Octokit/Octokit.csproj
+++ b/Octokit/Octokit.csproj
@@ -96,6 +96,14 @@
+
+
+
+
+
+
+
+
@@ -152,6 +160,7 @@
+
@@ -181,7 +190,6 @@
-
@@ -190,7 +198,6 @@
-