Implement Review API for Pull Requests (#1648)

* First Iteration Need to finish tests and docs

* Mostly Complete

* Fixing tests and adding review comments

* Added tests for reactive client

* Moved Reviews inside fo the Pull request client for better organization and began initial intigration testing

* Fixing bad recursive function breaking tests

* test fixes

* Add paging support to review comments call

* Fixing recursive function

* Addressing comments from PR

* fixing CI break

* Typo build break

* Fixing Convention Tests

* Adding correct nameof() usage in Ensure

* Small consitancy changes

* Trigger build

* Address PR Comments

* Fixup test naming

* Fix sub client ordering and incorrect URL

* Tidy up comments and remove StringEnum wrapper from Request models as it is only for Response models

* Rename GetReview to Get

* tweak debugger display

* Rework integration tests - implement the easy Get/GetAll ones first...

* Implement integration tests for Create method.
Move helpers to create PR/review into SetupHelper class
Fixed up review status enum to contain correct values
Tests for Approve/RequestChanges currently failing as a user cant approve/request changes on their own PR

* Implement secondary account settings for integration tests and a new [DualAccountTest] attribute for discovery when configured
Change integration test to create PR from the 2nd account, so the main test account is able to perform review actions on the PR

* Add integration tests for Delete, Dismiss and Submit methods
Fixed up API client implementation for delete (was looking for incorrect 201 http status)
Removed unnecessary await/async calls from client implementations that dont need to do anything with the result

* Attempting to add comments as part of a review revealed that we cant use the existing PullRequestReviewCommentCreate class as the API throws a validation error due to the CommitId field
These newer review APIs need a DraftPullRequestReviewComment (that doesnt have a commitId) instead

* add second test account user/password to configure-integration-tests script
This commit is contained in:
Travis Harris
2017-08-16 03:50:25 -07:00
committed by Ryan Gribble
parent 7c170213fd
commit ff9521ce3d
26 changed files with 3381 additions and 78 deletions

View File

@@ -0,0 +1,187 @@
using System;
using System.Reactive;
namespace Octokit.Reactive
{
/// <summary>
/// A client for GitHub's Pull Request Review API.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/pulls/reviews/">Review API documentation</a> for more information.
/// </remarks>
public interface IObservablePullRequestReviewsClient
{
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
IObservable<PullRequestReview> GetAll(string owner, string name, int number);
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
IObservable<PullRequestReview> GetAll(long repositoryId, int number);
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="options">Options for changing the API response</param>
IObservable<PullRequestReview> GetAll(string owner, string name, int number, ApiOptions options);
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="options">Options for changing the API response</param>
IObservable<PullRequestReview> GetAll(long repositoryId, int number, ApiOptions options);
/// <summary>
/// Gets a single pull request review by ID.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-a-single-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
IObservable<PullRequestReview> Get(string owner, string name, int number, long reviewId);
/// <summary>
/// Gets a single pull request review by ID.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-a-single-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
IObservable<PullRequestReview> Get(long repositoryId, int number, long reviewId);
/// <summary>
/// Creates a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The Pull Request number</param>
/// <param name="review">The review</param>
IObservable<PullRequestReview> Create(string owner, string name, int number, PullRequestReviewCreate review);
/// <summary>
/// Creates a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The Pull Request number</param>
/// <param name="review">The review</param>
IObservable<PullRequestReview> Create(long repositoryId, int number, PullRequestReviewCreate review);
/// <summary>
/// Deletes a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
IObservable<Unit> Delete(string owner, string name, int number, long reviewId);
/// <summary>
/// Deletes a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
IObservable<Unit> Delete(long repositoryId, int number, long reviewId);
/// <summary>
/// Submits a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="submitMessage">The message and event being submitted for the review</param>
IObservable<PullRequestReview> Submit(string owner, string name, int number, long reviewId, PullRequestReviewSubmit submitMessage);
/// <summary>
/// Submits a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="submitMessage">The message and event being submitted for the review</param>
IObservable<PullRequestReview> Submit(long repositoryId, int number, long reviewId, PullRequestReviewSubmit submitMessage);
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="dismissMessage">The message indicating why the review was dismissed</param>
IObservable<PullRequestReview> Dismiss(string owner, string name, int number, long reviewId, PullRequestReviewDismiss dismissMessage);
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="dismissMessage">The message indicating why the review was dismissed</param>
IObservable<PullRequestReview> Dismiss(long repositoryId, int number, long reviewId, PullRequestReviewDismiss dismissMessage);
/// <summary>
/// Lists comments for a single review
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
IObservable<PullRequestReviewComment> GetAllComments(string owner, string name, int number, long reviewId);
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
IObservable<PullRequestReviewComment> GetAllComments(long repositoryId, int number, long reviewId);
/// <summary>
/// Lists comments for a single review
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
IObservable<PullRequestReviewComment> GetAllComments(string owner, string name, int number, long reviewId, ApiOptions options);
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
IObservable<PullRequestReviewComment> GetAllComments(long repositoryId, int number, long reviewId, ApiOptions options);
}
}

View File

@@ -17,6 +17,11 @@ namespace Octokit.Reactive
[Obsolete("Please use IObservablePullRequestsClient.ReviewComment. This will be removed in a future version")] [Obsolete("Please use IObservablePullRequestsClient.ReviewComment. This will be removed in a future version")]
IObservablePullRequestReviewCommentsClient Comment { get; } IObservablePullRequestReviewCommentsClient Comment { get; }
/// <summary>
/// Client for managing reviews.
/// </summary>
IObservablePullRequestReviewsClient Review { get; }
/// <summary> /// <summary>
/// Client for managing review comments. /// Client for managing review comments.
/// </summary> /// </summary>

View File

@@ -0,0 +1,292 @@
using System;
using System.Reactive;
using System.Reactive.Threading.Tasks;
using Octokit.Reactive.Internal;
namespace Octokit.Reactive
{
/// <summary>
/// A client for GitHub's Pull Request Review API.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/pulls/reviews/">Review API documentation</a> for more information.
/// </remarks>
public class ObservablePullRequestReviewsClient : IObservablePullRequestReviewsClient
{
readonly IPullRequestReviewsClient _client;
readonly IConnection _connection;
public ObservablePullRequestReviewsClient(IGitHubClient client)
{
Ensure.ArgumentNotNull(client, nameof(client));
_client = client.PullRequest.Review;
_connection = client.Connection;
}
/// <summary>
/// Creates a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The Pull Request number</param>
/// <param name="review">The review</param>
public IObservable<PullRequestReview> Create(string owner, string name, int number, PullRequestReviewCreate review)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name,nameof(name));
Ensure.ArgumentNotNull(review, nameof(review));
return _client.Create(owner, name, number, review).ToObservable();
}
/// <summary>
/// Creates a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The Pull Request number</param>
/// <param name="review">The review</param>
public IObservable<PullRequestReview> Create(long repositoryId, int number, PullRequestReviewCreate review)
{
Ensure.ArgumentNotNull(review, nameof(review));
return _client.Create(repositoryId, number, review).ToObservable();
}
/// <summary>
/// Deletes a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public IObservable<Unit> Delete(string owner, string name, int number, long reviewId)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name,nameof(name));
return _client.Delete(owner, name, number, reviewId).ToObservable();
}
/// <summary>
/// Deletes a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public IObservable<Unit> Delete(long repositoryId, int number, long reviewId)
{
return _client.Delete(repositoryId, number, reviewId).ToObservable();
}
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="dismissMessage">The message indicating why the review was dismissed</param>
public IObservable<PullRequestReview> Dismiss(string owner, string name, int number, long reviewId, PullRequestReviewDismiss dismissMessage)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name,nameof(name));
Ensure.ArgumentNotNull(dismissMessage, nameof(dismissMessage));
return _client.Dismiss(owner, name, number, reviewId, dismissMessage).ToObservable();
}
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="dismissMessage">The message indicating why the review was dismissed</param>
public IObservable<PullRequestReview> Dismiss(long repositoryId, int number, long reviewId, PullRequestReviewDismiss dismissMessage)
{
Ensure.ArgumentNotNull(dismissMessage, nameof(dismissMessage));
return GetAll(repositoryId, number);
}
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
public IObservable<PullRequestReview> GetAll(string owner, string name, int number)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name,nameof(name));
return GetAll(owner, name, number, ApiOptions.None);
}
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
public IObservable<PullRequestReview> GetAll(long repositoryId, int number)
{
return GetAll(repositoryId, number, ApiOptions.None);
}
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="options">Options for changing the API response</param>
public IObservable<PullRequestReview> GetAll(string owner, string name, int number, ApiOptions options)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name,nameof(name));
Ensure.ArgumentNotNull(options, nameof(options));
return _connection.GetAndFlattenAllPages<PullRequestReview>(ApiUrls.PullRequestReviews(owner, name, number), null, null, options);
}
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="options">Options for changing the API response</param>
public IObservable<PullRequestReview> GetAll(long repositoryId, int number, ApiOptions options)
{
Ensure.ArgumentNotNull(options, nameof(options));
return _connection.GetAndFlattenAllPages<PullRequestReview>(ApiUrls.PullRequestReviews(repositoryId, number), null, null, options);
}
/// <summary>
/// Gets a single pull request review by ID.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-a-single-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public IObservable<PullRequestReview> Get(string owner, string name, int number, long reviewId)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name,nameof(name));
return _client.Get(owner, name, number, reviewId).ToObservable();
}
/// <summary>
/// Gets a single pull request review by ID.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-a-single-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public IObservable<PullRequestReview> Get(long repositoryId, int number, long reviewId)
{
return _client.Get(repositoryId, number, reviewId).ToObservable();
}
/// <summary>
/// Submits a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="submitMessage">The message and event being submitted for the review</param>
public IObservable<PullRequestReview> Submit(string owner, string name, int number, long reviewId, PullRequestReviewSubmit submitMessage)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name,nameof(name));
Ensure.ArgumentNotNull(submitMessage, nameof(submitMessage));
return _client.Submit(owner, name, number, reviewId, submitMessage).ToObservable();
}
/// <summary>
/// Submits a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="submitMessage">The message and event being submitted for the review</param>
public IObservable<PullRequestReview> Submit(long repositoryId, int number, long reviewId, PullRequestReviewSubmit submitMessage)
{
Ensure.ArgumentNotNull(submitMessage, nameof(submitMessage));
return _client.Submit(repositoryId, number, reviewId, submitMessage).ToObservable();
}
/// <summary>
/// Lists comments for a single review
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public IObservable<PullRequestReviewComment> GetAllComments(string owner, string name, int number, long reviewId)
{
return GetAllComments(owner, name, number, reviewId, ApiOptions.None);
}
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public IObservable<PullRequestReviewComment> GetAllComments(long repositoryId, int number, long reviewId)
{
return GetAllComments(repositoryId, number, reviewId, ApiOptions.None);
}
/// <summary>
/// Lists comments for a single review
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public IObservable<PullRequestReviewComment> GetAllComments(string owner, string name, int number, long reviewId, ApiOptions options)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name,nameof(name));
Ensure.ArgumentNotNull(options, nameof(options));
return _connection.GetAndFlattenAllPages<PullRequestReviewComment>(ApiUrls.PullRequestReviewComments(owner, name, number, reviewId), options);
}
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public IObservable<PullRequestReviewComment> GetAllComments(long repositoryId, int number, long reviewId, ApiOptions options)
{
Ensure.ArgumentNotNull(options, nameof(options));
return _connection.GetAndFlattenAllPages<PullRequestReviewComment>(ApiUrls.PullRequestReviewComments(repositoryId, number, reviewId),options);
}
}
}

View File

@@ -8,7 +8,7 @@ namespace Octokit.Reactive
/// A client for GitHub's Pull Requests API. /// A client for GitHub's Pull Requests API.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// See the <a href="http://developer.github.com/v3/activity/notifications/">Pull Requests API documentation</a> for more information. /// See the <a href="https://developer.github.com/v3/pulls/">Pull Requests API documentation</a> for more information.
/// </remarks> /// </remarks>
public class ObservablePullRequestsClient : IObservablePullRequestsClient public class ObservablePullRequestsClient : IObservablePullRequestsClient
{ {
@@ -21,6 +21,11 @@ namespace Octokit.Reactive
[Obsolete("Please use ObservablePullRequestsClient.ReviewComment. This will be removed in a future version")] [Obsolete("Please use ObservablePullRequestsClient.ReviewComment. This will be removed in a future version")]
public IObservablePullRequestReviewCommentsClient Comment { get { return this.ReviewComment; } } public IObservablePullRequestReviewCommentsClient Comment { get { return this.ReviewComment; } }
/// <summary>
/// Client for managing reviews.
/// </summary>
public IObservablePullRequestReviewsClient Review { get; private set; }
/// <summary> /// <summary>
/// Client for managing review comments. /// Client for managing review comments.
/// </summary> /// </summary>
@@ -37,6 +42,7 @@ namespace Octokit.Reactive
_client = client.Repository.PullRequest; _client = client.Repository.PullRequest;
_connection = client.Connection; _connection = client.Connection;
Review = new ObservablePullRequestReviewsClient(client);
ReviewComment = new ObservablePullRequestReviewCommentsClient(client); ReviewComment = new ObservablePullRequestReviewCommentsClient(client);
ReviewRequest = new ObservablePullRequestReviewRequestsClient(client); ReviewRequest = new ObservablePullRequestReviewRequestsClient(client);
} }

View File

@@ -38,6 +38,7 @@ namespace Octokit.Reactive
Oauth = new ObservableOauthClient(gitHubClient); Oauth = new ObservableOauthClient(gitHubClient);
Organization = new ObservableOrganizationsClient(gitHubClient); Organization = new ObservableOrganizationsClient(gitHubClient);
PullRequest = new ObservablePullRequestsClient(gitHubClient); PullRequest = new ObservablePullRequestsClient(gitHubClient);
PullRequestReview = new ObservablePullRequestReviewsClient(gitHubClient);
Repository = new ObservableRepositoriesClient(gitHubClient); Repository = new ObservableRepositoriesClient(gitHubClient);
User = new ObservableUsersClient(gitHubClient); User = new ObservableUsersClient(gitHubClient);
Git = new ObservableGitDatabaseClient(gitHubClient); Git = new ObservableGitDatabaseClient(gitHubClient);
@@ -60,6 +61,7 @@ namespace Octokit.Reactive
public IObservableOauthClient Oauth { get; private set; } public IObservableOauthClient Oauth { get; private set; }
public IObservableOrganizationsClient Organization { get; private set; } public IObservableOrganizationsClient Organization { get; private set; }
public IObservablePullRequestsClient PullRequest { get; private set; } public IObservablePullRequestsClient PullRequest { get; private set; }
public IObservablePullRequestReviewsClient PullRequestReview { get; private set; }
public IObservableRepositoriesClient Repository { get; private set; } public IObservableRepositoriesClient Repository { get; private set; }
public IObservableGistsClient Gist { get; private set; } public IObservableGistsClient Gist { get; private set; }
public IObservableUsersClient User { get; private set; } public IObservableUsersClient User { get; private set; }

View File

@@ -44,9 +44,9 @@ public class PullRequestReviewRequestsClientTests
[IntegrationTest] [IntegrationTest]
public async Task GetsNoRequestsWhenNoneExist() public async Task GetsNoRequestsWhenNoneExist()
{ {
var pullRequestId = await CreateTheWorld(_github, _context, createReviewRequests: false); var number = await CreateTheWorld(_github, _context, createReviewRequests: false);
var reviewRequests = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, pullRequestId); var reviewRequests = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, number);
Assert.NotNull(reviewRequests); Assert.NotNull(reviewRequests);
Assert.Empty(reviewRequests); Assert.Empty(reviewRequests);
@@ -55,9 +55,9 @@ public class PullRequestReviewRequestsClientTests
[IntegrationTest] [IntegrationTest]
public async Task GetsNoRequestsWhenNoneExistWithRepositoryId() public async Task GetsNoRequestsWhenNoneExistWithRepositoryId()
{ {
var pullRequestId = await CreateTheWorld(_github, _context, createReviewRequests: false); var number = await CreateTheWorld(_github, _context, createReviewRequests: false);
var reviewRequests = await _client.GetAll(_context.RepositoryId, pullRequestId); var reviewRequests = await _client.GetAll(_context.RepositoryId, number);
Assert.NotNull(reviewRequests); Assert.NotNull(reviewRequests);
Assert.Empty(reviewRequests); Assert.Empty(reviewRequests);
@@ -66,9 +66,9 @@ public class PullRequestReviewRequestsClientTests
[IntegrationTest] [IntegrationTest]
public async Task GetsRequests() public async Task GetsRequests()
{ {
var pullRequestId = await CreateTheWorld(_github, _context); var number = await CreateTheWorld(_github, _context);
var reviewRequests = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, pullRequestId); var reviewRequests = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, number);
Assert.Equal(_collaboratorLogins, reviewRequests.Select(rr => rr.Login)); Assert.Equal(_collaboratorLogins, reviewRequests.Select(rr => rr.Login));
} }
@@ -76,9 +76,9 @@ public class PullRequestReviewRequestsClientTests
[IntegrationTest] [IntegrationTest]
public async Task GetsRequestsWithRepositoryId() public async Task GetsRequestsWithRepositoryId()
{ {
var pullRequestId = await CreateTheWorld(_github, _context); var number = await CreateTheWorld(_github, _context);
var reviewRequests = await _client.GetAll(_context.RepositoryId, pullRequestId); var reviewRequests = await _client.GetAll(_context.RepositoryId, number);
Assert.Equal(_collaboratorLogins, reviewRequests.Select(rr => rr.Login)); Assert.Equal(_collaboratorLogins, reviewRequests.Select(rr => rr.Login));
} }
@@ -86,7 +86,7 @@ public class PullRequestReviewRequestsClientTests
[IntegrationTest] [IntegrationTest]
public async Task ReturnsCorrectCountOfReviewRequestsWithStart() public async Task ReturnsCorrectCountOfReviewRequestsWithStart()
{ {
var pullRequestId = await CreateTheWorld(_github, _context); var number = await CreateTheWorld(_github, _context);
var options = new ApiOptions var options = new ApiOptions
{ {
@@ -94,7 +94,7 @@ public class PullRequestReviewRequestsClientTests
PageCount = 1, PageCount = 1,
StartPage = 2 StartPage = 2
}; };
var reviewRequests = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, pullRequestId, options); var reviewRequests = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, number, options);
Assert.Equal(1, reviewRequests.Count); Assert.Equal(1, reviewRequests.Count);
} }
@@ -102,7 +102,7 @@ public class PullRequestReviewRequestsClientTests
[IntegrationTest] [IntegrationTest]
public async Task ReturnsCorrectCountOfReviewRequestsWithStartWithRepositoryId() public async Task ReturnsCorrectCountOfReviewRequestsWithStartWithRepositoryId()
{ {
var pullRequestId = await CreateTheWorld(_github, _context); var number = await CreateTheWorld(_github, _context);
var options = new ApiOptions var options = new ApiOptions
{ {
@@ -110,7 +110,7 @@ public class PullRequestReviewRequestsClientTests
PageCount = 2, PageCount = 2,
StartPage = 2 StartPage = 2
}; };
var reviewRequests = await _client.GetAll(_context.RepositoryId, pullRequestId, options); var reviewRequests = await _client.GetAll(_context.RepositoryId, number, options);
Assert.Equal(1, reviewRequests.Count); Assert.Equal(1, reviewRequests.Count);
} }
@@ -118,14 +118,14 @@ public class PullRequestReviewRequestsClientTests
[IntegrationTest] [IntegrationTest]
public async Task ReturnsDistinctResultsBasedOnStartPage() public async Task ReturnsDistinctResultsBasedOnStartPage()
{ {
var pullRequestId = await CreateTheWorld(_github, _context); var number = await CreateTheWorld(_github, _context);
var startOptions = new ApiOptions var startOptions = new ApiOptions
{ {
PageSize = 1, PageSize = 1,
PageCount = 1 PageCount = 1
}; };
var firstPage = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, pullRequestId, startOptions); var firstPage = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, number, startOptions);
var skipStartOptions = new ApiOptions var skipStartOptions = new ApiOptions
{ {
@@ -133,7 +133,7 @@ public class PullRequestReviewRequestsClientTests
PageCount = 1, PageCount = 1,
StartPage = 2 StartPage = 2
}; };
var secondPage = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, pullRequestId, skipStartOptions); var secondPage = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, number, skipStartOptions);
Assert.Equal(1, firstPage.Count); Assert.Equal(1, firstPage.Count);
Assert.Equal(1, secondPage.Count); Assert.Equal(1, secondPage.Count);
@@ -143,14 +143,14 @@ public class PullRequestReviewRequestsClientTests
[IntegrationTest] [IntegrationTest]
public async Task ReturnsDistinctResultsBasedOnStartPageWithRepositoryId() public async Task ReturnsDistinctResultsBasedOnStartPageWithRepositoryId()
{ {
var pullRequestId = await CreateTheWorld(_github, _context); var number = await CreateTheWorld(_github, _context);
var startOptions = new ApiOptions var startOptions = new ApiOptions
{ {
PageSize = 1, PageSize = 1,
PageCount = 1 PageCount = 1
}; };
var firstPage = await _client.GetAll(_context.RepositoryId, pullRequestId, startOptions); var firstPage = await _client.GetAll(_context.RepositoryId, number, startOptions);
var skipStartOptions = new ApiOptions var skipStartOptions = new ApiOptions
{ {
@@ -158,7 +158,7 @@ public class PullRequestReviewRequestsClientTests
PageCount = 1, PageCount = 1,
StartPage = 2 StartPage = 2
}; };
var secondPage = await _client.GetAll(_context.RepositoryId, pullRequestId, skipStartOptions); var secondPage = await _client.GetAll(_context.RepositoryId, number, skipStartOptions);
Assert.Equal(1, firstPage.Count); Assert.Equal(1, firstPage.Count);
Assert.Equal(1, secondPage.Count); Assert.Equal(1, secondPage.Count);
@@ -171,12 +171,12 @@ public class PullRequestReviewRequestsClientTests
[IntegrationTest] [IntegrationTest]
public async Task DeletesRequests() public async Task DeletesRequests()
{ {
var pullRequestId = await CreateTheWorld(_github, _context); var number = await CreateTheWorld(_github, _context);
var reviewRequestsBeforeDelete = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, pullRequestId); var reviewRequestsBeforeDelete = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, number);
var reviewRequestToCreate = new PullRequestReviewRequest(_collaboratorLogins); var reviewRequestToCreate = new PullRequestReviewRequest(_collaboratorLogins);
await _client.Delete(_context.RepositoryOwner, _context.RepositoryName, pullRequestId, reviewRequestToCreate); await _client.Delete(_context.RepositoryOwner, _context.RepositoryName, number, reviewRequestToCreate);
var reviewRequestsAfterDelete = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, pullRequestId); var reviewRequestsAfterDelete = await _client.GetAll(_context.RepositoryOwner, _context.RepositoryName, number);
Assert.NotEmpty(reviewRequestsBeforeDelete); Assert.NotEmpty(reviewRequestsBeforeDelete);
Assert.Empty(reviewRequestsAfterDelete); Assert.Empty(reviewRequestsAfterDelete);
@@ -185,12 +185,12 @@ public class PullRequestReviewRequestsClientTests
[IntegrationTest] [IntegrationTest]
public async Task DeletesRequestsWithRepositoryId() public async Task DeletesRequestsWithRepositoryId()
{ {
var pullRequestId = await CreateTheWorld(_github, _context); var number = await CreateTheWorld(_github, _context);
var reviewRequestsBeforeDelete = await _client.GetAll(_context.RepositoryId, pullRequestId); var reviewRequestsBeforeDelete = await _client.GetAll(_context.RepositoryId, number);
var reviewRequestToCreate = new PullRequestReviewRequest(_collaboratorLogins); var reviewRequestToCreate = new PullRequestReviewRequest(_collaboratorLogins);
await _client.Delete(_context.RepositoryId, pullRequestId, reviewRequestToCreate); await _client.Delete(_context.RepositoryId, number, reviewRequestToCreate);
var reviewRequestsAfterDelete = await _client.GetAll(_context.RepositoryId, pullRequestId); var reviewRequestsAfterDelete = await _client.GetAll(_context.RepositoryId, number);
Assert.NotEmpty(reviewRequestsBeforeDelete); Assert.NotEmpty(reviewRequestsBeforeDelete);
Assert.Empty(reviewRequestsAfterDelete); Assert.Empty(reviewRequestsAfterDelete);
@@ -202,10 +202,10 @@ public class PullRequestReviewRequestsClientTests
[IntegrationTest] [IntegrationTest]
public async Task CreatesRequests() public async Task CreatesRequests()
{ {
var pullRequestId = await CreateTheWorld(_github, _context, createReviewRequests: false); var number = await CreateTheWorld(_github, _context, createReviewRequests: false);
var reviewRequestToCreate = new PullRequestReviewRequest(_collaboratorLogins); var reviewRequestToCreate = new PullRequestReviewRequest(_collaboratorLogins);
var pr = await _client.Create(_context.RepositoryOwner, _context.RepositoryName, pullRequestId, reviewRequestToCreate); var pr = await _client.Create(_context.RepositoryOwner, _context.RepositoryName, number, reviewRequestToCreate);
Assert.Equal(_collaboratorLogins.ToList(), pr.RequestedReviewers.Select(rr => rr.Login)); Assert.Equal(_collaboratorLogins.ToList(), pr.RequestedReviewers.Select(rr => rr.Login));
} }
@@ -213,10 +213,10 @@ public class PullRequestReviewRequestsClientTests
[IntegrationTest] [IntegrationTest]
public async Task CreatesRequestsWithRepositoryId() public async Task CreatesRequestsWithRepositoryId()
{ {
var pullRequestId = await CreateTheWorld(_github, _context, createReviewRequests: false); var number = await CreateTheWorld(_github, _context, createReviewRequests: false);
var reviewRequestToCreate = new PullRequestReviewRequest(_collaboratorLogins); var reviewRequestToCreate = new PullRequestReviewRequest(_collaboratorLogins);
var pr = await _client.Create(_context.RepositoryId, pullRequestId, reviewRequestToCreate); var pr = await _client.Create(_context.RepositoryId, number, reviewRequestToCreate);
Assert.Equal(_collaboratorLogins.ToList(), pr.RequestedReviewers.Select(rr => rr.Login)); Assert.Equal(_collaboratorLogins.ToList(), pr.RequestedReviewers.Select(rr => rr.Login));
} }

View File

@@ -0,0 +1,691 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Octokit;
using Octokit.Tests.Integration;
using Octokit.Tests.Integration.Helpers;
using Xunit;
public class PullRequestReviewsClientTests
{
public class TheGetAllMethod
{
private readonly IGitHubClient _github;
public TheGetAllMethod()
{
_github = Helper.GetAuthenticatedClient();
}
[IntegrationTest]
public async Task GetsAllReviews()
{
var reviews = await _github.PullRequest.Review.GetAll("octokit", "octokit.net", 1648);
Assert.NotNull(reviews);
Assert.NotEmpty(reviews);
Assert.True(reviews.Count > 1);
Assert.False(string.IsNullOrEmpty(reviews[0].Body));
Assert.False(string.IsNullOrEmpty(reviews[0].CommitId));
Assert.False(string.IsNullOrEmpty(reviews[0].User.Login));
}
[IntegrationTest]
public async Task ReturnsCorrectCountOfReviewsWithoutStart()
{
var options = new ApiOptions
{
PageCount = 1,
PageSize = 1
};
var reviews = await _github.PullRequest.Review.GetAll("octokit", "octokit.net", 1648, options);
Assert.Equal(1, reviews.Count);
}
[IntegrationTest]
public async Task ReturnsCorrectCountOfReviewsWithStart()
{
var options = new ApiOptions
{
PageCount = 1,
PageSize = 1,
StartPage = 1
};
var reviews = await _github.PullRequest.Review.GetAll("octokit", "octokit.net", 1648, options);
Assert.Equal(1, reviews.Count);
}
[IntegrationTest]
public async Task ReturnsDistinctReviewsBasedOnStartPage()
{
var startOptions = new ApiOptions
{
PageCount = 1,
PageSize = 1,
StartPage = 1
};
var firstPage = await _github.PullRequest.Review.GetAll("octokit", "octokit.net", 1648, startOptions);
var skipStartOptions = new ApiOptions
{
PageSize = 1,
PageCount = 1,
StartPage = 2
};
var secondPage = await _github.PullRequest.Review.GetAll("octokit", "octokit.net", 1648, skipStartOptions);
Assert.Equal(1, firstPage.Count);
Assert.Equal(1, secondPage.Count);
Assert.NotEqual(firstPage.First().Id, secondPage.First().Id);
}
}
public class TheGetMethod
{
private readonly IGitHubClient _github;
public TheGetMethod()
{
_github = Helper.GetAuthenticatedClient();
}
[IntegrationTest]
public async Task GetsReview()
{
var review = await _github.PullRequest.Review.Get("octokit", "octokit.net", 1648, 54646850);
Assert.NotNull(review);
Assert.False(string.IsNullOrEmpty(review.Body));
Assert.False(string.IsNullOrEmpty(review.CommitId));
Assert.False(string.IsNullOrEmpty(review.User.Login));
}
}
public class TheCreateMethod
{
private readonly IGitHubClient _github;
private readonly IPullRequestReviewsClient _client;
private readonly IGitHubClient _github2;
public TheCreateMethod()
{
_github = Helper.GetAuthenticatedClient();
_client = _github.PullRequest.Review;
_github2 = Helper.GetAuthenticatedClient(true);
}
[DualAccountTest]
public async Task CanCreatePendingReview()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var body = "A review comment message";
var review = new PullRequestReviewCreate()
{
CommitId = pullRequest.Head.Sha,
Body = body,
Comments = new List<DraftPullRequestReviewComment>
{
new DraftPullRequestReviewComment("comment 1", "README.md", 1),
new DraftPullRequestReviewComment("comment 2", "README.md", 2)
}
};
var createdReview = await _client.Create(context.RepositoryOwner, context.RepositoryName, pullRequest.Number, review);
Assert.NotNull(createdReview);
Assert.Equal(body, createdReview.Body);
Assert.Equal(PullRequestReviewState.Pending, createdReview.State);
Assert.Equal(pullRequest.Head.Sha, createdReview.CommitId);
}
}
[DualAccountTest]
public async Task CanCreatePendingReviewWithRepositoryId()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
const string body = "A review comment message";
var review = new PullRequestReviewCreate()
{
CommitId = pullRequest.Head.Sha,
Body = body,
Comments = new List<DraftPullRequestReviewComment>
{
new DraftPullRequestReviewComment("comment 1", "README.md", 1),
new DraftPullRequestReviewComment("comment 2", "README.md", 2)
}
};
var createdReview = await _client.Create(context.RepositoryId, pullRequest.Number, review);
Assert.NotNull(createdReview);
Assert.Equal(body, createdReview.Body);
Assert.Equal(PullRequestReviewState.Pending, createdReview.State);
Assert.Equal(pullRequest.Head.Sha, createdReview.CommitId);
}
}
[DualAccountTest]
public async Task CanCreateCommentedReview()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var body = "A review comment message";
var review = new PullRequestReviewCreate()
{
CommitId = pullRequest.Head.Sha,
Body = body,
Event = PullRequestReviewEvent.Comment,
Comments = new List<DraftPullRequestReviewComment>
{
new DraftPullRequestReviewComment("comment 1", "README.md", 1),
new DraftPullRequestReviewComment("comment 2", "README.md", 2)
}
};
var createdReview = await _client.Create(context.RepositoryOwner, context.RepositoryName, pullRequest.Number, review);
Assert.NotNull(createdReview);
Assert.Equal(body, createdReview.Body);
Assert.Equal(PullRequestReviewState.Commented, createdReview.State);
Assert.Equal(pullRequest.Head.Sha, createdReview.CommitId);
}
}
[DualAccountTest]
public async Task CanCreateCommentedReviewWithRepositoryId()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
const string body = "A review comment message";
var review = new PullRequestReviewCreate()
{
CommitId = pullRequest.Head.Sha,
Body = body,
Event = PullRequestReviewEvent.Comment,
Comments = new List<DraftPullRequestReviewComment>
{
new DraftPullRequestReviewComment("comment 1", "README.md", 1),
new DraftPullRequestReviewComment("comment 2", "README.md", 2)
}
};
var createdReview = await _client.Create(context.RepositoryId, pullRequest.Number, review);
Assert.NotNull(createdReview);
Assert.Equal(body, createdReview.Body);
Assert.Equal(PullRequestReviewState.Commented, createdReview.State);
Assert.Equal(pullRequest.Head.Sha, createdReview.CommitId);
}
}
[DualAccountTest]
public async Task CanCreateChangesRequestedReview()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var body = "A review comment message";
var review = new PullRequestReviewCreate()
{
CommitId = pullRequest.Head.Sha,
Body = body,
Event = PullRequestReviewEvent.RequestChanges,
Comments = new List<DraftPullRequestReviewComment>
{
new DraftPullRequestReviewComment("comment 1", "README.md", 1),
new DraftPullRequestReviewComment("comment 2", "README.md", 2)
}
};
var createdReview = await _client.Create(context.RepositoryOwner, context.RepositoryName, pullRequest.Number, review);
Assert.NotNull(createdReview);
Assert.Equal(body, createdReview.Body);
Assert.Equal(PullRequestReviewState.ChangesRequested, createdReview.State);
Assert.Equal(pullRequest.Head.Sha, createdReview.CommitId);
}
}
[DualAccountTest]
public async Task CanCreateChangesRequestedReviewWithRepositoryId()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
const string body = "A review comment message";
var review = new PullRequestReviewCreate()
{
CommitId = pullRequest.Head.Sha,
Body = body,
Event = PullRequestReviewEvent.RequestChanges,
Comments = new List<DraftPullRequestReviewComment>
{
new DraftPullRequestReviewComment("comment 1", "README.md", 1),
new DraftPullRequestReviewComment("comment 2", "README.md", 2)
}
};
var createdReview = await _client.Create(context.RepositoryId, pullRequest.Number, review);
Assert.NotNull(createdReview);
Assert.Equal(body, createdReview.Body);
Assert.Equal(PullRequestReviewState.ChangesRequested, createdReview.State);
Assert.Equal(pullRequest.Head.Sha, createdReview.CommitId);
}
}
[DualAccountTest]
public async Task CanCreateApprovedReview()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var body = "A review comment message";
var review = new PullRequestReviewCreate()
{
CommitId = pullRequest.Head.Sha,
Body = body,
Event = PullRequestReviewEvent.Approve,
Comments = new List<DraftPullRequestReviewComment>
{
new DraftPullRequestReviewComment("comment 1", "README.md", 1),
new DraftPullRequestReviewComment("comment 2", "README.md", 2)
}
};
var createdReview = await _client.Create(context.RepositoryOwner, context.RepositoryName, pullRequest.Number, review);
Assert.NotNull(createdReview);
Assert.Equal(body, createdReview.Body);
Assert.Equal(PullRequestReviewState.Approved, createdReview.State);
Assert.Equal(pullRequest.Head.Sha, createdReview.CommitId);
}
}
[DualAccountTest]
public async Task CanCreateApprovedReviewWithRepositoryId()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
const string body = "A review comment message";
var review = new PullRequestReviewCreate()
{
CommitId = pullRequest.Head.Sha,
Body = body,
Event = PullRequestReviewEvent.Approve,
Comments = new List<DraftPullRequestReviewComment>
{
new DraftPullRequestReviewComment("comment 1", "README.md", 1),
new DraftPullRequestReviewComment("comment 2", "README.md", 2)
}
};
var createdReview = await _client.Create(context.RepositoryId, pullRequest.Number, review);
Assert.NotNull(createdReview);
Assert.Equal(body, createdReview.Body);
Assert.Equal(PullRequestReviewState.Approved, createdReview.State);
Assert.Equal(pullRequest.Head.Sha, createdReview.CommitId);
}
}
}
public class TheDeleteMethod
{
private readonly IGitHubClient _github;
private readonly IPullRequestReviewsClient _client;
private readonly IGitHubClient _github2;
public TheDeleteMethod()
{
_github = Helper.GetAuthenticatedClient();
_client = _github.PullRequest.Review;
_github2 = Helper.GetAuthenticatedClient(true);
}
[DualAccountTest]
public async Task CanDeleteReview()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var createdReview = await _github.CreatePullRequestReview(context.Repository, pullRequest.Number, "A pending review");
await _client.Delete(context.RepositoryOwner, context.RepositoryName, pullRequest.Number, createdReview.Id);
var retrievedReviews = await _client.GetAll(context.RepositoryOwner, context.RepositoryName, pullRequest.Number);
Assert.False(retrievedReviews.Any(x => x.Id == createdReview.Id));
}
}
[DualAccountTest]
public async Task CanDeleteReviewWithRepositoryId()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var createdReview = await _github.CreatePullRequestReview(context.Repository, pullRequest.Number, "A pending review");
await _client.Delete(context.RepositoryId, pullRequest.Number, createdReview.Id);
var retrievedReviews = await _client.GetAll(context.RepositoryId, pullRequest.Number);
Assert.False(retrievedReviews.Any(x => x.Id == createdReview.Id));
}
}
}
public class TheDismissMethod
{
private readonly IGitHubClient _github;
private readonly IPullRequestReviewsClient _client;
private readonly IGitHubClient _github2;
public TheDismissMethod()
{
_github = Helper.GetAuthenticatedClient();
_client = _github.PullRequest.Review;
_github2 = Helper.GetAuthenticatedClient(true);
}
[DualAccountTest]
public async Task CanDismissReview()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var createdReview = await _github.CreatePullRequestReview(context.Repository, pullRequest.Number, "A pending review", PullRequestReviewEvent.RequestChanges);
var dismissedReview = await _client.Dismiss(context.RepositoryOwner, context.RepositoryName, pullRequest.Number, createdReview.Id, new PullRequestReviewDismiss { Message = "No soup for you!" });
Assert.Equal(PullRequestReviewState.Dismissed, dismissedReview.State);
}
}
[DualAccountTest]
public async Task CanDismissReviewWithRepositoryId()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var createdReview = await _github.CreatePullRequestReview(context.Repository, pullRequest.Number, "A pending review", PullRequestReviewEvent.RequestChanges);
var dismissedReview = await _client.Dismiss(context.RepositoryId, pullRequest.Number, createdReview.Id, new PullRequestReviewDismiss { Message = "No soup for you!" });
Assert.Equal(PullRequestReviewState.Dismissed, dismissedReview.State);
}
}
}
public class TheGetAllCommentsMethod
{
private readonly IGitHubClient _github;
public TheGetAllCommentsMethod()
{
_github = Helper.GetAuthenticatedClient();
}
[IntegrationTest]
public async Task GetsAllComments()
{
var comments = await _github.PullRequest.Review.GetAllComments("octokit", "octokit.net", 1648, 54646850);
Assert.NotNull(comments);
Assert.NotEmpty(comments);
Assert.True(comments.Count > 1);
foreach (var comment in comments)
{
Assert.False(string.IsNullOrEmpty(comment.Body));
Assert.False(string.IsNullOrEmpty(comment.CommitId));
Assert.False(string.IsNullOrEmpty(comment.User.Login));
}
}
[IntegrationTest]
public async Task ReturnsCorrectCountOfCommentsWithoutStart()
{
var options = new ApiOptions
{
PageCount = 1,
PageSize = 1
};
var comments = await _github.PullRequest.Review.GetAllComments("octokit", "octokit.net", 1648, 54646850, options);
Assert.Equal(1, comments.Count);
}
[IntegrationTest]
public async Task ReturnsCorrectCountOfCommentsWithStart()
{
var options = new ApiOptions
{
PageCount = 1,
PageSize = 1,
StartPage = 1
};
var comments = await _github.PullRequest.Review.GetAllComments("octokit", "octokit.net", 1648, 54646850, options);
Assert.Equal(1, comments.Count);
}
[IntegrationTest]
public async Task ReturnsDistinctCommentsBasedOnStartPage()
{
var startOptions = new ApiOptions
{
PageCount = 1,
PageSize = 1,
StartPage = 1
};
var firstPage = await _github.PullRequest.Review.GetAllComments("octokit", "octokit.net", 1648, 54646850, startOptions);
var skipStartOptions = new ApiOptions
{
PageSize = 1,
PageCount = 1,
StartPage = 2
};
var secondPage = await _github.PullRequest.Review.GetAllComments("octokit", "octokit.net", 1648, 54646850, skipStartOptions);
Assert.Equal(1, firstPage.Count);
Assert.Equal(1, secondPage.Count);
Assert.NotEqual(firstPage.First().Id, secondPage.First().Id);
}
}
public class TheSubmitMethod
{
private readonly IGitHubClient _github;
private readonly IPullRequestReviewsClient _client;
private readonly IGitHubClient _github2;
public TheSubmitMethod()
{
_github = Helper.GetAuthenticatedClient();
_client = _github.PullRequest.Review;
_github2 = Helper.GetAuthenticatedClient(true);
}
[DualAccountTest]
public async Task CanSubmitCommentedReview()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var createdReview = await _github.CreatePullRequestReview(context.Repository, pullRequest.Number, "A pending review");
var submitMessage = new PullRequestReviewSubmit
{
Body = "Roger roger!",
Event = PullRequestReviewEvent.Comment
};
var submittedReview = await _client.Submit(context.RepositoryOwner, context.RepositoryName, pullRequest.Number, createdReview.Id, submitMessage);
Assert.Equal("Roger roger!", submittedReview.Body);
Assert.Equal(PullRequestReviewState.Commented, submittedReview.State);
}
}
[DualAccountTest]
public async Task CanSubmitCommentedReviewWithRepositoryId()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var createdReview = await _github.CreatePullRequestReview(context.Repository, pullRequest.Number, "A pending review");
var submitMessage = new PullRequestReviewSubmit
{
Body = "Roger roger!",
Event = PullRequestReviewEvent.Comment
};
var submittedReview = await _client.Submit(context.RepositoryId, pullRequest.Number, createdReview.Id, submitMessage);
Assert.Equal("Roger roger!", submittedReview.Body);
Assert.Equal(PullRequestReviewState.Commented, submittedReview.State);
}
}
[DualAccountTest]
public async Task CanSubmitChangesRequestedReview()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var createdReview = await _github.CreatePullRequestReview(context.Repository, pullRequest.Number, "A pending review");
var submitMessage = new PullRequestReviewSubmit
{
Body = "Roger roger!",
Event = PullRequestReviewEvent.RequestChanges
};
var submittedReview = await _client.Submit(context.RepositoryOwner, context.RepositoryName, pullRequest.Number, createdReview.Id, submitMessage);
Assert.Equal("Roger roger!", submittedReview.Body);
Assert.Equal(PullRequestReviewState.ChangesRequested, submittedReview.State);
}
}
[DualAccountTest]
public async Task CanSubmitChangesRequestedReviewWithRepositoryId()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var createdReview = await _github.CreatePullRequestReview(context.Repository, pullRequest.Number, "A pending review");
var submitMessage = new PullRequestReviewSubmit
{
Body = "Roger roger!",
Event = PullRequestReviewEvent.RequestChanges
};
var submittedReview = await _client.Submit(context.RepositoryId, pullRequest.Number, createdReview.Id, submitMessage);
Assert.Equal("Roger roger!", submittedReview.Body);
Assert.Equal(PullRequestReviewState.ChangesRequested, submittedReview.State);
}
}
[DualAccountTest]
public async Task CanSubmitApprovedReview()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var createdReview = await _github.CreatePullRequestReview(context.Repository, pullRequest.Number, "A pending review");
var submitMessage = new PullRequestReviewSubmit
{
Body = "Roger roger!",
Event = PullRequestReviewEvent.Approve
};
var submittedReview = await _client.Submit(context.RepositoryOwner, context.RepositoryName, pullRequest.Number, createdReview.Id, submitMessage);
Assert.Equal("Roger roger!", submittedReview.Body);
Assert.Equal(PullRequestReviewState.Approved, submittedReview.State);
}
}
[DualAccountTest]
public async Task CanSubmitApprovedReviewWithRepositoryId()
{
using (var context = await _github.CreateRepositoryContext("test-repo"))
{
await _github.CreateTheWorld(context.Repository);
var pullRequest = await _github2.CreatePullRequest(context.Repository);
var createdReview = await _github.CreatePullRequestReview(context.Repository, pullRequest.Number, "A pending review");
var submitMessage = new PullRequestReviewSubmit
{
Body = "Roger roger!",
Event = PullRequestReviewEvent.Approve
};
var submittedReview = await _client.Submit(context.RepositoryId, pullRequest.Number, createdReview.Id, submitMessage);
Assert.Equal("Roger roger!", submittedReview.Body);
Assert.Equal(PullRequestReviewState.Approved, submittedReview.State);
}
}
}
}

View File

@@ -27,6 +27,18 @@ namespace Octokit.Tests.Integration
return new Credentials(githubUsername, githubPassword); return new Credentials(githubUsername, githubPassword);
}); });
static readonly Lazy<Credentials> _credentialsSecondUserThunk = new Lazy<Credentials>(() =>
{
var githubUsername = Environment.GetEnvironmentVariable("OCTOKIT_GITHUBUSERNAME_2");
var githubPassword = Environment.GetEnvironmentVariable("OCTOKIT_GITHUBPASSWORD_2");
if (githubUsername == null || githubPassword == null)
return null;
return new Credentials(githubUsername, githubPassword);
});
static readonly Lazy<Credentials> _oauthApplicationCredentials = new Lazy<Credentials>(() => static readonly Lazy<Credentials> _oauthApplicationCredentials = new Lazy<Credentials>(() =>
{ {
var applicationClientId = ClientId; var applicationClientId = ClientId;
@@ -78,6 +90,8 @@ namespace Octokit.Tests.Integration
/// </summary> /// </summary>
public static Credentials Credentials { get { return _credentialsThunk.Value; } } public static Credentials Credentials { get { return _credentialsThunk.Value; } }
public static Credentials CredentialsSecondUser { get { return _credentialsSecondUserThunk.Value; } }
public static Credentials ApplicationCredentials { get { return _oauthApplicationCredentials.Value; } } public static Credentials ApplicationCredentials { get { return _oauthApplicationCredentials.Value; } }
public static Credentials BasicAuthCredentials { get { return _basicAuthCredentials.Value; } } public static Credentials BasicAuthCredentials { get { return _basicAuthCredentials.Value; } }
@@ -193,11 +207,11 @@ namespace Octokit.Tests.Integration
return stream; return stream;
} }
public static IGitHubClient GetAuthenticatedClient() public static IGitHubClient GetAuthenticatedClient(bool useSecondUser = false)
{ {
return new GitHubClient(new ProductHeaderValue("OctokitTests"), TargetUrl) return new GitHubClient(new ProductHeaderValue("OctokitTests"), TargetUrl)
{ {
Credentials = Credentials Credentials = useSecondUser ? CredentialsSecondUser : Credentials
}; };
} }

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
using System.Linq;
using Xunit;
using Xunit.Abstractions;
using Xunit.Sdk;
namespace Octokit.Tests.Integration
{
public class DualAccountTestDiscoverer : IXunitTestCaseDiscoverer
{
readonly IMessageSink diagnosticMessageSink;
public DualAccountTestDiscoverer(IMessageSink diagnosticMessageSink)
{
this.diagnosticMessageSink = diagnosticMessageSink;
}
public IEnumerable<IXunitTestCase> Discover(ITestFrameworkDiscoveryOptions discoveryOptions, ITestMethod testMethod, IAttributeInfo factAttribute)
{
if (Helper.CredentialsSecondUser == null)
{
return Enumerable.Empty<IXunitTestCase>();
}
return new[] { new XunitTestCase(diagnosticMessageSink, discoveryOptions.MethodDisplayOrDefault(), testMethod) };
}
}
[XunitTestCaseDiscoverer("Octokit.Tests.Integration.DualAccountTestDiscoverer", "Octokit.Tests.Integration")]
public class DualAccountTestAttribute : FactAttribute
{
}
}

View File

@@ -54,11 +54,34 @@ namespace Octokit.Tests.Integration.Helpers
await client.Git.Reference.Update(repository.Owner.Login, repository.Name, "heads/master", new ReferenceUpdate(newMaster.Sha)); await client.Git.Reference.Update(repository.Owner.Login, repository.Name, "heads/master", new ReferenceUpdate(newMaster.Sha));
// create new commit for feature branch // create new commit for feature branch
var featureBranchTree = await client.CreateTree(repository, new Dictionary<string, string> { { "README.md", "I am overwriting this blob with something new" } }); var featureBranchTree = await client.CreateTree(repository, new Dictionary<string, string> { { "README.md", "I am overwriting this blob with something new\nand a second line too" } });
var featureBranchCommit = await client.CreateCommit(repository, "this is the commit to merge into the pull request", featureBranchTree.Sha, newMaster.Sha); var featureBranchCommit = await client.CreateCommit(repository, "this is the commit to merge into the pull request", featureBranchTree.Sha, newMaster.Sha);
// create branch // create branch
return await client.Git.Reference.Create(repository.Owner.Login, repository.Name, new NewReference("refs/heads/my-branch", featureBranchCommit.Sha)); return await client.Git.Reference.Create(repository.Owner.Login, repository.Name, new NewReference("refs/heads/my-branch", featureBranchCommit.Sha));
} }
public static async Task<PullRequest> CreatePullRequest(this IGitHubClient client, Repository repository, string branch = "my-branch")
{
var pullRequest = new NewPullRequest("Nice title for the pull request", branch, "master");
var createdPullRequest = await client.PullRequest.Create(repository.Owner.Login, repository.Name, pullRequest);
return createdPullRequest;
}
public static async Task<PullRequestReview> CreatePullRequestReview(this IGitHubClient client, Repository repository, int number, string body, PullRequestReviewEvent? @event = null, string commitId = null, List<DraftPullRequestReviewComment> comments = null)
{
var review = new PullRequestReviewCreate()
{
CommitId = commitId,
Body = body,
Event = @event,
Comments = comments
};
var createdReview = await client.PullRequest.Review.Create(repository.Owner.Login, repository.Name, number, review);
return createdReview;
}
} }
} }

View File

@@ -0,0 +1,464 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using NSubstitute;
using Octokit;
using Octokit.Tests;
using Xunit;
public class PullRequestReviewsClientTests
{
public class TheCtor
{
[Fact]
public void EnsuresNonNullArguments()
{
Assert.Throws<ArgumentNullException>(() => new PullRequestReviewCommentsClient(null));
}
[Fact]
public void PullRequestReviewCreateEnsuresArgumentsValue()
{
string body = "body";
string path = "path";
PullRequestReviewEvent evt = PullRequestReviewEvent.Approve;
int position = 1;
var comment = new DraftPullRequestReviewComment(body, path, position);
var review = new PullRequestReviewCreate()
{
Body = body,
Event = evt
};
review.Comments.Add(comment);
Assert.Equal(body, review.Body);
Assert.Equal(evt, review.Event);
Assert.NotEmpty(review.Comments);
}
}
public class TheGetAllMethod
{
[Fact]
public async Task RequestsCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
await client.GetAll("owner", "name", 7);
connection.Received().GetAll<PullRequestReview>(Arg.Is<Uri>(u => u.ToString() == "repos/owner/name/pulls/7/reviews"), null, Args.ApiOptions);
}
[Fact]
public async Task RequestsCorrectUrlWithRepositoryId()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
await client.GetAll(1, 7);
connection.Received().GetAll<PullRequestReview>(
Arg.Is<Uri>(u => u.ToString() == "repositories/1/pulls/7/reviews"), Args.ApiOptions);
}
[Fact]
public async Task RequestsCorrectUrlWithApiOptions()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
var options = new ApiOptions
{
StartPage = 1,
PageCount = 1,
PageSize = 1
};
await client.GetAll("owner", "name", 7, options);
connection.Received().GetAll<PullRequestReview>(
Arg.Is<Uri>(u => u.ToString() == "repos/owner/name/pulls/7/reviews"), null, options);
}
[Fact]
public async Task RequestsCorrectUrlWithApiOptionsWithRepositoryId()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
var options = new ApiOptions
{
StartPage = 1,
PageCount = 1,
PageSize = 1
};
await client.GetAll(1, 7, options);
connection.Received().GetAll<PullRequestReview>(
Arg.Is<Uri>(u => u.ToString() == "repositories/1/pulls/7/reviews"), options);
}
[Fact]
public async Task EnsuresNotNullArguments()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(null, "name", 1));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll("owner", null, 1));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(null, "name", 1, ApiOptions.None));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll("owner", null, 1, ApiOptions.None));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll("owner", "name", 1, null));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(1, 1, null));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("", "name", 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("owner", "", 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("", "name", 1, ApiOptions.None));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("owner", "", 1, ApiOptions.None));
}
}
public class TheGetMethod
{
[Fact]
public void RequestsCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
client.Get("owner", "name", 53, 2);
connection.Received().Get<PullRequestReview>(
Arg.Is<Uri>(u => u.ToString() == "repos/owner/name/pulls/53/reviews/2"));
}
[Fact]
public void RequestsCorrectUrlWithRepositoryId()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
client.Get(1, 53, 2);
connection.Received().Get<PullRequestReview>(Arg.Is<Uri>(u => u.ToString() == "repositories/1/pulls/53/reviews/2"));
}
[Fact]
public async Task EnsuresNonNullArguments()
{
var client = new PullRequestReviewsClient(Substitute.For<IApiConnection>());
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Get(null, "name", 1, 1));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Get("owner", null, 1, 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.Get("", "name", 1, 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.Get("owner", "", 1, 1));
}
}
public class TheCreateMethod
{
[Fact]
public void PostsToCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
var comment = new DraftPullRequestReviewComment("Comment content", "file.css", 7);
var review = new PullRequestReviewCreate()
{
CommitId = "commit",
Body = "body",
Event = PullRequestReviewEvent.Approve
};
review.Comments.Add(comment);
client.Create("fakeOwner", "fakeRepoName", 13, review);
connection.Received().Post<PullRequestReview>(Arg.Is<Uri>(u => u.ToString() == "repos/fakeOwner/fakeRepoName/pulls/13/reviews"),
review, null, null);
}
[Fact]
public void PostsToCorrectUrlWithRepositoryId()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
var comment = new DraftPullRequestReviewComment("Comment content", "file.css", 7);
var review = new PullRequestReviewCreate()
{
CommitId = "commit",
Body = "body",
Event = PullRequestReviewEvent.Approve
};
review.Comments.Add(comment);
client.Create(1, 13, review);
connection.Received().Post<PullRequestReview>(Arg.Is<Uri>(u => u.ToString() == "repositories/1/pulls/13/reviews"),
review, null, null);
}
[Fact]
public async Task EnsuresNonNullArguments()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
string body = "Comment content";
string path = "file.css";
int position = 7;
var comment = new DraftPullRequestReviewComment(body, path, position);
var review = new PullRequestReviewCreate()
{
CommitId = "commit",
Body = "body",
Event = PullRequestReviewEvent.Approve
};
review.Comments.Add(comment);
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Create(null, "fakeRepoName", 1, review));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Create("fakeOwner", null, 1, review));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Create("fakeOwner", "fakeRepoName", 1, null));
await Assert.ThrowsAsync<ArgumentException>(() => client.Create("", "fakeRepoName", 1, review));
await Assert.ThrowsAsync<ArgumentException>(() => client.Create("fakeOwner", "", 1, review));
}
}
public class TheDeleteMethod
{
[Fact]
public async Task PostsToCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
await client.Delete("owner", "name", 13, 13);
connection.Received().Delete(Arg.Is<Uri>(u => u.ToString() == "repos/owner/name/pulls/13/reviews/13"));
}
[Fact]
public async Task PostsToCorrectUrlWithRepositoryId()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
await client.Delete(1, 13, 13);
connection.Received().Delete(Arg.Is<Uri>(u => u.ToString() == "repositories/1/pulls/13/reviews/13"));
}
[Fact]
public async Task EnsuresNonNullArguments()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Delete(null, "name", 1, 1));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Delete("owner", null, 1, 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.Delete("", "name", 1, 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.Delete("owner", "", 1, 1));
}
}
public class TheDismissMethod
{
[Fact]
public async Task PostsToCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
var dismissMessage = new PullRequestReviewDismiss()
{
Message = "test message"
};
await client.Dismiss("owner", "name", 13, 13, dismissMessage);
connection.Received().Put<PullRequestReview>(Arg.Is<Uri>(u => u.ToString() == "repos/owner/name/pulls/13/reviews/13/dismissals"), dismissMessage);
}
[Fact]
public async Task PostsToCorrectUrlWithRepositoryId()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
var dismissMessage = new PullRequestReviewDismiss()
{
Message = "test message"
};
await client.Dismiss(1, 13, 13, dismissMessage);
connection.Received().Put<PullRequestReview>(Arg.Is<Uri>(u => u.ToString() == "repositories/1/pulls/13/reviews/13/dismissals"), dismissMessage);
}
[Fact]
public async Task EnsuresNonNullArguments()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
var dismissMessage = new PullRequestReviewDismiss()
{
Message = "test message"
};
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Dismiss(null, "name", 1, 1, dismissMessage));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Dismiss("owner", null, 1, 1, dismissMessage));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Dismiss("owner", "name", 1, 1, null));
await Assert.ThrowsAsync<ArgumentException>(() => client.Dismiss("", "name", 1, 1, dismissMessage));
await Assert.ThrowsAsync<ArgumentException>(() => client.Dismiss("owner", "", 1, 1, dismissMessage));
}
}
public class TheGetAllCommentsMethod
{
[Fact]
public async Task RequestsCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
await client.GetAllComments("owner", "name", 13, 13);
connection.Received().GetAll<PullRequestReviewComment>(Arg.Is<Uri>(u => u.ToString() == "repos/owner/name/pulls/13/reviews/13/comments"), null, Args.ApiOptions);
}
[Fact]
public async Task RequestsCorrectUrlWithRepositoryId()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
await client.GetAllComments(1, 13, 13);
connection.Received().GetAll<PullRequestReviewComment>(Arg.Is<Uri>(u => u.ToString() == "repositories/1/pulls/13/reviews/13/comments"), null, Args.ApiOptions);
}
[Fact]
public async Task RequestsCorrectUrlWithApiOptions()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
var options = new ApiOptions
{
StartPage = 1,
PageCount = 1,
PageSize = 1
};
await client.GetAllComments("owner", "name", 13, 13, options);
connection.Received().GetAll<PullRequestReviewComment>(Arg.Is<Uri>(u => u.ToString() == "repos/owner/name/pulls/13/reviews/13/comments"), null, options);
}
[Fact]
public async Task RequestsCorrectUrlWithApiOptionsWithRepositoryId()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
var options = new ApiOptions
{
StartPage = 1,
PageCount = 1,
PageSize = 1
};
await client.GetAllComments(1, 13, 13, options);
connection.Received().GetAll<PullRequestReviewComment>(Arg.Is<Uri>(u => u.ToString() == "repositories/1/pulls/13/reviews/13/comments"), null, Args.ApiOptions);
}
[Fact]
public async Task EnsuresNonNullArguments()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllComments(null, "name", 1, 1));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllComments("owner", null, 1, 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAllComments("", "name", 1, 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAllComments("owner", "", 1, 1));
}
}
public class TheSubmitMethod
{
[Fact]
public async Task PostsToCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
var submitMessage = new PullRequestReviewSubmit()
{
Body = "string",
Event = PullRequestReviewEvent.Approve
};
await client.Submit("owner", "name", 13, 13, submitMessage);
connection.Received().Post<PullRequestReview>(Arg.Is<Uri>(u => u.ToString() == "repos/owner/name/pulls/13/reviews/13/events"), submitMessage, null, null);
}
[Fact]
public async Task PostsToCorrectUrlWithRepositoryId()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
var submitMessage = new PullRequestReviewSubmit()
{
Body = "string",
Event = PullRequestReviewEvent.Approve
};
await client.Submit(1, 13, 13, submitMessage);
connection.Received().Post<PullRequestReview>(Arg.Is<Uri>(u => u.ToString() == "repositories/1/pulls/13/reviews/13/events"), submitMessage, null, null);
}
[Fact]
public async Task EnsuresNonNullArguments()
{
var connection = Substitute.For<IApiConnection>();
var client = new PullRequestReviewsClient(connection);
var submitMessage = new PullRequestReviewSubmit()
{
Body = "string",
Event = PullRequestReviewEvent.Approve
};
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Submit(null, "name", 1, 1, submitMessage));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Submit("owner", null, 1, 1, submitMessage));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Submit("owner", "name", 1, 1, null));
await Assert.ThrowsAsync<ArgumentException>(() => client.Submit("", "name", 1, 1, submitMessage));
await Assert.ThrowsAsync<ArgumentException>(() => client.Submit("owner", "", 1, 1, submitMessage));
}
}
}

View File

@@ -179,8 +179,6 @@ namespace Octokit.Tests.Reactive
} }
); );
var acceptHeader = "application/vnd.github.squirrel-girl-preview";
var gitHubClient = Substitute.For<IGitHubClient>(); var gitHubClient = Substitute.For<IGitHubClient>();
gitHubClient.Connection.Get<List<PullRequestReviewComment>>(firstPageUrl, Args.EmptyDictionary, null) gitHubClient.Connection.Get<List<PullRequestReviewComment>>(firstPageUrl, Args.EmptyDictionary, null)
.Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReviewComment>>>(() => firstPageResponse)); .Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReviewComment>>>(() => firstPageResponse));

View File

@@ -0,0 +1,679 @@
using System;
using System.Collections.Generic;
using System.Reactive.Linq;
using System.Threading.Tasks;
using NSubstitute;
using Octokit.Internal;
using Octokit.Reactive;
using Xunit;
namespace Octokit.Tests.Reactive
{
public class ObservablePullRequestReviewsClientTests
{
public class TheCtor
{
[Fact]
public void EnsuresNonNullArguments()
{
Assert.Throws<ArgumentNullException>(
() => new ObservablePullRequestReviewsClient(null));
}
}
static IResponse CreateResponseWithApiInfo(IDictionary<string, Uri> links)
{
var response = Substitute.For<IResponse>();
response.ApiInfo.Returns(new ApiInfo(links, new List<string>(), new List<string>(), "etag", new RateLimit(new Dictionary<string, string>())));
return response;
}
public class TheGetAllMethod
{
[Fact]
public void RequestsCorrectUrl()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
client.GetAll("fake", "repo", 1);
gitHubClient.Received().PullRequest.Review.GetAll("fake", "repo", 1);
}
[Fact]
public void RequestsCorrectUrlWithRepositoryId()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
client.GetAll(1, 1);
gitHubClient.Received().PullRequest.Review.GetAll(1, 1);
}
[Fact]
public void RequestsCorrectUrlWithApiOptions()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var options = new ApiOptions
{
PageCount = 1,
PageSize = 1,
StartPage = 1
};
client.GetAll("fake", "repo", 1, options);
gitHubClient.Received().PullRequest.Review.GetAll("fake", "repo", 1, options);
}
[Fact]
public void RequestsCorrectUrlWithApiOptionsWithRepositoryId()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var options = new ApiOptions
{
PageCount = 1,
PageSize = 1,
StartPage = 1
};
client.GetAll(1, 1, options);
gitHubClient.Received().PullRequest.Review.GetAll(1, 1, options);
}
[Fact]
public async Task RequestsCorrectUrlMulti()
{
var firstPageUrl = new Uri("repos/owner/name/pulls/7/reviews", UriKind.Relative);
var secondPageUrl = new Uri("https://example.com/page/2");
var firstPageLinks = new Dictionary<string, Uri> { { "next", secondPageUrl } };
var firstPageResponse = new ApiResponse<List<PullRequestReview>>
(
CreateResponseWithApiInfo(firstPageLinks),
new List<PullRequestReview>
{
new PullRequestReview(1),
new PullRequestReview(2),
new PullRequestReview(3)
});
var thirdPageUrl = new Uri("https://example.com/page/3");
var secondPageLinks = new Dictionary<string, Uri> { { "next", thirdPageUrl } };
var secondPageResponse = new ApiResponse<List<PullRequestReview>>
(
CreateResponseWithApiInfo(secondPageLinks),
new List<PullRequestReview>
{
new PullRequestReview(4),
new PullRequestReview(5),
new PullRequestReview(6)
}
);
var lastPageResponse = new ApiResponse<List<PullRequestReview>>
(
new Response(),
new List<PullRequestReview>
{
new PullRequestReview(7)
}
);
var gitHubClient = Substitute.For<IGitHubClient>();
gitHubClient.Connection.Get<List<PullRequestReview>>(firstPageUrl, Args.EmptyDictionary, null)
.Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReview>>>(() => firstPageResponse));
gitHubClient.Connection.Get<List<PullRequestReview>>(secondPageUrl, Args.EmptyDictionary, null)
.Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReview>>>(() => secondPageResponse));
gitHubClient.Connection.Get<List<PullRequestReview>>(thirdPageUrl, Args.EmptyDictionary, null)
.Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReview>>>(() => lastPageResponse));
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var results = await client.GetAll("owner", "name", 7).ToArray();
Assert.Equal(7, results.Length);
gitHubClient.Connection.Received(1).Get<List<PullRequestReview>>(firstPageUrl, Args.EmptyDictionary, null);
gitHubClient.Connection.Received(1).Get<List<PullRequestReview>>(secondPageUrl, Args.EmptyDictionary, null);
gitHubClient.Connection.Received(1).Get<List<PullRequestReview>>(thirdPageUrl, Args.EmptyDictionary, null);
}
[Fact]
public async Task RequestsCorrectUrlMultiWithRepositoryId()
{
var firstPageUrl = new Uri("repositories/1/pulls/7/reviews", UriKind.Relative);
var secondPageUrl = new Uri("https://example.com/page/2");
var firstPageLinks = new Dictionary<string, Uri> { { "next", secondPageUrl } };
var firstPageResponse = new ApiResponse<List<PullRequestReview>>
(
CreateResponseWithApiInfo(firstPageLinks),
new List<PullRequestReview>
{
new PullRequestReview(1),
new PullRequestReview(2),
new PullRequestReview(3)
});
var thirdPageUrl = new Uri("https://example.com/page/3");
var secondPageLinks = new Dictionary<string, Uri> { { "next", thirdPageUrl } };
var secondPageResponse = new ApiResponse<List<PullRequestReview>>
(
CreateResponseWithApiInfo(secondPageLinks),
new List<PullRequestReview>
{
new PullRequestReview(4),
new PullRequestReview(5),
new PullRequestReview(6)
}
);
var lastPageResponse = new ApiResponse<List<PullRequestReview>>
(
new Response(),
new List<PullRequestReview>
{
new PullRequestReview(7)
}
);
var gitHubClient = Substitute.For<IGitHubClient>();
gitHubClient.Connection.Get<List<PullRequestReview>>(firstPageUrl, Args.EmptyDictionary, null)
.Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReview>>>(() => firstPageResponse));
gitHubClient.Connection.Get<List<PullRequestReview>>(secondPageUrl, Args.EmptyDictionary, null)
.Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReview>>>(() => secondPageResponse));
gitHubClient.Connection.Get<List<PullRequestReview>>(thirdPageUrl, Args.EmptyDictionary, null)
.Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReview>>>(() => lastPageResponse));
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var results = await client.GetAll(1, 7).ToArray();
Assert.Equal(7, results.Length);
gitHubClient.Connection.Received(1).Get<List<PullRequestReview>>(firstPageUrl, Args.EmptyDictionary, null);
gitHubClient.Connection.Received(1).Get<List<PullRequestReview>>(secondPageUrl, Args.EmptyDictionary, null);
gitHubClient.Connection.Received(1).Get<List<PullRequestReview>>(thirdPageUrl, Args.EmptyDictionary, null);
}
[Fact]
public async Task EnsuresNonNullArguments()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
Assert.Throws<ArgumentNullException>(() => client.GetAll(null, "name", 1));
Assert.Throws<ArgumentNullException>(() => client.GetAll("owner", null, 1));
Assert.Throws<ArgumentNullException>(() => client.GetAll(null, "name", 1, ApiOptions.None));
Assert.Throws<ArgumentNullException>(() => client.GetAll("owner", null, 1, ApiOptions.None));
Assert.Throws<ArgumentNullException>(() => client.GetAll("owner", "name", 1, null));
Assert.Throws<ArgumentNullException>(() => client.GetAll(1, 1, null));
Assert.Throws<ArgumentException>(() => client.GetAll("", "name", 1));
Assert.Throws<ArgumentException>(() => client.GetAll("owner", "", 1));
Assert.Throws<ArgumentException>(() => client.GetAll("", "name", 1, ApiOptions.None));
Assert.Throws<ArgumentException>(() => client.GetAll("owner", "", 1, ApiOptions.None));
}
}
public class TheGetMethod
{
[Fact]
public void RequestsCorrectUrl()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
client.Get("owner", "name", 53, 2);
gitHubClient.Received().PullRequest.Review.Get("owner", "name", 53, 2);
}
[Fact]
public void RequestsCorrectUrlWithRepositoryId()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
client.Get(1, 53, 2);
gitHubClient.Received().PullRequest.Review.Get(1, 53, 2);
}
[Fact]
public async Task EnsuresNonNullArguments()
{
var client = new ObservablePullRequestReviewsClient(Substitute.For<IGitHubClient>());
Assert.Throws<ArgumentNullException>(() => client.Get(null, "name", 1, 1));
Assert.Throws<ArgumentNullException>(() => client.Get("owner", null, 1, 1));
Assert.Throws<ArgumentException>(() => client.Get("", "name", 1, 1));
Assert.Throws<ArgumentException>(() => client.Get("owner", "", 1, 1));
}
}
public class TheCreateMethod
{
[Fact]
public void PostsToCorrectUrl()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var comment = new DraftPullRequestReviewComment("Comment content", "file.css", 7);
var review = new PullRequestReviewCreate()
{
CommitId = "commit",
Body = "body",
Event = PullRequestReviewEvent.Approve
};
review.Comments.Add(comment);
client.Create("owner", "name", 53, review);
gitHubClient.Received().PullRequest.Review.Create("owner", "name", 53, review);
}
[Fact]
public void PostsToCorrectUrlWithRepositoryId()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var comment = new DraftPullRequestReviewComment("Comment content", "file.css", 7);
var review = new PullRequestReviewCreate()
{
CommitId = "commit",
Body = "body",
Event = PullRequestReviewEvent.Approve
};
review.Comments.Add(comment);
client.Create(1, 13, review);
gitHubClient.Received().PullRequest.Review.Create(1, 53, review);
}
[Fact]
public void EnsuresNonNullArguments()
{
var client = new ObservablePullRequestReviewsClient(Substitute.For<IGitHubClient>());
string body = "Comment content";
string path = "file.css";
int position = 7;
var comment = new DraftPullRequestReviewComment(body, path, position);
var review = new PullRequestReviewCreate()
{
CommitId = "commit",
Body = "body",
Event = PullRequestReviewEvent.Approve
};
review.Comments.Add(comment);
Assert.Throws<ArgumentNullException>(() => client.Create(null, "fakeRepoName", 1, review));
Assert.Throws<ArgumentNullException>(() => client.Create("fakeOwner", null, 1, review));
Assert.Throws<ArgumentNullException>(() => client.Create("fakeOwner", "fakeRepoName", 1, null));
Assert.Throws<ArgumentException>(() => client.Create("", "fakeRepoName", 1, review));
Assert.Throws<ArgumentException>(() => client.Create("fakeOwner", "", 1, review));
}
}
public class TheDeleteMethod
{
[Fact]
public void PostsToCorrectUrl()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
client.Delete("owner", "name", 13, 13);
gitHubClient.Received().PullRequest.Review.Delete("owner", "name", 13, 13);
}
[Fact]
public void PostsToCorrectUrlWithRepositoryId()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
client.Delete(1, 13, 13);
gitHubClient.Received().PullRequest.Review.Delete(1, 13, 13);
}
[Fact]
public void EnsuresNonNullArguments()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
Assert.Throws<ArgumentNullException>(() => client.Delete(null, "name", 1, 1));
Assert.Throws<ArgumentNullException>(() => client.Delete("owner", null, 1, 1));
Assert.Throws<ArgumentException>(() => client.Delete("", "name", 1, 1));
Assert.Throws<ArgumentException>(() => client.Delete("owner", "", 1, 1));
}
}
public class TheDismissMethod
{
[Fact]
public void PostsToCorrectUrl()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var dismissMessage = new PullRequestReviewDismiss()
{
Message = "test message"
};
client.Dismiss("owner", "name", 13, 13, dismissMessage);
gitHubClient.Received().PullRequest.Review.Dismiss("owner", "name", 13, 13, dismissMessage);
}
[Fact]
public void PostsToCorrectUrlWithRepositoryId()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var dismissMessage = new PullRequestReviewDismiss()
{
Message = "test message"
};
client.Dismiss(1, 13, 13, dismissMessage);
gitHubClient.Received().PullRequest.Review.Dismiss(1, 13, 13, dismissMessage);
}
[Fact]
public void EnsuresNonNullArguments()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var dismissMessage = new PullRequestReviewDismiss()
{
Message = "test message"
};
Assert.Throws<ArgumentNullException>(() => client.Dismiss(null, "name", 1, 1, dismissMessage));
Assert.Throws<ArgumentNullException>(() => client.Dismiss("owner", null, 1, 1, dismissMessage));
Assert.Throws<ArgumentNullException>(() => client.Dismiss("owner", "name", 1, 1, null));
Assert.Throws<ArgumentException>(() => client.Dismiss("", "name", 1, 1, dismissMessage));
Assert.Throws<ArgumentException>(() => client.Dismiss("owner", "", 1, 1, dismissMessage));
}
}
public class TheGetAllCommentsMethod
{
[Fact]
public void RequestsCorrectUrl()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
client.GetAllComments("fake", "repo", 1, 1);
gitHubClient.Received().PullRequest.Review.GetAllComments("fake", "repo", 1, 1);
}
[Fact]
public void RequestsCorrectUrlWithRepositoryId()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
client.GetAllComments(1, 1, 1);
gitHubClient.Received().PullRequest.Review.GetAllComments(1, 1, 1);
}
[Fact]
public void RequestsCorrectUrlWithApiOptions()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var options = new ApiOptions
{
PageCount = 1,
PageSize = 1,
StartPage = 1
};
client.GetAllComments("fake", "repo", 1, 1, options);
gitHubClient.Received().PullRequest.Review.GetAllComments("fake", "repo", 1, 1, options);
}
[Fact]
public void RequestsCorrectUrlWithApiOptionsWithRepositoryId()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var options = new ApiOptions
{
PageCount = 1,
PageSize = 1,
StartPage = 1
};
client.GetAllComments(1, 1, 1, options);
gitHubClient.Received().PullRequest.Review.GetAllComments(1, 1, 1, options);
}
[Fact]
public async Task RequestsCorrectUrlMulti()
{
var firstPageUrl = new Uri("repos/owner/name/pulls/7/reviews/1/comments", UriKind.Relative);
var secondPageUrl = new Uri("https://example.com/page/2");
var firstPageLinks = new Dictionary<string, Uri> { { "next", secondPageUrl } };
var firstPageResponse = new ApiResponse<List<PullRequestReviewComment>>
(
CreateResponseWithApiInfo(firstPageLinks),
new List<PullRequestReviewComment>
{
new PullRequestReviewComment(1),
new PullRequestReviewComment(2),
new PullRequestReviewComment(3)
});
var thirdPageUrl = new Uri("https://example.com/page/3");
var secondPageLinks = new Dictionary<string, Uri> { { "next", thirdPageUrl } };
var secondPageResponse = new ApiResponse<List<PullRequestReviewComment>>
(
CreateResponseWithApiInfo(secondPageLinks),
new List<PullRequestReviewComment>
{
new PullRequestReviewComment(4),
new PullRequestReviewComment(5),
new PullRequestReviewComment(6)
}
);
var lastPageResponse = new ApiResponse<List<PullRequestReviewComment>>
(
new Response(),
new List<PullRequestReviewComment>
{
new PullRequestReviewComment(7)
}
);
var gitHubClient = Substitute.For<IGitHubClient>();
gitHubClient.Connection.Get<List<PullRequestReviewComment>>(firstPageUrl, Args.EmptyDictionary, null)
.Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReviewComment>>>(() => firstPageResponse));
gitHubClient.Connection.Get<List<PullRequestReviewComment>>(secondPageUrl, Args.EmptyDictionary, null)
.Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReviewComment>>>(() => secondPageResponse));
gitHubClient.Connection.Get<List<PullRequestReviewComment>>(thirdPageUrl, Args.EmptyDictionary, null)
.Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReviewComment>>>(() => lastPageResponse));
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var results = await client.GetAllComments("owner", "name", 7, 1).ToArray();
Assert.Equal(7, results.Length);
gitHubClient.Connection.Received(1).Get<List<PullRequestReviewComment>>(firstPageUrl, Args.EmptyDictionary, null);
gitHubClient.Connection.Received(1).Get<List<PullRequestReviewComment>>(secondPageUrl, Args.EmptyDictionary, null);
gitHubClient.Connection.Received(1).Get<List<PullRequestReviewComment>>(thirdPageUrl, Args.EmptyDictionary, null);
}
[Fact]
public async Task RequestsCorrectUrlMultiWithRepositoryId()
{
var firstPageUrl = new Uri("repositories/1/pulls/7/reviews/1/comments", UriKind.Relative);
var secondPageUrl = new Uri("https://example.com/page/2");
var firstPageLinks = new Dictionary<string, Uri> { { "next", secondPageUrl } };
var firstPageResponse = new ApiResponse<List<PullRequestReviewComment>>
(
CreateResponseWithApiInfo(firstPageLinks),
new List<PullRequestReviewComment>
{
new PullRequestReviewComment(1),
new PullRequestReviewComment(2),
new PullRequestReviewComment(3)
});
var thirdPageUrl = new Uri("https://example.com/page/3");
var secondPageLinks = new Dictionary<string, Uri> { { "next", thirdPageUrl } };
var secondPageResponse = new ApiResponse<List<PullRequestReviewComment>>
(
CreateResponseWithApiInfo(secondPageLinks),
new List<PullRequestReviewComment>
{
new PullRequestReviewComment(4),
new PullRequestReviewComment(5),
new PullRequestReviewComment(6)
}
);
var lastPageResponse = new ApiResponse<List<PullRequestReviewComment>>
(
new Response(),
new List<PullRequestReviewComment>
{
new PullRequestReviewComment(7)
}
);
var gitHubClient = Substitute.For<IGitHubClient>();
gitHubClient.Connection.Get<List<PullRequestReviewComment>>(firstPageUrl, Args.EmptyDictionary, null)
.Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReviewComment>>>(() => firstPageResponse));
gitHubClient.Connection.Get<List<PullRequestReviewComment>>(secondPageUrl, Args.EmptyDictionary, null)
.Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReviewComment>>>(() => secondPageResponse));
gitHubClient.Connection.Get<List<PullRequestReviewComment>>(thirdPageUrl, Args.EmptyDictionary, null)
.Returns(Task.Factory.StartNew<IApiResponse<List<PullRequestReviewComment>>>(() => lastPageResponse));
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var results = await client.GetAllComments(1, 7, 1).ToArray();
Assert.Equal(7, results.Length);
gitHubClient.Connection.Received(1).Get<List<PullRequestReviewComment>>(firstPageUrl, Args.EmptyDictionary, null);
gitHubClient.Connection.Received(1).Get<List<PullRequestReviewComment>>(secondPageUrl, Args.EmptyDictionary, null);
gitHubClient.Connection.Received(1).Get<List<PullRequestReviewComment>>(thirdPageUrl, Args.EmptyDictionary, null);
}
[Fact]
public async Task EnsuresNonNullArguments()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
Assert.Throws<ArgumentNullException>(() => client.GetAllComments(null, "name", 1, 1));
Assert.Throws<ArgumentNullException>(() => client.GetAllComments("owner", null, 1, 1));
Assert.Throws<ArgumentNullException>(() => client.GetAllComments(null, "name", 1, 1, ApiOptions.None));
Assert.Throws<ArgumentNullException>(() => client.GetAllComments("owner", null, 1, 1, ApiOptions.None));
Assert.Throws<ArgumentNullException>(() => client.GetAllComments("owner", "name", 1, 1, null));
Assert.Throws<ArgumentNullException>(() => client.GetAllComments(1, 1, 1, null));
Assert.Throws<ArgumentException>(() => client.GetAllComments("", "name", 1, 1));
Assert.Throws<ArgumentException>(() => client.GetAllComments("owner", "", 1, 1));
Assert.Throws<ArgumentException>(() => client.GetAllComments("", "name", 1, 1, ApiOptions.None));
Assert.Throws<ArgumentException>(() => client.GetAllComments("owner", "", 1, 1, ApiOptions.None));
}
}
public class TheSubmitMethod
{
[Fact]
public void PostsToCorrectUrl()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var submitMessage = new PullRequestReviewSubmit()
{
Body = "string",
Event = PullRequestReviewEvent.Approve
};
client.Submit("owner", "name", 13, 13, submitMessage);
gitHubClient.Received().PullRequest.Review.Submit("owner", "name", 13, 13, submitMessage);
}
[Fact]
public void PostsToCorrectUrlWithRepositoryId()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var submitMessage = new PullRequestReviewSubmit()
{
Body = "string",
Event = PullRequestReviewEvent.Approve
};
client.Submit(1, 13, 13, submitMessage);
gitHubClient.Received().PullRequest.Review.Submit(1, 13, 13, submitMessage);
}
[Fact]
public void EnsuresNonNullArguments()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservablePullRequestReviewsClient(gitHubClient);
var submitMessage = new PullRequestReviewSubmit()
{
Body = "string",
Event = PullRequestReviewEvent.Approve
};
Assert.Throws<ArgumentNullException>(() => client.Submit(null, "name", 1, 1, submitMessage));
Assert.Throws<ArgumentNullException>(() => client.Submit("owner", null, 1, 1, submitMessage));
Assert.Throws<ArgumentNullException>(() => client.Submit("owner", "name", 1, 1, null));
Assert.Throws<ArgumentException>(() => client.Submit("", "name", 1, 1, submitMessage));
Assert.Throws<ArgumentException>(() => client.Submit("owner", "", 1, 1, submitMessage));
}
}
}
}

View File

@@ -0,0 +1,189 @@
using System.Collections.Generic;
using System.Threading.Tasks;
namespace Octokit
{
/// <summary>
/// A client for GitHub's Pull Request Review API.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/pulls/reviews/">Review API documentation</a> for more information.
/// </remarks>
public interface IPullRequestReviewsClient
{
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
Task<IReadOnlyList<PullRequestReview>> GetAll(string owner, string name, int number);
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
Task<IReadOnlyList<PullRequestReview>> GetAll(long repositoryId, int number);
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="options">Options for changing the API response</param>
Task<IReadOnlyList<PullRequestReview>> GetAll(string owner, string name, int number, ApiOptions options);
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="options">Options for changing the API response</param>
Task<IReadOnlyList<PullRequestReview>> GetAll(long repositoryId, int number, ApiOptions options);
/// <summary>
/// Gets a single pull request review by ID.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-a-single-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
Task<PullRequestReview> Get(string owner, string name, int number, long reviewId);
/// <summary>
/// Gets a single pull request review by ID.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-a-single-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
Task<PullRequestReview> Get(long repositoryId, int number, long reviewId);
/// <summary>
/// Creates a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The Pull Request number</param>
/// <param name="review">The review</param>
Task<PullRequestReview> Create(string owner, string name, int number, PullRequestReviewCreate review);
/// <summary>
/// Creates a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The Pull Request number</param>
/// <param name="review">The review</param>
Task<PullRequestReview> Create(long repositoryId, int number, PullRequestReviewCreate review);
/// <summary>
/// Deletes a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
Task Delete(string owner, string name, int number, long reviewId);
/// <summary>
/// Deletes a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
Task Delete(long repositoryId, int number, long reviewId);
/// <summary>
/// Submits a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="submitMessage">The message and event being submitted for the review</param>
Task<PullRequestReview> Submit(string owner, string name, int number, long reviewId, PullRequestReviewSubmit submitMessage);
/// <summary>
/// Submits a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="submitMessage">The message and event being submitted for the review</param>
Task<PullRequestReview> Submit(long repositoryId, int number, long reviewId, PullRequestReviewSubmit submitMessage);
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="dismissMessage">The message indicating why the review was dismissed</param>
Task<PullRequestReview> Dismiss(string owner, string name, int number, long reviewId, PullRequestReviewDismiss dismissMessage);
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="dismissMessage">The message indicating why the review was dismissed</param>
Task<PullRequestReview> Dismiss(long repositoryId, int number, long reviewId, PullRequestReviewDismiss dismissMessage);
/// <summary>
/// Lists comments for a single review
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
Task<IReadOnlyList<PullRequestReviewComment>> GetAllComments(string owner, string name, int number, long reviewId);
/// <summary>
/// Lists comments for a single review
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
Task<IReadOnlyList<PullRequestReviewComment>> GetAllComments(long repositoryId, int number, long reviewId);
/// <summary>
/// Lists comments for a single review
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="options">Options for changing the API response</param>
Task<IReadOnlyList<PullRequestReviewComment>> GetAllComments(string owner, string name, int number, long reviewId, ApiOptions options);
/// <summary>
/// Lists comments for a single review
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="options">Options for changing the API response</param>
Task<IReadOnlyList<PullRequestReviewComment>> GetAllComments(long repositoryId, int number, long reviewId, ApiOptions options);
}
}

View File

@@ -19,6 +19,11 @@ namespace Octokit
[Obsolete("Please use IPullRequestsClient.ReviewComment instead. This method will be removed in a future version")] [Obsolete("Please use IPullRequestsClient.ReviewComment instead. This method will be removed in a future version")]
IPullRequestReviewCommentsClient Comment { get; } IPullRequestReviewCommentsClient Comment { get; }
/// <summary>
/// Client for managing reviews.
/// </summary>
IPullRequestReviewsClient Review { get; }
/// <summary> /// <summary>
/// Client for managing review comments. /// Client for managing review comments.
/// </summary> /// </summary>

View File

@@ -0,0 +1,301 @@
using System;
using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
namespace Octokit
{
/// <summary>
/// A client for GitHub's Pull Request Review API.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/pulls/reviews/">Review API documentation</a> for more information.
/// </remarks>
public class PullRequestReviewsClient : ApiClient, IPullRequestReviewsClient
{
public PullRequestReviewsClient(IApiConnection apiConnection)
: base(apiConnection)
{
}
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
public Task<IReadOnlyList<PullRequestReview>> GetAll(string owner, string name, int number)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
return GetAll(owner, name, number, ApiOptions.None);
}
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
public Task<IReadOnlyList<PullRequestReview>> GetAll(long repositoryId, int number)
{
return GetAll(repositoryId, number, ApiOptions.None);
}
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="options">Options for changing the API response</param>
public Task<IReadOnlyList<PullRequestReview>> GetAll(string owner, string name, int number, ApiOptions options)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
Ensure.ArgumentNotNull(options, nameof(options));
var endpoint = ApiUrls.PullRequestReviews(owner, name, number);
return ApiConnection.GetAll<PullRequestReview>(endpoint, null, options);
}
/// <summary>
/// Gets reviews for a specified pull request.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="options">Options for changing the API response</param>
public Task<IReadOnlyList<PullRequestReview>> GetAll(long repositoryId, int number, ApiOptions options)
{
Ensure.ArgumentNotNull(options, nameof(options));
var endpoint = ApiUrls.PullRequestReviews(repositoryId, number);
return ApiConnection.GetAll<PullRequestReview>(endpoint, options);
}
/// <summary>
/// Gets a single pull request review by ID.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-a-single-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public Task<PullRequestReview> Get(string owner, string name, int number, long reviewId)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
var endpoint = ApiUrls.PullRequestReview(owner, name, number, reviewId);
return ApiConnection.Get<PullRequestReview>(endpoint);
}
/// <summary>
/// Gets a single pull request review by ID.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-a-single-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public Task<PullRequestReview> Get(long repositoryId, int number, long reviewId)
{
var endpoint = ApiUrls.PullRequestReview(repositoryId, number, reviewId);
return ApiConnection.Get<PullRequestReview>(endpoint);
}
/// <summary>
/// Creates a review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The Pull Request number</param>
/// <param name="review">The review</param>
public Task<PullRequestReview> Create(string owner, string name, int number, PullRequestReviewCreate review)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
Ensure.ArgumentNotNull(review, nameof(review));
var endpoint = ApiUrls.PullRequestReviews(owner, name, number);
return ApiConnection.Post<PullRequestReview>(endpoint, review, null, null);
}
/// <summary>
/// Creates a review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The Pull Request number</param>
/// <param name="review">The review</param>
public Task<PullRequestReview> Create(long repositoryId, int number, PullRequestReviewCreate review)
{
Ensure.ArgumentNotNull(review, nameof(review));
var endpoint = ApiUrls.PullRequestReviews(repositoryId, number);
return ApiConnection.Post<PullRequestReview>(endpoint, review, null, null);
}
/// <summary>
/// Deletes a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public Task Delete(string owner, string name, int number, long reviewId)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
var endpoint = ApiUrls.PullRequestReview(owner, name, number, reviewId);
return ApiConnection.Delete(endpoint);
}
/// <summary>
/// Deletes a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#delete-a-pending-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public Task Delete(long repositoryId, int number, long reviewId)
{
var endpoint = ApiUrls.PullRequestReview(repositoryId, number, reviewId);
return ApiConnection.Delete(endpoint);
}
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="dismissMessage">The message indicating why the review was dismissed</param>
public Task<PullRequestReview> Dismiss(string owner, string name, int number, long reviewId, PullRequestReviewDismiss dismissMessage)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
Ensure.ArgumentNotNull(dismissMessage, nameof(dismissMessage));
var endpoint = ApiUrls.PullRequestReviewDismissal(owner, name, number, reviewId);
return ApiConnection.Put<PullRequestReview>(endpoint, dismissMessage);
}
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#dismiss-a-pull-request-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="dismissMessage">The message indicating why the review was dismissed</param>
public Task<PullRequestReview> Dismiss(long repositoryId, int number, long reviewId, PullRequestReviewDismiss dismissMessage)
{
Ensure.ArgumentNotNull(dismissMessage, nameof(dismissMessage));
var endpoint = ApiUrls.PullRequestReviewDismissal(repositoryId, number, reviewId);
return ApiConnection.Put<PullRequestReview>(endpoint, dismissMessage);
}
/// <summary>
/// Submits a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="submitMessage">The message and event being submitted for the review</param>
public Task<PullRequestReview> Submit(string owner, string name, int number, long reviewId, PullRequestReviewSubmit submitMessage)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
Ensure.ArgumentNotNull(submitMessage, nameof(submitMessage));
var endpoint = ApiUrls.PullRequestReviewSubmit(owner, name, number, reviewId);
return ApiConnection.Post<PullRequestReview>(endpoint, submitMessage, null, null);
}
/// <summary>
/// Submits a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#submit-a-pull-request-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="submitMessage">The message and event being submitted for the review</param>
public Task<PullRequestReview> Submit(long repositoryId, int number, long reviewId, PullRequestReviewSubmit submitMessage)
{
Ensure.ArgumentNotNull(submitMessage, nameof(submitMessage));
var endpoint = ApiUrls.PullRequestReviewSubmit(repositoryId, number, reviewId);
return ApiConnection.Post<PullRequestReview>(endpoint, submitMessage, null, null);
}
/// <summary>
/// Lists comments for a single review
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public Task<IReadOnlyList<PullRequestReviewComment>> GetAllComments(string owner, string name, int number, long reviewId)
{
return GetAllComments(owner, name, number, reviewId, ApiOptions.None);
}
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
public Task<IReadOnlyList<PullRequestReviewComment>> GetAllComments(long repositoryId, int number, long reviewId)
{
return GetAllComments(repositoryId, number, reviewId, ApiOptions.None);
}
/// <summary>
/// Lists comments for a single review
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="options">Options for changing the API response</param>
public Task<IReadOnlyList<PullRequestReviewComment>> GetAllComments(string owner, string name, int number, long reviewId, ApiOptions options)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
var endpoint = ApiUrls.PullRequestReviewComments(owner, name, number, reviewId);
return ApiConnection.GetAll<PullRequestReviewComment>(endpoint, null, options);
}
/// <summary>
/// Dismisses a pull request review.
/// </summary>
/// <remarks>https://developer.github.com/v3/pulls/reviews/#get-comments-for-a-single-review</remarks>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <param name="options">Options for changing the API response</param>
public Task<IReadOnlyList<PullRequestReviewComment>> GetAllComments(long repositoryId, int number, long reviewId, ApiOptions options)
{
var endpoint = ApiUrls.PullRequestReviewComments(repositoryId, number, reviewId);
return ApiConnection.GetAll<PullRequestReviewComment>(endpoint, null, options);
}
}
}

View File

@@ -9,12 +9,13 @@ namespace Octokit
/// A client for GitHub's Pull Requests API. /// A client for GitHub's Pull Requests API.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// See the <a href="http://developer.github.com/v3/activity/notifications/">Pull Requests API documentation</a> for more information. /// See the <a href="https://developer.github.com/v3/pulls/">Pull Requests API documentation</a> for more information.
/// </remarks> /// </remarks>
public class PullRequestsClient : ApiClient, IPullRequestsClient public class PullRequestsClient : ApiClient, IPullRequestsClient
{ {
public PullRequestsClient(IApiConnection apiConnection) : base(apiConnection) public PullRequestsClient(IApiConnection apiConnection) : base(apiConnection)
{ {
Review = new PullRequestReviewsClient(apiConnection);
ReviewComment = new PullRequestReviewCommentsClient(apiConnection); ReviewComment = new PullRequestReviewCommentsClient(apiConnection);
ReviewRequest = new PullRequestReviewRequestsClient(apiConnection); ReviewRequest = new PullRequestReviewRequestsClient(apiConnection);
} }
@@ -25,6 +26,11 @@ namespace Octokit
[Obsolete("Please use PullRequestsClient.ReviewComment instead. This method will be removed in a future version")] [Obsolete("Please use PullRequestsClient.ReviewComment instead. This method will be removed in a future version")]
public IPullRequestReviewCommentsClient Comment { get { return this.ReviewComment; } } public IPullRequestReviewCommentsClient Comment { get { return this.ReviewComment; } }
/// <summary>
/// Client for managing reviews.
/// </summary>
public IPullRequestReviewsClient Review { get; set; }
/// <summary> /// <summary>
/// Client for managing review comments. /// Client for managing review comments.
/// </summary> /// </summary>
@@ -43,8 +49,8 @@ namespace Octokit
/// </remarks> /// </remarks>
public Task<PullRequest> Get(string owner, string name, int number) public Task<PullRequest> Get(string owner, string name, int number)
{ {
Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
return ApiConnection.Get<PullRequest>(ApiUrls.PullRequest(owner, name, number)); return ApiConnection.Get<PullRequest>(ApiUrls.PullRequest(owner, name, number));
} }
@@ -70,8 +76,8 @@ namespace Octokit
/// <param name="name">The name of the repository</param> /// <param name="name">The name of the repository</param>
public Task<IReadOnlyList<PullRequest>> GetAllForRepository(string owner, string name) public Task<IReadOnlyList<PullRequest>> GetAllForRepository(string owner, string name)
{ {
Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
return GetAllForRepository(owner, name, new PullRequestRequest(), ApiOptions.None); return GetAllForRepository(owner, name, new PullRequestRequest(), ApiOptions.None);
} }
@@ -99,9 +105,9 @@ namespace Octokit
/// <param name="options">Options for changing the API response</param> /// <param name="options">Options for changing the API response</param>
public Task<IReadOnlyList<PullRequest>> GetAllForRepository(string owner, string name, ApiOptions options) public Task<IReadOnlyList<PullRequest>> GetAllForRepository(string owner, string name, ApiOptions options)
{ {
Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
Ensure.ArgumentNotNull(options, "options"); Ensure.ArgumentNotNull(options, nameof(options));
return GetAllForRepository(owner, name, new PullRequestRequest(), options); return GetAllForRepository(owner, name, new PullRequestRequest(), options);
} }
@@ -116,7 +122,7 @@ namespace Octokit
/// <param name="options">Options for changing the API response</param> /// <param name="options">Options for changing the API response</param>
public Task<IReadOnlyList<PullRequest>> GetAllForRepository(long repositoryId, ApiOptions options) public Task<IReadOnlyList<PullRequest>> GetAllForRepository(long repositoryId, ApiOptions options)
{ {
Ensure.ArgumentNotNull(options, "options"); Ensure.ArgumentNotNull(options, nameof(options));
return GetAllForRepository(repositoryId, new PullRequestRequest(), options); return GetAllForRepository(repositoryId, new PullRequestRequest(), options);
} }
@@ -132,9 +138,9 @@ namespace Octokit
/// <param name="request">Used to filter and sort the list of pull requests returned</param> /// <param name="request">Used to filter and sort the list of pull requests returned</param>
public Task<IReadOnlyList<PullRequest>> GetAllForRepository(string owner, string name, PullRequestRequest request) public Task<IReadOnlyList<PullRequest>> GetAllForRepository(string owner, string name, PullRequestRequest request)
{ {
Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
Ensure.ArgumentNotNull(request, "request"); Ensure.ArgumentNotNull(request, nameof(request));
return GetAllForRepository(owner, name, request, ApiOptions.None); return GetAllForRepository(owner, name, request, ApiOptions.None);
} }
@@ -149,7 +155,7 @@ namespace Octokit
/// <param name="request">Used to filter and sort the list of pull requests returned</param> /// <param name="request">Used to filter and sort the list of pull requests returned</param>
public Task<IReadOnlyList<PullRequest>> GetAllForRepository(long repositoryId, PullRequestRequest request) public Task<IReadOnlyList<PullRequest>> GetAllForRepository(long repositoryId, PullRequestRequest request)
{ {
Ensure.ArgumentNotNull(request, "request"); Ensure.ArgumentNotNull(request, nameof(request));
return GetAllForRepository(repositoryId, request, ApiOptions.None); return GetAllForRepository(repositoryId, request, ApiOptions.None);
} }
@@ -166,10 +172,10 @@ namespace Octokit
/// <param name="options">Options for changing the API response</param> /// <param name="options">Options for changing the API response</param>
public Task<IReadOnlyList<PullRequest>> GetAllForRepository(string owner, string name, PullRequestRequest request, ApiOptions options) public Task<IReadOnlyList<PullRequest>> GetAllForRepository(string owner, string name, PullRequestRequest request, ApiOptions options)
{ {
Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
Ensure.ArgumentNotNull(request, "request"); Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(options, "options"); Ensure.ArgumentNotNull(options, nameof(options));
return ApiConnection.GetAll<PullRequest>(ApiUrls.PullRequests(owner, name), return ApiConnection.GetAll<PullRequest>(ApiUrls.PullRequests(owner, name),
request.ToParametersDictionary(), options); request.ToParametersDictionary(), options);
@@ -186,8 +192,8 @@ namespace Octokit
/// <param name="options">Options for changing the API response</param> /// <param name="options">Options for changing the API response</param>
public Task<IReadOnlyList<PullRequest>> GetAllForRepository(long repositoryId, PullRequestRequest request, ApiOptions options) public Task<IReadOnlyList<PullRequest>> GetAllForRepository(long repositoryId, PullRequestRequest request, ApiOptions options)
{ {
Ensure.ArgumentNotNull(request, "request"); Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(options, "options"); Ensure.ArgumentNotNull(options, nameof(options));
return ApiConnection.GetAll<PullRequest>(ApiUrls.PullRequests(repositoryId), return ApiConnection.GetAll<PullRequest>(ApiUrls.PullRequests(repositoryId),
request.ToParametersDictionary(), options); request.ToParametersDictionary(), options);
@@ -202,9 +208,9 @@ namespace Octokit
/// <param name="newPullRequest">A <see cref="NewPullRequest"/> instance describing the new PullRequest to create</param> /// <param name="newPullRequest">A <see cref="NewPullRequest"/> instance describing the new PullRequest to create</param>
public Task<PullRequest> Create(string owner, string name, NewPullRequest newPullRequest) public Task<PullRequest> Create(string owner, string name, NewPullRequest newPullRequest)
{ {
Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
Ensure.ArgumentNotNull(newPullRequest, "newPullRequest"); Ensure.ArgumentNotNull(newPullRequest, nameof(newPullRequest));
return ApiConnection.Post<PullRequest>(ApiUrls.PullRequests(owner, name), newPullRequest); return ApiConnection.Post<PullRequest>(ApiUrls.PullRequests(owner, name), newPullRequest);
} }
@@ -217,7 +223,7 @@ namespace Octokit
/// <param name="newPullRequest">A <see cref="NewPullRequest"/> instance describing the new PullRequest to create</param> /// <param name="newPullRequest">A <see cref="NewPullRequest"/> instance describing the new PullRequest to create</param>
public Task<PullRequest> Create(long repositoryId, NewPullRequest newPullRequest) public Task<PullRequest> Create(long repositoryId, NewPullRequest newPullRequest)
{ {
Ensure.ArgumentNotNull(newPullRequest, "newPullRequest"); Ensure.ArgumentNotNull(newPullRequest, nameof(newPullRequest));
return ApiConnection.Post<PullRequest>(ApiUrls.PullRequests(repositoryId), newPullRequest); return ApiConnection.Post<PullRequest>(ApiUrls.PullRequests(repositoryId), newPullRequest);
} }
@@ -233,9 +239,9 @@ namespace Octokit
/// </param> /// </param>
public Task<PullRequest> Update(string owner, string name, int number, PullRequestUpdate pullRequestUpdate) public Task<PullRequest> Update(string owner, string name, int number, PullRequestUpdate pullRequestUpdate)
{ {
Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
Ensure.ArgumentNotNull(pullRequestUpdate, "pullRequestUpdate"); Ensure.ArgumentNotNull(pullRequestUpdate, nameof(pullRequestUpdate));
return ApiConnection.Patch<PullRequest>(ApiUrls.PullRequest(owner, name, number), pullRequestUpdate); return ApiConnection.Patch<PullRequest>(ApiUrls.PullRequest(owner, name, number), pullRequestUpdate);
} }
@@ -250,7 +256,7 @@ namespace Octokit
/// </param> /// </param>
public Task<PullRequest> Update(long repositoryId, int number, PullRequestUpdate pullRequestUpdate) public Task<PullRequest> Update(long repositoryId, int number, PullRequestUpdate pullRequestUpdate)
{ {
Ensure.ArgumentNotNull(pullRequestUpdate, "pullRequestUpdate"); Ensure.ArgumentNotNull(pullRequestUpdate, nameof(pullRequestUpdate));
return ApiConnection.Patch<PullRequest>(ApiUrls.PullRequest(repositoryId, number), pullRequestUpdate); return ApiConnection.Patch<PullRequest>(ApiUrls.PullRequest(repositoryId, number), pullRequestUpdate);
} }
@@ -265,9 +271,9 @@ namespace Octokit
/// <param name="mergePullRequest">A <see cref="MergePullRequest"/> instance describing a pull request merge</param> /// <param name="mergePullRequest">A <see cref="MergePullRequest"/> instance describing a pull request merge</param>
public async Task<PullRequestMerge> Merge(string owner, string name, int number, MergePullRequest mergePullRequest) public async Task<PullRequestMerge> Merge(string owner, string name, int number, MergePullRequest mergePullRequest)
{ {
Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
Ensure.ArgumentNotNull(mergePullRequest, "mergePullRequest"); Ensure.ArgumentNotNull(mergePullRequest, nameof(mergePullRequest));
try try
{ {
@@ -299,7 +305,7 @@ namespace Octokit
/// <param name="mergePullRequest">A <see cref="MergePullRequest"/> instance describing a pull request merge</param> /// <param name="mergePullRequest">A <see cref="MergePullRequest"/> instance describing a pull request merge</param>
public async Task<PullRequestMerge> Merge(long repositoryId, int number, MergePullRequest mergePullRequest) public async Task<PullRequestMerge> Merge(long repositoryId, int number, MergePullRequest mergePullRequest)
{ {
Ensure.ArgumentNotNull(mergePullRequest, "mergePullRequest"); Ensure.ArgumentNotNull(mergePullRequest, nameof(mergePullRequest));
try try
{ {
@@ -331,8 +337,8 @@ namespace Octokit
/// <param name="number">The pull request number</param> /// <param name="number">The pull request number</param>
public async Task<bool> Merged(string owner, string name, int number) public async Task<bool> Merged(string owner, string name, int number)
{ {
Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
try try
{ {
@@ -375,8 +381,8 @@ namespace Octokit
/// <param name="number">The pull request number</param> /// <param name="number">The pull request number</param>
public Task<IReadOnlyList<PullRequestCommit>> Commits(string owner, string name, int number) public Task<IReadOnlyList<PullRequestCommit>> Commits(string owner, string name, int number)
{ {
Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
return ApiConnection.GetAll<PullRequestCommit>(ApiUrls.PullRequestCommits(owner, name, number)); return ApiConnection.GetAll<PullRequestCommit>(ApiUrls.PullRequestCommits(owner, name, number));
} }
@@ -401,8 +407,8 @@ namespace Octokit
/// <param name="number">The pull request number</param> /// <param name="number">The pull request number</param>
public Task<IReadOnlyList<PullRequestFile>> Files(string owner, string name, int number) public Task<IReadOnlyList<PullRequestFile>> Files(string owner, string name, int number)
{ {
Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, "name"); Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));
return ApiConnection.GetAll<PullRequestFile>(ApiUrls.PullRequestFiles(owner, name, number)); return ApiConnection.GetAll<PullRequestFile>(ApiUrls.PullRequestFiles(owner, name, number));
} }

View File

@@ -1339,6 +1339,18 @@ namespace Octokit
return "repos/{0}/{1}/pulls/{2}/comments".FormatUri(owner, name, number); return "repos/{0}/{1}/pulls/{2}/comments".FormatUri(owner, name, number);
} }
/// <summary>
/// Returns the <see cref="Uri"/> for the reviews opf a specified pull request
/// </summary>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <returns>The <see cref="Uri"/></returns>
public static Uri PullRequestReviews(string owner, string name, int number)
{
return "repos/{0}/{1}/pulls/{2}/reviews".FormatUri(owner, name, number);
}
/// <summary> /// <summary>
/// Returns the <see cref="Uri"/> for the specified pull request review comment. /// Returns the <see cref="Uri"/> for the specified pull request review comment.
/// </summary> /// </summary>
@@ -1351,6 +1363,106 @@ namespace Octokit
return "repos/{0}/{1}/pulls/comments/{2}".FormatUri(owner, name, number); return "repos/{0}/{1}/pulls/comments/{2}".FormatUri(owner, name, number);
} }
/// <summary>
/// Returns the <see cref="Uri"/> for the specified pull request review.
/// </summary>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <returns>The <see cref="Uri"/></returns>
public static Uri PullRequestReview(string owner, string name, int number, long reviewId)
{
return "repos/{0}/{1}/pulls/{2}/reviews/{3}".FormatUri(owner, name, number, reviewId);
}
/// <summary>
/// Returns the <see cref="Uri"/> for dismissing a specified pull request review
/// </summary>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <returns>The <see cref="Uri"/></returns>
public static Uri PullRequestReviewDismissal(long repositoryId, int number, long reviewId)
{
return "repositories/{0}/pulls/{1}/reviews/{2}/dismissals".FormatUri(repositoryId, number, reviewId);
}
/// <summary>
/// Returns the <see cref="Uri"/> for dismissing a specified pull request review
/// </summary>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <returns>The <see cref="Uri"/></returns>
public static Uri PullRequestReviewDismissal(string owner, string name, int number, long reviewId)
{
return "repos/{0}/{1}/pulls/{2}/reviews/{3}/dismissals".FormatUri(owner, name, number, reviewId);
}
/// <summary>
/// Returns the <see cref="Uri"/> for submitting a pull request review
/// </summary>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <returns>The <see cref="Uri"/> that </returns>
public static Uri PullRequestReviewSubmit(long repositoryId, int number, long reviewId)
{
return "repositories/{0}/pulls/{1}/reviews/{2}/events".FormatUri(repositoryId, number, reviewId);
}
/// <summary>
/// Returns the <see cref="Uri"/> for submitting a pull request review
/// </summary>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <returns>The <see cref="Uri"/></returns>
public static Uri PullRequestReviewSubmit(string owner, string name, int number, long reviewId)
{
return "repos/{0}/{1}/pulls/{2}/reviews/{3}/events".FormatUri(owner, name, number, reviewId);
}
/// <summary>
/// Returns the <see cref="Uri"/> for submitting a pull request review
/// </summary>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <returns>The <see cref="Uri"/> that </returns>
public static Uri PullRequestReviewComments(long repositoryId, int number, long reviewId)
{
return "repositories/{0}/pulls/{1}/reviews/{2}/comments".FormatUri(repositoryId, number, reviewId);
}
/// <summary>
/// Returns the <see cref="Uri"/> for submitting a pull request review
/// </summary>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <returns>The <see cref="Uri"/></returns>
public static Uri PullRequestReviewComments(string owner, string name, int number, long reviewId)
{
return "repos/{0}/{1}/pulls/{2}/reviews/{3}/comments".FormatUri(owner, name, number, reviewId);
}
/// <summary>
/// Returns the <see cref="Uri"/> for a specified pull request review.
/// </summary>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <param name="reviewId">The pull request review number</param>
/// <returns>The <see cref="Uri"/></returns>
public static Uri PullRequestReview(long repositoryId, int number, long reviewId)
{
return "repositories/{0}/pulls/{1}/reviews/{2}".FormatUri(repositoryId, number, reviewId);
}
/// <summary> /// <summary>
/// Returns the <see cref="Uri"/> for the reaction of a specified pull request review comment. /// Returns the <see cref="Uri"/> for the reaction of a specified pull request review comment.
/// </summary> /// </summary>
@@ -2815,6 +2927,17 @@ namespace Octokit
return "repositories/{0}/pulls/{1}/comments".FormatUri(repositoryId, number); return "repositories/{0}/pulls/{1}/comments".FormatUri(repositoryId, number);
} }
/// <summary>
/// Returns the <see cref="Uri"/> for the reviews of a specified pull request
/// </summary>
/// <param name="repositoryId">The Id of the repository</param>
/// <param name="number">The pull request number</param>
/// <returns>The <see cref="Uri"/> that </returns>
public static Uri PullRequestReviews(long repositoryId, int number)
{
return "repositories/{0}/pulls/{1}/reviews".FormatUri(repositoryId, number);
}
/// <summary> /// <summary>
/// Returns the <see cref="Uri"/> for the pull request review comments on a specified repository. /// Returns the <see cref="Uri"/> for the pull request review comments on a specified repository.
/// </summary> /// </summary>

View File

@@ -0,0 +1,48 @@
using System.Diagnostics;
using System.Globalization;
namespace Octokit
{
/// <summary>
/// A draft comment that is part of a Pull Request Review
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class DraftPullRequestReviewComment : RequestParameters
{
/// <summary>
/// Creates a draft comment
/// </summary>
/// <param name="body">The text of the comment</param>
/// <param name="path">The relative path of the file to comment on</param>
/// <param name="position">The line index in the diff to comment on</param>
public DraftPullRequestReviewComment(string body, string path, int position)
{
Ensure.ArgumentNotNullOrEmptyString(body, "body");
Ensure.ArgumentNotNullOrEmptyString(path, "path");
Body = body;
Path = path;
Position = position;
}
/// <summary>
/// The text of the comment.
/// </summary>
public string Body { get; private set; }
/// <summary>
/// The relative path of the file to comment on.
/// </summary>
public string Path { get; private set; }
/// <summary>
/// The line index in the diff to comment on.
/// </summary>
public int Position { get; private set; }
internal string DebuggerDisplay
{
get { return string.Format(CultureInfo.InvariantCulture, "Path: {0}, Position: {1}", Path, Position); }
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Diagnostics;
using System.Globalization;
using Octokit.Internal;
using System.Collections.Generic;
namespace Octokit
{
/// <summary>
/// Used to create a pull request review
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class PullRequestReviewCreate : RequestParameters
{
public PullRequestReviewCreate()
{
Comments = new List<DraftPullRequestReviewComment>();
}
/// <summary>
/// The Commit ID which the review is being created for. Default is the latest.
/// </summary>
public string CommitId { get; set; }
/// <summary>
/// The body of the review message
/// </summary>
public string Body { get; set; }
/// <summary>
/// The review event - Approve, Request Changes, Comment or leave blank (null) for Pending.
/// </summary>
public PullRequestReviewEvent? Event { get; set; }
/// <summary>
/// List of comments to include with this review
/// </summary>
public List<DraftPullRequestReviewComment> Comments { get; set; }
internal string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture, "CommitId: {0}, Body: {1} ", CommitId, Body);
}
}
}
}

View File

@@ -0,0 +1,31 @@
using System.Diagnostics;
using System.Globalization;
using Octokit.Internal;
using System.Collections.Generic;
namespace Octokit
{
/// <summary>
/// Used to dismiss a pull request review
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class PullRequestReviewDismiss : RequestParameters
{
public PullRequestReviewDismiss()
{
}
/// <summary>
/// The message explaining why this review is being dismissed
/// </summary>
public string Message { get; set; }
internal string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture, "Message: {0} ", Message);
}
}
}
}

View File

@@ -0,0 +1,57 @@
using System.Diagnostics;
using System.Globalization;
using Octokit.Internal;
using System.Collections.Generic;
namespace Octokit
{
/// <summary>
/// Used to submit a pending pull request review
/// </summary>
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class PullRequestReviewSubmit : RequestParameters
{
public PullRequestReviewSubmit()
{
}
/// <summary>
/// The body of the review message
/// </summary>
public string Body { get; set; }
/// <summary>
/// The review event - Approve, Request Changes, Comment
/// </summary>
public PullRequestReviewEvent Event { get; set; }
internal string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture, "Event: {0} ", Event);
}
}
}
public enum PullRequestReviewEvent
{
/// <summary>
/// The review is approved
/// </summary>
[Parameter(Value = "APPROVE")]
Approve,
/// <summary>
/// The review requests changes that must be addressed before merging
/// </summary>
[Parameter(Value = "REQUEST_CHANGES")]
RequestChanges,
/// <summary>
/// The review provides comment without explicit approval
/// </summary>
[Parameter(Value = "COMMENT")]
Comment
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.Diagnostics;
using System.Globalization;
using Octokit.Internal;
namespace Octokit
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class PullRequestReview
{
public PullRequestReview() { }
public PullRequestReview(long id)
{
Id = id;
}
public PullRequestReview(long id, string commitId, User user, string body, string htmlUrl, string pullRequestUrl, PullRequestReviewState state)
{
Id = id;
CommitId = commitId;
User = user;
Body = body;
HtmlUrl = htmlUrl;
PullRequestUrl = pullRequestUrl;
State = state;
}
/// <summary>
/// The review Id.
/// </summary>
public long Id { get; protected set; }
/// <summary>
/// The state of the review
/// </summary>
public StringEnum<PullRequestReviewState> State { get; protected set; }
/// <summary>
/// The commit Id the review is associated with.
/// </summary>
public string CommitId { get; protected set; }
/// <summary>
/// The user that created the review.
/// </summary>
public User User { get; protected set; }
/// <summary>
/// The text of the review.
/// </summary>
public string Body { get; protected set; }
/// <summary>
/// The URL for this review on Github.com
/// </summary>
public string HtmlUrl { get; protected set; }
/// <summary>
/// The URL for the pull request via the API.
/// </summary>
public string PullRequestUrl { get; protected set; }
internal string DebuggerDisplay
{
get { return string.Format(CultureInfo.InvariantCulture, "Id: {0}, State: {1}, User: {2}", Id, State.DebuggerDisplay, User.DebuggerDisplay); }
}
}
public enum PullRequestReviewState
{
[Parameter(Value = "APPROVED")]
Approved,
[Parameter(Value = "CHANGES_REQUESTED")]
ChangesRequested,
[Parameter(Value = "COMMENTED")]
Commented,
[Parameter(Value = "DISMISSED")]
Dismissed,
[Parameter(Value = "PENDING")]
Pending
}
}

View File

@@ -45,7 +45,16 @@ namespace Octokit
internal string DebuggerDisplay internal string DebuggerDisplay
{ {
get { return StringValue; } get
{
TEnum value;
if (TryParse(out value))
{
return value.ToString();
}
return StringValue;
}
} }
public bool TryParse(out TEnum value) public bool TryParse(out TEnum value)

View File

@@ -79,9 +79,15 @@ Write-Host "You should use a test account when running the Octokit integration t
Write-Host Write-Host
Write-Host Write-Host
VerifyEnvironmentVariable "account name" "OCTOKIT_GITHUBUSERNAME" VerifyEnvironmentVariable "test account name" "OCTOKIT_GITHUBUSERNAME"
VerifyEnvironmentVariable "account password" "OCTOKIT_GITHUBPASSWORD" $true VerifyEnvironmentVariable "test account password" "OCTOKIT_GITHUBPASSWORD" $true
VerifyEnvironmentVariable "OAuth token" "OCTOKIT_OAUTHTOKEN" VerifyEnvironmentVariable "test account OAuth token" "OCTOKIT_OAUTHTOKEN"
if (AskYesNoQuestion "Some tests require a second test account, do you want to set one up?" "OCTOKIT_PRIVATEREPOSITORIES")
{
VerifyEnvironmentVariable "Second test account name" "OCTOKIT_GITHUBUSERNAME_2"
VerifyEnvironmentVariable "Second account password" "OCTOKIT_GITHUBPASSWORD_2"
}
AskYesNoQuestion "Do you have private repositories associated with your test account?" "OCTOKIT_PRIVATEREPOSITORIES" | Out-Null AskYesNoQuestion "Do you have private repositories associated with your test account?" "OCTOKIT_PRIVATEREPOSITORIES" | Out-Null