Implement Lock/Unlock Issue

This commit is contained in:
Prayank Mathur
2016-03-25 11:26:37 +05:30
parent f354d1bf00
commit 171b3c520a
9 changed files with 265 additions and 8 deletions

View File

@@ -1,5 +1,6 @@
using System; using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Reactive;
namespace Octokit.Reactive namespace Octokit.Reactive
{ {
@@ -156,5 +157,25 @@ namespace Octokit.Reactive
/// </param> /// </param>
/// <returns></returns> /// <returns></returns>
IObservable<Issue> Update(string owner, string name, int number, IssueUpdate issueUpdate); IObservable<Issue> Update(string owner, string name, int number, IssueUpdate issueUpdate);
/// <summary>
/// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue.
/// </summary>
/// <remarks>https://developer.github.com/v3/issues/#lock-an-issue</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The issue number</param>
/// <returns></returns>
IObservable<Unit> LockIssue(string owner, string name, int number);
/// <summary>
/// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue.
/// </summary>
/// <remarks>https://developer.github.com/v3/issues/#unlock-an-issue</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The issue number</param>
/// <returns></returns>
IObservable<Unit> UnlockIssue(string owner, string name, int number);
} }
} }

View File

@@ -1,6 +1,7 @@
using System; using System;
using System.Reactive.Threading.Tasks; using System.Reactive.Threading.Tasks;
using Octokit.Reactive.Internal; using Octokit.Reactive.Internal;
using System.Reactive;
namespace Octokit.Reactive namespace Octokit.Reactive
{ {
@@ -222,5 +223,37 @@ namespace Octokit.Reactive
return _client.Update(owner, name, number, issueUpdate).ToObservable(); return _client.Update(owner, name, number, issueUpdate).ToObservable();
} }
/// <summary>
/// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue.
/// </summary>
/// <remarks>https://developer.github.com/v3/issues/#lock-an-issue</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The issue number</param>
/// <returns></returns>
public IObservable<Unit> LockIssue(string owner, string name, int number)
{
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Ensure.ArgumentNotNullOrEmptyString(name, "name");
return _client.LockIssue(owner, name, number).ToObservable();
}
/// <summary>
/// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue.
/// </summary>
/// <remarks>https://developer.github.com/v3/issues/#unlock-an-issue</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The issue number</param>
/// <returns></returns>
public IObservable<Unit> UnlockIssue(string owner, string name, int number)
{
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Ensure.ArgumentNotNullOrEmptyString(name, "name");
return _client.UnlockIssue(owner, name, number).ToObservable();
}
} }
} }

View File

@@ -62,6 +62,26 @@ public class IssuesClientTests : IDisposable
} }
[IntegrationTest] [IntegrationTest]
public async Task CanLockAndUnlockIssue()
{
var newIssue = new NewIssue("a test issue") { Body = "A new unassigned issue" };
var issue = await _issuesClient.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue);
var retrieved = await _issuesClient.Get(_context.RepositoryOwner, _context.RepositoryName, issue.Number);
Assert.Equal(false, issue.Locked);
await _issuesClient.LockIssue(_context.RepositoryOwner, _context.RepositoryName, issue.Number);
retrieved = await _issuesClient.Get(_context.RepositoryOwner, _context.RepositoryName, issue.Number);
Assert.NotNull(retrieved);
Assert.Equal(true, issue.Locked);
await _issuesClient.UnlockIssue(_context.RepositoryOwner, _context.RepositoryName, issue.Number);
retrieved = await _issuesClient.Get(_context.RepositoryOwner, _context.RepositoryName, issue.Number);
Assert.NotNull(retrieved);
Assert.Equal(false, issue.Locked);
}
[IntegrationTest]
public async Task CanListOpenIssuesWithDefaultSort() public async Task CanListOpenIssuesWithDefaultSort()
{ {
var newIssue1 = new NewIssue("A test issue1") { Body = "A new unassigned issue" }; var newIssue1 = new NewIssue("A test issue1") { Body = "A new unassigned issue" };

View File

@@ -72,6 +72,23 @@ public class ObservableIssuesClientTests : IDisposable
Assert.Equal("Modified integration test issue", updateResult.Title); Assert.Equal("Modified integration test issue", updateResult.Title);
} }
[IntegrationTest]
public async Task CanLockAndUnlockIssues()
{
var newIssue = new NewIssue("Integration Test Issue");
var createResult = await _client.Create(_context.RepositoryOwner, _context.RepositoryName, newIssue);
Assert.Equal(false, createResult.Locked);
await _client.LockIssue(_context.RepositoryOwner, _context.RepositoryName, createResult.Number);
var lockResult = await _client.Get(_context.RepositoryOwner, _context.RepositoryName, createResult.Number);
Assert.Equal(true, lockResult.Locked);
await _client.UnlockIssue(_context.RepositoryOwner, _context.RepositoryName, createResult.Number);
var unlockIssueResult = await _client.Get(_context.RepositoryOwner, _context.RepositoryName, createResult.Number);
Assert.Equal(false, unlockIssueResult.Locked);
}
public void Dispose() public void Dispose()
{ {
_context.Dispose(); _context.Dispose();

View File

@@ -185,6 +185,58 @@ namespace Octokit.Tests.Clients
} }
} }
public class TheLockIssueMethod
{
[Fact]
public void PostsToCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new IssuesClient(connection);
client.LockIssue("fake", "repo", 42);
connection.Received().Put(Arg.Is<Uri>(u => u.ToString() == "repos/fake/repo/issues/42/lock"));
}
[Fact]
public async Task EnsuresArgumentsNotNull()
{
var connection = Substitute.For<IApiConnection>();
var client = new IssuesClient(connection);
await Assert.ThrowsAsync<ArgumentNullException>(() => client.LockIssue(null, "name", 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.LockIssue("", "name", 1));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.LockIssue("owner", null, 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.LockIssue("owner", "", 1));
}
}
public class TheUnlockIssueMethod
{
[Fact]
public void PostsToCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new IssuesClient(connection);
client.UnlockIssue("fake", "repo", 42);
connection.Received().Delete(Arg.Is<Uri>(u => u.ToString() == "repos/fake/repo/issues/42/lock"));
}
[Fact]
public async Task EnsuresArgumentsNotNull()
{
var connection = Substitute.For<IApiConnection>();
var client = new IssuesClient(connection);
await Assert.ThrowsAsync<ArgumentNullException>(() => client.UnlockIssue(null, "name", 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.UnlockIssue("", "name", 1));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.UnlockIssue("owner", null, 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.UnlockIssue("owner", "", 1));
}
}
public class TheCtor public class TheCtor
{ {
[Fact] [Fact]

View File

@@ -329,11 +329,61 @@ public class ObservableIssuesClientTests
var gitHubClient = Substitute.For<IGitHubClient>(); var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservableIssuesClient(gitHubClient); var client = new ObservableIssuesClient(gitHubClient);
Assert.Throws<ArgumentNullException>(() => client.Create(null, "name", new NewIssue("title"))); Assert.Throws<ArgumentNullException>(() => client.Update(null, "name", 42, new IssueUpdate()));
Assert.Throws<ArgumentException>(() => client.Create("", "name", new NewIssue("x"))); Assert.Throws<ArgumentException>(() => client.Update("", "name", 42, new IssueUpdate()));
Assert.Throws<ArgumentNullException>(() => client.Create("owner", null, new NewIssue("x"))); Assert.Throws<ArgumentNullException>(() => client.Update("owner", null, 42, new IssueUpdate()));
Assert.Throws<ArgumentException>(() => client.Create("owner", "", new NewIssue("x"))); Assert.Throws<ArgumentException>(() => client.Update("owner", "", 42, new IssueUpdate()));
Assert.Throws<ArgumentNullException>(() => client.Create("owner", "name", null)); Assert.Throws<ArgumentNullException>(() => client.Update("owner", "name", 42, null));
}
}
public class TheLockIssueMethod
{
[Fact]
public void LockIssue()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservableIssuesClient(gitHubClient);
client.LockIssue("fake", "repo", 42);
gitHubClient.Issue.Received().LockIssue("fake", "repo", 42);
}
[Fact]
public void EnsuresArgumentsNotNull()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservableIssuesClient(gitHubClient);
Assert.Throws<ArgumentNullException>(() => client.LockIssue(null, "name", 42));
Assert.Throws<ArgumentException>(() => client.LockIssue("", "name", 42));
Assert.Throws<ArgumentNullException>(() => client.LockIssue("owner", null, 42));
Assert.Throws<ArgumentException>(() => client.LockIssue("owner", "", 42));
}
}
public class TheUnlockIssueMethod
{
[Fact]
public void UnlockIssue()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservableIssuesClient(gitHubClient);
client.UnlockIssue("fake", "repo", 42);
gitHubClient.Issue.Received().UnlockIssue("fake", "repo", 42);
}
[Fact]
public void EnsuresArgumentsNotNull()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservableIssuesClient(gitHubClient);
Assert.Throws<ArgumentNullException>(() => client.UnlockIssue(null, "name", 42));
Assert.Throws<ArgumentException>(() => client.UnlockIssue("", "name", 42));
Assert.Throws<ArgumentNullException>(() => client.UnlockIssue("owner", null, 42));
Assert.Throws<ArgumentException>(() => client.UnlockIssue("owner", "", 42));
} }
} }

View File

@@ -152,10 +152,10 @@ namespace Octokit
Task<Issue> Create(string owner, string name, NewIssue newIssue); Task<Issue> Create(string owner, string name, NewIssue newIssue);
/// <summary> /// <summary>
/// Creates an issue for the specified repository. Any user with pull access to a repository can create an /// Updates an issue for the specified repository. Any user with pull access to a repository can update an
/// issue. /// issue.
/// </summary> /// </summary>
/// <remarks>http://developer.github.com/v3/issues/#create-an-issue</remarks> /// <remarks>http://developer.github.com/v3/issues/#edit-an-issue</remarks>
/// <param name="owner">The owner of the repository</param> /// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param> /// <param name="name">The name of the repository</param>
/// <param name="number">The issue number</param> /// <param name="number">The issue number</param>
@@ -163,5 +163,25 @@ namespace Octokit
/// </param> /// </param>
/// <returns></returns> /// <returns></returns>
Task<Issue> Update(string owner, string name, int number, IssueUpdate issueUpdate); Task<Issue> Update(string owner, string name, int number, IssueUpdate issueUpdate);
/// <summary>
/// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue.
/// </summary>
/// <remarks>https://developer.github.com/v3/issues/#lock-an-issue</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The issue number</param>
/// <returns></returns>
Task LockIssue(string owner, string name, int number);
/// <summary>
/// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue.
/// </summary>
/// <remarks>https://developer.github.com/v3/issues/#unlock-an-issue</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The issue number</param>
/// <returns></returns>
Task UnlockIssue(string owner, string name, int number);
} }
} }

View File

@@ -225,5 +225,37 @@ namespace Octokit
return ApiConnection.Patch<Issue>(ApiUrls.Issue(owner, name, number), issueUpdate); return ApiConnection.Patch<Issue>(ApiUrls.Issue(owner, name, number), issueUpdate);
} }
/// <summary>
/// Locks an issue for the specified repository. Issue owners and users with push access can lock an issue.
/// </summary>
/// <remarks>https://developer.github.com/v3/issues/#lock-an-issue</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The issue number</param>
/// <returns></returns>
public Task LockIssue(string owner, string name, int number)
{
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Ensure.ArgumentNotNullOrEmptyString(name, "name");
return ApiConnection.Put(ApiUrls.IssueLock(owner, name, number));
}
/// <summary>
/// Unlocks an issue for the specified repository. Issue owners and users with push access can unlock an issue.
/// </summary>
/// <remarks>https://developer.github.com/v3/issues/#unlock-an-issue</remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The issue number</param>
/// <returns></returns>
public Task UnlockIssue(string owner, string name, int number)
{
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Ensure.ArgumentNotNullOrEmptyString(name, "name");
return ApiConnection.Delete(ApiUrls.IssueLock(owner, name, number));
}
} }
} }

View File

@@ -294,6 +294,18 @@ namespace Octokit
return "repos/{0}/{1}/issues/{2}".FormatUri(owner, name, number); return "repos/{0}/{1}/issues/{2}".FormatUri(owner, name, number);
} }
/// <summary>
/// Returns the <see cref="Uri"/> for the specified issue to be locked/unlocked.
/// </summary>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="number">The issue number</param>
/// <returns></returns>
public static Uri IssueLock(string owner, string name, int number)
{
return "repos/{0}/{1}/issues/{2}/lock".FormatUri(owner, name, number);
}
/// <summary> /// <summary>
/// Returns the <see cref="Uri"/> for the comments for all issues in a specific repo. /// Returns the <see cref="Uri"/> for the comments for all issues in a specific repo.
/// </summary> /// </summary>