From 8c8c6370656217021ad1d33afda763977a904643 Mon Sep 17 00:00:00 2001 From: Ryan Gribble Date: Wed, 17 Feb 2016 22:20:55 +1000 Subject: [PATCH] Add Reactive implementation and unit/integration tests --- .../Clients/IObservableUserKeysClient.cs | 37 +++++++- .../Clients/ObservableUserKeysClient.cs | 46 ++++++++- .../ObservableGithubClientExtensions.cs | 11 +++ .../Octokit.Tests.Integration.csproj | 1 + .../Reactive/ObservableUserKeysClientTests.cs | 87 +++++++++++++++++ Octokit.Tests/Octokit.Tests.csproj | 1 + .../Reactive/ObservableUserKeysClientTests.cs | 93 +++++++++++++++++++ 7 files changed, 272 insertions(+), 4 deletions(-) create mode 100644 Octokit.Tests.Integration/Reactive/ObservableUserKeysClientTests.cs create mode 100644 Octokit.Tests/Reactive/ObservableUserKeysClientTests.cs 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)); + } + } + } +}