From 265d9a0b2af20e8a20769c8bbd580c41de286a1c Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sun, 13 Oct 2024 22:06:04 +0100 Subject: [PATCH 1/4] Implemented Delete Push Target --- .../Clients/AccountClient.cs | 17 +++++++++++++++++ .../Clients/IAccountClient.cs | 7 +++++++ .../Internals/IAccountApi.cs | 3 +++ src/PinguApps.Appwrite.Playground/App.cs | 7 +++---- .../Requests/Account/DeletePushTargetRequest.cs | 14 ++++++++++++++ .../DeletePushTargetRequestValidator.cs | 11 +++++++++++ 6 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 src/PinguApps.Appwrite.Shared/Requests/Account/DeletePushTargetRequest.cs create mode 100644 src/PinguApps.Appwrite.Shared/Requests/Account/Validators/DeletePushTargetRequestValidator.cs diff --git a/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs b/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs index a05eb3e6..3299627d 100644 --- a/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs @@ -669,6 +669,23 @@ public async Task> CreatePushTarget(CreatePushTargetReque } } + /// + public async Task DeletePushTarget(DeletePushTargetRequest request) + { + try + { + request.Validate(true); + + var result = await _accountApi.DeletePushTarget(GetCurrentSessionOrThrow(), request.TargetId); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } + /// public async Task> UpdatePushTarget(UpdatePushTargetRequest request) { diff --git a/src/PinguApps.Appwrite.Client/Clients/IAccountClient.cs b/src/PinguApps.Appwrite.Client/Clients/IAccountClient.cs index 8c8a9026..377b872f 100644 --- a/src/PinguApps.Appwrite.Client/Clients/IAccountClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/IAccountClient.cs @@ -312,6 +312,13 @@ public interface IAccountClient /// The target Task> CreatePushTarget(CreatePushTargetRequest request); + /// + /// Appwrite Docs + /// + /// The request content + /// 204 success code + Task DeletePushTarget(DeletePushTargetRequest request); + /// /// Appwrite Docs /// diff --git a/src/PinguApps.Appwrite.Client/Internals/IAccountApi.cs b/src/PinguApps.Appwrite.Client/Internals/IAccountApi.cs index c8741b47..67a5acac 100644 --- a/src/PinguApps.Appwrite.Client/Internals/IAccountApi.cs +++ b/src/PinguApps.Appwrite.Client/Internals/IAccountApi.cs @@ -121,6 +121,9 @@ internal interface IAccountApi : IBaseApi [Post("/account/targets/push")] Task> CreatePushTarget([Header("x-appwrite-session")] string session, CreatePushTargetRequest request); + [Delete("/account/targets/{targetId}/push")] + Task DeletePushTarget([Header("x-appwrite-session")] string session, string targetId); + [Put("/account/targets/{targetId}/push")] Task> UpdatePushTarget([Header("x-appwrite-session")] string session, string targetId, UpdatePushTargetRequest request); diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index 55ae865b..09bab76e 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -19,13 +19,12 @@ public async Task Run(string[] args) { _client.SetSession(_session); - var request = new UpdatePushTargetRequest() + var request = new DeletePushTargetRequest() { - TargetId = "670be3330025c0f23b93", - Identifier = "token" + TargetId = "670be3330025c0f23b93" }; - var response = await _client.Account.UpdatePushTarget(request); + var response = await _client.Account.DeletePushTarget(request); Console.WriteLine(response.Result.Match( result => result.ToString(), diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/DeletePushTargetRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/DeletePushTargetRequest.cs new file mode 100644 index 00000000..7c1a9269 --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/DeletePushTargetRequest.cs @@ -0,0 +1,14 @@ +using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Attributes; +using PinguApps.Appwrite.Shared.Requests.Account.Validators; + +namespace PinguApps.Appwrite.Shared.Requests.Account; +public class DeletePushTargetRequest : BaseRequest +{ + /// + /// Target ID. + /// + [JsonPropertyName("targetId")] + [SdkExclude] + public string TargetId { get; set; } = string.Empty; +} diff --git a/src/PinguApps.Appwrite.Shared/Requests/Account/Validators/DeletePushTargetRequestValidator.cs b/src/PinguApps.Appwrite.Shared/Requests/Account/Validators/DeletePushTargetRequestValidator.cs new file mode 100644 index 00000000..17741a01 --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Requests/Account/Validators/DeletePushTargetRequestValidator.cs @@ -0,0 +1,11 @@ +using FluentValidation; + +namespace PinguApps.Appwrite.Shared.Requests.Account.Validators; +public class DeletePushTargetRequestValidator : AbstractValidator +{ + public DeletePushTargetRequestValidator() + { + RuleFor(x => x.TargetId) + .NotEmpty().WithMessage("TargetId is required."); + } +} From 0be6e1619d796efe66555b79d297680a405ef9a7 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sun, 13 Oct 2024 22:08:41 +0100 Subject: [PATCH 2/4] added tests for delete push target request --- .../Account/DeletePushTargetRequestTests.cs | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 tests/PinguApps.Appwrite.Shared.Tests/Requests/Account/DeletePushTargetRequestTests.cs diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Requests/Account/DeletePushTargetRequestTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Requests/Account/DeletePushTargetRequestTests.cs new file mode 100644 index 00000000..17826eef --- /dev/null +++ b/tests/PinguApps.Appwrite.Shared.Tests/Requests/Account/DeletePushTargetRequestTests.cs @@ -0,0 +1,103 @@ +using FluentValidation; +using PinguApps.Appwrite.Shared.Requests.Account; +using PinguApps.Appwrite.Shared.Utils; + +namespace PinguApps.Appwrite.Shared.Tests.Requests.Account; +public class DeletePushTargetRequestTests +{ + [Fact] + public void Constructor_InitializesWithExpectedValues() + { + // Arrange & Act + var request = new DeletePushTargetRequest(); + + // Assert + Assert.Equal(string.Empty, request.TargetId); + } + + [Fact] + public void Properties_CanBeSet() + { + var targetId = IdUtils.GenerateUniqueId(); + + // Arrange + var request = new DeletePushTargetRequest(); + + // Act + request.TargetId = targetId; + + // Assert + Assert.Equal(targetId, request.TargetId); + } + + public static TheoryData ValidRequestsData = + [ + new DeletePushTargetRequest + { + TargetId = IdUtils.GenerateUniqueId() + } + ]; + + [Theory] + [MemberData(nameof(ValidRequestsData))] + public void IsValid_WithValidData_ReturnsTrue(DeletePushTargetRequest request) + { + // Act + var isValid = request.IsValid(); + + // Assert + Assert.True(isValid); + } + + public static TheoryData InvalidRequestsData = + [ + new DeletePushTargetRequest + { + TargetId = "" + }, + new DeletePushTargetRequest + { + TargetId = null! + } + ]; + + [Theory] + [MemberData(nameof(InvalidRequestsData))] + public void IsValid_WithInvalidData_ReturnsFalse(DeletePushTargetRequest request) + { + // Act + var isValid = request.IsValid(); + + // Assert + Assert.False(isValid); + } + + [Fact] + public void Validate_WithThrowOnFailuresTrue_ThrowsValidationExceptionOnFailure() + { + // Arrange + var request = new DeletePushTargetRequest + { + TargetId = "" + }; + + // Assert + Assert.Throws(() => request.Validate(true)); + } + + [Fact] + public void Validate_WithThrowOnFailuresFalse_ReturnsInvalidResultOnFailure() + { + // Arrange + var request = new DeletePushTargetRequest + { + TargetId = "" + }; + + // Act + var result = request.Validate(false); + + // Assert + Assert.False(result.IsValid); + } +} From 72958c1ac3595ad46844bd62739e937a5b961945 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sun, 13 Oct 2024 22:12:14 +0100 Subject: [PATCH 3/4] added tests for delete push target --- .../AccountClientTests.DeletePushTarget.cs | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.DeletePushTarget.cs diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.DeletePushTarget.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.DeletePushTarget.cs new file mode 100644 index 00000000..8d149e58 --- /dev/null +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.DeletePushTarget.cs @@ -0,0 +1,97 @@ +using System.Net; +using PinguApps.Appwrite.Client.Clients; +using PinguApps.Appwrite.Shared.Requests.Account; +using PinguApps.Appwrite.Shared.Tests; +using PinguApps.Appwrite.Shared.Utils; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Client.Tests.Clients.Account; +public partial class AccountClientTests +{ + [Fact] + public async Task DeletePushTarget_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = new DeletePushTargetRequest + { + TargetId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Delete, $"{TestConstants.Endpoint}/account/targets/{request.TargetId}/push") + .ExpectedHeaders() + .Respond(HttpStatusCode.NoContent); + + _appwriteClient.SetSession(TestConstants.Session); + + // Act + var result = await _appwriteClient.Account.DeletePushTarget(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task DeletePushTarget_ShouldReturnError_WhenSessionIsNull() + { + // Arrange + var request = new DeletePushTargetRequest + { + TargetId = IdUtils.GenerateUniqueId() + }; + + // Act + var result = await _appwriteClient.Account.DeletePushTarget(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + + [Fact] + public async Task DeletePushTarget_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = new DeletePushTargetRequest + { + TargetId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Delete, $"{TestConstants.Endpoint}/account/targets/{request.TargetId}/push") + .ExpectedHeaders() + .Respond(HttpStatusCode.BadRequest, TestConstants.AppJson, TestConstants.AppwriteError); + + _appwriteClient.SetSession(TestConstants.Session); + + // Act + var result = await _appwriteClient.Account.DeletePushTarget(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task DeletePushTarget_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = new DeletePushTargetRequest + { + TargetId = IdUtils.GenerateUniqueId() + }; + + _mockHttp.Expect(HttpMethod.Delete, $"{TestConstants.Endpoint}/account/targets/{request.TargetId}/push") + .ExpectedHeaders() + .Throw(new HttpRequestException("An error occurred")); + + _appwriteClient.SetSession(TestConstants.Session); + + // Act + var result = await _appwriteClient.Account.DeletePushTarget(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} From 1abc4d18821f0e706a323a81f4cc86b0c2c0f6dd Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Sun, 13 Oct 2024 22:14:03 +0100 Subject: [PATCH 4/4] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c1dca24f..9a359133 100644 --- a/README.md +++ b/README.md @@ -141,11 +141,11 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( ## ⌛ Progress -![Server & Client - 99 / 295](https://img.shields.io/badge/Server_&_Client-99%20%2F%20295-gold?style=for-the-badge) +![Server & Client - 100 / 295](https://img.shields.io/badge/Server_&_Client-100%20%2F%20295-gold?style=for-the-badge) ![Server - 53 / 202](https://img.shields.io/badge/Server-53%20%2F%20202-red?style=for-the-badge) -![Client - 46 / 93](https://img.shields.io/badge/Client-46%20%2F%2093-gold?style=for-the-badge) +![Client - 47 / 93](https://img.shields.io/badge/Client-47%20%2F%2093-gold?style=for-the-badge) ### 🔑 Key | Icon | Definition | @@ -155,7 +155,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( | ❌ | There is currently no intention to implement the endpoint for the given SDK type (client or server) | ### Account -![Account - 57 / 58](https://img.shields.io/badge/Account-57%20%2F%2058-forestgreen?style=for-the-badge) +![Account - 58 / 58](https://img.shields.io/badge/Account-58%20%2F%2058-blue?style=for-the-badge) | Endpoint | Client | Server | |:-:|:-:|:-:| @@ -197,7 +197,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( | [Update Status](https://appwrite.io/docs/references/1.6.x/client-rest/account#updateStatus) | ✅ | ❌ | | [Create Push Target](https://appwrite.io/docs/references/1.6.x/client-rest/account#createPushTarget) | ✅ | ❌ | | [Update Push Target](https://appwrite.io/docs/references/1.6.x/client-rest/account#updatePushTarget) | ✅ | ❌ | -| [Delete Push Target](https://appwrite.io/docs/references/1.6.x/client-rest/account#deletePushTarget) | ⬛ | ❌ | +| [Delete Push Target](https://appwrite.io/docs/references/1.6.x/client-rest/account#deletePushTarget) | ✅ | ❌ | | [Create Email Token (OTP)](https://appwrite.io/docs/references/1.6.x/client-rest/account#createEmailToken) | ✅ | ✅ | | [Create Magic URL Token](https://appwrite.io/docs/references/1.6.x/client-rest/account#createMagicURLToken) | ✅ | ✅ | | [Create OAuth2 Token](https://appwrite.io/docs/references/1.6.x/client-rest/account#createOAuth2Token) | ✅| ✅ |