Merge pull request #524 from octokit/user-emails-delete

Add support for deleting emails for the authenticated user
This commit is contained in:
Phil Haack
2014-07-08 10:20:50 -07:00
10 changed files with 163 additions and 12 deletions
@@ -1,6 +1,6 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reactive;
namespace Octokit.Reactive
{
@@ -30,6 +30,16 @@ namespace Octokit.Reactive
/// </remarks>
/// <param name="emailAddresses">The email addresses to add.</param>
/// <returns>Returns the added <see cref="EmailAddress"/>es.</returns>
IObservable<string> Add(params string[] emailAddresses);
IObservable<EmailAddress> Add(params string[] emailAddresses);
/// <summary>
/// Deletes email addresses for the authenticated user.
/// </summary>
/// <remarks>
/// http://developer.github.com/v3/users/emails/#delete-email-addresses
/// </remarks>
/// <param name="emailAddresses">The email addresses to delete.</param>
/// <returns>Returns the added <see cref="EmailAddress"/>es.</returns>
IObservable<Unit> Delete(params string[] emailAddresses);
}
}
@@ -1,4 +1,5 @@
using Octokit.Reactive.Internal;
using System.Reactive;
using Octokit.Reactive.Internal;
using System;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
@@ -44,9 +45,22 @@ namespace Octokit.Reactive
/// </remarks>
/// <param name="emailAddresses">The email addresses to add.</param>
/// <returns>Returns the added <see cref="EmailAddress"/>es.</returns>
public IObservable<string> Add(params string[] emailAddresses)
public IObservable<EmailAddress> Add(params string[] emailAddresses)
{
return _client.Add(emailAddresses).ToObservable().SelectMany(a => a);
}
/// <summary>
/// Deletes email addresses for the authenticated user.
/// </summary>
/// <remarks>
/// http://developer.github.com/v3/users/emails/#delete-email-addresses
/// </remarks>
/// <param name="emailAddresses">The email addresses to delete.</param>
/// <returns>Returns the added <see cref="EmailAddress"/>es.</returns>
public IObservable<Unit> Delete(params string[] emailAddresses)
{
return _client.Delete(emailAddresses).ToObservable();
}
}
}
@@ -1,4 +1,4 @@
using System.Net.Http.Headers;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
@@ -17,5 +17,26 @@ namespace Octokit.Tests.Integration.Clients
var emails = await github.User.Email.GetAll();
Assert.NotEmpty(emails);
}
const string testEmailAddress = "hahaha-not-a-real-email@foo.com";
[IntegrationTest]
public async Task CanAddAndDeleteEmail()
{
var github = new GitHubClient(new ProductHeaderValue("OctokitTests"))
{
Credentials = Helper.Credentials
};
await github.User.Email.Add(testEmailAddress);
var emails = await github.User.Email.GetAll();
Assert.Contains(testEmailAddress, emails.Select(x => x.Email));
await github.User.Email.Delete(testEmailAddress);
emails = await github.User.Email.GetAll();
Assert.DoesNotContain(testEmailAddress, emails.Select(x => x.Email));
}
}
}
+30 -3
View File
@@ -1,8 +1,6 @@
using NSubstitute;
using Octokit.Tests.Helpers;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Xunit;
namespace Octokit.Tests.Clients
@@ -35,7 +33,7 @@ namespace Octokit.Tests.Clients
client.Add("octocat@github.com");
connection.Received(1)
.Post<IReadOnlyList<string>>(Arg.Is<Uri>(u => u.ToString() == "user/emails"), Arg.Any<string[]>());
.Post<IReadOnlyList<EmailAddress>>(Arg.Is<Uri>(u => u.ToString() == "user/emails"), Arg.Any<string[]>());
}
[Fact]
@@ -53,6 +51,35 @@ namespace Octokit.Tests.Clients
}
}
public class TheDeleteMethod
{
[Fact]
public void PostsToCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new UserEmailsClient(connection);
client.Delete("octocat@github.com");
connection.Received(1)
.Delete(Arg.Is<Uri>(u => u.ToString() == "user/emails"), Arg.Any<string[]>());
}
[Fact]
public void EnsuresNonNullArgument()
{
var client = new UserEmailsClient(Substitute.For<IApiConnection>());
Assert.Throws<ArgumentNullException>(() => client.Delete(null));
}
[Fact]
public void EnsuresNoNullEmails()
{
var client = new UserEmailsClient(Substitute.For<IApiConnection>());
Assert.Throws<ArgumentException>(() => client.Delete("octokit@github.com", null));
}
}
public class TheCtor
{
[Fact]
+11 -1
View File
@@ -30,6 +30,16 @@ namespace Octokit
/// </remarks>
/// <param name="emailAddresses">The email addresses to add.</param>
/// <returns>Returns the added <see cref="EmailAddress"/>es.</returns>
Task<IReadOnlyList<string>> Add(params string[] emailAddresses);
Task<IReadOnlyList<EmailAddress>> Add(params string[] emailAddresses);
/// <summary>
/// Deletes email addresses for the authenticated user.
/// </summary>
/// <remarks>
/// http://developer.github.com/v3/users/emails/#delete-email-addresses
/// </remarks>
/// <param name="emailAddresses">The email addresses to delete.</param>
/// <returns>Returns the added <see cref="EmailAddress"/>es.</returns>
Task Delete(params string[] emailAddresses);
}
}
+19 -2
View File
@@ -41,13 +41,30 @@ namespace Octokit
/// </remarks>
/// <param name="emailAddresses">The email addresses to add.</param>
/// <returns>Returns the added <see cref="EmailAddress"/>es.</returns>
public Task<IReadOnlyList<string>> Add(params string[] emailAddresses)
public Task<IReadOnlyList<EmailAddress>> Add(params string[] emailAddresses)
{
Ensure.ArgumentNotNull(emailAddresses, "emailAddresses");
if (emailAddresses.Any(String.IsNullOrWhiteSpace))
throw new ArgumentException("Cannot contain null, empty or whitespace values", "emailAddresses");
return ApiConnection.Post<IReadOnlyList<string>>(ApiUrls.Emails(), emailAddresses);
return ApiConnection.Post<IReadOnlyList<EmailAddress>>(ApiUrls.Emails(), emailAddresses);
}
/// <summary>
/// Deletes email addresses for the authenticated user.
/// </summary>
/// <remarks>
/// http://developer.github.com/v3/users/emails/#delete-email-addresses
/// </remarks>
/// <param name="emailAddresses">The email addresses to delete.</param>
/// <returns>Returns the added <see cref="EmailAddress"/>es.</returns>
public Task Delete(params string[] emailAddresses)
{
Ensure.ArgumentNotNull(emailAddresses, "emailAddresses");
if (emailAddresses.Any(String.IsNullOrWhiteSpace))
throw new ArgumentException("Cannot contain null, empty or whitespace values", "emailAddresses");
return ApiConnection.Delete(ApiUrls.Emails(), emailAddresses);
}
}
}
+14
View File
@@ -286,6 +286,20 @@ namespace Octokit
return Connection.Delete(uri);
}
/// <summary>
/// Deletes the API object at the specified URI.
/// </summary>
/// <param name="uri">URI of the API resource to delete</param>
/// <param name="data">Object that describes the API resource; this will be serialized and used as the request's body</param>
/// <returns>A <see cref="Task"/> for the request's execution.</returns>
public Task Delete(Uri uri, object data)
{
Ensure.ArgumentNotNull(uri, "uri");
Ensure.ArgumentNotNull(data, "data");
return Connection.Delete(uri, data);
}
/// <summary>
/// Executes a GET to the API object at the specified URI. This operation is appropriate for
/// API calls which queue long running calculations.
+22
View File
@@ -295,6 +295,28 @@ namespace Octokit
return response.StatusCode;
}
/// <summary>
/// Performs an asynchronous HTTP DELETE request that expects an empty response.
/// </summary>
/// <param name="uri">URI endpoint to send request to</param>
/// <param name="data">The object to serialize as the body of the request</param>
/// <returns>The returned <seealso cref="HttpStatusCode"/></returns>
public async Task<HttpStatusCode> Delete(Uri uri, object data)
{
Ensure.ArgumentNotNull(uri, "uri");
Ensure.ArgumentNotNull(data, "data");
var request = new Request
{
Method = HttpMethod.Delete,
Body = data,
BaseAddress = BaseAddress,
Endpoint = uri
};
var response = await Run<object>(request, CancellationToken.None);
return response.StatusCode;
}
/// <summary>
/// Base address for the connection.
/// </summary>
+9 -1
View File
@@ -147,7 +147,7 @@ namespace Octokit
/// </summary>
/// <typeparam name="T">The API resource's type.</typeparam>
/// <param name="uri">URI of the API resource to update</param>
/// /// <param name="data">Object that describes the API resource; this will be serialized and used as the request's body</param>
/// <param name="data">Object that describes the API resource; this will be serialized and used as the request's body</param>
/// <returns>The updated API resource.</returns>
/// <exception cref="ApiException">Thrown when an API error occurs.</exception>
Task<T> Patch<T>(Uri uri, object data);
@@ -170,6 +170,14 @@ namespace Octokit
/// <returns>A <see cref="Task"/> for the request's execution.</returns>
Task Delete(Uri uri);
/// <summary>
/// Deletes the API object at the specified URI.
/// </summary>
/// <param name="uri">URI of the API resource to delete</param>
/// <param name="data">Object that describes the API resource; this will be serialized and used as the request's body</param>
/// <returns>A <see cref="Task"/> for the request's execution.</returns>
Task Delete(Uri uri, object data);
/// <summary>
/// Executes a GET to the API object at the specified URI. This operation is appropriate for
/// API calls which queue long running calculations.
+8
View File
@@ -130,6 +130,14 @@ namespace Octokit
/// <returns>The returned <seealso cref="HttpStatusCode"/></returns>
Task<HttpStatusCode> Delete(Uri uri);
/// <summary>
/// Performs an asynchronous HTTP DELETE request that expects an empty response.
/// </summary>
/// <param name="uri">URI endpoint to send request to</param>
/// <param name="data">The object to serialize as the body of the request</param>
/// <returns>The returned <seealso cref="HttpStatusCode"/></returns>
Task<HttpStatusCode> Delete(Uri uri, object data);
/// <summary>
/// Base address for the connection.
/// </summary>