diff --git a/Octokit.Reactive/Clients/IObservableUserKeysClient.cs b/Octokit.Reactive/Clients/IObservableUserKeysClient.cs
index a26686e0..bf196a00 100644
--- a/Octokit.Reactive/Clients/IObservableUserKeysClient.cs
+++ b/Octokit.Reactive/Clients/IObservableUserKeysClient.cs
@@ -1,4 +1,6 @@
using System;
+using System.Diagnostics.CodeAnalysis;
+using System.Reactive;
namespace Octokit.Reactive
{
@@ -16,7 +18,7 @@ namespace Octokit.Reactive
///
/// https://developer.github.com/v3/users/keys/#list-your-public-keys
///
- /// The s for the authenticated user.
+ ///
IObservable GetAll();
///
@@ -25,7 +27,38 @@ namespace Octokit.Reactive
///
/// https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user
///
- /// The s for the user.
+ ///
IObservable GetAll(string userName);
+
+ ///
+ /// Retrieves the for the specified id.
+ ///
+ ///
+ /// https://developer.github.com/v3/users/keys/#get-a-single-public-key
+ ///
+ /// The ID of the SSH key
+ ///
+ [SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get")]
+ IObservable Get(int id);
+
+ ///
+ /// Create a public key .
+ ///
+ ///
+ /// https://developer.github.com/v3/users/keys/#create-a-public-key
+ ///
+ /// The SSH Key contents
+ ///
+ IObservable Create(NewPublicKey newKey);
+
+ ///
+ /// Delete a public key.
+ ///
+ ///
+ /// https://developer.github.com/v3/users/keys/#delete-a-public-key
+ ///
+ /// The id of the key to delete
+ ///
+ IObservable Delete(int id);
}
}
diff --git a/Octokit.Reactive/Clients/ObservableUserKeysClient.cs b/Octokit.Reactive/Clients/ObservableUserKeysClient.cs
index 8e43bdd8..15245375 100644
--- a/Octokit.Reactive/Clients/ObservableUserKeysClient.cs
+++ b/Octokit.Reactive/Clients/ObservableUserKeysClient.cs
@@ -1,4 +1,5 @@
using System;
+using System.Reactive;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
@@ -27,7 +28,7 @@ namespace Octokit.Reactive
///
/// https://developer.github.com/v3/users/keys/#list-your-public-keys
///
- /// The s for the authenticated user.
+ ///
public IObservable GetAll()
{
return _client.GetAll().ToObservable().SelectMany(k => k);
@@ -39,10 +40,51 @@ namespace Octokit.Reactive
///
/// https://developer.github.com/v3/users/keys/#list-public-keys-for-a-user
///
- /// The s for the user.
+ ///
public IObservable GetAll(string userName)
{
return _client.GetAll(userName).ToObservable().SelectMany(k => k);
}
+
+ ///
+ /// Retrieves the for the specified id.
+ ///
+ ///
+ /// https://developer.github.com/v3/users/keys/#get-a-single-public-key
+ ///
+ /// The ID of the SSH key
+ ///
+ public IObservable Get(int id)
+ {
+ return _client.Get(id).ToObservable();
+ }
+
+ ///
+ /// Create a public key .
+ ///
+ ///
+ /// https://developer.github.com/v3/users/keys/#create-a-public-key
+ ///
+ /// The SSH Key contents
+ ///
+ public IObservable Create(NewPublicKey newKey)
+ {
+ Ensure.ArgumentNotNull(newKey, "newKey");
+
+ return _client.Create(newKey).ToObservable();
+ }
+
+ ///
+ /// Delete a public key.
+ ///
+ ///
+ /// https://developer.github.com/v3/users/keys/#delete-a-public-key
+ ///
+ /// The id of the key to delete
+ ///
+ public IObservable Delete(int id)
+ {
+ return _client.Delete(id).ToObservable();
+ }
}
}
\ No newline at end of file
diff --git a/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs b/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs
index 030795b0..8ef1fbbc 100644
--- a/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs
+++ b/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs
@@ -41,5 +41,16 @@ namespace Octokit.Tests.Integration.Helpers
return new EnterpriseUserContext(user);
}
+
+ internal async static Task CreatePublicKeyContext(this IObservableGitHubClient client)
+ {
+ // Create a key
+ string keyTitle = "title";
+ string keyData = "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAjo4DqFKg8dOxiz/yjypmN1A4itU5QOStyYrfOFuTinesU/2zm9hqxJ5BctIhgtSHJ5foxkhsiBji0qrUg73Q25BThgNg8YFE8njr4EwjmqSqW13akx/zLV0GFFU0SdJ2F6rBldhi93lMnl0ex9swBqa3eLTY8C+HQGBI6MQUMw+BKp0oFkz87Kv+Pfp6lt/Uo32ejSxML1PT5hTH5n+fyl0ied+sRmPGZWmWoHB5Bc9mox7lB6I6A/ZgjtBqbEEn4HQ2/6vp4ojKfSgA4Mm7XMu0bZzX0itKjH1QWD9Lr5apV1cmZsj49Xf8SHucTtH+bq98hb8OOXEGFzplwsX2MQ==";
+
+ var key = await client.User.Keys.Create(new NewPublicKey(keyTitle, keyData));
+
+ return new PublicKeyContext(key);
+ }
}
}
\ No newline at end of file
diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
index 84358320..93cf79b3 100644
--- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
+++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
@@ -149,6 +149,7 @@
+
diff --git a/Octokit.Tests.Integration/Reactive/ObservableUserKeysClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableUserKeysClientTests.cs
new file mode 100644
index 00000000..4dc15728
--- /dev/null
+++ b/Octokit.Tests.Integration/Reactive/ObservableUserKeysClientTests.cs
@@ -0,0 +1,87 @@
+using System.Linq;
+using System.Threading.Tasks;
+using Octokit.Reactive;
+using Octokit.Tests.Integration.Helpers;
+using Xunit;
+using System.Reactive.Linq;
+
+namespace Octokit.Tests.Integration.Clients
+{
+ public class ObservableUserKeysClientTests
+ {
+ readonly IObservableGitHubClient _github;
+
+ public ObservableUserKeysClientTests()
+ {
+ _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient());
+ }
+
+ [IntegrationTest]
+ public async Task CanGetAllForCurrentUser()
+ {
+ using (var context = await _github.CreatePublicKeyContext())
+ {
+ var observable = _github.User.Keys.GetAll();
+ var keys = await (observable.ToList());
+
+ Assert.NotEmpty(keys);
+
+ var first = keys[0];
+ Assert.NotNull(first.Id);
+ Assert.NotNull(first.Key);
+ Assert.NotNull(first.Title);
+ Assert.NotNull(first.Url);
+ }
+ }
+
+ [IntegrationTest]
+ public async Task CanGetAllForGivenUser()
+ {
+ var observable = _github.User.Keys.GetAll("shiftkey");
+ var keys = await (observable.ToList());
+
+ Assert.NotEmpty(keys);
+
+ var first = keys[0];
+ Assert.NotNull(first.Id);
+ Assert.NotNull(first.Key);
+ Assert.Null(first.Title);
+ Assert.Null(first.Url);
+ }
+
+ [IntegrationTest]
+ public async Task CanGetKeyById()
+ {
+ using (var context = await _github.CreatePublicKeyContext())
+ {
+ var observable = _github.User.Keys.Get(context.KeyId);
+ var key = await observable;
+
+ Assert.Equal(key.Title, context.KeyTitle);
+ Assert.Equal(key.Key, context.KeyData);
+ }
+ }
+
+ [IntegrationTest]
+ public async Task CanCreateAndDeleteKey()
+ {
+ // Create a key
+ string keyTitle = "title";
+ string keyData = "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAjo4DqFKg8dOxiz/yjypmN1A4itU5QOStyYrfOFuTinesU/2zm9hqxJ5BctIhgtSHJ5foxkhsiBji0qrUg73Q25BThgNg8YFE8njr4EwjmqSqW13akx/zLV0GFFU0SdJ2F6rBldhi93lMnl0ex9swBqa3eLTY8C+HQGBI6MQUMw+BKp0oFkz87Kv+Pfp6lt/Uo32ejSxML1PT5hTH5n+fyl0ied+sRmPGZWmWoHB5Bc9mox7lB6I6A/ZgjtBqbEEn4HQ2/6vp4ojKfSgA4Mm7XMu0bZzX0itKjH1QWD9Lr5apV1cmZsj49Xf8SHucTtH+bq98hb8OOXEGFzplwsX2MQ==";
+
+ var observable = _github.User.Keys.Create(new NewPublicKey(keyTitle, keyData));
+ var key = await observable;
+
+ Assert.NotNull(key);
+ Assert.Equal(key.Title, "title");
+ Assert.Equal(key.Key, keyData);
+
+ // Delete key
+ await _github.User.Keys.Delete(key.Id);
+
+ // Verify key no longer exists
+ var keys = await (_github.User.Keys.GetAll().ToList());
+ Assert.False(keys.Any(k => k.Title == keyTitle && k.Key == keyData));
+ }
+ }
+}
diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj
index 6cf9e013..99537721 100644
--- a/Octokit.Tests/Octokit.Tests.csproj
+++ b/Octokit.Tests/Octokit.Tests.csproj
@@ -217,6 +217,7 @@
+
diff --git a/Octokit.Tests/Reactive/ObservableUserKeysClientTests.cs b/Octokit.Tests/Reactive/ObservableUserKeysClientTests.cs
new file mode 100644
index 00000000..508e129a
--- /dev/null
+++ b/Octokit.Tests/Reactive/ObservableUserKeysClientTests.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Linq;
+using NSubstitute;
+using Octokit.Reactive;
+using Xunit;
+
+namespace Octokit.Tests.Reactive
+{
+ public class ObservableUserKeysClientTests
+ {
+ public class TheGetAllMethod
+ {
+ [Fact]
+ public void CallsIntoClient()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservableUserKeysClient(gitHubClient);
+
+ client.GetAll();
+
+ gitHubClient.User.Keys.Received().GetAll();
+ }
+ }
+
+ public class TheGetAllForUserMethod
+ {
+ [Fact]
+ public void CallsIntoClient()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservableUserKeysClient(gitHubClient);
+
+ client.GetAll("auser");
+
+ gitHubClient.User.Keys.Received().GetAll("auser");
+ }
+ }
+
+ public class TheGetMethod
+ {
+ [Fact]
+ public void CallsIntoClient()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservableUserKeysClient(gitHubClient);
+
+ client.Get(1);
+
+ gitHubClient.User.Keys.Received().Get(1);
+ }
+ }
+
+ public class TheCreateMethod
+ {
+ [Fact]
+ public void CallsIntoClient()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservableUserKeysClient(gitHubClient);
+
+ client.Create(new NewPublicKey("title", "ABCDEFG"));
+
+ gitHubClient.User.Keys.Received().Create(
+ Arg.Is(a =>
+ a.Title == "title" &&
+ a.Key == "ABCDEFG"));
+ }
+ }
+
+ public class TheDeleteMethod
+ {
+ [Fact]
+ public void CallsIntoClient()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservableUserKeysClient(gitHubClient);
+
+ client.Delete(1);
+
+ gitHubClient.User.Keys.Received().Delete(1);
+ }
+ }
+
+ public class TheCtor
+ {
+ [Fact]
+ public void EnsuresArgument()
+ {
+ Assert.Throws(() => new ObservableUserKeysClient(null));
+ }
+ }
+ }
+}