diff --git a/Octokit.Reactive/Clients/IObservableIssuesClient.cs b/Octokit.Reactive/Clients/IObservableIssuesClient.cs index 3081488e98..8057f9e23e 100644 --- a/Octokit.Reactive/Clients/IObservableIssuesClient.cs +++ b/Octokit.Reactive/Clients/IObservableIssuesClient.cs @@ -44,6 +44,11 @@ public interface IObservableIssuesClient /// IObservableIssueTimelineClient Timeline { get; } + /// + /// Client for locking/unlocking conversation on an issue + /// + IObservableLockUnlockClient LockUnlock { get; } + /// /// Gets a single Issue by number. /// @@ -316,41 +321,5 @@ public interface IObservableIssuesClient /// An instance describing the changes to make to the issue /// IObservable Update(long repositoryId, int number, IssueUpdate issueUpdate); - - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - /// The reason for locking the issue - IObservable Lock(string owner, string name, int number, LockReason? lockReason = null); - - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The Id of the repository - /// The issue number - /// The reason for locking the issue - IObservable Lock(long repositoryId, int number, LockReason? lockReason = null); - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - IObservable Unlock(string owner, string name, int number); - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The Id of the repository - /// The issue number - IObservable Unlock(long repositoryId, int number); } } \ No newline at end of file diff --git a/Octokit.Reactive/Clients/IObservableLockUnlockClient.cs b/Octokit.Reactive/Clients/IObservableLockUnlockClient.cs new file mode 100644 index 0000000000..b897141b59 --- /dev/null +++ b/Octokit.Reactive/Clients/IObservableLockUnlockClient.cs @@ -0,0 +1,47 @@ +using System; +using System.Reactive; + +namespace Octokit.Reactive +{ + /// + /// Client to manage locking/unlocking a conversation for an Issue or a Pull request + /// + public interface IObservableLockUnlockClient + { + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The reason for locking the issue + IObservable Lock(string owner, string name, int number, LockReason? lockReason = null); + + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The Id of the repository + /// The issue number + /// The reason for locking the issue + IObservable Lock(long repositoryId, int number, LockReason? lockReason = null); + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + IObservable Unlock(string owner, string name, int number); + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The Id of the repository + /// The issue number + IObservable Unlock(long repositoryId, int number); + } +} diff --git a/Octokit.Reactive/Clients/IObservablePullRequestsClient.cs b/Octokit.Reactive/Clients/IObservablePullRequestsClient.cs index 007886afcf..997d662212 100644 --- a/Octokit.Reactive/Clients/IObservablePullRequestsClient.cs +++ b/Octokit.Reactive/Clients/IObservablePullRequestsClient.cs @@ -26,6 +26,11 @@ public interface IObservablePullRequestsClient /// IObservablePullRequestReviewRequestsClient ReviewRequest { get; } + /// + /// Client for locking/unlocking a conversation on a pull request + /// + IObservableLockUnlockClient LockUnlock { get; } + /// /// Gets a single Pull Request by number. /// diff --git a/Octokit.Reactive/Clients/ObservableIssuesClient.cs b/Octokit.Reactive/Clients/ObservableIssuesClient.cs index 2f2df7c915..033408d31c 100644 --- a/Octokit.Reactive/Clients/ObservableIssuesClient.cs +++ b/Octokit.Reactive/Clients/ObservableIssuesClient.cs @@ -48,6 +48,11 @@ public class ObservableIssuesClient : IObservableIssuesClient /// public IObservableIssueTimelineClient Timeline { get; private set; } + /// + /// Client for locking/unlocking conversation on an issue + /// + public IObservableLockUnlockClient LockUnlock { get; protected set; } + public ObservableIssuesClient(IGitHubClient client) { Ensure.ArgumentNotNull(client, nameof(client)); @@ -60,6 +65,7 @@ public ObservableIssuesClient(IGitHubClient client) Milestone = new ObservableMilestonesClient(client); Comment = new ObservableIssueCommentsClient(client); Timeline = new ObservableIssueTimelineClient(client); + LockUnlock = new ObservableLockUnlockClient(client); } /// @@ -473,58 +479,6 @@ public IObservable Update(long repositoryId, int number, IssueUpdate issu return _client.Update(repositoryId, number, issueUpdate).ToObservable(); } - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - /// The reason for locking the issue - public IObservable Lock(string owner, string name, int number, LockReason? lockReason = null) - { - Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); - Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); - - return _client.Lock(owner, name, number, lockReason).ToObservable(); - } - - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The Id of the repository - /// The issue number - /// The reason for locking the issue - public IObservable Lock(long repositoryId, int number, LockReason? lockReason = null) - { - return _client.Lock(repositoryId, number, lockReason).ToObservable(); - } - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - public IObservable Unlock(string owner, string name, int number) - { - Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); - Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); - - return _client.Unlock(owner, name, number).ToObservable(); - } - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The Id of the repository - /// The issue number - public IObservable Unlock(long repositoryId, int number) - { - return _client.Unlock(repositoryId, number).ToObservable(); - } + } } diff --git a/Octokit.Reactive/Clients/ObservableLockUnlockClient.cs b/Octokit.Reactive/Clients/ObservableLockUnlockClient.cs new file mode 100644 index 0000000000..3010741a8c --- /dev/null +++ b/Octokit.Reactive/Clients/ObservableLockUnlockClient.cs @@ -0,0 +1,75 @@ +using System; +using System.Reactive; +using System.Reactive.Threading.Tasks; + +namespace Octokit.Reactive +{ + /// + /// Client to manage locking/unlocking a conversation for an Issue or a Pull request + /// + public class ObservableLockUnlockClient : IObservableLockUnlockClient + { + readonly ILockUnlockClient _client; + + public ObservableLockUnlockClient(IGitHubClient client) + { + Ensure.ArgumentNotNull(client, nameof(client)); + + _client = client.Issue.LockUnlock; + } + + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The reason for locking the issue + public IObservable Lock(string owner, string name, int number, LockReason? lockReason = null) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + + return _client.Lock(owner, name, number, lockReason).ToObservable(); + } + + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The Id of the repository + /// The issue number + /// The reason for locking the issue + public IObservable Lock(long repositoryId, int number, LockReason? lockReason = null) + { + return _client.Lock(repositoryId, number, lockReason).ToObservable(); + } + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + public IObservable Unlock(string owner, string name, int number) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + + return _client.Unlock(owner, name, number).ToObservable(); + } + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The Id of the repository + /// The issue number + public IObservable Unlock(long repositoryId, int number) + { + return _client.Unlock(repositoryId, number).ToObservable(); + } + } +} diff --git a/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs b/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs index 9fbafba8ba..0f34376011 100644 --- a/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs +++ b/Octokit.Reactive/Clients/ObservablePullRequestsClient.cs @@ -30,6 +30,11 @@ public class ObservablePullRequestsClient : IObservablePullRequestsClient /// public IObservablePullRequestReviewRequestsClient ReviewRequest { get; private set; } + /// + /// Client for locking/unlocking a conversation on a pull request + /// + public IObservableLockUnlockClient LockUnlock { get; private set; } + public ObservablePullRequestsClient(IGitHubClient client) { Ensure.ArgumentNotNull(client, nameof(client)); @@ -39,6 +44,7 @@ public ObservablePullRequestsClient(IGitHubClient client) Review = new ObservablePullRequestReviewsClient(client); ReviewComment = new ObservablePullRequestReviewCommentsClient(client); ReviewRequest = new ObservablePullRequestReviewRequestsClient(client); + LockUnlock = new ObservableLockUnlockClient(client); } /// diff --git a/Octokit.Tests.Integration/Clients/IssuesClientTests.cs b/Octokit.Tests.Integration/Clients/IssuesClientTests.cs index 16bf28f76f..2a92b35b59 100644 --- a/Octokit.Tests.Integration/Clients/IssuesClientTests.cs +++ b/Octokit.Tests.Integration/Clients/IssuesClientTests.cs @@ -241,12 +241,12 @@ public async Task CanLockAndUnlockIssue() var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); Assert.False(issue.Locked); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var retrieved = await _issuesClient.Get(_context.RepositoryOwner, _context.RepositoryName, issue.Number); Assert.NotNull(retrieved); Assert.True(retrieved.Locked); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); retrieved = await _issuesClient.Get(_context.RepositoryOwner, _context.RepositoryName, issue.Number); Assert.NotNull(retrieved); Assert.False(retrieved.Locked); @@ -259,7 +259,7 @@ public async Task CanAccessActiveLockReason() var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); Assert.False(issue.Locked); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number, LockReason.OffTopic); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number, LockReason.OffTopic); var retrieved = await _issuesClient.Get(_context.RepositoryOwner, _context.RepositoryName, issue.Number); Assert.NotNull(retrieved); Assert.True(retrieved.Locked); @@ -273,12 +273,12 @@ public async Task CanLockAndUnlockIssueWithRepositoryId() var issue = await _issuesClient.Create(_context.Repository.Id, newIssue); Assert.False(issue.Locked); - await _issuesClient.Lock(_context.Repository.Id, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.Repository.Id, issue.Number); var retrieved = await _issuesClient.Get(_context.Repository.Id, issue.Number); Assert.NotNull(retrieved); Assert.True(retrieved.Locked); - await _issuesClient.Unlock(_context.Repository.Id, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.Repository.Id, issue.Number); retrieved = await _issuesClient.Get(_context.Repository.Id, issue.Number); Assert.NotNull(retrieved); Assert.False(retrieved.Locked); diff --git a/Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs b/Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs index 9daa2834fd..a223d65e60 100644 --- a/Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/IssuesEventsClientTests.cs @@ -63,9 +63,9 @@ public async Task ReturnsCorrectCountOfEventInfosWithoutStart() { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -83,9 +83,9 @@ public async Task ReturnsCorrectCountOfEventInfosWithoutStartWithRepositoryId() { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -103,9 +103,9 @@ public async Task ReturnsCorrectCountOfEventInfosWithStart() { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -124,9 +124,9 @@ public async Task ReturnsCorrectCountOfEventInfosWithStartWithRepositoryId() { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -145,9 +145,9 @@ public async Task ReturnsDistinctEventInfosBasedOnStartPage() { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var startOptions = new ApiOptions { @@ -174,9 +174,9 @@ public async Task ReturnsDistinctEventInfosBasedOnStartPageWithRepositoryId() { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var startOptions = new ApiOptions { @@ -259,9 +259,9 @@ public async Task ReturnsCorrectCountOfIssueEventsWithoutStart() { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -279,9 +279,9 @@ public async Task ReturnsCorrectCountOfIssueEventsWithoutStartWithRepositoryId() { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -299,9 +299,9 @@ public async Task ReturnsCorrectCountOfIssueEventsWithStart() { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -320,9 +320,9 @@ public async Task ReturnsCorrectCountOfIssueEventsWithStartWithRepositoryId() { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var options = new ApiOptions { @@ -341,9 +341,9 @@ public async Task ReturnsDistinctIssueEventsBasedOnStartPage() { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var startOptions = new ApiOptions { @@ -370,9 +370,9 @@ public async Task ReturnsDistinctIssueEventsBasedOnStartPageWithRepositoryId() { var newIssue = new NewIssue("issue 1") { Body = "A new unassigned issue" }; var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); - await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); + await _issuesClient.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); var startOptions = new ApiOptions { diff --git a/Octokit.Tests.Integration/Clients/PullRequestsClientTests.cs b/Octokit.Tests.Integration/Clients/PullRequestsClientTests.cs index 8985e28b32..d8c6cc410e 100644 --- a/Octokit.Tests.Integration/Clients/PullRequestsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/PullRequestsClientTests.cs @@ -653,6 +653,25 @@ public async Task CanClose() Assert.Equal(pullRequest.Body, result.Body); } + [IntegrationTest] + public async Task CanLockAndUnlock() + { + await CreateTheWorld(); + + var newPullRequest = new NewPullRequest("a pull request to lock", branchName, "main"); + var pullRequest = await _fixture.Create(Helper.UserName, _context.RepositoryName, newPullRequest); + + await _fixture.LockUnlock.Lock(Helper.UserName, _context.RepositoryName, pullRequest.Number, LockReason.OffTopic); + var retrived = await _fixture.Get(Helper.UserName, _context.RepositoryName, pullRequest.Number); + + Assert.Equal(retrived.ActiveLockReason, LockReason.OffTopic); + + await _fixture.LockUnlock.Unlock(Helper.UserName, _context.RepositoryName, pullRequest.Number); + var unlocked = await _fixture.Get(Helper.UserName, _context.RepositoryName, pullRequest.Number); + + Assert.Null(unlocked.ActiveLockReason); + } + [IntegrationTest] public async Task CanFindClosedPullRequest() { diff --git a/Octokit.Tests.Integration/Reactive/ObservableIssuesClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableIssuesClientTests.cs index bedb3d3791..146228e980 100644 --- a/Octokit.Tests.Integration/Reactive/ObservableIssuesClientTests.cs +++ b/Octokit.Tests.Integration/Reactive/ObservableIssuesClientTests.cs @@ -118,11 +118,11 @@ public async Task CanLockAndUnlockIssues() var createResult = await _client.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue); Assert.False(createResult.Locked); - await _client.Lock(_context.RepositoryOwner, _context.RepositoryName, createResult.Number); + await _client.LockUnlock.Lock(_context.RepositoryOwner, _context.RepositoryName, createResult.Number); var lockResult = await _client.Get(_context.RepositoryOwner, _context.RepositoryName, createResult.Number); Assert.True(lockResult.Locked); - await _client.Unlock(_context.RepositoryOwner, _context.RepositoryName, createResult.Number); + await _client.LockUnlock.Unlock(_context.RepositoryOwner, _context.RepositoryName, createResult.Number); var unlockIssueResult = await _client.Get(_context.RepositoryOwner, _context.RepositoryName, createResult.Number); Assert.False(unlockIssueResult.Locked); } diff --git a/Octokit.Tests/Clients/IssuesClientTests.cs b/Octokit.Tests/Clients/IssuesClientTests.cs index 5eaceb81d7..6cfc3e783f 100644 --- a/Octokit.Tests/Clients/IssuesClientTests.cs +++ b/Octokit.Tests/Clients/IssuesClientTests.cs @@ -478,7 +478,7 @@ public void PostsToCorrectUrl() var connection = Substitute.For(); var client = new IssuesClient(connection); - client.Lock("fake", "repo", 42); + client.LockUnlock.Lock("fake", "repo", 42); connection.Received().Put(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/42/lock"), Arg.Any()); } @@ -489,7 +489,7 @@ public void PostsToCorrectUrlWithRepositoryId() var connection = Substitute.For(); var client = new IssuesClient(connection); - client.Lock(1, 42); + client.LockUnlock.Lock(1, 42); connection.Received().Put(Arg.Is(u => u.ToString() == "repositories/1/issues/42/lock"), Arg.Any()); } @@ -500,11 +500,11 @@ public async Task EnsuresNonNullArguments() var connection = Substitute.For(); var client = new IssuesClient(connection); - await Assert.ThrowsAsync(() => client.Lock(null, "name", 1)); - await Assert.ThrowsAsync(() => client.Lock("owner", null, 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Lock(null, "name", 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Lock("owner", null, 1)); - await Assert.ThrowsAsync(() => client.Lock("", "name", 1)); - await Assert.ThrowsAsync(() => client.Lock("owner", "", 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Lock("", "name", 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Lock("owner", "", 1)); } } @@ -516,7 +516,7 @@ public void PostsToCorrectUrl() var connection = Substitute.For(); var client = new IssuesClient(connection); - client.Unlock("fake", "repo", 42); + client.LockUnlock.Unlock("fake", "repo", 42); connection.Received().Delete(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/42/lock")); } @@ -527,7 +527,7 @@ public void PostsToCorrectUrlWithApiOptions() var connection = Substitute.For(); var client = new IssuesClient(connection); - client.Unlock(1, 42); + client.LockUnlock.Unlock(1, 42); connection.Received().Delete(Arg.Is(u => u.ToString() == "repositories/1/issues/42/lock")); } @@ -538,11 +538,11 @@ public async Task EnsuresNonNullArguments() var connection = Substitute.For(); var client = new IssuesClient(connection); - await Assert.ThrowsAsync(() => client.Unlock(null, "name", 1)); - await Assert.ThrowsAsync(() => client.Unlock("owner", null, 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Unlock(null, "name", 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Unlock("owner", null, 1)); - await Assert.ThrowsAsync(() => client.Unlock("", "name", 1)); - await Assert.ThrowsAsync(() => client.Unlock("owner", "", 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Unlock("", "name", 1)); + await Assert.ThrowsAsync(() => client.LockUnlock.Unlock("owner", "", 1)); } } diff --git a/Octokit.Tests/Reactive/ObservableIssuesClientTests.cs b/Octokit.Tests/Reactive/ObservableIssuesClientTests.cs index 347f17ad9f..6245620aab 100644 --- a/Octokit.Tests/Reactive/ObservableIssuesClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableIssuesClientTests.cs @@ -645,9 +645,9 @@ public void LocksIssue() var gitHubClient = Substitute.For(); var client = new ObservableIssuesClient(gitHubClient); - client.Lock("fake", "repo", 42); + client.LockUnlock.Lock("fake", "repo", 42); - gitHubClient.Issue.Received().Lock("fake", "repo", 42); + gitHubClient.Issue.Received().LockUnlock.Lock("fake", "repo", 42); } [Fact] @@ -656,9 +656,9 @@ public void LocksIssueWithRepositoryId() var gitHubClient = Substitute.For(); var client = new ObservableIssuesClient(gitHubClient); - client.Lock(1, 42); + client.LockUnlock.Lock(1, 42); - gitHubClient.Issue.Received().Lock(1, 42); + gitHubClient.Issue.Received().LockUnlock.Lock(1, 42); } [Fact] @@ -667,11 +667,11 @@ public void EnsuresNonNullArguments() var gitHubClient = Substitute.For(); var client = new ObservableIssuesClient(gitHubClient); - Assert.Throws(() => client.Lock(null, "name", 42)); - Assert.Throws(() => client.Lock("owner", null, 42)); + Assert.Throws(() => client.LockUnlock.Lock(null, "name", 42)); + Assert.Throws(() => client.LockUnlock.Lock("owner", null, 42)); - Assert.Throws(() => client.Lock("", "name", 42)); - Assert.Throws(() => client.Lock("owner", "", 42)); + Assert.Throws(() => client.LockUnlock.Lock("", "name", 42)); + Assert.Throws(() => client.LockUnlock.Lock("owner", "", 42)); } } @@ -683,9 +683,9 @@ public void UnlocksIssue() var gitHubClient = Substitute.For(); var client = new ObservableIssuesClient(gitHubClient); - client.Unlock("fake", "repo", 42); + client.LockUnlock.Unlock("fake", "repo", 42); - gitHubClient.Issue.Received().Unlock("fake", "repo", 42); + gitHubClient.Issue.Received().LockUnlock.Unlock("fake", "repo", 42); } [Fact] @@ -694,9 +694,9 @@ public void UnlocksIssueWithRepositoryId() var gitHubClient = Substitute.For(); var client = new ObservableIssuesClient(gitHubClient); - client.Unlock(1, 42); + client.LockUnlock.Unlock(1, 42); - gitHubClient.Issue.Received().Unlock(1, 42); + gitHubClient.Issue.Received().LockUnlock.Unlock(1, 42); } [Fact] @@ -705,11 +705,11 @@ public void EnsuresNonNullArguments() var gitHubClient = Substitute.For(); var client = new ObservableIssuesClient(gitHubClient); - Assert.Throws(() => client.Unlock(null, "name", 42)); - Assert.Throws(() => client.Unlock("owner", null, 42)); + Assert.Throws(() => client.LockUnlock.Unlock(null, "name", 42)); + Assert.Throws(() => client.LockUnlock.Unlock("owner", null, 42)); - Assert.Throws(() => client.Unlock("", "name", 42)); - Assert.Throws(() => client.Unlock("owner", "", 42)); + Assert.Throws(() => client.LockUnlock.Unlock("", "name", 42)); + Assert.Throws(() => client.LockUnlock.Unlock("owner", "", 42)); } } diff --git a/Octokit/Clients/IIssuesClient.cs b/Octokit/Clients/IIssuesClient.cs index 63f5611d09..c8dc2c1acd 100644 --- a/Octokit/Clients/IIssuesClient.cs +++ b/Octokit/Clients/IIssuesClient.cs @@ -41,6 +41,8 @@ public interface IIssuesClient IIssueTimelineClient Timeline { get; } + ILockUnlockClient LockUnlock { get; } + /// /// Gets a single Issue by number. /// @@ -314,40 +316,5 @@ public interface IIssuesClient /// Task Update(long repositoryId, int number, IssueUpdate issueUpdate); - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - /// The reason for locking the issue - Task Lock(string owner, string name, int number, LockReason? lockReason = null); - - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The Id of the repository - /// The issue number - /// The reason for locking the issue - Task Lock(long repositoryId, int number, LockReason? lockReason = null); - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - Task Unlock(string owner, string name, int number); - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The Id of the repository - /// The issue number - Task Unlock(long repositoryId, int number); } } \ No newline at end of file diff --git a/Octokit/Clients/ILockUnlockClient.cs b/Octokit/Clients/ILockUnlockClient.cs new file mode 100644 index 0000000000..da5f6ff86c --- /dev/null +++ b/Octokit/Clients/ILockUnlockClient.cs @@ -0,0 +1,47 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + /// + /// Client to manage locking/unlocking a conversation for an Issue or a Pull request + /// + public interface ILockUnlockClient + { + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The reason for locking the issue + Task Lock(string owner, string name, int number, LockReason? lockReason = null); + + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The Id of the repository + /// The issue number + /// The reason for locking the issue + Task Lock(long repositoryId, int number, LockReason? lockReason = null); + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + Task Unlock(string owner, string name, int number); + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The Id of the repository + /// The issue number + Task Unlock(long repositoryId, int number); + + } +} diff --git a/Octokit/Clients/IPullRequestsClient.cs b/Octokit/Clients/IPullRequestsClient.cs index 639c9c4f7c..e35d22d6e7 100644 --- a/Octokit/Clients/IPullRequestsClient.cs +++ b/Octokit/Clients/IPullRequestsClient.cs @@ -28,6 +28,11 @@ public interface IPullRequestsClient /// IPullRequestReviewRequestsClient ReviewRequest { get; } + /// + /// Client for locking/unlocking a coversation on a pull request + /// + ILockUnlockClient LockUnlock { get; } + /// /// Get a pull request by number. /// diff --git a/Octokit/Clients/IssuesClient.cs b/Octokit/Clients/IssuesClient.cs index 508e6c2180..01c8c4d5fc 100644 --- a/Octokit/Clients/IssuesClient.cs +++ b/Octokit/Clients/IssuesClient.cs @@ -23,6 +23,7 @@ public IssuesClient(IApiConnection apiConnection) : base(apiConnection) Milestone = new MilestonesClient(apiConnection); Comment = new IssueCommentsClient(apiConnection); Timeline = new IssueTimelineClient(apiConnection); + LockUnlock = new LockUnlockClient(apiConnection); } /// @@ -57,6 +58,11 @@ public IssuesClient(IApiConnection apiConnection) : base(apiConnection) /// public IIssueTimelineClient Timeline { get; private set; } + /// + /// Client for locking and unlocking a conversation on a Issue or Pull request + /// + public ILockUnlockClient LockUnlock { get; private set; } + /// /// Gets a single Issue by number. /// @@ -491,64 +497,6 @@ public Task Update(long repositoryId, int number, IssueUpdate issueUpdate Ensure.ArgumentNotNull(issueUpdate, nameof(issueUpdate)); return ApiConnection.Patch(ApiUrls.Issue(repositoryId, number), issueUpdate); - } - - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - /// The reason for locking the issue - [ManualRoute("PUT", "/repos/{owner}/{repo}/issues/{issue_number}/lock")] - public Task Lock(string owner, string name, int number, LockReason? lockReason = null) - { - Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); - Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); - - return ApiConnection.Put(ApiUrls.IssueLock(owner, name, number), lockReason.HasValue ? new { LockReason = lockReason } : new object()); - } - - /// - /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue. - /// - /// https://developer.github.com/v3/issues/#lock-an-issue - /// The Id of the repository - /// The issue number - /// The reason for locking the issue - [ManualRoute("PUT", "/repositories/{id}/issues/{number}/lock")] - public Task Lock(long repositoryId, int number, LockReason? lockReason = null) - { - return ApiConnection.Put(ApiUrls.IssueLock(repositoryId, number), lockReason.HasValue ? new { LockReaons = lockReason } : new object()); - } - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The owner of the repository - /// The name of the repository - /// The issue number - [ManualRoute("DELETE", "/repos/{owner}/{repo}/issues/{issue_number}/lock")] - public Task Unlock(string owner, string name, int number) - { - Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); - Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); - - return ApiConnection.Delete(ApiUrls.IssueLock(owner, name, number)); - } - - /// - /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue. - /// - /// https://developer.github.com/v3/issues/#unlock-an-issue - /// The Id of the repository - /// The issue number - [ManualRoute("DELETE", "/repositories/{id}/issues/{number}/lock")] - public Task Unlock(long repositoryId, int number) - { - return ApiConnection.Delete(ApiUrls.IssueLock(repositoryId, number)); - } + } } } diff --git a/Octokit/Clients/LockUnlockClient.cs b/Octokit/Clients/LockUnlockClient.cs new file mode 100644 index 0000000000..4acf702da3 --- /dev/null +++ b/Octokit/Clients/LockUnlockClient.cs @@ -0,0 +1,76 @@ +using System.Threading.Tasks; + +namespace Octokit +{ + /// + /// Client to manage locking/unlocking a conversation for an Issue or a Pull request + /// + public class LockUnlockClient : ApiClient, ILockUnlockClient + { + /// + /// Instantiates a new GitHub Issue Lock API client. + /// + /// An API connection + public LockUnlockClient(IApiConnection apiConnection) : base(apiConnection) + { + + } + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + /// The reason for locking the issue + [ManualRoute("PUT", "/repos/{owner}/{repo}/issues/{issue_number}/lock")] + public Task Lock(string owner, string name, int number, LockReason? lockReason = null) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + + return ApiConnection.Put(ApiUrls.IssueLock(owner, name, number), lockReason.HasValue ? new { LockReason = lockReason } : new object()); + } + + /// + /// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#lock-an-issue + /// The Id of the repository + /// The issue number + /// The reason for locking the issue + [ManualRoute("PUT", "/repositories/{id}/issues/{number}/lock")] + public Task Lock(long repositoryId, int number, LockReason? lockReason = null) + { + return ApiConnection.Put(ApiUrls.IssueLock(repositoryId, number), lockReason.HasValue ? new { LockReaons = lockReason } : new object()); + } + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The owner of the repository + /// The name of the repository + /// The issue number + [ManualRoute("DELETE", "/repos/{owner}/{repo}/issues/{issue_number}/lock")] + public Task Unlock(string owner, string name, int number) + { + Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); + Ensure.ArgumentNotNullOrEmptyString(name, nameof(name)); + + return ApiConnection.Delete(ApiUrls.IssueLock(owner, name, number)); + } + + /// + /// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue or pull request's conversation. + /// + /// https://developer.github.com/v3/issues/#unlock-an-issue + /// The Id of the repository + /// The issue number + [ManualRoute("DELETE", "/repositories/{id}/issues/{number}/lock")] + public Task Unlock(long repositoryId, int number) + { + return ApiConnection.Delete(ApiUrls.IssueLock(repositoryId, number)); + } + } +} diff --git a/Octokit/Clients/PullRequestsClient.cs b/Octokit/Clients/PullRequestsClient.cs index 07c63b9748..34bf1cda62 100644 --- a/Octokit/Clients/PullRequestsClient.cs +++ b/Octokit/Clients/PullRequestsClient.cs @@ -18,6 +18,7 @@ public PullRequestsClient(IApiConnection apiConnection) : base(apiConnection) Review = new PullRequestReviewsClient(apiConnection); ReviewComment = new PullRequestReviewCommentsClient(apiConnection); ReviewRequest = new PullRequestReviewRequestsClient(apiConnection); + LockUnlock = new LockUnlockClient(apiConnection); } /// @@ -35,6 +36,11 @@ public PullRequestsClient(IApiConnection apiConnection) : base(apiConnection) /// public IPullRequestReviewRequestsClient ReviewRequest { get; set; } + /// + /// Client for locking/unlocking a coversation on a pull request + /// + public ILockUnlockClient LockUnlock { get; set; } + /// /// Get a pull request by number. /// diff --git a/Octokit/Models/Response/PullRequest.cs b/Octokit/Models/Response/PullRequest.cs index 9ca99408ad..e7690c7d44 100644 --- a/Octokit/Models/Response/PullRequest.cs +++ b/Octokit/Models/Response/PullRequest.cs @@ -16,7 +16,7 @@ public PullRequest(int number) Number = number; } - public PullRequest(long id, string nodeId, string url, string htmlUrl, string diffUrl, string patchUrl, string issueUrl, string statusesUrl, int number, ItemState state, string title, string body, DateTimeOffset createdAt, DateTimeOffset updatedAt, DateTimeOffset? closedAt, DateTimeOffset? mergedAt, GitReference head, GitReference @base, User user, User assignee, IReadOnlyList assignees, bool draft, bool? mergeable, MergeableState? mergeableState, User mergedBy, string mergeCommitSha, int comments, int commits, int additions, int deletions, int changedFiles, Milestone milestone, bool locked, bool? maintainerCanModify, IReadOnlyList requestedReviewers, IReadOnlyList requestedTeams, IReadOnlyList