Merge pull request #1223 from dampir/fix1151

Add ApiOption overloads to methods on IDeploymentsClient
This commit is contained in:
Brendan Forster
2016-04-04 13:49:34 -04:00
7 changed files with 284 additions and 35 deletions
@@ -16,6 +16,19 @@ namespace Octokit.Reactive
/// <returns>All the <see cref="Deployment"/>s for the specified repository.</returns>
IObservable<Deployment> GetAll(string owner, string name);
/// <summary>
/// Gets all the deployments for the specified repository. Any user with pull access
/// to a repository can view deployments.
/// </summary>
/// <remarks>
/// http://developer.github.com/v3/repos/deployments/#list-deployments
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>All the <see cref="Deployment"/>s for the specified repository.</returns>
IObservable<Deployment> GetAll(string owner, string name, ApiOptions options);
/// <summary>
/// Creates a new deployment for the specified repository.
/// Users with push access can create a deployment for a given ref.
@@ -34,8 +34,28 @@ namespace Octokit.Reactive.Clients
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Ensure.ArgumentNotNullOrEmptyString(name, "name");
return GetAll(owner, name, ApiOptions.None);
}
/// <summary>
/// Gets all the deployments for the specified repository. Any user with pull access
/// to a repository can view deployments.
/// </summary>
/// <remarks>
/// http://developer.github.com/v3/repos/deployments/#list-deployments
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>All the <see cref="Deployment"/>s for the specified repository.</returns>
public IObservable<Deployment> GetAll(string owner, string name, ApiOptions options)
{
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Ensure.ArgumentNotNullOrEmptyString(name, "name");
Ensure.ArgumentNotNull(options, "options");
return _connection.GetAndFlattenAllPages<Deployment>(
ApiUrls.Deployments(owner, name));
ApiUrls.Deployments(owner, name), options);
}
/// <summary>
@@ -1,9 +1,10 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Octokit;
using Octokit.Tests.Integration;
using Xunit;
using Octokit.Tests.Integration.Helpers;
using Xunit;
public class DeploymentsClientTests : IDisposable
{
@@ -40,6 +41,40 @@ public class DeploymentsClientTests : IDisposable
_commit = github.Git.Commit.Create(_context.RepositoryOwner, _context.RepositoryName, newCommit).Result;
}
private IEnumerable<Commit> CreateCommits(int commitCount)
{
var github = Helper.GetAuthenticatedClient();
var list = new List<Commit>();
for (int i = 0; i < commitCount; i++)
{
var blob = new NewBlob
{
Content = string.Format("Hello World {0}!", i),
Encoding = EncodingType.Utf8
};
var blobResult = github.Git.Blob.Create(_context.RepositoryOwner, _context.RepositoryName, blob).Result;
var newTree = new NewTree();
newTree.Tree.Add(new NewTreeItem
{
Type = TreeType.Blob,
Mode = FileMode.File,
Path = "README.md",
Sha = blobResult.Sha
});
var treeResult = github.Git.Tree.Create(_context.RepositoryOwner, _context.RepositoryName, newTree).Result;
var newCommit = new NewCommit("test-commit", treeResult.Sha);
var commit = github.Git.Commit.Create(_context.RepositoryOwner, _context.RepositoryName, newCommit).Result;
list.Add(commit);
}
return list;
}
[IntegrationTest]
public async Task CanCreateDeployment()
{
@@ -51,7 +86,7 @@ public class DeploymentsClientTests : IDisposable
}
[IntegrationTest]
public async Task CanGetDeployments()
public async Task ReturnsDeployments()
{
var newDeployment = new NewDeployment(_commit.Sha) { AutoMerge = false };
await _deploymentsClient.Create(_context.RepositoryOwner, _context.RepositoryName, newDeployment);
@@ -61,6 +96,81 @@ public class DeploymentsClientTests : IDisposable
Assert.NotEmpty(deployments);
}
[IntegrationTest]
public async Task ReturnsCorrectCountOfDeploymentsWithoutStart()
{
var commits = CreateCommits(6);
foreach (var commit in commits)
{
var newDeployment = new NewDeployment(commit.Sha) { AutoMerge = false };
await _deploymentsClient.Create(_context.RepositoryOwner, _context.RepositoryName, newDeployment);
}
var options = new ApiOptions
{
PageSize = 5,
PageCount = 1
};
var releases = await _deploymentsClient.GetAll(_context.RepositoryOwner, _context.RepositoryName, options);
Assert.Equal(5, releases.Count);
}
[IntegrationTest]
public async Task ReturnsCorrectCountOfDeploymentsWithStart()
{
var commits = CreateCommits(6);
foreach (var commit in commits)
{
var newDeployment = new NewDeployment(commit.Sha) { AutoMerge = false };
await _deploymentsClient.Create(_context.RepositoryOwner, _context.RepositoryName, newDeployment);
}
var options = new ApiOptions
{
PageSize = 3,
PageCount = 1,
StartPage = 2
};
var releases = await _deploymentsClient.GetAll(_context.RepositoryOwner, _context.RepositoryName, options);
Assert.Equal(3, releases.Count);
}
[IntegrationTest]
public async Task ReturnsDistinctResultsBasedOnStartPage()
{
var commits = CreateCommits(6);
foreach (var commit in commits)
{
var newDeployment = new NewDeployment(commit.Sha) { AutoMerge = false };
await _deploymentsClient.Create(_context.RepositoryOwner, _context.RepositoryName, newDeployment);
}
var startOptions = new ApiOptions
{
PageSize = 3,
PageCount = 1
};
var firstPage = await _deploymentsClient.GetAll(_context.RepositoryOwner, _context.RepositoryName, startOptions);
var skipStartOptions = new ApiOptions
{
PageSize = 3,
PageCount = 1,
StartPage = 2
};
var secondPage = await _deploymentsClient.GetAll(_context.RepositoryOwner, _context.RepositoryName, skipStartOptions);
Assert.NotEqual(firstPage[0].Id, secondPage[0].Id);
Assert.NotEqual(firstPage[1].Id, secondPage[1].Id);
Assert.NotEqual(firstPage[2].Id, secondPage[2].Id);
}
public void Dispose()
{
_context.Dispose();
+35 -10
View File
@@ -2,19 +2,24 @@
using System.Threading.Tasks;
using NSubstitute;
using Octokit;
using Octokit.Tests;
using Xunit;
public class DeploymentsClientTests
{
public class TheGetAllMethod
{
private const string name = "name";
private const string owner = "owner";
[Fact]
public async Task EnsuresNonNullArguments()
{
var client = new DeploymentsClient(Substitute.For<IApiConnection>());
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(null, "name"));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll("owner", null));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(null, name));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(owner, null));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAll(owner, name, null));
}
[Fact]
@@ -22,8 +27,8 @@ public class DeploymentsClientTests
{
var client = new DeploymentsClient(Substitute.For<IApiConnection>());
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("", "name"));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("owner", ""));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("", name));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll(owner, ""));
}
[Theory]
@@ -36,8 +41,8 @@ public class DeploymentsClientTests
{
var client = new DeploymentsClient(Substitute.For<IApiConnection>());
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll(whitespace, "name"));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll("owner", whitespace));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll(whitespace, name));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAll(owner, whitespace));
}
[Fact]
@@ -45,16 +50,36 @@ public class DeploymentsClientTests
{
var connection = Substitute.For<IApiConnection>();
var client = new DeploymentsClient(connection);
var expectedUrl = "repos/owner/name/deployments";
var expectedUrl = string.Format("repos/{0}/{1}/deployments", owner, name);
client.GetAll("owner", "name");
connection.Received(1).GetAll<Deployment>(Arg.Is<Uri>(u => u.ToString() == expectedUrl));
client.GetAll(owner, name);
connection.Received(1)
.GetAll<Deployment>(Arg.Is<Uri>(u => u.ToString() == expectedUrl), Args.ApiOptions);
}
[Fact]
public void RequestsCorrectUrlWithApiOptions()
{
var connection = Substitute.For<IApiConnection>();
var client = new DeploymentsClient(connection);
var expectedUrl = string.Format("repos/{0}/{1}/deployments", owner, name);
var options = new ApiOptions
{
PageSize = 1,
PageCount = 1,
StartPage = 1
};
client.GetAll(owner, name, options);
connection.Received(1)
.GetAll<Deployment>(Arg.Is<Uri>(u => u.ToString() == expectedUrl), options);
}
}
public class TheCreateMethod
{
readonly NewDeployment newDeployment = new NewDeployment("aRef");
private readonly NewDeployment newDeployment = new NewDeployment("aRef");
[Fact]
public async Task EnsuresNonNullArguments()
@@ -13,8 +13,10 @@ namespace Octokit.Tests.Reactive
{
public class TheGetAllMethod
{
readonly IGitHubClient _githubClient;
readonly ObservableDeploymentsClient _client;
private readonly IGitHubClient _githubClient;
private readonly ObservableDeploymentsClient _client;
private const string owner = "owner";
private const string name = "name";
public TheGetAllMethod()
{
@@ -25,43 +27,88 @@ namespace Octokit.Tests.Reactive
[Fact]
public void EnsuresNonNullArguments()
{
Assert.Throws<ArgumentNullException>(() => _client.GetAll(null, "repo"));
Assert.Throws<ArgumentNullException>(() => _client.GetAll("owner", null));
Assert.Throws<ArgumentNullException>(() => _client.GetAll(null, name));
Assert.Throws<ArgumentNullException>(() => _client.GetAll(owner, null));
Assert.Throws<ArgumentNullException>(() => _client.GetAll(owner, name, null));
}
[Fact]
public void EnsuresNonEmptyArguments()
{
Assert.Throws<ArgumentException>(() => _client.GetAll("", "repo"));
Assert.Throws<ArgumentException>(() => _client.GetAll("owner", ""));
Assert.Throws<ArgumentException>(() => _client.GetAll("", name));
Assert.Throws<ArgumentException>(() => _client.GetAll(owner, ""));
}
[Fact]
public async Task EnsuresNonWhitespaceArguments()
{
await AssertEx.ThrowsWhenGivenWhitespaceArgument(
async whitespace => await _client.GetAll(whitespace, "repo"));
async whitespace => await _client.GetAll(whitespace, name));
await AssertEx.ThrowsWhenGivenWhitespaceArgument(
async whitespace => await _client.GetAll("owner", whitespace));
async whitespace => await _client.GetAll(owner, whitespace));
}
[Fact]
public void CallsDeploymentsUrl()
public void RequestsCorrectUrl()
{
var expectedUri = ApiUrls.Deployments("owner", "repo");
var expectedUrl = string.Format("repos/{0}/{1}/deployments", owner, name);
_client.GetAll("owner", "repo");
_githubClient.Connection
.Received(1)
.Get<List<Deployment>>(Arg.Is(expectedUri),
Arg.Any<IDictionary<string, string>>(), Arg.Any<string>());
_client.GetAll(owner, name);
_githubClient.Connection.Received(1)
.Get<List<Deployment>>(Arg.Is<Uri>(u => u.ToString() == expectedUrl),
Arg.Is<IDictionary<string, string>>(dictionary => dictionary.Count == 0),
Arg.Any<string>());
}
[Fact]
public void RequestsCorrectUrlWithApiOptions()
{
var expectedUrl = string.Format("repos/{0}/{1}/deployments", owner, name);
// all properties are setted => only 2 options (StartPage, PageSize) in dictionary
var options = new ApiOptions
{
StartPage = 1,
PageCount = 1,
PageSize = 1
};
_client.GetAll(owner, name, options);
_githubClient.Connection.Received(1)
.Get<List<Deployment>>(Arg.Is<Uri>(u => u.ToString() == expectedUrl),
Arg.Is<IDictionary<string, string>>(dictionary => dictionary.Count == 2),
null);
// StartPage is setted => only 1 option (StartPage) in dictionary
options = new ApiOptions
{
StartPage = 1
};
_client.GetAll(owner, name, options);
_githubClient.Connection.Received(1)
.Get<List<Deployment>>(Arg.Is<Uri>(u => u.ToString() == expectedUrl),
Arg.Is<IDictionary<string, string>>(dictionary => dictionary.Count == 1),
null);
// PageCount is setted => none of options in dictionary
options = new ApiOptions
{
PageCount = 1
};
_client.GetAll(owner, name, options);
_githubClient.Connection.Received(1)
.Get<List<Deployment>>(Arg.Is<Uri>(u => u.ToString() == expectedUrl),
Arg.Is<IDictionary<string, string>>(dictionary => dictionary.Count == 0),
null);
}
}
public class TheCreateMethod
{
IGitHubClient _githubClient;
ObservableDeploymentsClient _client;
private readonly IGitHubClient _githubClient;
private ObservableDeploymentsClient _client;
public TheCreateMethod()
{
@@ -117,9 +164,10 @@ namespace Octokit.Tests.Reactive
var newDeployment = new NewDeployment("ref");
_client.Create("owner", "repo", newDeployment);
_githubClient.Repository.Deployment.Received(1).Create(Arg.Is("owner"),
Arg.Is("repo"),
Arg.Is(newDeployment));
Arg.Is("repo"),
Arg.Is(newDeployment));
}
}
@@ -132,4 +180,4 @@ namespace Octokit.Tests.Reactive
}
}
}
}
}
+22 -2
View File
@@ -34,10 +34,30 @@ namespace Octokit
/// <returns>All the <see cref="Deployment"/>s for the specified repository.</returns>
public Task<IReadOnlyList<Deployment>> GetAll(string owner, string name)
{
Ensure.ArgumentNotNullOrEmptyString(owner, "login");
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Ensure.ArgumentNotNullOrEmptyString(name, "name");
return ApiConnection.GetAll<Deployment>(ApiUrls.Deployments(owner, name));
return GetAll(owner, name, ApiOptions.None);
}
/// <summary>
/// Gets all the deployments for the specified repository. Any user with pull access
/// to a repository can view deployments.
/// </summary>
/// <remarks>
/// http://developer.github.com/v3/repos/deployments/#list-deployments
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>All the <see cref="Deployment"/>s for the specified repository.</returns>
public Task<IReadOnlyList<Deployment>> GetAll(string owner, string name, ApiOptions options)
{
Ensure.ArgumentNotNullOrEmptyString(owner, "owner");
Ensure.ArgumentNotNullOrEmptyString(name, "name");
Ensure.ArgumentNotNull(options, "options");
return ApiConnection.GetAll<Deployment>(ApiUrls.Deployments(owner, name), options);
}
/// <summary>
+13
View File
@@ -24,6 +24,19 @@ namespace Octokit
/// <returns>All the <see cref="Deployment"/>s for the specified repository.</returns>
Task<IReadOnlyList<Deployment>> GetAll(string owner, string name);
/// <summary>
/// Gets all the deployments for the specified repository. Any user with pull access
/// to a repository can view deployments.
/// </summary>
/// <remarks>
/// http://developer.github.com/v3/repos/deployments/#list-deployments
/// </remarks>
/// <param name="owner">The owner of the repository</param>
/// <param name="name">The name of the repository</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>All the <see cref="Deployment"/>s for the specified repository.</returns>
Task<IReadOnlyList<Deployment>> GetAll(string owner, string name, ApiOptions options);
/// <summary>
/// Creates a new deployment for the specified repository.
/// Users with push access can create a deployment for a given ref.