-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #343 from alfhenrik/user-followers-api
Implement User Followers API
- Loading branch information
Showing
21 changed files
with
1,161 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics.CodeAnalysis; | ||
using System.Linq; | ||
using System.Reactive; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace Octokit.Reactive | ||
{ | ||
public interface IObservableFollowersClient | ||
{ | ||
/// <summary> | ||
/// List the authenticated user’s followers | ||
/// </summary> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#list-followers-of-a-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <see cref="IReadOnlyList{User}"/> of <see cref="User"/>s that follow the authenticated user.</returns> | ||
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] | ||
IObservable<User> GetAllForCurrent(); | ||
|
||
/// <summary> | ||
/// List a user’s followers | ||
/// </summary> | ||
/// <param name="login">The login name for the user</param> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#list-followers-of-a-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <see cref="IReadOnlyList{User}"/> of <see cref="User"/>s that follow the passed user.</returns> | ||
IObservable<User> GetAll(string login); | ||
|
||
/// <summary> | ||
/// List who the authenticated user is following | ||
/// </summary> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#list-users-followed-by-another-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <see cref="IReadOnlyList{User}"/> of <see cref="User"/>s that the authenticated user follows.</returns> | ||
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] | ||
IObservable<User> GetFollowingForCurrent(); | ||
|
||
/// <summary> | ||
/// List who a user is following | ||
/// </summary> | ||
/// <param name="login">The login name of the user</param> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#list-users-followed-by-another-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <see cref="IReadOnlyList{User}"/> of <see cref="User"/>s that the passed user follows.</returns> | ||
IObservable<User> GetFollowing(string login); | ||
|
||
/// <summary> | ||
/// Check if the authenticated user follows another user | ||
/// </summary> | ||
/// <param name="following">The login name of the other user</param> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#check-if-you-are-following-a-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <c>bool</c> representing the success of the operation.</returns> | ||
IObservable<bool> IsFollowingForCurrent(string following); | ||
|
||
/// <summary> | ||
/// Check if one user follows another user | ||
/// </summary> | ||
/// <param name="login">The login name of the user</param> | ||
/// <param name="following">The login name of the other user</param> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#check-if-one-user-follows-another">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <c>bool</c> representing the success of the operation.</returns> | ||
IObservable<bool> IsFollowing(string login, string following); | ||
|
||
/// <summary> | ||
/// Follow a user | ||
/// </summary> | ||
/// <param name="login">The login name of the user to follow</param> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#follow-a-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <c>bool</c> representing the success of the operation.</returns> | ||
IObservable<bool> Follow(string login); | ||
|
||
/// <summary> | ||
/// Unfollow a user | ||
/// </summary> | ||
/// <param name="login">The login name of the user to unfollow</param> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#unfollow-a-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns></returns> | ||
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Unfollow", | ||
Justification = "Unfollow is consistent with the GitHub website")] | ||
IObservable<Unit> Unfollow(string login); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
using System; | ||
using System.Reactive; | ||
using System.Reactive.Threading.Tasks; | ||
using Octokit.Reactive.Internal; | ||
|
||
namespace Octokit.Reactive | ||
{ | ||
public class ObservableFollowersClient : IObservableFollowersClient | ||
{ | ||
readonly IFollowersClient _client; | ||
readonly IConnection _connection; | ||
|
||
/// <summary> | ||
/// Initializes a new User Followers API client. | ||
/// </summary> | ||
/// <param name="client">An <see cref="IGitHubClient" /> used to make the requests</param> | ||
public ObservableFollowersClient(IGitHubClient client) | ||
{ | ||
Ensure.ArgumentNotNull(client, "client"); | ||
|
||
_client = client.User.Followers; | ||
_connection = client.Connection; | ||
} | ||
|
||
/// <summary> | ||
/// List the authenticated user’s followers | ||
/// </summary> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#list-followers-of-a-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <see cref="IReadOnlyList{User}"/> of <see cref="User"/>s that follow the authenticated user.</returns> | ||
public IObservable<User> GetAllForCurrent() | ||
{ | ||
return _connection.GetAndFlattenAllPages<User>(ApiUrls.Followers()); | ||
} | ||
|
||
/// <summary> | ||
/// List a user’s followers | ||
/// </summary> | ||
/// <param name="login">The login name for the user</param> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#list-followers-of-a-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <see cref="IReadOnlyList{User}"/> of <see cref="User"/>s that follow the passed user.</returns> | ||
public IObservable<User> GetAll(string login) | ||
{ | ||
Ensure.ArgumentNotNullOrEmptyString(login, "login"); | ||
|
||
return _connection.GetAndFlattenAllPages<User>(ApiUrls.Followers(login)); | ||
} | ||
|
||
/// <summary> | ||
/// List who the authenticated user is following | ||
/// </summary> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#list-users-followed-by-another-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <see cref="IReadOnlyList{User}"/> of <see cref="User"/>s that the authenticated user follows.</returns> | ||
public IObservable<User> GetFollowingForCurrent() | ||
{ | ||
return _connection.GetAndFlattenAllPages<User>(ApiUrls.Following()); | ||
} | ||
|
||
/// <summary> | ||
/// List who a user is following | ||
/// </summary> | ||
/// <param name="login">The login name of the user</param> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#list-users-followed-by-another-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <see cref="IReadOnlyList{User}"/> of <see cref="User"/>s that the passed user follows.</returns> | ||
public IObservable<User> GetFollowing(string login) | ||
{ | ||
Ensure.ArgumentNotNullOrEmptyString(login, "login"); | ||
|
||
return _connection.GetAndFlattenAllPages<User>(ApiUrls.Following(login)); | ||
} | ||
|
||
/// <summary> | ||
/// Check if the authenticated user follows another user | ||
/// </summary> | ||
/// <param name="following">The login name of the other user</param> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#check-if-you-are-following-a-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <c>bool</c> representing the success of the operation.</returns> | ||
public IObservable<bool> IsFollowingForCurrent(string following) | ||
{ | ||
Ensure.ArgumentNotNullOrEmptyString(following, "following"); | ||
|
||
return _client.IsFollowingForCurrent(following).ToObservable(); | ||
} | ||
|
||
/// <summary> | ||
/// Check if one user follows another user | ||
/// </summary> | ||
/// <param name="login">The login name of the user</param> | ||
/// <param name="following">The login name of the other user</param> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#check-if-one-user-follows-another">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <c>bool</c> representing the success of the operation.</returns> | ||
public IObservable<bool> IsFollowing(string login, string following) | ||
{ | ||
Ensure.ArgumentNotNullOrEmptyString(login, "login"); | ||
Ensure.ArgumentNotNullOrEmptyString(following, "following"); | ||
|
||
return _client.IsFollowing(login, following).ToObservable(); | ||
} | ||
|
||
/// <summary> | ||
/// Follow a user | ||
/// </summary> | ||
/// <param name="login">The login name of the user to follow</param> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#follow-a-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns>A <c>bool</c> representing the success of the operation.</returns> | ||
public IObservable<bool> Follow(string login) | ||
{ | ||
Ensure.ArgumentNotNullOrEmptyString(login, "login"); | ||
|
||
return _client.Follow(login).ToObservable(); | ||
} | ||
|
||
/// <summary> | ||
/// Unfollow a user | ||
/// </summary> | ||
/// <param name="login">The login name of the user to unfollow</param> | ||
/// <remarks> | ||
/// See the <a href="http://developer.github.com/v3/users/followers/#unfollow-a-user">API documentation</a> for more information. | ||
/// </remarks> | ||
/// <returns></returns> | ||
public IObservable<System.Reactive.Unit> Unfollow(string login) | ||
{ | ||
Ensure.ArgumentNotNullOrEmptyString(login, "login"); | ||
|
||
return _client.Unfollow(login).ToObservable(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
110 changes: 110 additions & 0 deletions
110
Octokit.Tests.Integration/Clients/FollowersClientTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Net.Http.Headers; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using Octokit; | ||
using Octokit.Tests.Integration; | ||
using Xunit; | ||
|
||
public class FollowersClientTests : IDisposable | ||
{ | ||
readonly GitHubClient _github; | ||
readonly User _currentUser; | ||
|
||
public FollowersClientTests() | ||
{ | ||
_github = new GitHubClient(new ProductHeaderValue("OctokitTests")) | ||
{ | ||
Credentials = Helper.Credentials | ||
}; | ||
_currentUser = _github.User.Current().Result; | ||
} | ||
|
||
[IntegrationTest] | ||
public async Task ReturnsUsersTheCurrentUserIsFollowing() | ||
{ | ||
await _github.User.Followers.Follow("alfhenrik"); | ||
|
||
var following = await _github.User.Followers.GetFollowingForCurrent(); | ||
|
||
Assert.NotNull(following); | ||
Assert.True(following.Any(f => f.Login == "alfhenrik")); | ||
} | ||
|
||
[IntegrationTest] | ||
public async Task ReturnsUsersTheUserIsFollowing() | ||
{ | ||
var following = await _github.User.Followers.GetFollowing("alfhenrik"); | ||
|
||
Assert.NotNull(following); | ||
Assert.NotEmpty(following); | ||
} | ||
|
||
[IntegrationTest] | ||
public async Task ReturnsUsersFollowingTheUser() | ||
{ | ||
await _github.User.Followers.Follow("alfhenrik"); | ||
|
||
var followers = await _github.User.Followers.GetAll("alfhenrik"); | ||
|
||
Assert.NotEmpty(followers); | ||
Assert.True(followers.Any(f => f.Login == _currentUser.Login)); | ||
} | ||
|
||
[IntegrationTest] | ||
public async Task ChecksIfIsFollowingUserWhenFollowingUser() | ||
{ | ||
await _github.User.Followers.Follow("alfhenrik"); | ||
|
||
var isFollowing = await _github.User.Followers.IsFollowingForCurrent("alfhenrik"); | ||
|
||
Assert.True(isFollowing); | ||
} | ||
|
||
[IntegrationTest] | ||
public async Task ChecksIfIsFollowingUserWhenNotFollowingUser() | ||
{ | ||
var isFollowing = await _github.User.Followers.IsFollowingForCurrent("alfhenrik"); | ||
|
||
Assert.False(isFollowing); | ||
} | ||
|
||
[IntegrationTest] | ||
public async Task FollowUserNotBeingFollowedByTheUser() | ||
{ | ||
var result = await _github.User.Followers.Follow("alfhenrik"); | ||
var following = await _github.User.Followers.GetFollowingForCurrent(); | ||
|
||
Assert.True(result); | ||
Assert.NotEmpty(following); | ||
Assert.True(following.Any(f => f.Login == "alfhenrik")); | ||
} | ||
|
||
[IntegrationTest] | ||
public async Task UnfollowUserBeingFollowedByTheUser() | ||
{ | ||
await _github.User.Followers.Follow("alfhenrik"); | ||
var followers = await _github.User.Followers.GetAll("alfhenrik"); | ||
Assert.True(followers.Any(f => f.Login == _currentUser.Login)); | ||
|
||
await _github.User.Followers.Unfollow("alfhenrik"); | ||
followers = await _github.User.Followers.GetAll("alfhenrik"); | ||
Assert.False(followers.Any(f => f.Login == _currentUser.Login)); | ||
} | ||
|
||
[IntegrationTest] | ||
public async Task UnfollowUserNotBeingFollowedTheUser() | ||
{ | ||
var followers = await _github.User.Followers.GetAll("alfhenrik"); | ||
Assert.False(followers.Any(f => f.Login == _currentUser.Login)); | ||
|
||
await _github.User.Followers.Unfollow("alfhenrik"); | ||
} | ||
|
||
public void Dispose() | ||
{ | ||
_github.User.Followers.Unfollow("alfhenrik"); | ||
} | ||
} |
Oops, something went wrong.