Skip to content

Commit

Permalink
preview support for repository visibility (#2217)
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanJosipovic authored Feb 21, 2021
1 parent e40c792 commit 6105a9d
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 30 deletions.
43 changes: 29 additions & 14 deletions Octokit.Tests/Clients/RepositoriesClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ public void UsesTheUserReposUrl()

client.Create(new NewRepository("aName"));

connection.Received().Post<Repository>(Arg.Is<Uri>(u => u.ToString() == "user/repos"), Arg.Any<NewRepository>());
connection.Received().Post<Repository>(Arg.Is<Uri>(u => u.ToString() == "user/repos"),
Arg.Any<NewRepository>(),
"application/vnd.github.nebula-preview+json");
}

[Fact]
Expand All @@ -52,7 +54,7 @@ public void TheNewRepositoryDescription()

client.Create(newRepository);

connection.Received().Post<Repository>(Args.Uri, newRepository);
connection.Received().Post<Repository>(Args.Uri, newRepository, "application/vnd.github.nebula-preview+json");
}

[Fact]
Expand All @@ -68,7 +70,7 @@ public async Task ThrowsRepositoryExistsExceptionWhenRepositoryExistsForCurrentU
var connection = Substitute.For<IApiConnection>();
connection.Connection.BaseAddress.Returns(GitHubClient.GitHubApiUrl);
connection.Connection.Credentials.Returns(credentials);
connection.Post<Repository>(Args.Uri, newRepository)
connection.Post<Repository>(Args.Uri, newRepository, "application/vnd.github.nebula-preview+json")
.Returns<Task<Repository>>(_ => { throw new ApiValidationException(response); });
var client = new RepositoriesClient(connection);

Expand All @@ -95,7 +97,7 @@ public async Task ThrowsExceptionWhenPrivateRepositoryQuotaExceeded()
var connection = Substitute.For<IApiConnection>();
connection.Connection.BaseAddress.Returns(GitHubClient.GitHubApiUrl);
connection.Connection.Credentials.Returns(credentials);
connection.Post<Repository>(Args.Uri, newRepository)
connection.Post<Repository>(Args.Uri, newRepository, "application/vnd.github.nebula-preview+json")
.Returns<Task<Repository>>(_ => { throw new ApiValidationException(response); });
var client = new RepositoriesClient(connection);

Expand Down Expand Up @@ -127,7 +129,8 @@ public async Task UsesTheOrganizationsReposUrl()

connection.Received().Post<Repository>(
Arg.Is<Uri>(u => u.ToString() == "orgs/theLogin/repos"),
Args.NewRepository);
Args.NewRepository,
"application/vnd.github.nebula-preview+json");
}

[Fact]
Expand All @@ -139,7 +142,7 @@ public async Task TheNewRepositoryDescription()

await client.Create("aLogin", newRepository);

connection.Received().Post<Repository>(Args.Uri, newRepository);
connection.Received().Post<Repository>(Args.Uri, newRepository, "application/vnd.github.nebula-preview+json");
}

[Fact]
Expand All @@ -153,7 +156,7 @@ public async Task ThrowsRepositoryExistsExceptionWhenRepositoryExistsForSpecifie
+ @"""code"":""custom"",""field"":""name"",""message"":""name already exists on this account""}]}");
var connection = Substitute.For<IApiConnection>();
connection.Connection.BaseAddress.Returns(GitHubClient.GitHubApiUrl);
connection.Post<Repository>(Args.Uri, newRepository)
connection.Post<Repository>(Args.Uri, newRepository, "application/vnd.github.nebula-preview+json")
.Returns<Task<Repository>>(_ => { throw new ApiValidationException(response); });
var client = new RepositoriesClient(connection);

Expand All @@ -178,7 +181,7 @@ public async Task ThrowsValidationException()
+ @"""http://developer.github.com/v3/repos/#create"",""errors"":[]}");
var connection = Substitute.For<IApiConnection>();
connection.Connection.BaseAddress.Returns(GitHubClient.GitHubApiUrl);
connection.Post<Repository>(Args.Uri, newRepository)
connection.Post<Repository>(Args.Uri, newRepository, "application/vnd.github.nebula-preview+json")
.Returns<Task<Repository>>(_ => { throw new ApiValidationException(response); });
var client = new RepositoriesClient(connection);

Expand All @@ -199,7 +202,7 @@ public async Task ThrowsRepositoryExistsExceptionForEnterpriseInstance()
+ @"""code"":""custom"",""field"":""name"",""message"":""name already exists on this account""}]}");
var connection = Substitute.For<IApiConnection>();
connection.Connection.BaseAddress.Returns(new Uri("https://example.com"));
connection.Post<Repository>(Args.Uri, newRepository)
connection.Post<Repository>(Args.Uri, newRepository, "application/vnd.github.nebula-preview+json")
.Returns<Task<Repository>>(_ => { throw new ApiValidationException(response); });
var client = new RepositoriesClient(connection);

Expand Down Expand Up @@ -402,7 +405,9 @@ public async Task RequestsCorrectUrl()
await client.Get("owner", "name");

connection.Received()
.Get<Repository>(Arg.Is<Uri>(u => u.ToString() == "repos/owner/name"));
.Get<Repository>(Arg.Is<Uri>(u => u.ToString() == "repos/owner/name"),
null,
"application/vnd.github.nebula-preview+json");
}

[Fact]
Expand Down Expand Up @@ -483,7 +488,10 @@ public async Task RequestsTheCorrectUrlAndReturnsRepositories()
await client.GetAllForCurrent();

connection.Received()
.GetAll<Repository>(Arg.Is<Uri>(u => u.ToString() == "user/repos"), Args.ApiOptions);
.GetAll<Repository>(Arg.Is<Uri>(u => u.ToString() == "user/repos"),
null,
"application/vnd.github.nebula-preview+json",
Args.ApiOptions);
}

[Fact]
Expand All @@ -503,6 +511,7 @@ public async Task CanFilterByType()
.GetAll<Repository>(
Arg.Is<Uri>(u => u.ToString() == "user/repos"),
Arg.Is<Dictionary<string, string>>(d => d["type"] == "all"),
"application/vnd.github.nebula-preview+json",
Args.ApiOptions);
}

Expand All @@ -524,6 +533,7 @@ public async Task CanFilterBySort()
.GetAll<Repository>(
Arg.Is<Uri>(u => u.ToString() == "user/repos"),
Arg.Is<Dictionary<string, string>>(d => d["type"] == "private" && d["sort"] == "full_name"),
"application/vnd.github.nebula-preview+json",
Args.ApiOptions);
}

Expand All @@ -546,6 +556,7 @@ public async Task CanFilterBySortDirection()
.GetAll<Repository>(
Arg.Is<Uri>(u => u.ToString() == "user/repos"),
Arg.Is<Dictionary<string, string>>(d => d["type"] == "member" && d["sort"] == "updated" && d["direction"] == "asc"),
"application/vnd.github.nebula-preview+json",
Args.ApiOptions);
}

Expand All @@ -557,7 +568,7 @@ public async Task CanFilterByVisibility()

var request = new RepositoryRequest
{
Visibility = RepositoryVisibility.Private
Visibility = RepositoryRequestVisibility.Private
};

await client.GetAllForCurrent(request);
Expand All @@ -566,6 +577,7 @@ public async Task CanFilterByVisibility()
.GetAll<Repository>(
Arg.Is<Uri>(u => u.ToString() == "user/repos"),
Arg.Is<Dictionary<string, string>>(d => d["visibility"] == "private"),
"application/vnd.github.nebula-preview+json",
Args.ApiOptions);
}

Expand All @@ -587,6 +599,7 @@ public async Task CanFilterByAffiliation()
.GetAll<Repository>(
Arg.Is<Uri>(u => u.ToString() == "user/repos"),
Arg.Is<Dictionary<string, string>>(d => d["affiliation"] == "owner" && d["sort"] == "full_name"),
"application/vnd.github.nebula-preview+json",
Args.ApiOptions);
}
}
Expand Down Expand Up @@ -631,7 +644,7 @@ public async Task RequestsTheCorrectUrl()
await client.GetAllForOrg("orgname");

connection.Received()
.GetAll<Repository>(Arg.Is<Uri>(u => u.ToString() == "orgs/orgname/repos"), Args.ApiOptions);
.GetAll<Repository>(Arg.Is<Uri>(u => u.ToString() == "orgs/orgname/repos"), null, "application/vnd.github.nebula-preview+json", Args.ApiOptions);
}

[Fact]
Expand Down Expand Up @@ -1063,7 +1076,9 @@ public void PatchesCorrectUrl()
client.Edit("owner", "repo", update);

connection.Received()
.Patch<Repository>(Arg.Is<Uri>(u => u.ToString() == "repos/owner/repo"), Arg.Any<RepositoryUpdate>());
.Patch<Repository>(Arg.Is<Uri>(u => u.ToString() == "repos/owner/repo"),
Arg.Any<RepositoryUpdate>(),
"application/vnd.github.nebula-preview+json");
}

[Fact]
Expand Down
2 changes: 1 addition & 1 deletion Octokit.Tests/Models/RepositoryRequestTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void ContainsSetValues()
request = new RepositoryRequest
{
Affiliation = RepositoryAffiliation.All,
Visibility = RepositoryVisibility.Public
Visibility = RepositoryRequestVisibility.Public
};

parameters = request.ToParametersDictionary();
Expand Down
24 changes: 17 additions & 7 deletions Octokit/Clients/RepositoriesClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public RepositoriesClient(IApiConnection apiConnection) : base(apiConnection)
/// <param name="newRepository">A <see cref="NewRepository"/> instance describing the new repository to create</param>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>A <see cref="Repository"/> instance for the created repository.</returns>
[Preview("nebula")]
[ManualRoute("POST", "/user/repos")]
public Task<Repository> Create(NewRepository newRepository)
{
Expand All @@ -68,6 +69,7 @@ public Task<Repository> Create(NewRepository newRepository)
/// <param name="newRepository">A <see cref="NewRepository"/> instance describing the new repository to create</param>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>A <see cref="Repository"/> instance for the created repository</returns>
[Preview("nebula")]
[ManualRoute("POST", "/orgs/{org}/repos")]
public Task<Repository> Create(string organizationLogin, NewRepository newRepository)
{
Expand All @@ -83,7 +85,7 @@ async Task<Repository> Create(Uri url, string organizationLogin, NewRepository n
{
try
{
return await ApiConnection.Post<Repository>(url, newRepository).ConfigureAwait(false);
return await ApiConnection.Post<Repository>(url, newRepository, AcceptHeaders.VisibilityPreview).ConfigureAwait(false);
}
catch (ApiValidationException e)
{
Expand Down Expand Up @@ -211,6 +213,7 @@ public Task<Repository> Transfer(long repositoryId, RepositoryTransfer repositor
/// <param name="name">The name of the repository</param>
/// <param name="update">New values to update the repository with</param>
/// <returns>The updated <see cref="T:Octokit.Repository"/></returns>
[Preview("nebula")]
[ManualRoute("PATCH", "/repos/{owner}/{repo}")]
public Task<Repository> Edit(string owner, string name, RepositoryUpdate update)
{
Expand All @@ -219,7 +222,7 @@ public Task<Repository> Edit(string owner, string name, RepositoryUpdate update)
Ensure.ArgumentNotNull(update, nameof(update));
Ensure.ArgumentNotNull(update.Name, nameof(update.Name));

return ApiConnection.Patch<Repository>(ApiUrls.Repository(owner, name), update);
return ApiConnection.Patch<Repository>(ApiUrls.Repository(owner, name), update, AcceptHeaders.VisibilityPreview);
}

/// <summary>
Expand All @@ -246,13 +249,14 @@ public Task<Repository> Edit(long repositoryId, RepositoryUpdate update)
/// <param name="name">The name of the repository</param>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>A <see cref="Repository"/></returns>
[Preview("nebula")]
[ManualRoute("GET", "/repos/{owner}/{repo}")]
public Task<Repository> Get(string owner, string name)
{
Ensure.ArgumentNotNullOrEmptyString(owner, nameof(owner));
Ensure.ArgumentNotNullOrEmptyString(name, nameof(name));

return ApiConnection.Get<Repository>(ApiUrls.Repository(owner, name));
return ApiConnection.Get<Repository>(ApiUrls.Repository(owner, name), null, AcceptHeaders.VisibilityPreview);
}

/// <summary>
Expand All @@ -279,7 +283,7 @@ public Task<Repository> Get(long repositoryId)
/// </remarks>
/// <exception cref="AuthorizationException">Thrown if the client is not authenticated.</exception>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>A <see cref="IReadOnlyList{Repository}"/> of <see cref="Repository"/>.</returns>
/// <returns>A <see cref="IReadOnlyList{Repository}"/> of <see cref="Repository"/>.</returns>
[ManualRoute("GET", "/repositories")]
public Task<IReadOnlyList<Repository>> GetAllPublic()
{
Expand Down Expand Up @@ -317,6 +321,7 @@ public Task<IReadOnlyList<Repository>> GetAllPublic(PublicRepositoryRequest requ
/// <exception cref="AuthorizationException">Thrown if the client is not authenticated.</exception>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>A <see cref="IReadOnlyList{Repository}"/> of <see cref="Repository"/>.</returns>
[Preview("nebula")]
[ManualRoute("GET", "/user/repos")]
public Task<IReadOnlyList<Repository>> GetAllForCurrent()
{
Expand All @@ -333,12 +338,13 @@ public Task<IReadOnlyList<Repository>> GetAllForCurrent()
/// <exception cref="AuthorizationException">Thrown if the client is not authenticated.</exception>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>A <see cref="IReadOnlyList{Repository}"/> of <see cref="Repository"/>.</returns>
[Preview("nebula")]
[ManualRoute("GET", "/user/repos")]
public Task<IReadOnlyList<Repository>> GetAllForCurrent(ApiOptions options)
{
Ensure.ArgumentNotNull(options, nameof(options));

return ApiConnection.GetAll<Repository>(ApiUrls.Repositories(), options);
return ApiConnection.GetAll<Repository>(ApiUrls.Repositories(), null, AcceptHeaders.VisibilityPreview, options);
}

/// <summary>
Expand All @@ -352,6 +358,7 @@ public Task<IReadOnlyList<Repository>> GetAllForCurrent(ApiOptions options)
/// <exception cref="AuthorizationException">Thrown if the client is not authenticated.</exception>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>A <see cref="IReadOnlyList{Repository}"/> of <see cref="Repository"/>.</returns>
[Preview("nebula")]
[ManualRoute("GET", "/user/repos")]
public Task<IReadOnlyList<Repository>> GetAllForCurrent(RepositoryRequest request)
{
Expand All @@ -372,13 +379,14 @@ public Task<IReadOnlyList<Repository>> GetAllForCurrent(RepositoryRequest reques
/// <exception cref="AuthorizationException">Thrown if the client is not authenticated.</exception>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>A <see cref="IReadOnlyList{Repository}"/> of <see cref="Repository"/>.</returns>
[Preview("nebula")]
[ManualRoute("GET", "/user/repos")]
public Task<IReadOnlyList<Repository>> GetAllForCurrent(RepositoryRequest request, ApiOptions options)
{
Ensure.ArgumentNotNull(request, nameof(request));
Ensure.ArgumentNotNull(options, nameof(options));

return ApiConnection.GetAll<Repository>(ApiUrls.Repositories(), request.ToParametersDictionary(), options);
return ApiConnection.GetAll<Repository>(ApiUrls.Repositories(), request.ToParametersDictionary(), AcceptHeaders.VisibilityPreview, options);
}

/// <summary>
Expand Down Expand Up @@ -427,6 +435,7 @@ public Task<IReadOnlyList<Repository>> GetAllForUser(string login, ApiOptions op
/// </remarks>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>A <see cref="IReadOnlyList{Repository}"/> of <see cref="Repository"/>.</returns>
[Preview("nebula")]
[ManualRoute("GET", "/orgs/{org}/repos")]
public Task<IReadOnlyList<Repository>> GetAllForOrg(string organization)
{
Expand All @@ -445,13 +454,14 @@ public Task<IReadOnlyList<Repository>> GetAllForOrg(string organization)
/// <param name="options">Options for changing the API response</param>
/// <exception cref="ApiException">Thrown when a general API error occurs.</exception>
/// <returns>A <see cref="IReadOnlyList{Repository}"/> of <see cref="Repository"/>.</returns>
[Preview("nebula")]
[ManualRoute("GET", "/orgs/{org}/repos")]
public Task<IReadOnlyList<Repository>> GetAllForOrg(string organization, ApiOptions options)
{
Ensure.ArgumentNotNullOrEmptyString(organization, nameof(organization));
Ensure.ArgumentNotNull(options, nameof(options));

return ApiConnection.GetAll<Repository>(ApiUrls.OrganizationRepositories(organization), options);
return ApiConnection.GetAll<Repository>(ApiUrls.OrganizationRepositories(organization), null, AcceptHeaders.VisibilityPreview, options);
}

/// <summary>
Expand Down
2 changes: 2 additions & 0 deletions Octokit/Helpers/AcceptHeaders.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public static class AcceptHeaders

public const string OAuthApplicationsPreview = "application/vnd.github.doctor-strange-preview+json";

public const string VisibilityPreview = "application/vnd.github.nebula-preview+json";

/// <summary>
/// Combines multiple preview headers. GitHub API supports Accept header with multiple
/// values separated by comma.
Expand Down
Loading

0 comments on commit 6105a9d

Please sign in to comment.