Skip to content

Commit

Permalink
feat: Adds cancel invitation
Browse files Browse the repository at this point in the history
* Added api request to cancel an organization invitation

* Added tests

---------

Co-authored-by: Nick Floyd <139819+nickfloyd@users.noreply.github.com>
  • Loading branch information
thomaslem and nickfloyd authored Feb 13, 2024
1 parent bf3a3a3 commit c2178a4
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 1 deletion.
14 changes: 13 additions & 1 deletion Octokit.Reactive/Clients/IObservableOrganizationMembersClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,19 @@ public interface IObservableOrganizationMembersClient
/// <param name="options">Options to change API behaviour</param>
/// <returns></returns>
IObservable<OrganizationMembershipInvitation> GetAllFailedInvitations(string org, ApiOptions options);


/// <summary>
/// Cancel an organization invitation. In order to cancel an organization invitation, the authenticated user must be an organization owner.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/orgs/members#cancel-an-organization-invitation">API Documentation</a>
/// for more information.
/// </remarks>
/// <param name="org">The login for the organization</param>
/// <param name="invitationId">The unique identifier of the invitation</param>
/// <returns></returns>
IObservable<Unit> CancelOrganizationInvitation(string org, int invitationId);

/// <summary>
/// Returns all <see cref="OrganizationMembership" />s for the current user.
/// </summary>
Expand Down
19 changes: 19 additions & 0 deletions Octokit.Reactive/Clients/ObservableOrganizationMembersClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,25 @@ public IObservable<OrganizationMembershipInvitation> GetAllFailedInvitations(str
return _connection.GetAndFlattenAllPages<OrganizationMembershipInvitation>(ApiUrls.OrganizationFailedInvitations(org), null, options);
}

/// <summary>
/// Cancel an organization invitation. In order to cancel an organization invitation, the authenticated user must be an organization owner.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/orgs/members#cancel-an-organization-invitation">API Documentation</a>
/// for more information.
/// </remarks>
/// <param name="org">The login for the organization</param>
/// <param name="invitationId">The unique identifier of the invitation</param>
/// <returns></returns>
[ManualRoute("DELETE", "/orgs/{org}/invitations/{invitation_id}")]
public IObservable<Unit> CancelOrganizationInvitation(string org, int invitationId)
{
Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
Ensure.ArgumentNotNullOrDefault(invitationId, nameof(invitationId));

return _client.CancelOrganizationInvitation(org, invitationId).ToObservable();
}

/// <summary>
/// Returns all <see cref="OrganizationMembership" />s for the current user.
/// </summary>
Expand Down
24 changes: 24 additions & 0 deletions Octokit.Tests/Clients/OrganizationMembersClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -628,5 +628,29 @@ public async Task EnsureNonNullArguments()
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllPendingInvitations("org", null));
}
}

public class TheCancelOrganizationInvitationMethod
{
[Fact]
public void PostsToCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new OrganizationMembersClient(connection);

client.CancelOrganizationInvitation("org", 1);

connection.Received().Delete(Arg.Is<Uri>(u => u.ToString() == "orgs/org/invitations/1"));
}

[Fact]
public async Task EnsureNonNullArguments()
{
var client = new OrganizationMembersClient(Substitute.For<IApiConnection>());

await Assert.ThrowsAsync<ArgumentNullException>(() => client.CancelOrganizationInvitation(null, 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.CancelOrganizationInvitation("", 1));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.CancelOrganizationInvitation("org", 0));
}
}
}
}
24 changes: 24 additions & 0 deletions Octokit.Tests/Reactive/ObservableOrganizationMembersClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -434,5 +434,29 @@ public async Task EnsuresNonNullArguments()
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllPendingInvitations("org", null).ToTask());
}
}

public class TheCancelOrganizationInvitationMethod
{
[Fact]
public void CancelInvitationFromClientOrganizationMember()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservableOrganizationMembersClient(gitHubClient);

client.CancelOrganizationInvitation("org", 1);

gitHubClient.Organization.Member.Received().CancelOrganizationInvitation("org", 1);
}

[Fact]
public async Task EnsuresNonNullArguments()
{
var client = new ObservableOrganizationMembersClient(Substitute.For<IGitHubClient>());

await Assert.ThrowsAsync<ArgumentNullException>(() => client.CancelOrganizationInvitation(null, 1).ToTask());
await Assert.ThrowsAsync<ArgumentException>(() => client.CancelOrganizationInvitation("", 1).ToTask());
await Assert.ThrowsAsync<ArgumentNullException>(() => client.CancelOrganizationInvitation("org", 0).ToTask());
}
}
}
}
12 changes: 12 additions & 0 deletions Octokit/Clients/IOrganizationMembersClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,18 @@ public interface IOrganizationMembersClient
/// <returns></returns>
Task<IReadOnlyList<OrganizationMembershipInvitation>> GetAllFailedInvitations(string org, ApiOptions options);

/// <summary>
/// Cancel an organization invitation. In order to cancel an organization invitation, the authenticated user must be an organization owner.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/orgs/members#cancel-an-organization-invitation">API Documentation</a>
/// for more information.
/// </remarks>
/// <param name="org">The login for the organization</param>
/// <param name="invitationId">The unique identifier of the invitation</param>
/// <returns></returns>
Task CancelOrganizationInvitation(string org, int invitationId);

/// <summary>
/// Returns all <see cref="OrganizationMembership" />s for the current user.
/// </summary>
Expand Down
19 changes: 19 additions & 0 deletions Octokit/Clients/OrganizationMembersClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,25 @@ public Task<IReadOnlyList<OrganizationMembershipInvitation>> GetAllFailedInvitat
return ApiConnection.GetAll<OrganizationMembershipInvitation>(ApiUrls.OrganizationFailedInvitations(org), null, options);
}

/// <summary>
/// Cancel an organization invitation. In order to cancel an organization invitation, the authenticated user must be an organization owner.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/orgs/members#cancel-an-organization-invitation">API Documentation</a>
/// for more information.
/// </remarks>
/// <param name="org">The login for the organization</param>
/// <param name="invitationId">The unique identifier of the invitation</param>
/// <returns></returns>
[ManualRoute("DELETE", "/orgs/{org}/invitations/{invitation_id}")]
public Task CancelOrganizationInvitation(string org, int invitationId)
{
Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
Ensure.ArgumentNotNullOrDefault(invitationId, nameof(invitationId));

return ApiConnection.Delete(ApiUrls.CancelOrganizationInvitation(org, invitationId));
}

/// <summary>
/// Returns all <see cref="OrganizationMembership" />s for the current user.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions Octokit/Helpers/ApiUrls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,17 @@ public static Uri OrganizationFailedInvitations(string org)
return "orgs/{0}/failed_invitations".FormatUri(org);
}

/// <summary>
/// Returns the <see cref="Uri"/> to cancel an organization invitation
/// </summary>
/// <param name="org">The name of the organization</param>
/// <param name="invitationId">The unique identifier of the invitation</param>
/// <returns></returns>
public static Uri CancelOrganizationInvitation(string org, int invitationId)
{
return "orgs/{0}/invitations/{1}".FormatUri(org, invitationId);
}

/// <summary>
/// Returns the <see cref="Uri"/> that returns all of the outside collaborators of the organization
/// </summary>
Expand Down

0 comments on commit c2178a4

Please sign in to comment.