-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implemented Lock/Unlock Functionality for Issues #1185
Changes from 4 commits
171b3c5
2c167bf
8ff574a
63bd122
55f4e72
5173ade
8e49f04
7324039
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,6 +61,25 @@ public async Task CanCreateRetrieveAndCloseIssue() | |
} | ||
|
||
[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.False(issue.Locked); | ||
|
||
await _issuesClient.Lock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); | ||
retrieved = await _issuesClient.Get(_context.RepositoryOwner, _context.RepositoryName, issue.Number); | ||
Assert.NotNull(retrieved); | ||
Assert.True(issue.Locked); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should be checking |
||
|
||
await _issuesClient.Unlock(_context.RepositoryOwner, _context.RepositoryName, issue.Number); | ||
retrieved = await _issuesClient.Get(_context.RepositoryOwner, _context.RepositoryName, issue.Number); | ||
Assert.NotNull(retrieved); | ||
Assert.False(issue.Locked); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
} | ||
|
||
[IntegrationTest] | ||
public async Task CanListOpenIssuesWithDefaultSort() | ||
{ | ||
var newIssue1 = new NewIssue("A test issue1") { Body = "A new unassigned issue" }; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -337,6 +337,56 @@ public void EnsuresArgumentsNotNull() | |
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
} | ||
|
||
public class TheLockIssueMethod | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this now should be "TheLockMethod" |
||
{ | ||
[Fact] | ||
public void LockIssue() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "LocksIssue" |
||
{ | ||
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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "TheUnlockMethod" |
||
{ | ||
[Fact] | ||
public void UnlockIssue() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wording for the unit tests should read TheBlahMethod....DoesSomething So... (note Unlocks rather than Unlock) |
||
{ | ||
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)); | ||
} | ||
} | ||
|
||
public class TheCtor | ||
{ | ||
[Fact] | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -152,16 +152,36 @@ public interface IIssuesClient | |
Task<Issue> Create(string owner, string name, NewIssue newIssue); | ||
|
||
/// <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. | ||
/// </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="name">The name of the repository</param> | ||
/// <param name="number">The issue number</param> | ||
/// <param name="issueUpdate">An <see cref="IssueUpdate"/> instance describing the changes to make to the issue | ||
/// </param> | ||
/// <returns></returns> | ||
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<Issue> Lock(string owner, string name, int number); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This endpoint doesn't return any data, so it needs to return a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given that the API does return a HTTP 204 NoContent response when "succesful" the way ive seen this implemented in octokit in other places (eg OrganizationMembers.Publicize()) is that the Octokit call returns a Task then internally it calls the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 |
||
|
||
/// <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 Unlock(string owner, string name, int number); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -225,5 +225,37 @@ public Task<Issue> Update(string owner, string name, int number, IssueUpdate iss | |
|
||
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<Issue> Lock(string owner, string name, int number) | ||
{ | ||
Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); | ||
Ensure.ArgumentNotNullOrEmptyString(name, "name"); | ||
|
||
return ApiConnection.Put<Issue>(ApiUrls.IssueLock(owner, name, number), AcceptHeaders.IssueLockingUnlockingApiPreview); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not quite the right overload, and sadly This works for me: return ApiConnection.Put<Issue>(ApiUrls.IssueLock(owner, name, number), new object(), null, AcceptHeaders.IssueLockingUnlockingApiPreview); |
||
} | ||
|
||
/// <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 Unlock(string owner, string name, int number) | ||
{ | ||
Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); | ||
Ensure.ArgumentNotNullOrEmptyString(name, "name"); | ||
|
||
return ApiConnection.Delete(ApiUrls.IssueLock(owner, name, number), AcceptHeaders.IssueLockingUnlockingApiPreview); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't the right overload, and we don't have an equivalent that let's us specify an We should add this to Task DeleteWith(Uri uri, string accepts); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The inconsistency of overloads for Post Put Delete and Get makes me 😢 too! Rather than introduce the first/only occurence of this "{verb}With" terminology to get around the overload collisions, perhaps in this case we could just go with adding an overload for
Or alternatively, perhaps the "With" terminology is a good idea, and we could (on a separate PR) introduce a whole new set of "With" overloads, and start to obsolete the old ones eg
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don't think we can pass |
||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,9 @@ public static class AcceptHeaders | |
|
||
public const string StarCreationTimestamps = "application/vnd.github.v3.star+json"; | ||
|
||
public const string IssueLockingUnlockingApiPreview = "application/vnd.github.the-key-preview+json"; | ||
|
||
public const string CommitReferenceSha1Preview = "application/vnd.github.chitauri-preview+sha"; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra whitespace line introduced here :) |
||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, you should be returned the updated
Issue
fromLock
andUnlock
here - to simplify this test (and do less network calls) you could assign this returned value toretrieved
...EDIT: nevermind, I didn't understand the API correctly. Disregard this, but we need to change the method signature for
Lock
.