Skip to content

Commit

Permalink
Merge pull request #331 from PinguApps/308-task-teams-list-team-membe…
Browse files Browse the repository at this point in the history
…rships

Implemented list team memberships
  • Loading branch information
pingu2k4 authored Oct 19, 2024
2 parents 98f3556 + a0c564c commit f81ed71
Show file tree
Hide file tree
Showing 12 changed files with 356 additions and 39 deletions.
17 changes: 0 additions & 17 deletions .github/workflows/pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,3 @@ jobs:
contents: read
issues: read
checks: write

run_code_review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Code Review GPT
uses: mattzcarey/[email protected]
with:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
MODEL: 'gpt-4o'
GITHUB_TOKEN: ${{ github.token }}
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,11 @@ string emailAddressOrErrorMessage = userResponse.Result.Match(

## ⌛ Progress
<!-- `red` for first third, `gold` for second third, `forestgreen` for final third, `blue` for 100% -->
![Server & Client - 110 / 318](https://img.shields.io/badge/Server_&_Client-110%20%2F%20318-gold?style=for-the-badge)
![Server & Client - 112 / 318](https://img.shields.io/badge/Server_&_Client-112%20%2F%20318-gold?style=for-the-badge)

![Server - 58 / 225](https://img.shields.io/badge/Server-58%20%2F%20225-red?style=for-the-badge)
![Server - 59 / 225](https://img.shields.io/badge/Server-59%20%2F%20225-red?style=for-the-badge)

![Client - 52 / 93](https://img.shields.io/badge/Client-52%20%2F%2093-gold?style=for-the-badge)
![Client - 53 / 93](https://img.shields.io/badge/Client-53%20%2F%2093-gold?style=for-the-badge)

### 🔑 Key
| Icon | Definition |
Expand Down Expand Up @@ -256,16 +256,16 @@ string emailAddressOrErrorMessage = userResponse.Result.Match(
| [Update Phone Verification](https://appwrite.io/docs/references/1.6.x/server-rest/users#updatePhoneVerification) |||

### Teams
![Teams - 10 / 26](https://img.shields.io/badge/Teams-10%20%2F%2026-gold?style=for-the-badge)
![Teams - 12 / 26](https://img.shields.io/badge/Teams-12%20%2F%2026-gold?style=for-the-badge)

| Endpoint | Client | Server |
|:-:|:-:|:-:|
| [List Teams](https://appwrite.io/docs/references/1.6.x/client-rest/teams#list) |||
| [Create Team](https://appwrite.io/docs/references/1.6.x/client-rest/teams#create) |||
| [Get Team](https://appwrite.io/docs/references/1.6.x/client-rest/teams#get) |||
| [Update Name](https://appwrite.io/docs/references/1.6.x/client-rest/teams#updateName) |||
| [Delete Team](https://appwrite.io/docs/references/1.6.x/client-rest/teams#delete) | | |
| [List Team Memberships](https://appwrite.io/docs/references/1.6.x/client-rest/teams#listMemberships) | | |
| [Delete Team](https://appwrite.io/docs/references/1.6.x/client-rest/teams#delete) | | |
| [List Team Memberships](https://appwrite.io/docs/references/1.6.x/client-rest/teams#listMemberships) | | |
| [Create Team Membership](https://appwrite.io/docs/references/1.6.x/client-rest/teams#createMembership) |||
| [Get Team Membership](https://appwrite.io/docs/references/1.6.x/client-rest/teams#getMembership) |||
| [Update Membership](https://appwrite.io/docs/references/1.6.x/client-rest/teams#updateMembership) |||
Expand Down
8 changes: 7 additions & 1 deletion src/PinguApps.Appwrite.Client/Clients/ITeamsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,13 @@ public interface ITeamsClient
/// <param name="request">The request content</param>
/// <returns>The team</returns>
Task<AppwriteResult<Team>> UpdateName(UpdateNameRequest request);
[Obsolete("This method hasn't yet been implemented!")]

/// <summary>
/// Use this endpoint to list a team's members using the team's ID. All team members have read access to this endpoint.
/// <para><see href="https://appwrite.io/docs/references/1.6.x/client-rest/teams#listMemberships">Appwrite Docs</see></para>
/// </summary>
/// <param name="request">The request content</param>
/// <returns>The memberships list</returns>
Task<AppwriteResult<MembershipsList>> ListTeamMemberships(ListTeamMembershipsRequest request);
[Obsolete("This method hasn't yet been implemented!")]
Task<AppwriteResult<Membership>> CreateTeamMembership(CreateTeamMembershipRequest request);
Expand Down
17 changes: 15 additions & 2 deletions src/PinguApps.Appwrite.Client/Clients/TeamsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,22 @@ public async Task<AppwriteResult<Team>> UpdateName(UpdateNameRequest request)
}
}

[ExcludeFromCodeCoverage]
/// <inheritdoc/>
public Task<AppwriteResult<MembershipsList>> ListTeamMemberships(ListTeamMembershipsRequest request) => throw new NotImplementedException();
public async Task<AppwriteResult<MembershipsList>> ListTeamMemberships(ListTeamMembershipsRequest request)
{
try
{
request.Validate(true);

var result = await _teamsApi.ListTeamMemberships(GetCurrentSessionOrThrow(), request.TeamId, RequestUtils.GetQueryStrings(request.Queries), request.Search);

return result.GetApiResponse();
}
catch (Exception e)
{
return e.GetExceptionResponse<MembershipsList>();
}
}

[ExcludeFromCodeCoverage]
/// <inheritdoc/>
Expand Down
17 changes: 8 additions & 9 deletions src/PinguApps.Appwrite.Playground/App.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,21 @@ public async Task Run(string[] args)
{
_client.SetSession(_session);

var request = new UpdateNameRequest()
var request = new ListTeamMembershipsRequest()
{
TeamId = "67142b78001c379958cb",
Name = "a good team name"
TeamId = "67142b78001c379958cb"
};

//var clientResponse = await _client.Teams.UpdateName(request);
var clientResponse = await _client.Teams.ListTeamMemberships(request);

//Console.WriteLine(clientResponse.Result.Match(
// result => result.ToString(),
// appwriteError => appwriteError.Message,
// internalError => internalError.Message));
Console.WriteLine(clientResponse.Result.Match(
result => result.ToString(),
appwriteError => appwriteError.Message,
internalError => internalError.Message));

Console.WriteLine("############################################################################");

var serverResponse = await _server.Teams.UpdateName(request);
var serverResponse = await _server.Teams.ListTeamMemberships(request);

Console.WriteLine(serverResponse.Result.Match(
result => result.ToString(),
Expand Down
8 changes: 7 additions & 1 deletion src/PinguApps.Appwrite.Server/Clients/ITeamsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,13 @@ public interface ITeamsClient
/// <param name="request">The request content</param>
/// <returns>The team</returns>
Task<AppwriteResult<Team>> UpdateName(UpdateNameRequest request);
[Obsolete("This method hasn't yet been implemented!")]

/// <summary>
/// Use this endpoint to list a team's members using the team's ID. All team members have read access to this endpoint.
/// <para><see href="https://appwrite.io/docs/references/1.6.x/server-rest/teams#listMemberships">Appwrite Docs</see></para>
/// </summary>
/// <param name="request">The request content</param>
/// <returns>The memberships list</returns>
Task<AppwriteResult<MembershipsList>> ListTeamMemberships(ListTeamMembershipsRequest request);
[Obsolete("This method hasn't yet been implemented!")]
Task<AppwriteResult<Membership>> CreateTeamMembership(CreateTeamMembershipRequest request);
Expand Down
17 changes: 15 additions & 2 deletions src/PinguApps.Appwrite.Server/Clients/TeamsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,22 @@ public async Task<AppwriteResult<Team>> UpdateName(UpdateNameRequest request)
}
}

[ExcludeFromCodeCoverage]
/// <inheritdoc/>
public Task<AppwriteResult<MembershipsList>> ListTeamMemberships(ListTeamMembershipsRequest request) => throw new NotImplementedException();
public async Task<AppwriteResult<MembershipsList>> ListTeamMemberships(ListTeamMembershipsRequest request)
{
try
{
request.Validate(true);

var result = await _teamsApi.ListTeamMemberships(request.TeamId, RequestUtils.GetQueryStrings(request.Queries), request.Search);

return result.GetApiResponse();
}
catch (Exception e)
{
return e.GetExceptionResponse<MembershipsList>();
}
}

[ExcludeFromCodeCoverage]
/// <inheritdoc/>
Expand Down
2 changes: 1 addition & 1 deletion src/PinguApps.Appwrite.Shared/Responses/MembershipsList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ namespace PinguApps.Appwrite.Shared.Responses;
/// <param name="Memberships">List of memberships. Can be one of: <see cref="Membership"/></param>
public record MembershipsList(
[property: JsonPropertyName("total")] int Total,
[property: JsonPropertyName("memberships")] List<Membership> Memberships
[property: JsonPropertyName("memberships")] IReadOnlyList<Membership> Memberships
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
using System.Net;
using PinguApps.Appwrite.Client.Clients;
using PinguApps.Appwrite.Shared.Requests.Teams;
using PinguApps.Appwrite.Shared.Tests;
using PinguApps.Appwrite.Shared.Utils;
using RichardSzalay.MockHttp;

namespace PinguApps.Appwrite.Client.Tests.Clients.Teams;
public partial class TeamsClientTests
{
[Fact]
public async Task ListTeamMemberships_ShouldReturnSuccess_WhenApiCallSucceeds()
{
// Arrange
var request = new ListTeamMembershipsRequest
{
TeamId = IdUtils.GenerateUniqueId()
};

_mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/teams/{request.TeamId}/memberships")
.ExpectedHeaders(true)
.Respond(TestConstants.AppJson, TestConstants.MembershipsListResponse);

_appwriteClient.SetSession(TestConstants.Session);

// Act
var result = await _appwriteClient.Teams.ListTeamMemberships(request);

// Assert
Assert.True(result.Success);
}

[Fact]
public async Task ListTeamMemberships_ShouldProvideQueryParams_WhenQueriesAndSearchProvided()
{
// Arrange
var query = Query.Limit(5);
var search = "SearchString";
var request = new ListTeamMembershipsRequest
{
TeamId = IdUtils.GenerateUniqueId(),
Queries = [query],
Search = search
};

var expectedQueryParams = new Dictionary<string, string>
{
{ "queries[]", query.GetQueryString() },
{ "search", search }
};

_mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/teams/{request.TeamId}/memberships")
.ExpectedHeaders(true)
.WithQueryString($"queries[]={query.GetQueryString()}&search={search}")
.Respond(TestConstants.AppJson, TestConstants.LogsListResponse);

_appwriteClient.SetSession(TestConstants.Session);

// Act
var result = await _appwriteClient.Teams.ListTeamMemberships(request);

// Assert
Assert.True(result.Success);
}

[Fact]
public async Task ListTeamMemberships_ShouldReturnError_WhenSessionIsNull()
{
// Arrange
var request = new ListTeamMembershipsRequest
{
TeamId = IdUtils.GenerateUniqueId()
};

// Act
var result = await _appwriteClient.Teams.ListTeamMemberships(request);

// Assert
Assert.True(result.IsError);
Assert.True(result.IsInternalError);
Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message);
}

[Fact]
public async Task ListTeamMemberships_ShouldHandleException_WhenApiCallFails()
{
// Arrange
var request = new ListTeamMembershipsRequest
{
TeamId = IdUtils.GenerateUniqueId()
};

_mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/teams/{request.TeamId}/memberships")
.ExpectedHeaders(true)
.Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError);

_appwriteClient.SetSession(TestConstants.Session);

// Act
var result = await _appwriteClient.Teams.ListTeamMemberships(request);

// Assert
Assert.True(result.IsError);
Assert.True(result.IsAppwriteError);
}

[Fact]
public async Task ListTeamMemberships_ShouldReturnErrorResponse_WhenExceptionOccurs()
{
// Arrange
var request = new ListTeamMembershipsRequest
{
TeamId = IdUtils.GenerateUniqueId()
};

_mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/teams/{request.TeamId}/memberships")
.ExpectedHeaders(true)
.Throw(new HttpRequestException("An error occurred"));

_appwriteClient.SetSession(TestConstants.Session);

// Act
var result = await _appwriteClient.Teams.ListTeamMemberships(request);

// Assert
Assert.False(result.Success);
Assert.True(result.IsInternalError);
Assert.Equal("An error occurred", result.Result.AsT2.Message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using PinguApps.Appwrite.Client.Clients;
using PinguApps.Appwrite.Shared.Requests.Teams;
using PinguApps.Appwrite.Shared.Tests;
using PinguApps.Appwrite.Shared.Utils;
using RichardSzalay.MockHttp;

namespace PinguApps.Appwrite.Client.Tests.Clients.Teams;
Expand All @@ -26,6 +27,38 @@ public async Task ListTeams_ShouldReturnSuccess_WhenApiCallSucceeds()
Assert.True(result.Success);
}

[Fact]
public async Task ListTeams_ShouldProvideQueryParamss_WhenQueriesAndSearchProvided()
{
// Arrange
var query = Query.Limit(5);
var search = "SearchString";
var request = new ListTeamsRequest
{
Queries = [query],
Search = search
};

var expectedQueryParams = new Dictionary<string, string>
{
{ "queries[]", query.GetQueryString() },
{ "search", search }
};

_mockHttp.Expect(HttpMethod.Get, $"{TestConstants.Endpoint}/teams")
.ExpectedHeaders(true)
.WithQueryString($"queries[]={query.GetQueryString()}&search={search}")
.Respond(TestConstants.AppJson, TestConstants.TeamsListResponse);

_appwriteClient.SetSession(TestConstants.Session);

// Act
var result = await _appwriteClient.Teams.ListTeams(request);

// Assert
Assert.True(result.Success);
}

[Fact]
public async Task ListTeams_ShouldReturnError_WhenSessionIsNull()
{
Expand Down
Loading

0 comments on commit f81ed71

Please sign in to comment.