diff --git a/Octokit.Tests.Integration/Clients/IssuesLabelsClientTests.cs b/Octokit.Tests.Integration/Clients/IssuesLabelsClientTests.cs
new file mode 100644
index 00000000..c4e49d36
--- /dev/null
+++ b/Octokit.Tests.Integration/Clients/IssuesLabelsClientTests.cs
@@ -0,0 +1,101 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Net.Http.Headers;
+using System.Threading;
+using System.Threading.Tasks;
+using Octokit;
+using Octokit.Tests.Integration;
+using Xunit;
+
+public class IssuesLabelsClientTests
+{
+ readonly IGitHubClient _gitHubClient;
+ readonly IIssuesLabelsClient _issuesLabelsClient;
+ readonly IIssuesClient _issuesClient;
+ readonly Repository _repository;
+ readonly string _repositoryOwner;
+ readonly string _repositoryName;
+
+ public IssuesLabelsClientTests()
+ {
+ _gitHubClient = new GitHubClient(new ProductHeaderValue("OctokitTests"))
+ {
+ Credentials = Helper.Credentials
+ };
+ _issuesLabelsClient= _gitHubClient.Issue.Labels;
+ _issuesClient = _gitHubClient.Issue;
+ var repoName = Helper.MakeNameWithTimestamp("public-repo");
+
+ _repository = _gitHubClient.Repository.Create(new NewRepository { Name = repoName }).Result;
+ _repositoryOwner = _repository.Owner.Login;
+ _repositoryName = _repository.Name;
+ }
+
+ [IntegrationTest]
+ public async Task CanListLabelsForAnIssue()
+ {
+ var newIssue = new NewIssue("A test issue") { Body = "A new unassigned issue" };
+ var newLabel = new NewLabel("test label", "#FFFFFF");
+
+ var label = _issuesLabelsClient.Create(_repositoryOwner, _repository.Name, newLabel).Result;
+ var issue = await _issuesClient.Create(_repositoryOwner, _repositoryName, newIssue);
+
+ var issueLabelsInfo = await _issuesLabelsClient.GetForIssue(_repositoryOwner, _repositoryName, issue.Number);
+ Assert.Empty(issueLabelsInfo);
+
+ var issueUpdate = new IssueUpdate();
+ issueUpdate.Labels.Add(label.Name);
+ var updated = _issuesClient.Update(_repositoryOwner, _repository.Name, issue.Number, issueUpdate)
+ .Result;
+ Assert.NotNull(updated);
+ issueLabelsInfo = await _issuesLabelsClient.GetForIssue(_repositoryOwner, _repositoryName, issue.Number);
+
+ Assert.Equal(1, issueLabelsInfo.Count);
+ Assert.Equal(newLabel.Color, issueLabelsInfo[0].Color);
+ }
+
+ [IntegrationTest]
+ public async Task CanListIssueLabelsForARepository()
+ {
+ // create 2 new issues
+ var newIssue1 = new NewIssue("A test issue1") { Body = "Everything's coming up Millhouse" };
+ var newLabel1 = new NewLabel("test label 1", "#FFFFFF");
+ var newLabel2 = new NewLabel("test label 2", "#FFFFFF");
+
+ var issue1 = await _issuesClient.Create(_repositoryOwner, _repository.Name, newIssue1);
+
+ var label1 = _issuesLabelsClient.Create(_repositoryOwner, _repository.Name, newLabel1).Result;
+ var label2 = _issuesLabelsClient.Create(_repositoryOwner, _repository.Name, newLabel2).Result;
+
+ // close and open issue1
+ var issueUpdate = new IssueUpdate();
+ issueUpdate.Labels.Add(label1.Name);
+ issueUpdate.Labels.Add(label2.Name);
+ var updated1 = _issuesClient.Update(_repositoryOwner, _repository.Name, issue1.Number, issueUpdate)
+ .Result;
+ Assert.NotNull(updated1);
+
+ var issueLabels = await _issuesLabelsClient.GetForRepository(_repositoryOwner, _repositoryName);
+
+ Assert.Equal(2, issueLabels.Count);
+ }
+
+ [IntegrationTest]
+ public async Task CanRetrieveIssueLabelByName()
+ {
+ var newLabel = new NewLabel("test label 1b", "#FFFFFF");
+ var label = _issuesLabelsClient.Create(_repositoryOwner, _repository.Name, newLabel).Result;
+ Assert.NotNull(label);
+
+ var issueLabelLookupByName = await _issuesLabelsClient.Get(_repositoryOwner, _repositoryName, label.Name);
+
+ Assert.Equal(label.Name, issueLabelLookupByName.Name);
+ Assert.Equal(label.Color, issueLabelLookupByName.Color);
+ }
+
+ public void Dispose()
+ {
+ Helper.DeleteRepo(_repository);
+ }
+}
diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
index 5c1824f2..53447816 100644
--- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
+++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
@@ -61,6 +61,7 @@
+
diff --git a/Octokit.Tests/Clients/IssuesLabelsClientTests.cs b/Octokit.Tests/Clients/IssuesLabelsClientTests.cs
new file mode 100644
index 00000000..74ffbd53
--- /dev/null
+++ b/Octokit.Tests/Clients/IssuesLabelsClientTests.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Threading.Tasks;
+using NSubstitute;
+using Octokit.Tests.Helpers;
+using Xunit;
+
+namespace Octokit.Tests.Clients
+{
+ public class IssuesLabelsClientTests
+ {
+ public class TheGetForIssueMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new IssuesLabelsClient(connection);
+
+ await client.GetForIssue("fake", "repo", 42);
+
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/42/labels"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new IssuesLabelsClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Get(null, "name", "label"));
+ await AssertEx.Throws(async () => await client.Get("owner", null, "label"));
+ await AssertEx.Throws(async () => await client.Get("owner", "name", null));
+ }
+ }
+
+ public class TheGetForRepositoryMethod
+ {
+ [Fact]
+ public async Task RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new IssuesLabelsClient(connection);
+
+ await client.GetForRepository("fake", "repo");
+
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/labels"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new IssuesLabelsClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Get(null, "name", "label"));
+ await AssertEx.Throws(async () => await client.Get("owner", null, "label"));
+ await AssertEx.Throws(async () => await client.Get("owner", "name", null));
+ }
+ }
+
+ public class TheGetMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new IssuesLabelsClient(connection);
+
+ client.Get("fake", "repo", "label");
+
+ connection.Received().Get(Arg.Is(u => u.ToString() == "repos/fake/repo/issues/labels/label"),
+ null);
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new IssuesLabelsClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Get(null, "name", "label"));
+ await AssertEx.Throws(async () => await client.Get("owner", null, "label"));
+ }
+ }
+ }
+}
diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj
index ab7436b8..8d3989be 100644
--- a/Octokit.Tests/Octokit.Tests.csproj
+++ b/Octokit.Tests/Octokit.Tests.csproj
@@ -65,6 +65,7 @@
+
diff --git a/Octokit/Clients/IIssuesClient.cs b/Octokit/Clients/IIssuesClient.cs
index c5110bd4..ba5c7247 100644
--- a/Octokit/Clients/IIssuesClient.cs
+++ b/Octokit/Clients/IIssuesClient.cs
@@ -20,6 +20,11 @@ namespace Octokit
///
IMilestonesClient Milestone { get; }
+ ///
+ /// Client for managing labels.
+ ///
+ IIssuesLabelsClient Labels { get; }
+
///
/// Client for managing comments.
///
diff --git a/Octokit/Clients/IIssuesLabelsClient.cs b/Octokit/Clients/IIssuesLabelsClient.cs
index c47fdea6..a2edcc17 100644
--- a/Octokit/Clients/IIssuesLabelsClient.cs
+++ b/Octokit/Clients/IIssuesLabelsClient.cs
@@ -6,22 +6,39 @@ namespace Octokit
{
public interface IIssuesLabelsClient
{
+ ///
+ /// Gets all labels for the issue.
+ ///
+ ///
+ /// See the API documentation for more information.
+ ///
+ /// The owner of the repository
+ /// The name of the repository
+ /// The number of the issue
+ /// The list of labels
+ Task> GetForIssue(string owner, string repo, int number);
+
///
/// Gets all labels for the repository.
///
///
- /// http://developer.github.com/v3/repos/:owner/:repo/labels/:name
+ /// See the API documentation for more information.
///
- ///
+ /// The owner of the repository
+ /// The name of the repository
+ /// The list of labels
Task> GetForRepository(string owner, string repo);
///
/// Gets a single Label by name.
///
///
- /// http://developer.github.com/v3/repos/:owner/:repo/labels/:name
+ /// See the API documentation for more information.
///
- ///
+ /// The owner of the repository
+ /// The name of the repository
+ /// The name of the label
+ /// The label
[SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get",
Justification = "Method makes a network request")]
Task