diff --git a/README.md b/README.md index e1eed56e..0d9bfee4 100644 --- a/README.md +++ b/README.md @@ -138,14 +138,14 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( ``` ## ⌛ Progress - -![Server & Client - 23 / 288](https://img.shields.io/badge/Server_&_Client-23%20%2F%20288-red?style=for-the-badge) + +![Server & Client - 24 / 288](https://img.shields.io/badge/Server_&_Client-24%20%2F%20288-red?style=for-the-badge) ![Server - 2 / 195](https://img.shields.io/badge/Server-2%20%2F%20195-red?style=for-the-badge) - -![Client - 21 / 93](https://img.shields.io/badge/Client-21%20%2F%2093-red?style=for-the-badge) + +![Client - 22 / 93](https://img.shields.io/badge/Client-22%20%2F%2093-red?style=for-the-badge) ### 🔑 Key | Icon | Definition | @@ -155,8 +155,8 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( | ❌ | There is currently no intention to implement the endpoint for the given SDK type (client or server) | ### Account - -![Account - 23 / 52](https://img.shields.io/badge/Account-23%20%2F%2052-yellow?style=for-the-badge) + +![Account - 24 / 52](https://img.shields.io/badge/Account-24%20%2F%2052-yellow?style=for-the-badge) | Endpoint | Client | Server | |:-:|:-:|:-:| @@ -172,7 +172,7 @@ string emailAddressOrErrorMessage = userResponse.Result.Match( | [Verify Authenticator](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateMfaAuthenticator) | ✅ | ❌ | | [Delete Authenticator](https://appwrite.io/docs/references/1.5.x/client-rest/account#deleteMfaAuthenticator) | ✅ | ❌ | | [Create 2FA Challenge](https://appwrite.io/docs/references/1.5.x/client-rest/account#createMfaChallenge) | ✅ | ❌ | -| [Create MFA Challenge (confirmation)](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateMfaChallenge) | ⬛ | ❌ | +| [Create MFA Challenge (confirmation)](https://appwrite.io/docs/references/1.5.x/client-rest/account#updateMfaChallenge) | ✅ | ❌ | | [List Factors](https://appwrite.io/docs/references/1.5.x/client-rest/account#listMfaFactors) | ⬛ | ❌ | | [Get MFA Recovery Codes](https://appwrite.io/docs/references/1.5.x/client-rest/account#getMfaRecoveryCodes) | ⬛ | ❌ | | [Create MFA Recovery Codes](https://appwrite.io/docs/references/1.5.x/client-rest/account#createMfaRecoveryCodes) | ⬛ | ❌ | diff --git a/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs b/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs index 7ed8f4e9..a83e1caa 100644 --- a/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs @@ -25,8 +25,9 @@ public AccountClient(IServiceProvider services) string? ISessionAware.Session { get; set; } ISessionAware? _sessionAware; - public string? Session => GetSession(); - private string? GetSession() + public string? Session => GetCurrentSession(); + + private string? GetCurrentSession() { if (_sessionAware is null) { @@ -36,12 +37,17 @@ public AccountClient(IServiceProvider services) return _sessionAware.Session; } + private string GetCurrentSessionOrThrow() + { + return GetCurrentSession() ?? throw new Exception(ISessionAware.SessionExceptionMessage); + } + /// public async Task> Get() { try { - var result = await _accountApi.GetAccount(Session); + var result = await _accountApi.GetAccount(GetCurrentSessionOrThrow()); return result.GetApiResponse(); } @@ -75,7 +81,7 @@ public async Task> UpdateEmail(UpdateEmailRequest request) { request.Validate(true); - var result = await _accountApi.UpdateEmail(Session, request); + var result = await _accountApi.UpdateEmail(GetCurrentSessionOrThrow(), request); return result.GetApiResponse(); } @@ -92,7 +98,7 @@ public async Task> UpdateName(UpdateNameRequest request) { request.Validate(true); - var result = await _accountApi.UpdateName(Session, request); + var result = await _accountApi.UpdateName(GetCurrentSessionOrThrow(), request); return result.GetApiResponse(); } @@ -109,7 +115,7 @@ public async Task> UpdatePassword(UpdatePasswordRequest req { request.Validate(true); - var result = await _accountApi.UpdatePassword(Session, request); + var result = await _accountApi.UpdatePassword(GetCurrentSessionOrThrow(), request); return result.GetApiResponse(); } @@ -126,7 +132,7 @@ public async Task> UpdatePhone(UpdatePhoneRequest request) { request.Validate(true); - var result = await _accountApi.UpdatePhone(Session, request); + var result = await _accountApi.UpdatePhone(GetCurrentSessionOrThrow(), request); return result.GetApiResponse(); } @@ -141,7 +147,7 @@ public async Task>> GetAccoun { try { - var result = await _accountApi.GetAccountPreferences(Session); + var result = await _accountApi.GetAccountPreferences(GetCurrentSessionOrThrow()); return result.GetApiResponse(); } @@ -158,7 +164,7 @@ public async Task> UpdatePreferences(UpdatePreferencesReque { request.Validate(true); - var result = await _accountApi.UpdatePreferences(Session, request); + var result = await _accountApi.UpdatePreferences(GetCurrentSessionOrThrow(), request); return result.GetApiResponse(); } @@ -207,7 +213,7 @@ public async Task> GetSession(string sessionId = "curren { try { - var result = await _accountApi.GetSession(Session, sessionId); + var result = await _accountApi.GetSession(GetCurrentSessionOrThrow(), sessionId); return result.GetApiResponse(); } @@ -222,7 +228,7 @@ public async Task> UpdateSession(string sessionId = "cur { try { - var result = await _accountApi.UpdateSession(Session, sessionId); + var result = await _accountApi.UpdateSession(GetCurrentSessionOrThrow(), sessionId); return result.GetApiResponse(); } @@ -239,7 +245,7 @@ public async Task> CreateEmailVerification(CreateEmailVeri { request.Validate(true); - var result = await _accountApi.CreateEmailVerification(Session, request); + var result = await _accountApi.CreateEmailVerification(GetCurrentSessionOrThrow(), request); return result.GetApiResponse(); } @@ -271,7 +277,7 @@ public async Task> CreateJwt() { try { - var result = await _accountApi.CreateJwt(Session); + var result = await _accountApi.CreateJwt(GetCurrentSessionOrThrow()); return result.GetApiResponse(); } @@ -288,7 +294,7 @@ public async Task> ListLogs(List? queries = null { var queryStrings = queries?.Select(x => x.GetQueryString()) ?? []; - var result = await _accountApi.ListLogs(Session, queryStrings); + var result = await _accountApi.ListLogs(GetCurrentSessionOrThrow(), queryStrings); return result.GetApiResponse(); } @@ -305,7 +311,7 @@ public async Task> AddAuthenticator(AddAuthenticatorRequ { request.Validate(true); - var result = await _accountApi.AddAuthenticator(Session, request.Type); + var result = await _accountApi.AddAuthenticator(GetCurrentSessionOrThrow(), request.Type); return result.GetApiResponse(); } @@ -322,7 +328,7 @@ public async Task> VerifyAuthenticator(VerifyAuthenticatorR { request.Validate(true); - var result = await _accountApi.VerifyAuthenticator(Session, request.Type, request); + var result = await _accountApi.VerifyAuthenticator(GetCurrentSessionOrThrow(), request.Type, request); return result.GetApiResponse(); } @@ -339,7 +345,7 @@ public async Task> UpdateMfa(UpdateMfaRequest request) { request.Validate(true); - var result = await _accountApi.UpdateMfa(Session, request); + var result = await _accountApi.UpdateMfa(GetCurrentSessionOrThrow(), request); return result.GetApiResponse(); } @@ -356,7 +362,7 @@ public async Task DeleteAuthenticator(DeleteAuthenticatorRequest { request.Validate(true); - var result = await _accountApi.DeleteAuthenticator(Session, request.Type, request); + var result = await _accountApi.DeleteAuthenticator(GetCurrentSessionOrThrow(), request.Type, request); return result.GetApiResponse(); } @@ -373,7 +379,7 @@ public async Task> Create2faChallenge(Create2faChal { request.Validate(true); - var result = await _accountApi.Create2faChallenge(Session, request); + var result = await _accountApi.Create2faChallenge(GetCurrentSessionOrThrow(), request); return result.GetApiResponse(); } @@ -382,4 +388,21 @@ public async Task> Create2faChallenge(Create2faChal return e.GetExceptionResponse(); } } + + /// + public async Task Create2faChallengeConfirmation(Create2faChallengeConfirmationRequest request) + { + try + { + request.Validate(true); + + var result = await _accountApi.Create2faChallengeConfirmation(GetCurrentSessionOrThrow(), request); + + return result.GetApiResponse(); + } + catch (Exception e) + { + return e.GetExceptionResponse(); + } + } } diff --git a/src/PinguApps.Appwrite.Client/Clients/IAccountClient.cs b/src/PinguApps.Appwrite.Client/Clients/IAccountClient.cs index ad44e7a4..ce08188d 100644 --- a/src/PinguApps.Appwrite.Client/Clients/IAccountClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/IAccountClient.cs @@ -176,10 +176,18 @@ public interface IAccountClient Task DeleteAuthenticator(DeleteAuthenticatorRequest request); /// - /// Begin the process of MFA verification after sign-in. Finish the flow with updateMfaChallenge method + /// Begin the process of MFA verification after sign-in. Finish the flow with /// Appwrite Docs /// /// The request content /// The Mfa Challenge Task> Create2faChallenge(Create2faChallengeRequest request); + + /// + /// Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use + /// Appwrite Docs + /// + /// The request content + /// The result + Task Create2faChallengeConfirmation(Create2faChallengeConfirmationRequest request); } diff --git a/src/PinguApps.Appwrite.Client/Clients/ISessionAware.cs b/src/PinguApps.Appwrite.Client/Clients/ISessionAware.cs index 60672b1d..d6fae2c4 100644 --- a/src/PinguApps.Appwrite.Client/Clients/ISessionAware.cs +++ b/src/PinguApps.Appwrite.Client/Clients/ISessionAware.cs @@ -5,4 +5,6 @@ internal interface ISessionAware public string? Session { get; protected set; } public void UpdateSession(string? session) => Session = session; + + public const string SessionExceptionMessage = "Session cannot be null."; } diff --git a/src/PinguApps.Appwrite.Client/Internals/IAccountApi.cs b/src/PinguApps.Appwrite.Client/Internals/IAccountApi.cs index 107faa12..acc647d4 100644 --- a/src/PinguApps.Appwrite.Client/Internals/IAccountApi.cs +++ b/src/PinguApps.Appwrite.Client/Internals/IAccountApi.cs @@ -9,28 +9,28 @@ namespace PinguApps.Appwrite.Client.Internals; internal interface IAccountApi : IBaseApi { [Get("/account")] - Task> GetAccount([Header("x-appwrite-session")] string? session); + Task> GetAccount([Header("x-appwrite-session")] string session); [Post("/account")] Task> CreateAccount(CreateAccountRequest request); [Patch("/account/email")] - Task> UpdateEmail([Header("x-appwrite-session")] string? session, UpdateEmailRequest request); + Task> UpdateEmail([Header("x-appwrite-session")] string session, UpdateEmailRequest request); [Patch("/account/name")] - Task> UpdateName([Header("x-appwrite-session")] string? session, UpdateNameRequest request); + Task> UpdateName([Header("x-appwrite-session")] string session, UpdateNameRequest request); [Patch("/account/password")] - Task> UpdatePassword([Header("x-appwrite-session")] string? session, UpdatePasswordRequest request); + Task> UpdatePassword([Header("x-appwrite-session")] string session, UpdatePasswordRequest request); [Patch("/account/phone")] - Task> UpdatePhone([Header("x-appwrite-session")] string? session, UpdatePhoneRequest request); + Task> UpdatePhone([Header("x-appwrite-session")] string session, UpdatePhoneRequest request); [Get("/account/prefs")] - Task>> GetAccountPreferences([Header("x-appwrite-session")] string? session); + Task>> GetAccountPreferences([Header("x-appwrite-session")] string session); [Patch("/account/prefs")] - Task> UpdatePreferences([Header("x-appwrite-session")] string? session, UpdatePreferencesRequest request); + Task> UpdatePreferences([Header("x-appwrite-session")] string session, UpdatePreferencesRequest request); [Post("/account/tokens/email")] Task> CreateEmailToken(CreateEmailTokenRequest request); @@ -39,36 +39,39 @@ internal interface IAccountApi : IBaseApi Task> CreateSession(CreateSessionRequest request); [Get("/account/sessions/{sessionId}")] - Task> GetSession([Header("x-appwrite-session")] string? session, string sessionId); + Task> GetSession([Header("x-appwrite-session")] string session, string sessionId); [Patch("/account/sessions/{sessionId}")] - Task> UpdateSession([Header("x-appwrite-session")] string? session, string sessionId); + Task> UpdateSession([Header("x-appwrite-session")] string session, string sessionId); [Post("/account/verification")] - Task> CreateEmailVerification([Header("x-appwrite-session")] string? session, CreateEmailVerificationRequest request); + Task> CreateEmailVerification([Header("x-appwrite-session")] string session, CreateEmailVerificationRequest request); [Put("/account/verification")] Task> CreateEmailVerificationConfirmation(CreateEmailVerificationConfirmationRequest request); [Post("/account/jwt")] - Task> CreateJwt([Header("x-appwrite-session")] string? session); + Task> CreateJwt([Header("x-appwrite-session")] string session); [Get("/account/logs")] [QueryUriFormat(System.UriFormat.Unescaped)] - Task> ListLogs([Header("x-appwrite-session")] string? session, [Query(CollectionFormat.Multi), AliasAs("queries[]")] IEnumerable queries); + Task> ListLogs([Header("x-appwrite-session")] string session, [Query(CollectionFormat.Multi), AliasAs("queries[]")] IEnumerable queries); [Post("/account/mfa/authenticators/{type}")] - Task> AddAuthenticator([Header("x-appwrite-session")] string? session, string type); + Task> AddAuthenticator([Header("x-appwrite-session")] string session, string type); [Put("/account/mfa/authenticators/{type}")] - Task> VerifyAuthenticator([Header("x-appwrite-session")] string? session, string type, VerifyAuthenticatorRequest request); + Task> VerifyAuthenticator([Header("x-appwrite-session")] string session, string type, VerifyAuthenticatorRequest request); [Patch("/account/mfa")] - Task> UpdateMfa([Header("x-appwrite-session")] string? session, UpdateMfaRequest request); + Task> UpdateMfa([Header("x-appwrite-session")] string session, UpdateMfaRequest request); [Delete("/account/mfa/authenticators/{type}")] - Task DeleteAuthenticator([Header("x-appwrite-session")] string? session, string type, [Body] DeleteAuthenticatorRequest request); + Task DeleteAuthenticator([Header("x-appwrite-session")] string session, string type, [Body] DeleteAuthenticatorRequest request); [Post("/account/mfa/challenge")] - Task> Create2faChallenge([Header("x-appwrite-session")] string? session, Create2faChallengeRequest request); + Task> Create2faChallenge([Header("x-appwrite-session")] string session, Create2faChallengeRequest request); + + [Put("/account/mfa/challenge")] + Task Create2faChallengeConfirmation([Header("x-appwrite-session")] string session, Create2faChallengeConfirmationRequest request); } diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index c41f9dad..6d5873d9 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -20,15 +20,25 @@ public async Task Run(string[] args) { _client.SetSession(_session); + Console.WriteLine(_client.Session); + //var response = await _client.Account.AddAuthenticator(); - var response = await _client.Account.Create2faChallenge(new Shared.Requests.Create2faChallengeRequest + //var response = await _client.Account.Create2faChallenge(new Shared.Requests.Create2faChallengeRequest + //{ + // Factor = Shared.Enums.SecondFactor.Email + //}); + + var response = await _client.Account.Create2faChallengeConfirmation(new Shared.Requests.Create2faChallengeConfirmationRequest { - Factor = Shared.Enums.SecondFactor.Email + ChallengeId = "66b771b7bdcb152aaa5b", + Otp = "474376" }); Console.WriteLine(response.Result.Match( account => account.ToString(), appwriteError => appwriteError.Message, internalERror => internalERror.Message)); + + Console.WriteLine(_client.Session); } } diff --git a/src/PinguApps.Appwrite.Shared/Requests/Create2faChallengeConfirmationRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Create2faChallengeConfirmationRequest.cs new file mode 100644 index 00000000..f8972e13 --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Requests/Create2faChallengeConfirmationRequest.cs @@ -0,0 +1,22 @@ +using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Requests.Validators; + +namespace PinguApps.Appwrite.Shared.Requests; + +/// +/// The request for creating a 2fa challenge confirmation +/// +public class Create2faChallengeConfirmationRequest : BaseRequest +{ + /// + /// ID of the challenge + /// + [JsonPropertyName("challengeId")] + public string ChallengeId { get; set; } = string.Empty; + + /// + /// Valid verification token + /// + [JsonPropertyName("otp")] + public string Otp { get; set; } = string.Empty; +} diff --git a/src/PinguApps.Appwrite.Shared/Requests/Create2faChallengeRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/Create2faChallengeRequest.cs index fc3ae30d..8a6f17e0 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/Create2faChallengeRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/Create2faChallengeRequest.cs @@ -3,6 +3,10 @@ using PinguApps.Appwrite.Shared.Requests.Validators; namespace PinguApps.Appwrite.Shared.Requests; + +/// +/// The request for creating a 2fa challenge +/// public class Create2faChallengeRequest : BaseRequest { /// diff --git a/src/PinguApps.Appwrite.Shared/Requests/Validators/Create2faChallengeConfirmationRequestValidator.cs b/src/PinguApps.Appwrite.Shared/Requests/Validators/Create2faChallengeConfirmationRequestValidator.cs new file mode 100644 index 00000000..93ae8d7a --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Requests/Validators/Create2faChallengeConfirmationRequestValidator.cs @@ -0,0 +1,11 @@ +using FluentValidation; + +namespace PinguApps.Appwrite.Shared.Requests.Validators; +public class Create2faChallengeConfirmationRequestValidator : AbstractValidator +{ + public Create2faChallengeConfirmationRequestValidator() + { + RuleFor(x => x.ChallengeId).NotEmpty(); + RuleFor(x => x.Otp).NotEmpty(); + } +} diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.AddAuthenticator.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.AddAuthenticator.cs index d358f5c6..09bf07f5 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.AddAuthenticator.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.AddAuthenticator.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Requests; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -50,6 +51,21 @@ public async Task AddAuthenticator_ShouldHitDifferentEndpoint_WhenNewTypeIsUsed( Assert.Equal(1, matches); } + [Fact] + public async Task AddAuthenticator_ShouldReturnError_WhenSessionIsNull() + { + // Arrange + var request = new AddAuthenticatorRequest(); + + // Act + var result = await _appwriteClient.Account.AddAuthenticator(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task AddAuthenticator_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create2faChallenge.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create2faChallenge.cs index d537dcbc..8c2163f2 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create2faChallenge.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create2faChallenge.cs @@ -1,6 +1,7 @@ using System.Net; using System.Text.Json; using System.Text.Json.Serialization; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Requests; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -31,6 +32,21 @@ public async Task Create2faChallenge_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task Create2faChallenge_ShouldReturnError_WhenSessionIsNull() + { + // Arrange + var request = new Create2faChallengeRequest(); + + // Act + var result = await _appwriteClient.Account.Create2faChallenge(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task Create2faChallenge_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create2faChallengeConfirmation.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create2faChallengeConfirmation.cs new file mode 100644 index 00000000..d1af2a74 --- /dev/null +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Create2faChallengeConfirmation.cs @@ -0,0 +1,104 @@ +using System.Net; +using PinguApps.Appwrite.Client.Clients; +using PinguApps.Appwrite.Shared.Requests; +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 Create2faChallengeConfirmation_ShouldReturnSuccess_WhenApiCallSucceeds() + { + // Arrange + var request = new Create2faChallengeConfirmationRequest() + { + ChallengeId = IdUtils.GenerateUniqueId(), + Otp = "123456" + }; + + _mockHttp.Expect(HttpMethod.Put, $"{Constants.Endpoint}/account/mfa/challenge") + .ExpectedHeaders(true) + .WithJsonContent(request) + .Respond(HttpStatusCode.NoContent); + + _appwriteClient.SetSession(Constants.Session); + + // Act + var result = await _appwriteClient.Account.Create2faChallengeConfirmation(request); + + // Assert + Assert.True(result.Success); + } + + [Fact] + public async Task Create2faChallengeConfirmation_ShouldReturnError_WhenSessionIsNull() + { + // Arrange + var request = new Create2faChallengeConfirmationRequest() + { + ChallengeId = IdUtils.GenerateUniqueId(), + Otp = "123456" + }; + + // Act + var result = await _appwriteClient.Account.Create2faChallengeConfirmation(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + + [Fact] + public async Task Create2faChallengeConfirmation_ShouldHandleException_WhenApiCallFails() + { + // Arrange + var request = new Create2faChallengeConfirmationRequest() + { + ChallengeId = IdUtils.GenerateUniqueId(), + Otp = "123456" + }; + + _mockHttp.Expect(HttpMethod.Put, $"{Constants.Endpoint}/account/mfa/challenge") + .ExpectedHeaders(true) + .WithJsonContent(request) + .Respond(HttpStatusCode.BadRequest, Constants.AppJson, Constants.AppwriteError); + + _appwriteClient.SetSession(Constants.Session); + + // Act + var result = await _appwriteClient.Account.Create2faChallengeConfirmation(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsAppwriteError); + } + + [Fact] + public async Task Create2faChallengeConfirmation_ShouldReturnErrorResponse_WhenExceptionOccurs() + { + // Arrange + var request = new Create2faChallengeConfirmationRequest() + { + ChallengeId = IdUtils.GenerateUniqueId(), + Otp = "123456" + }; + + _mockHttp.Expect(HttpMethod.Put, $"{Constants.Endpoint}/account/mfa/challenge") + .ExpectedHeaders(true) + .WithJsonContent(request) + .Throw(new HttpRequestException("An error occurred")); + + _appwriteClient.SetSession(Constants.Session); + + // Act + var result = await _appwriteClient.Account.Create2faChallengeConfirmation(request); + + // Assert + Assert.False(result.Success); + Assert.True(result.IsInternalError); + Assert.Equal("An error occurred", result.Result.AsT2.Message); + } +} diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailVerification.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailVerification.cs index e9781649..ff598a4e 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailVerification.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateEmailVerification.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Requests; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -29,6 +30,24 @@ public async Task CreateEmailVerification_ShouldReturnSuccess_WhenApiCallSucceed Assert.True(result.Success); } + [Fact] + public async Task CreateEmailVerification_ShouldReturnError_WhenSessionIsNull() + { + // Arrange + var request = new CreateEmailVerificationRequest() + { + Url = "https://localhost:5001/abc123" + }; + + // Act + var result = await _appwriteClient.Account.CreateEmailVerification(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task CreateEmailVerification_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateJwt.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateJwt.cs index 20166795..72e454d6 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateJwt.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.CreateJwt.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -22,6 +23,18 @@ public async Task CreateJwt_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task CreateJwt_ShouldReturnError_WhenSessionIsNull() + { + // Act + var result = await _appwriteClient.Account.CreateJwt(); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task CreateJwt_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.DeleteAuthenticator.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.DeleteAuthenticator.cs index 0498c263..ed80a453 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.DeleteAuthenticator.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.DeleteAuthenticator.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Requests; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -56,6 +57,24 @@ public async Task DeleteAuthenticator_ShouldHitDifferentEndpoint_WhenNewTypeIsUs Assert.Equal(1, matches); } + [Fact] + public async Task DeleteAuthenticator_ShouldReturnError_WhenSessionIsNull() + { + // Arrange + var request = new DeleteAuthenticatorRequest() + { + Otp = "123456" + }; + + // Act + var result = await _appwriteClient.Account.DeleteAuthenticator(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task DeleteAuthenticator_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Get.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Get.cs index ff31f349..fdfea111 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Get.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.Get.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -22,6 +23,18 @@ public async Task Get_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task Get_ShouldReturnError_WhenSessionIsNull() + { + // Act + var result = await _appwriteClient.Account.Get(); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task Get_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.GetAccountPreferences.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.GetAccountPreferences.cs index 51f3c482..f7ba0d8f 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.GetAccountPreferences.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.GetAccountPreferences.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -22,6 +23,18 @@ public async Task GetAccountPreferences_ShouldReturnSuccess_WhenApiCallSucceeds( Assert.True(result.Success); } + [Fact] + public async Task GetAccountPreferences_ShouldReturnError_WhenSessionIsNull() + { + // Act + var result = await _appwriteClient.Account.GetAccountPreferences(); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task GetAccountPreferences_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.GetSession.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.GetSession.cs index c254bc53..e9c0076d 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.GetSession.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.GetSession.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -40,6 +41,18 @@ public async Task GetSession_ShouldRequestSession_WhenSessionProvided() Assert.True(result.Success); } + [Fact] + public async Task GetSession_ShouldReturnError_WhenSessionIsNull() + { + // Act + var result = await _appwriteClient.Account.GetSession(); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task GetSession_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.ListLogs.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.ListLogs.cs index 041d269c..0e10c60c 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.ListLogs.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.ListLogs.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Tests; using PinguApps.Appwrite.Shared.Utils; using RichardSzalay.MockHttp; @@ -43,6 +44,18 @@ public async Task ListLogs_ShouldProvideQueries_WhenQueriesProvided() Assert.True(result.Success); } + [Fact] + public async Task ListLogs_ShouldReturnError_WhenSessionIsNull() + { + // Act + var result = await _appwriteClient.Account.ListLogs(); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task ListLogs_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateEmail.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateEmail.cs index fd6b2f55..acbe26d8 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateEmail.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateEmail.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Requests; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -30,6 +31,25 @@ public async Task UpdateEmail_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task UpdateEmail_ShouldReturnError_WhenSessionIsNull() + { + // Arrange + var request = new UpdateEmailRequest() + { + Email = "email@example.com", + Password = "password" + }; + + // Act + var result = await _appwriteClient.Account.UpdateEmail(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task UpdateEmail_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateMfa.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateMfa.cs index 885abe12..4a78658b 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateMfa.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateMfa.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Requests; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -29,6 +30,24 @@ public async Task UpdateMfa_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task UpdateMfa_ShouldReturnError_WhenSessionIsNull() + { + // Arrange + var request = new UpdateMfaRequest() + { + MfaEnabled = true + }; + + // Act + var result = await _appwriteClient.Account.UpdateMfa(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task UpdateMfa_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateName.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateName.cs index 090f035a..5dcd0a13 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateName.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateName.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Requests; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -29,6 +30,24 @@ public async Task UpdateName_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task UpdateName_ShouldReturnError_WhenSessionIsNull() + { + // Arrange + var request = new UpdateNameRequest() + { + Name = "newName" + }; + + // Act + var result = await _appwriteClient.Account.UpdateName(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task UpdateName_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePassword.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePassword.cs index b9d3ace1..13b74ac5 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePassword.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePassword.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Requests; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -30,6 +31,25 @@ public async Task UpdatePassword_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task UpdatePassword_ShouldReturnError_WhenSessionIsNull() + { + // Arrange + var request = new UpdatePasswordRequest() + { + OldPassword = "oldPassword", + NewPassword = "newPassword" + }; + + // Act + var result = await _appwriteClient.Account.UpdatePassword(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task UpdatePassword_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhone.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhone.cs index 6d4ea07a..a9fa0ef0 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhone.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePhone.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Requests; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -30,6 +31,25 @@ public async Task UpdatePhone_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task UpdatePhone_ShouldReturnError_WhenSessionIsNull() + { + // Arrange + var request = new UpdatePhoneRequest() + { + Password = "Password", + Phone = "+14155552671" + }; + + // Act + var result = await _appwriteClient.Account.UpdatePhone(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task UpdatePhone_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePreferences.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePreferences.cs index 032be346..70d92f56 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePreferences.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdatePreferences.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Requests; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -29,6 +30,24 @@ public async Task UpdatePreferences_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task UpdatePreferences_ShouldReturnError_WhenSessionIsNull() + { + // Arrange + var request = new UpdatePreferencesRequest() + { + Preferences = new Dictionary { { "key1", "val1" }, { "key2", "val2" } } + }; + + // Act + var result = await _appwriteClient.Account.UpdatePreferences(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task UpdatePreferences_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateSession.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateSession.cs index 3b364b01..7bd37908 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateSession.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.UpdateSession.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Tests; using PinguApps.Appwrite.Shared.Utils; using RichardSzalay.MockHttp; @@ -42,6 +43,18 @@ public async Task UpdateSession_ShouldReturnSuccess_WhenApiCallSucceeds() Assert.True(result.Success); } + [Fact] + public async Task UpdateSession_ShouldReturnError_WhenSessionIsNull() + { + // Act + var result = await _appwriteClient.Account.UpdateSession(); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task UpdateSession_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.VerifyAuthenticator.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.VerifyAuthenticator.cs index c10a34cc..4b2bcb8c 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.VerifyAuthenticator.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.VerifyAuthenticator.cs @@ -1,4 +1,5 @@ using System.Net; +using PinguApps.Appwrite.Client.Clients; using PinguApps.Appwrite.Shared.Requests; using PinguApps.Appwrite.Shared.Tests; using RichardSzalay.MockHttp; @@ -55,6 +56,24 @@ public async Task VerifyAuthenticator_ShouldHitDifferentEndpoint_WhenNewTypeIsUs Assert.Equal(1, matches); } + [Fact] + public async Task VerifyAuthenticator_ShouldReturnError_WhenSessionIsNull() + { + // Arrange + var request = new VerifyAuthenticatorRequest + { + Otp = "123456" + }; + + // Act + var result = await _appwriteClient.Account.VerifyAuthenticator(request); + + // Assert + Assert.True(result.IsError); + Assert.True(result.IsInternalError); + Assert.Equal(ISessionAware.SessionExceptionMessage, result.Result.AsT2.Message); + } + [Fact] public async Task VerifyAuthenticator_ShouldHandleException_WhenApiCallFails() { diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.cs index 5b13235b..c42858a7 100644 --- a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.cs +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountClientTests.cs @@ -1,4 +1,7 @@ using Microsoft.Extensions.DependencyInjection; +using Moq; +using PinguApps.Appwrite.Client.Clients; +using PinguApps.Appwrite.Client.Internals; using PinguApps.Appwrite.Shared.Tests; using Refit; using RichardSzalay.MockHttp; @@ -23,29 +26,22 @@ public AccountClientTests() _appwriteClient = serviceProvider.GetRequiredService(); } -} - -public static class AccountTestsExtensions -{ - public static MockedRequest ExpectedHeaders(this MockedRequest request, bool addSessionHeaders = false) - { - var req = request - .WithHeaders("x-appwrite-project", Constants.ProjectId) - .WithHeaders("x-sdk-name", Constants.SdkName) - .WithHeaders("x-sdk-platform", "client") - .WithHeaders("x-sdk-language", Constants.SdkLanguage) - .WithHeaders("x-sdk-version", Constants.SdkVersion) - .WithHeaders("x-appwrite-response-format", Constants.AppwriteResponseFormat); - - if (addSessionHeaders) - return req.ExpectSessionHeaders(); - - return req; - } - public static MockedRequest ExpectSessionHeaders(this MockedRequest request) + [Fact] + public void SetSession_UpdatesSession() { - return request - .WithHeaders("x-appwrite-session", Constants.Session); + // Arrange + var sc = new ServiceCollection(); + var mockAccountApi = new Mock(); + sc.AddSingleton(mockAccountApi.Object); + var sp = sc.BuildServiceProvider(); + var accountClient = new AccountClient(sp); + var sessionAware = accountClient as ISessionAware; + + // Act + sessionAware.UpdateSession(Constants.Session); + + // Assert + Assert.Equal(Constants.Session, accountClient.Session); } } diff --git a/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountTestsExtensions.cs b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountTestsExtensions.cs new file mode 100644 index 00000000..dd6e9a7c --- /dev/null +++ b/tests/PinguApps.Appwrite.Client.Tests/Clients/Account/AccountTestsExtensions.cs @@ -0,0 +1,29 @@ +using PinguApps.Appwrite.Shared.Tests; +using RichardSzalay.MockHttp; + +namespace PinguApps.Appwrite.Client.Tests.Clients.Account; + +public static class AccountTestsExtensions +{ + public static MockedRequest ExpectedHeaders(this MockedRequest request, bool addSessionHeaders = false) + { + var req = request + .WithHeaders("x-appwrite-project", Constants.ProjectId) + .WithHeaders("x-sdk-name", Constants.SdkName) + .WithHeaders("x-sdk-platform", "client") + .WithHeaders("x-sdk-language", Constants.SdkLanguage) + .WithHeaders("x-sdk-version", Constants.SdkVersion) + .WithHeaders("x-appwrite-response-format", Constants.AppwriteResponseFormat); + + if (addSessionHeaders) + return req.ExpectSessionHeaders(); + + return req; + } + + public static MockedRequest ExpectSessionHeaders(this MockedRequest request) + { + return request + .WithHeaders("x-appwrite-session", Constants.Session); + } +} diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Requests/Create2faChallengeConfirmationRequestTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Requests/Create2faChallengeConfirmationRequestTests.cs new file mode 100644 index 00000000..0137b81e --- /dev/null +++ b/tests/PinguApps.Appwrite.Shared.Tests/Requests/Create2faChallengeConfirmationRequestTests.cs @@ -0,0 +1,98 @@ +using FluentValidation; +using PinguApps.Appwrite.Shared.Requests; + +namespace PinguApps.Appwrite.Shared.Tests.Requests; +public class Create2faChallengeConfirmationRequestTests +{ + [Fact] + public void Constructor_InitializesWithExpectedValues() + { + // Arrange & Act + var request = new Create2faChallengeConfirmationRequest(); + + // Assert + Assert.Equal(string.Empty, request.ChallengeId); + Assert.Equal(string.Empty, request.Otp); + } + + [Fact] + public void Properties_CanBeSet() + { + // Arrange + var request = new Create2faChallengeConfirmationRequest(); + var challengeId = "Challenge"; + var otp = "Otp"; + + // Act + request.ChallengeId = challengeId; + request.Otp = otp; + + // Assert + Assert.Equal(challengeId, request.ChallengeId); + Assert.Equal(otp, request.Otp); + } + + [Theory] + [InlineData("A string", "A string")] + [InlineData("123456", "123456")] + [InlineData("A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. ", "A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. A much longer string. ")] + public void IsValid_WithValidInputs_ReturnsTrue(string challenge, string otp) + { + // Arrange + var request = new Create2faChallengeConfirmationRequest + { + ChallengeId = challenge, + Otp = otp + }; + + // Act + var isValid = request.IsValid(); + + // Assert + Assert.True(isValid); + } + + [Theory] + [InlineData("", "123456")] + [InlineData(null, "123456")] + [InlineData("123456", "")] + [InlineData("123456", null)] + public void IsValid_WithInvalidInputs_ReturnsFalse(string? challenge, string? otp) + { + // Arrange + var request = new Create2faChallengeConfirmationRequest + { + ChallengeId = challenge!, + Otp = otp! + }; + + // Act + var isValid = request.IsValid(); + + // Assert + Assert.False(isValid); + } + + [Fact] + public void Validate_WithThrowOnFailuresTrue_ThrowsValidationExceptionOnFailure() + { + // Arrange + var request = new Create2faChallengeConfirmationRequest(); + + // Assert + Assert.Throws(() => request.Validate(true)); + } + + [Fact] + public void Validate_WithThrowOnFailuresFalse_ReturnsInvalidResultOnFailure() + { + // Arrange + var request = new Create2faChallengeConfirmationRequest(); + + // Act + var result = request.Validate(false); + + // Assert + Assert.False(result.IsValid); + } +} diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Requests/Create2faChallengeRequestTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Requests/Create2faChallengeRequestTests.cs index 2170ccfd..616ae8f6 100644 --- a/tests/PinguApps.Appwrite.Shared.Tests/Requests/Create2faChallengeRequestTests.cs +++ b/tests/PinguApps.Appwrite.Shared.Tests/Requests/Create2faChallengeRequestTests.cs @@ -58,8 +58,6 @@ public void IsValid_WithInvalidInputs_ReturnsFalse(SecondFactor factor) Factor = factor }; - var ggg = (int)factor; - // Act var isValid = request.IsValid();