From 031a97f9072a3c195cf04a2d629b3922e4d849ef Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 9 Jul 2024 03:44:47 +0100 Subject: [PATCH 01/10] Added IRequestValidator and applied to UpdatePhoneRequest --- src/PinguApps.Appwrite.Playground/App.cs | 4 +-- .../PinguApps.Appwrite.Shared.csproj | 1 + .../Requests/IRequestValidator.cs | 18 +++++++++++++ .../Requests/UpdatePhoneRequest.cs | 27 ++++++++++++++++++- 4 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 src/PinguApps.Appwrite.Shared/Requests/IRequestValidator.cs diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index ef9e73ac..5d343e87 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -23,8 +23,8 @@ public async Task Run(string[] args) var request = new UpdatePhoneRequest { - Password = "MyNewPassword", - Phone = "+14155552671" + Password = "sword", + Phone = "14155552671" }; var result = await _client.Account.UpdatePhone(request); diff --git a/src/PinguApps.Appwrite.Shared/PinguApps.Appwrite.Shared.csproj b/src/PinguApps.Appwrite.Shared/PinguApps.Appwrite.Shared.csproj index aea6e504..d0d524fc 100644 --- a/src/PinguApps.Appwrite.Shared/PinguApps.Appwrite.Shared.csproj +++ b/src/PinguApps.Appwrite.Shared/PinguApps.Appwrite.Shared.csproj @@ -7,6 +7,7 @@ + diff --git a/src/PinguApps.Appwrite.Shared/Requests/IRequestValidator.cs b/src/PinguApps.Appwrite.Shared/Requests/IRequestValidator.cs new file mode 100644 index 00000000..779dfaf3 --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Requests/IRequestValidator.cs @@ -0,0 +1,18 @@ +using FluentValidation.Results; + +namespace PinguApps.Appwrite.Shared.Requests; +public interface IRequestValidator +{ + /// + /// Checks if the data within the request is valid + /// + /// true if the request is valid + public bool IsValid(); + + /// + /// Checks if the data within the request is valid, and returns errors if any are found + /// + /// If true, then will throw an exception if any errors are found. False by default + /// ValidationResult, containing bool indicating validity and any errors found + public ValidationResult Validate(bool throwOnFailures = false); +} diff --git a/src/PinguApps.Appwrite.Shared/Requests/UpdatePhoneRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/UpdatePhoneRequest.cs index 1eb7ac70..0e785e1f 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/UpdatePhoneRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/UpdatePhoneRequest.cs @@ -1,11 +1,13 @@ using System.Text.Json.Serialization; +using FluentValidation; +using FluentValidation.Results; namespace PinguApps.Appwrite.Shared.Requests; /// /// The request for updating a users phone /// -public class UpdatePhoneRequest +public class UpdatePhoneRequest : IRequestValidator { /// /// Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212 @@ -18,4 +20,27 @@ public class UpdatePhoneRequest /// [JsonPropertyName("password")] public string Password { get; set; } = string.Empty; + + /// + public bool IsValid() => Validate().IsValid; + + /// + public ValidationResult Validate(bool throwOnFailures = false) + { + var validator = new UpdatePhoneRequestValidator(); + + if (throwOnFailures) + return validator.Validate(this, x => x.ThrowOnFailures()); + + return validator.Validate(this); + } +} + +internal class UpdatePhoneRequestValidator : AbstractValidator +{ + public UpdatePhoneRequestValidator() + { + RuleFor(x => x.Phone).NotEmpty().Matches("^\\+\\d*$"); + RuleFor(x => x.Password).NotEmpty().MinimumLength(8); + } } From 74e7467d78cc286982a9b928e06c499f1e2efd10 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 9 Jul 2024 03:56:59 +0100 Subject: [PATCH 02/10] Returning internal error if request was invalid --- src/PinguApps.Appwrite.Client/Clients/AccountClient.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs b/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs index 99d6fdbb..6ef83d89 100644 --- a/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs @@ -112,6 +112,8 @@ public async Task> UpdatePhone(UpdatePhoneRequest request) { try { + request.Validate(true); + var result = await _accountApi.UpdatePhone(Session, request); return result.GetApiResponse(); From 58aa32632ef27feab7b220354151d74d9d2fd34b Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 9 Jul 2024 03:57:09 +0100 Subject: [PATCH 03/10] added full test coverage for additions --- .../Requests/UpdatePhoneRequestTests.cs | 72 ++++++++++++++++++- 1 file changed, 71 insertions(+), 1 deletion(-) diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdatePhoneRequestTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdatePhoneRequestTests.cs index 318d74fe..1458cccd 100644 --- a/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdatePhoneRequestTests.cs +++ b/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdatePhoneRequestTests.cs @@ -1,4 +1,5 @@ -using PinguApps.Appwrite.Shared.Requests; +using FluentValidation; +using PinguApps.Appwrite.Shared.Requests; namespace PinguApps.Appwrite.Shared.Tests.Requests; @@ -33,4 +34,73 @@ public void Properties_CanBeSet(string password, string phone) Assert.Equal(password, request.Password); Assert.Equal(phone, request.Phone); } + + [Fact] + public void IsValid_WithValidPhoneAndPassword_ReturnsTrue() + { + // Arrange + var request = new UpdatePhoneRequest + { + Phone = "+16175551212", + Password = "password123" + }; + + // Act + bool isValid = request.IsValid(); + + // Assert + Assert.True(isValid); + } + + [Theory] + [InlineData("", "password123")] // Empty phone + [InlineData("+16175551212", "")] // Empty password + [InlineData("16175551212", "password123")] // Invalid phone + [InlineData("+16175551212", "pass")] // Short password + public void IsValid_WithInvalidInputs_ReturnsFalse(string phone, string password) + { + // Arrange + var request = new UpdatePhoneRequest + { + Phone = phone, + Password = password + }; + + // Act + var isValid = request.IsValid(); + + // Assert + Assert.False(isValid); + } + + [Fact] + public void Validate_WithThrowOnFailuresTrue_ThrowsValidationExceptionOnFailure() + { + // Arrange + var request = new UpdatePhoneRequest + { + Phone = "invalid", + Password = "short" + }; + + // Assert + Assert.Throws(() => request.Validate(true)); + } + + [Fact] + public void Validate_WithThrowOnFailuresFalse_ReturnsInvalidResultOnFailure() + { + // Arrange + var request = new UpdatePhoneRequest + { + Phone = "invalid", + Password = "short" + }; + + // Act + var result = request.Validate(false); + + // Assert + Assert.False(result.IsValid); + } } From 95e38386739b5ffc3be479bcb19371faacf4d4bd Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 9 Jul 2024 04:32:23 +0100 Subject: [PATCH 04/10] Changes request validator interface into an abstract base class to save repetition --- src/PinguApps.Appwrite.Playground/App.cs | 2 ++ .../Requests/BaseRequest.cs | 20 ++++++++++++++ .../Requests/CreateAccountRequest.cs | 5 +++- .../Requests/IRequestValidator.cs | 18 ------------- .../Requests/UpdatePhoneRequest.cs | 27 ++----------------- .../CreateAccountRequestValidator.cs | 13 +++++++++ .../Validators/UpdatePhoneRequestValidator.cs | 11 ++++++++ 7 files changed, 52 insertions(+), 44 deletions(-) create mode 100644 src/PinguApps.Appwrite.Shared/Requests/BaseRequest.cs delete mode 100644 src/PinguApps.Appwrite.Shared/Requests/IRequestValidator.cs create mode 100644 src/PinguApps.Appwrite.Shared/Requests/Validators/CreateAccountRequestValidator.cs create mode 100644 src/PinguApps.Appwrite.Shared/Requests/Validators/UpdatePhoneRequestValidator.cs diff --git a/src/PinguApps.Appwrite.Playground/App.cs b/src/PinguApps.Appwrite.Playground/App.cs index 5d343e87..7bf51bd8 100644 --- a/src/PinguApps.Appwrite.Playground/App.cs +++ b/src/PinguApps.Appwrite.Playground/App.cs @@ -27,6 +27,8 @@ public async Task Run(string[] args) Phone = "14155552671" }; + var f = request.IsValid(); + var result = await _client.Account.UpdatePhone(request); result.Result.Switch( diff --git a/src/PinguApps.Appwrite.Shared/Requests/BaseRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/BaseRequest.cs new file mode 100644 index 00000000..858a9d7b --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Requests/BaseRequest.cs @@ -0,0 +1,20 @@ +using FluentValidation; +using FluentValidation.Results; + +namespace PinguApps.Appwrite.Shared.Requests; +public abstract class BaseRequest + where TRequest : class + where TValidator : IValidator, new() +{ + public bool IsValid() => Validate().IsValid; + + public ValidationResult Validate(bool throwOnFailures = false) + { + var validator = new TValidator(); + + if (throwOnFailures) + return validator.Validate(this as TRequest, options => options.ThrowOnFailures()); + + return validator.Validate((this as TRequest)!); + } +} diff --git a/src/PinguApps.Appwrite.Shared/Requests/CreateAccountRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/CreateAccountRequest.cs index 45ed939e..02b5d146 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/CreateAccountRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/CreateAccountRequest.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Requests.Validators; using PinguApps.Appwrite.Shared.Utils; namespace PinguApps.Appwrite.Shared.Requests; @@ -6,7 +7,7 @@ namespace PinguApps.Appwrite.Shared.Requests; /// /// The request for creating an account /// -public class CreateAccountRequest +public class CreateAccountRequest : BaseRequest { /// /// User ID. Choose a custom ID or generate a random ID with . Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars @@ -32,3 +33,5 @@ public class CreateAccountRequest [JsonPropertyName("name")] public string? Name { get; set; } } + + diff --git a/src/PinguApps.Appwrite.Shared/Requests/IRequestValidator.cs b/src/PinguApps.Appwrite.Shared/Requests/IRequestValidator.cs deleted file mode 100644 index 779dfaf3..00000000 --- a/src/PinguApps.Appwrite.Shared/Requests/IRequestValidator.cs +++ /dev/null @@ -1,18 +0,0 @@ -using FluentValidation.Results; - -namespace PinguApps.Appwrite.Shared.Requests; -public interface IRequestValidator -{ - /// - /// Checks if the data within the request is valid - /// - /// true if the request is valid - public bool IsValid(); - - /// - /// Checks if the data within the request is valid, and returns errors if any are found - /// - /// If true, then will throw an exception if any errors are found. False by default - /// ValidationResult, containing bool indicating validity and any errors found - public ValidationResult Validate(bool throwOnFailures = false); -} diff --git a/src/PinguApps.Appwrite.Shared/Requests/UpdatePhoneRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/UpdatePhoneRequest.cs index 0e785e1f..2697ea02 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/UpdatePhoneRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/UpdatePhoneRequest.cs @@ -1,13 +1,12 @@ using System.Text.Json.Serialization; -using FluentValidation; -using FluentValidation.Results; +using PinguApps.Appwrite.Shared.Requests.Validators; namespace PinguApps.Appwrite.Shared.Requests; /// /// The request for updating a users phone /// -public class UpdatePhoneRequest : IRequestValidator +public class UpdatePhoneRequest : BaseRequest { /// /// Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212 @@ -20,27 +19,5 @@ public class UpdatePhoneRequest : IRequestValidator /// [JsonPropertyName("password")] public string Password { get; set; } = string.Empty; - - /// - public bool IsValid() => Validate().IsValid; - - /// - public ValidationResult Validate(bool throwOnFailures = false) - { - var validator = new UpdatePhoneRequestValidator(); - - if (throwOnFailures) - return validator.Validate(this, x => x.ThrowOnFailures()); - - return validator.Validate(this); - } } -internal class UpdatePhoneRequestValidator : AbstractValidator -{ - public UpdatePhoneRequestValidator() - { - RuleFor(x => x.Phone).NotEmpty().Matches("^\\+\\d*$"); - RuleFor(x => x.Password).NotEmpty().MinimumLength(8); - } -} diff --git a/src/PinguApps.Appwrite.Shared/Requests/Validators/CreateAccountRequestValidator.cs b/src/PinguApps.Appwrite.Shared/Requests/Validators/CreateAccountRequestValidator.cs new file mode 100644 index 00000000..9f9308e2 --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Requests/Validators/CreateAccountRequestValidator.cs @@ -0,0 +1,13 @@ +using FluentValidation; + +namespace PinguApps.Appwrite.Shared.Requests.Validators; +public class CreateAccountRequestValidator : AbstractValidator +{ + public CreateAccountRequestValidator() + { + RuleFor(x => x.UserId).NotEmpty().Matches("^[a-zA-Z0-9][a-zA-Z0-9._-]{0,35}$"); + RuleFor(x => x.Email).NotEmpty().EmailAddress(); + RuleFor(x => x.Password).NotEmpty().MinimumLength(8).MaximumLength(256); + RuleFor(x => x.Name).MaximumLength(128); + } +} diff --git a/src/PinguApps.Appwrite.Shared/Requests/Validators/UpdatePhoneRequestValidator.cs b/src/PinguApps.Appwrite.Shared/Requests/Validators/UpdatePhoneRequestValidator.cs new file mode 100644 index 00000000..0c9004a6 --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Requests/Validators/UpdatePhoneRequestValidator.cs @@ -0,0 +1,11 @@ +using FluentValidation; + +namespace PinguApps.Appwrite.Shared.Requests.Validators; +public class UpdatePhoneRequestValidator : AbstractValidator +{ + public UpdatePhoneRequestValidator() + { + RuleFor(x => x.Phone).NotEmpty().Matches("^\\+\\d*$"); + RuleFor(x => x.Password).NotEmpty().MinimumLength(8); + } +} From 5692cef7106ef0f5ccc0574679d9af090ad1464e Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 9 Jul 2024 04:41:11 +0100 Subject: [PATCH 05/10] Added valdiators and using them for remaining requests --- .../Clients/AccountClient.cs | 8 ++++++++ .../Servers/AccountServer.cs | 2 ++ .../Requests/UpdateEmailRequest.cs | 3 ++- .../Requests/UpdateNameRequest.cs | 3 ++- .../Requests/UpdatePasswordRequest.cs | 3 ++- .../Validators/UpdateEmailRequestValidator.cs | 11 +++++++++++ .../Requests/Validators/UpdateNameRequestValidator.cs | 10 ++++++++++ .../Validators/UpdatePasswordRequestValidator.cs | 11 +++++++++++ 8 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 src/PinguApps.Appwrite.Shared/Requests/Validators/UpdateEmailRequestValidator.cs create mode 100644 src/PinguApps.Appwrite.Shared/Requests/Validators/UpdateNameRequestValidator.cs create mode 100644 src/PinguApps.Appwrite.Shared/Requests/Validators/UpdatePasswordRequestValidator.cs diff --git a/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs b/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs index 6ef83d89..46e7339c 100644 --- a/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs +++ b/src/PinguApps.Appwrite.Client/Clients/AccountClient.cs @@ -52,6 +52,8 @@ public async Task> Create(CreateAccountRequest request) { try { + request.Validate(true); + var result = await _accountApi.CreateAccount(request); return result.GetApiResponse(); @@ -67,6 +69,8 @@ public async Task> UpdateEmail(UpdateEmailRequest request) { try { + request.Validate(true); + var result = await _accountApi.UpdateEmail(Session, request); return result.GetApiResponse(); @@ -82,6 +86,8 @@ public async Task> UpdateName(UpdateNameRequest request) { try { + request.Validate(true); + var result = await _accountApi.UpdateName(Session, request); return result.GetApiResponse(); @@ -97,6 +103,8 @@ public async Task> UpdatePassword(UpdatePasswordRequest req { try { + request.Validate(true); + var result = await _accountApi.UpdatePassword(Session, request); return result.GetApiResponse(); diff --git a/src/PinguApps.Appwrite.Server/Servers/AccountServer.cs b/src/PinguApps.Appwrite.Server/Servers/AccountServer.cs index ac745208..0c73395d 100644 --- a/src/PinguApps.Appwrite.Server/Servers/AccountServer.cs +++ b/src/PinguApps.Appwrite.Server/Servers/AccountServer.cs @@ -20,6 +20,8 @@ public async Task> Create(CreateAccountRequest request) { try { + request.Validate(true); + var result = await _accountApi.CreateAccount(request); return result.GetApiResponse(); diff --git a/src/PinguApps.Appwrite.Shared/Requests/UpdateEmailRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/UpdateEmailRequest.cs index 587facfa..69c81bfe 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/UpdateEmailRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/UpdateEmailRequest.cs @@ -1,11 +1,12 @@ using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Requests.Validators; namespace PinguApps.Appwrite.Shared.Requests; /// /// The request for updating a users email /// -public class UpdateEmailRequest +public class UpdateEmailRequest : BaseRequest { /// /// User email diff --git a/src/PinguApps.Appwrite.Shared/Requests/UpdateNameRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/UpdateNameRequest.cs index 7f900135..073ec102 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/UpdateNameRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/UpdateNameRequest.cs @@ -1,11 +1,12 @@ using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Requests.Validators; namespace PinguApps.Appwrite.Shared.Requests; /// /// The request for updating a users name /// -public class UpdateNameRequest +public class UpdateNameRequest : BaseRequest { /// /// User name. Max length: 128 chars diff --git a/src/PinguApps.Appwrite.Shared/Requests/UpdatePasswordRequest.cs b/src/PinguApps.Appwrite.Shared/Requests/UpdatePasswordRequest.cs index 5ec48369..8b85783a 100644 --- a/src/PinguApps.Appwrite.Shared/Requests/UpdatePasswordRequest.cs +++ b/src/PinguApps.Appwrite.Shared/Requests/UpdatePasswordRequest.cs @@ -1,11 +1,12 @@ using System.Text.Json.Serialization; +using PinguApps.Appwrite.Shared.Requests.Validators; namespace PinguApps.Appwrite.Shared.Requests; /// /// The request for updating a users password /// -public class UpdatePasswordRequest +public class UpdatePasswordRequest : BaseRequest { /// /// New user password. Must be at least 8 chars diff --git a/src/PinguApps.Appwrite.Shared/Requests/Validators/UpdateEmailRequestValidator.cs b/src/PinguApps.Appwrite.Shared/Requests/Validators/UpdateEmailRequestValidator.cs new file mode 100644 index 00000000..03fa19c9 --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Requests/Validators/UpdateEmailRequestValidator.cs @@ -0,0 +1,11 @@ +using FluentValidation; + +namespace PinguApps.Appwrite.Shared.Requests.Validators; +public class UpdateEmailRequestValidator : AbstractValidator +{ + public UpdateEmailRequestValidator() + { + RuleFor(x => x.Email).NotEmpty().EmailAddress(); + RuleFor(x => x.Password).NotEmpty().MinimumLength(8); + } +} diff --git a/src/PinguApps.Appwrite.Shared/Requests/Validators/UpdateNameRequestValidator.cs b/src/PinguApps.Appwrite.Shared/Requests/Validators/UpdateNameRequestValidator.cs new file mode 100644 index 00000000..fbbf7e0d --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Requests/Validators/UpdateNameRequestValidator.cs @@ -0,0 +1,10 @@ +using FluentValidation; + +namespace PinguApps.Appwrite.Shared.Requests.Validators; +public class UpdateNameRequestValidator : AbstractValidator +{ + public UpdateNameRequestValidator() + { + RuleFor(x => x.Name).NotEmpty().MaximumLength(128); + } +} diff --git a/src/PinguApps.Appwrite.Shared/Requests/Validators/UpdatePasswordRequestValidator.cs b/src/PinguApps.Appwrite.Shared/Requests/Validators/UpdatePasswordRequestValidator.cs new file mode 100644 index 00000000..721f6166 --- /dev/null +++ b/src/PinguApps.Appwrite.Shared/Requests/Validators/UpdatePasswordRequestValidator.cs @@ -0,0 +1,11 @@ +using FluentValidation; + +namespace PinguApps.Appwrite.Shared.Requests.Validators; +public class UpdatePasswordRequestValidator : AbstractValidator +{ + public UpdatePasswordRequestValidator() + { + RuleFor(x => x.NewPassword).NotEmpty().MinimumLength(8); + RuleFor(x => x.OldPassword).MinimumLength(8).When(x => x.OldPassword is not null); + } +} From 68305cb3e331e66f1ca6b3543a6adb8acebe46e3 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 9 Jul 2024 04:54:23 +0100 Subject: [PATCH 06/10] Added tests for update password request --- .../Requests/UpdatePasswordRequestTests.cs | 73 ++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdatePasswordRequestTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdatePasswordRequestTests.cs index 3320c3ea..ffdf611b 100644 --- a/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdatePasswordRequestTests.cs +++ b/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdatePasswordRequestTests.cs @@ -1,4 +1,5 @@ -using PinguApps.Appwrite.Shared.Requests; +using FluentValidation; +using PinguApps.Appwrite.Shared.Requests; namespace PinguApps.Appwrite.Shared.Tests.Requests; @@ -32,4 +33,74 @@ public void Properties_CanBeSet(string? oldPassword, string newPassword) Assert.Equal(oldPassword, request.OldPassword); Assert.Equal(newPassword, request.NewPassword); } + + [Theory] + [InlineData(null, "Password")] + [InlineData("Password", "Passw0rd")] + public void IsValid_WithValidData_ReturnsTrue(string? oldPassword, string newPassword) + { + // Arrange + var request = new UpdatePasswordRequest + { + NewPassword = newPassword, + OldPassword = oldPassword + }; + + // Act + bool isValid = request.IsValid(); + + // Assert + Assert.True(isValid); + } + + [Theory] + [InlineData("Password", "")] // Empty new + [InlineData("pass", "Password")] // Short old + [InlineData("Password", "pass")] // Short new + public void IsValid_WithInvalidData_ReturnsFalse(string oldPassword, string newPassword) + { + // Arrange + var request = new UpdatePasswordRequest + { + OldPassword = oldPassword, + NewPassword = newPassword + }; + + // Act + var isValid = request.IsValid(); + + // Assert + Assert.False(isValid); + } + + [Fact] + public void Validate_WithThrowOnFailuresTrue_ThrowsValidationExceptionOnFailure() + { + // Arrange + var request = new UpdatePhoneRequest + { + Phone = "invalid", + Password = "short" + }; + + // Assert + Assert.Throws(() => request.Validate(true)); + } + + [Fact] + public void Validate_WithThrowOnFailuresFalse_ReturnsInvalidResultOnFailure() + { + // Arrange + var request = new UpdatePhoneRequest + { + Phone = "invalid", + Password = "short" + }; + + // Act + var result = request.Validate(false); + + // Assert + Assert.False(result.IsValid); + } } From 757a54ae1809d59b7dc3d34748ebccdeabf15e44 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 9 Jul 2024 04:54:55 +0100 Subject: [PATCH 07/10] changed assignment --- .../Requests/UpdatePasswordRequestTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdatePasswordRequestTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdatePasswordRequestTests.cs index ffdf611b..cd91ad9e 100644 --- a/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdatePasswordRequestTests.cs +++ b/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdatePasswordRequestTests.cs @@ -47,7 +47,7 @@ public void IsValid_WithValidData_ReturnsTrue(string? oldPassword, string newPas }; // Act - bool isValid = request.IsValid(); + var isValid = request.IsValid(); // Assert Assert.True(isValid); From 468e600df9e10b80feca25d91b9d6d7ac75bb32e Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 9 Jul 2024 05:06:41 +0100 Subject: [PATCH 08/10] Added Create Account tests --- .../Requests/CreateAccountRequestTests.cs | 95 ++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Requests/CreateAccountRequestTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Requests/CreateAccountRequestTests.cs index 9f92b18f..2ea80a7d 100644 --- a/tests/PinguApps.Appwrite.Shared.Tests/Requests/CreateAccountRequestTests.cs +++ b/tests/PinguApps.Appwrite.Shared.Tests/Requests/CreateAccountRequestTests.cs @@ -1,4 +1,5 @@ -using PinguApps.Appwrite.Shared.Requests; +using FluentValidation; +using PinguApps.Appwrite.Shared.Requests; namespace PinguApps.Appwrite.Shared.Tests.Requests; public class CreateAccountRequestTests @@ -35,4 +36,96 @@ public void Properties_CanBeSet(string email, string password, string? name) Assert.Equal(password, request.Password); Assert.Equal(name, request.Name); } + + [Theory] + [InlineData(null, "pingu@example.com", "Password", null)] + [InlineData("321654987", "pingu@example.com", "12345678", "Pingu")] + [InlineData("a.s-d_f", "pingu@example.com", "12345678", "Pingu")] + public void IsValid_WithValidData_ReturnsTrue(string? userId, string email, string password, string? name) + { + // Arrange + var request = new CreateAccountRequest + { + Email = email, + Password = password, + Name = name + }; + + if (userId is not null) + { + request.UserId = userId; + } + + // Act + var isValid = request.IsValid(); + + // Assert + Assert.True(isValid); + } + + [Theory] + [InlineData("badChar^", "pingu@example.com", "Password", "Pingu")] + [InlineData(".bad", "pingu@example.com", "Password", "Pingu")] + [InlineData("_bad", "pingu@example.com", "Password", "Pingu")] + [InlineData("-bad", "pingu@example.com", "Password", "Pingu")] + [InlineData("", "pingu@example.com", "Password", "Pingu")] + [InlineData("1234567890123456789012345678901234567", "pingu@example.com", "Password", "Pingu")] + [InlineData(null, "not an email", "Password", "Pingu")] + [InlineData(null, "", "Password", "Pingu")] + [InlineData(null, "pingu@example.com", "short", "Pingu")] + [InlineData(null, "pingu@example.com", "", "Pingu")] + public void IsValid_WithInvalidData_ReturnsFalse(string? userId, string email, string password, string? name) + { + // Arrange + var request = new CreateAccountRequest + { + Email = email, + Password = password, + Name = name + }; + + if (userId is not null) + { + request.UserId = userId; + } + + // Act + var isValid = request.IsValid(); + + // Assert + Assert.False(isValid); + } + + [Fact] + public void Validate_WithThrowOnFailuresTrue_ThrowsValidationExceptionOnFailure() + { + // Arrange + var request = new CreateAccountRequest + { + UserId = ".badChar^", + Email = "not an email", + Password = "short" + }; + + // Assert + Assert.Throws(() => request.Validate(true)); + } + + [Fact] + public void Validate_WithThrowOnFailuresFalse_ReturnsInvalidResultOnFailure() + { + // Arrange + var request = new CreateAccountRequest + { + UserId = ".badChar^", + Email = "not an email", + Password = "short" + }; + + // Act + var result = request.Validate(false); + + // Assert + Assert.False(result.IsValid); + } } From 3e1089cbb2492c65d4e7969eff774709943e4f87 Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 9 Jul 2024 22:38:40 +0100 Subject: [PATCH 09/10] Added tests for update email request --- .../Requests/UpdateEmailRequestTests.cs | 74 ++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdateEmailRequestTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdateEmailRequestTests.cs index 18a8ae85..ec08e031 100644 --- a/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdateEmailRequestTests.cs +++ b/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdateEmailRequestTests.cs @@ -1,4 +1,5 @@ -using PinguApps.Appwrite.Shared.Requests; +using FluentValidation; +using PinguApps.Appwrite.Shared.Requests; namespace PinguApps.Appwrite.Shared.Tests.Requests; public class UpdateEmailRequestTests @@ -32,4 +33,75 @@ public void Properties_CanBeSet(string email, string password) Assert.Equal(email, request.Email); Assert.Equal(password, request.Password); } + + [Theory] + [InlineData("pingu@example.com", "Password")] + [InlineData("something@anotherthing.somethingelse", "£$%^&*()")] + public void IsValid_WithValidData_ReturnsTrue(string email, string password) + { + // Arrange + var request = new UpdateEmailRequest + { + Email = email, + Password = password + }; + + // Act + var isValid = request.IsValid(); + + // Assert + Assert.True(isValid); + } + + [Theory] + [InlineData("not an email", "Password")] + [InlineData("", "Password")] + [InlineData("pingu@example.com", "short")] + [InlineData("pingu@example.com", "")] + public void IsValid_WithInvalidData_ReturnsFalse(string email, string password) + { + // Arrange + var request = new UpdateEmailRequest + { + Email = email, + Password = password + }; + + // Act + var isValid = request.IsValid(); + + // Assert + Assert.False(isValid); + } + + [Fact] + public void Validate_WithThrowOnFailuresTrue_ThrowsValidationExceptionOnFailure() + { + // Arrange + var request = new UpdateEmailRequest + { + Email = "not an email", + Password = "short" + }; + + // Assert + Assert.Throws(() => request.Validate(true)); + } + + [Fact] + public void Validate_WithThrowOnFailuresFalse_ReturnsInvalidResultOnFailure() + { + // Arrange + var request = new UpdateEmailRequest + { + Email = "not an email", + Password = "short" + }; + + // Act + var result = request.Validate(false); + + // Assert + Assert.False(result.IsValid); + } } From abaab4eb85d29efa31b5fb9081a73b78bd97c23d Mon Sep 17 00:00:00 2001 From: Matthew Parker Date: Tue, 9 Jul 2024 22:42:36 +0100 Subject: [PATCH 10/10] Added tests to UpdateNameRequest --- .../Requests/UpdateNameRequestTests.cs | 67 ++++++++++++++++++- 1 file changed, 66 insertions(+), 1 deletion(-) diff --git a/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdateNameRequestTests.cs b/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdateNameRequestTests.cs index 04b20ecf..0ad91c61 100644 --- a/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdateNameRequestTests.cs +++ b/tests/PinguApps.Appwrite.Shared.Tests/Requests/UpdateNameRequestTests.cs @@ -1,4 +1,5 @@ -using PinguApps.Appwrite.Shared.Requests; +using FluentValidation; +using PinguApps.Appwrite.Shared.Requests; namespace PinguApps.Appwrite.Shared.Tests.Requests; public class UpdateNameRequestTests @@ -28,4 +29,68 @@ public void Properties_CanBeSet(string name) // Assert Assert.Equal(name, request.Name); } + + [Theory] + [InlineData("John")] + [InlineData("John Smith")] + public void IsValid_WithValidData_ReturnsTrue(string name) + { + // Arrange + var request = new UpdateNameRequest + { + Name = name + }; + + // Act + var isValid = request.IsValid(); + + // Assert + Assert.True(isValid); + } + + [Theory] + [InlineData("")] + public void IsValid_WithInvalidData_ReturnsFalse(string name) + { + // Arrange + var request = new UpdateNameRequest + { + Name = name + }; + + // Act + var isValid = request.IsValid(); + + // Assert + Assert.False(isValid); + } + + [Fact] + public void Validate_WithThrowOnFailuresTrue_ThrowsValidationExceptionOnFailure() + { + // Arrange + var request = new UpdateNameRequest + { + Name = "" + }; + + // Assert + Assert.Throws(() => request.Validate(true)); + } + + [Fact] + public void Validate_WithThrowOnFailuresFalse_ReturnsInvalidResultOnFailure() + { + // Arrange + var request = new UpdateNameRequest + { + Name = "" + }; + + // Act + var result = request.Validate(false); + + // Assert + Assert.False(result.IsValid); + } }