-
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.
[Feat] Add Repository Autolinks Client (#2868)
- Loading branch information
1 parent
c9ddf3e
commit 2a87dd0
Showing
13 changed files
with
649 additions
and
11 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 |
---|---|---|
@@ -1,6 +1,6 @@ | ||
using System; | ||
using System.Reactive; | ||
using System.Threading.Tasks; | ||
|
||
|
||
namespace Octokit.Reactive | ||
{ | ||
|
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,59 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Reactive; | ||
|
||
namespace Octokit.Reactive | ||
{ | ||
/// <summary> | ||
/// A client for GitHub's Repository Autolinks API | ||
/// </summary> | ||
/// <remarks> | ||
/// See the <a href="https://docs.github.com/en/rest/repos/autolinks">API documentation</a> for more information. | ||
/// </remarks> | ||
public interface IObservableAutolinksClient | ||
{ | ||
/// <summary> | ||
/// Returns a single autolink reference by ID that was configured for the given repository | ||
/// </summary> | ||
/// <param name="owner">The account owner of the repository</param> | ||
/// <param name="repo">The name of the repository</param> | ||
/// <param name="autolinkId">The unique identifier of the autolink</param> | ||
/// <remarks>See the <a href="https://docs.github.com/en/rest/repos/autolinks#get-an-autolink-reference-of-a-repository">API documentation</a> for more information.</remarks> | ||
IObservable<Autolink> Get(string owner, string repo, int autolinkId); | ||
|
||
/// <summary> | ||
/// Returns a list of autolinks configured for the given repository | ||
/// </summary> | ||
/// <param name="owner">The account owner of the repository</param> | ||
/// <param name="repo">The name of the repository</param> | ||
/// <remarks>See the <a href="https://docs.github.com/en/rest/repos/autolinks#list-all-autolinks-of-a-repository">API documentation</a> for more information.</remarks> | ||
IObservable<Autolink> GetAll(string owner, string repo); | ||
|
||
/// <summary> | ||
/// Returns a list of autolinks configured for the given repository | ||
/// </summary> | ||
/// <param name="owner">The account owner of the repository</param> | ||
/// <param name="repo">The name of the repository</param> | ||
/// <param name="options">Options for changing the API response</param> | ||
/// <remarks>See the <a href="https://docs.github.com/en/rest/repos/autolinks#list-all-autolinks-of-a-repository">API documentation</a> for more information.</remarks> | ||
IObservable<Autolink> GetAll(string owner, string repo, ApiOptions options); | ||
|
||
/// <summary> | ||
/// Create an autolink reference for a repository | ||
/// </summary> | ||
/// <param name="owner">The account owner of the repository</param> | ||
/// <param name="repo">The name of the repository</param> | ||
/// <param name="autolink">The Autolink object to be created for the repository</param> | ||
/// <remarks>See the <a href="https://docs.github.com/en/rest/repos/autolinks#create-an-autolink-reference-for-a-repository">API documentation</a> for more information.</remarks> | ||
IObservable<Autolink> Create(string owner, string repo, AutolinkRequest autolink); | ||
|
||
/// <summary> | ||
/// Deletes a single autolink reference by ID that was configured for the given repository | ||
/// </summary> | ||
/// <param name="owner">The account owner of the repository</param> | ||
/// <param name="repo">The name of the repository</param> | ||
/// <param name="autolinkId">The unique identifier of the autolink</param> | ||
/// <remarks>See the <a href="https://docs.github.com/en/rest/repos/autolinks#delete-an-autolink-reference-from-a-repository">API documentation</a> for more information.</remarks> | ||
IObservable<Unit> Delete(string owner, string repo, int autolinkId); | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
using System; | ||
using System.Reactive; | ||
using System.Reactive.Threading.Tasks; | ||
using Octokit.Reactive.Internal; | ||
|
||
|
||
namespace Octokit.Reactive | ||
{ | ||
/// <inheritdoc/> | ||
public class ObservableAutolinksClient : IObservableAutolinksClient | ||
{ | ||
readonly IAutolinksClient _client; | ||
readonly IConnection _connection; | ||
|
||
|
||
public ObservableAutolinksClient(IGitHubClient client) | ||
{ | ||
Ensure.ArgumentNotNull(client, nameof(client)); | ||
|
||
_client = client.Repository.Autolinks; | ||
_connection = client.Connection; | ||
} | ||
|
||
|
||
/// <inheritdoc/> | ||
public IObservable<Autolink> Get(string owner, string repo, int autolinkId) | ||
{ | ||
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); | ||
Ensure.ArgumentNotNullOrEmptyString(repo, nameof(repo)); | ||
|
||
return _client.Get(owner, repo, autolinkId).ToObservable(); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public IObservable<Autolink> GetAll(string owner, string repo) | ||
{ | ||
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); | ||
Ensure.ArgumentNotNullOrEmptyString(repo, nameof(repo)); | ||
|
||
return this.GetAll(owner, repo, ApiOptions.None); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public IObservable<Autolink> GetAll(string owner, string repo, ApiOptions options) | ||
{ | ||
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); | ||
Ensure.ArgumentNotNullOrEmptyString(repo, nameof(repo)); | ||
Ensure.ArgumentNotNull(options, nameof(options)); | ||
|
||
return _connection.GetAndFlattenAllPages<Autolink>(ApiUrls.AutolinksGetAll(owner, repo), options); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public IObservable<Autolink> Create(string owner, string repo, AutolinkRequest autolink) | ||
{ | ||
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); | ||
Ensure.ArgumentNotNullOrEmptyString(repo, nameof(repo)); | ||
Ensure.ArgumentNotNull(autolink, nameof(autolink)); | ||
|
||
return _client.Create(owner, repo, autolink).ToObservable(); | ||
} | ||
|
||
/// <inheritdoc/> | ||
public IObservable<Unit> Delete(string owner, string repo, int autolinkId) | ||
{ | ||
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner)); | ||
Ensure.ArgumentNotNullOrEmptyString(repo, nameof(repo)); | ||
|
||
return _client.Delete(owner, repo, autolinkId).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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
using NSubstitute; | ||
using System; | ||
using System.Threading.Tasks; | ||
using Xunit; | ||
|
||
|
||
namespace Octokit.Tests.Clients | ||
{ | ||
public class AutolinksClientTests | ||
{ | ||
public class TheCtor | ||
{ | ||
[Fact] | ||
public void EnsuresNonNullArguments() | ||
{ | ||
Assert.Throws<ArgumentNullException>(() => new AutolinksClient(null)); | ||
} | ||
} | ||
|
||
|
||
public class TheGetMethod | ||
{ | ||
[Fact] | ||
public async Task RequestsCorrectUrl() | ||
{ | ||
var connection = Substitute.For<IApiConnection>(); | ||
var client = new AutolinksClient(connection); | ||
|
||
await client.Get("fakeOwner", "fakeRepo", 42); | ||
|
||
connection.Received().Get<Autolink>( | ||
Arg.Is<Uri>(u => u.ToString() == "repos/fakeOwner/fakeRepo/autolinks/42")); | ||
} | ||
|
||
[Fact] | ||
public async Task EnsuresNonNullArguments() | ||
{ | ||
var connection = Substitute.For<IApiConnection>(); | ||
var client = new AutolinksClient(connection); | ||
|
||
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Get(null, "repo", 42)); | ||
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Get("owner", null, 42)); | ||
} | ||
|
||
[Fact] | ||
public async Task EnsuresNonEmptyArguments() | ||
{ | ||
var connection = Substitute.For<IApiConnection>(); | ||
var client = new AutolinksClient(connection); | ||
|
||
await Assert.ThrowsAsync<ArgumentException>(() => client.Get("", "repo", 42)); | ||
await Assert.ThrowsAsync<ArgumentException>(() => client.Get("owner", "", 42)); | ||
} | ||
} | ||
|
||
public class TheGetAllMethod | ||
{ | ||
[Fact] | ||
public async Task RequestsCorrectUrl() | ||
{ | ||
var connection = Substitute.For<IApiConnection>(); | ||
var client = new AutolinksClient(connection); | ||
|
||
await client.GetAll("fakeOwner", "fakeRepo"); | ||
|
||
connection.Received().GetAll<Autolink>( | ||
Arg.Is<Uri>(u => u.ToString() == "repos/fakeOwner/fakeRepo/autolinks"), Args.ApiOptions); | ||
} | ||
|
||
[Fact] | ||
public async Task RequestsCorrectUrlWithApiOptions() | ||
{ | ||
var connection = Substitute.For<IApiConnection>(); | ||
var client = new AutolinksClient(connection); | ||
|
||
var options = new ApiOptions | ||
{ | ||
PageCount = 1, | ||
PageSize = 1, | ||
StartPage = 1 | ||
}; | ||
|
||
await client.GetAll("fakeOwner", "fakeRepo", options); | ||
|
||
connection.Received(1) | ||
.GetAll<Autolink>(Arg.Is<Uri>(u => u.ToString() == "repos/fakeOwner/fakeRepo/autolinks"), | ||
options); | ||
} | ||
|
||
[Fact] | ||
public async Task EnsuresNonNullArguments() | ||
{ | ||
var connection = Substitute.For<IApiConnection>(); | ||
var client = new AutolinksClient(connection); | ||
|
||
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(null, "repo")); | ||
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll("owner", null)); | ||
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(null, "repo", ApiOptions.None)); | ||
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll("owner", null, ApiOptions.None)); | ||
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll("owner", "repo", null)); | ||
} | ||
|
||
[Fact] | ||
public async Task EnsuresNonEmptyArguments() | ||
{ | ||
var connection = Substitute.For<IApiConnection>(); | ||
var client = new AutolinksClient(connection); | ||
|
||
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("", "repo")); | ||
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("owner", "")); | ||
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("", "repo", ApiOptions.None)); | ||
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("owner", "", ApiOptions.None)); | ||
} | ||
} | ||
|
||
public class TheCreateMethod | ||
{ | ||
[Fact] | ||
public async Task PostsToCorrectUrl() | ||
{ | ||
var newAutolink = new AutolinkRequest("fakeKeyPrefix", "fakeUrlTemplate", true); | ||
var connection = Substitute.For<IApiConnection>(); | ||
var client = new AutolinksClient(connection); | ||
|
||
await client.Create("fakeOwner", "fakeRepo", newAutolink); | ||
|
||
connection.Received().Post<Autolink>( | ||
Arg.Is<Uri>(u => u.ToString() == "repos/fakeOwner/fakeRepo/autolinks"), | ||
Arg.Is<AutolinkRequest>(a => a.KeyPrefix == "fakeKeyPrefix" | ||
&& a.UrlTemplate == "fakeUrlTemplate" | ||
&& a.IsAlphanumeric == true)); | ||
} | ||
|
||
[Fact] | ||
public async Task EnsuresNonNullArguments() | ||
{ | ||
var connection = Substitute.For<IApiConnection>(); | ||
var client = new AutolinksClient(connection); | ||
|
||
var newAutolink = new AutolinkRequest("fakeKeyPrefix", "fakeUrlTemplate", true); | ||
|
||
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Create(null, "repo", newAutolink)); | ||
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Create("owner", null, newAutolink)); | ||
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Create("owner", "repo", null)); | ||
} | ||
|
||
[Fact] | ||
public async Task EnsuresNonEmptyArguments() | ||
{ | ||
var connection = Substitute.For<IApiConnection>(); | ||
var client = new AutolinksClient(connection); | ||
|
||
var newAutolink = new AutolinkRequest("fakeKeyPrefix", "fakeUrlTemplate", true); | ||
|
||
await Assert.ThrowsAsync<ArgumentException>(() => client.Create("", "repo", newAutolink)); | ||
await Assert.ThrowsAsync<ArgumentException>(() => client.Create("owner", "", newAutolink)); | ||
} | ||
} | ||
|
||
public class TheDeleteMethod | ||
{ | ||
[Fact] | ||
public async Task DeletesCorrectUrl() | ||
{ | ||
var connection = Substitute.For<IApiConnection>(); | ||
var client = new AutolinksClient(connection); | ||
|
||
await client.Delete("fakeOwner", "fakeRepo", 42); | ||
|
||
connection.Received().Delete( | ||
Arg.Is<Uri>(u => u.ToString() == "repos/fakeOwner/fakeRepo/autolinks/42")); | ||
} | ||
|
||
[Fact] | ||
public async Task EnsuresNonNullArguments() | ||
{ | ||
var connection = Substitute.For<IApiConnection>(); | ||
var client = new AutolinksClient(connection); | ||
|
||
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Delete(null, "repo", 42)); | ||
await Assert.ThrowsAsync<ArgumentNullException>(() => client.Delete("owner", null, 42)); | ||
} | ||
|
||
[Fact] | ||
public async Task EnsuresNonEmptyArguments() | ||
{ | ||
var connection = Substitute.For<IApiConnection>(); | ||
var client = new AutolinksClient(connection); | ||
|
||
await Assert.ThrowsAsync<ArgumentException>(() => client.Delete("", "repo", 42)); | ||
await Assert.ThrowsAsync<ArgumentException>(() => client.Delete("owner", "", 42)); | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.