diff --git a/YuckQi.Domain.sln b/YuckQi.Domain.sln index 5c44514..cec7856 100644 --- a/YuckQi.Domain.sln +++ b/YuckQi.Domain.sln @@ -9,12 +9,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YuckQi.Domain.Validation", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YuckQi.Domain.Services", "src\YuckQi.Domain.Services\YuckQi.Domain.Services.csproj", "{0F24D228-C35A-4DB0-BD64-3E33A3D02B02}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YuckQi.Domain.Validation.UnitTests", "test\YuckQi.Domain.Validation.UnitTests\YuckQi.Domain.Validation.UnitTests.csproj", "{153AC057-A111-4A2D-950B-8FB331A1124E}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YuckQi.Domain.Validation.UnitTests", "test\YuckQi.Domain.Validation.UnitTests\YuckQi.Domain.Validation.UnitTests.csproj", "{153AC057-A111-4A2D-950B-8FB331A1124E}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{5B0AF740-A98C-402C-BE34-FD3E95384BA3}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Unit Tests", "Unit Tests", "{4012738B-4956-416F-AC49-28E5F00297B3}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "YuckQi.Domain.UnitTests", "test\YuckQi.Domain.UnitTests\YuckQi.Domain.UnitTests.csproj", "{EA0EA1BA-AC4C-4D6C-839F-BF0F60A40346}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -37,6 +39,10 @@ Global {153AC057-A111-4A2D-950B-8FB331A1124E}.Debug|Any CPU.Build.0 = Debug|Any CPU {153AC057-A111-4A2D-950B-8FB331A1124E}.Release|Any CPU.ActiveCfg = Release|Any CPU {153AC057-A111-4A2D-950B-8FB331A1124E}.Release|Any CPU.Build.0 = Release|Any CPU + {EA0EA1BA-AC4C-4D6C-839F-BF0F60A40346}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA0EA1BA-AC4C-4D6C-839F-BF0F60A40346}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA0EA1BA-AC4C-4D6C-839F-BF0F60A40346}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA0EA1BA-AC4C-4D6C-839F-BF0F60A40346}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -44,6 +50,7 @@ Global GlobalSection(NestedProjects) = preSolution {153AC057-A111-4A2D-950B-8FB331A1124E} = {4012738B-4956-416F-AC49-28E5F00297B3} {4012738B-4956-416F-AC49-28E5F00297B3} = {5B0AF740-A98C-402C-BE34-FD3E95384BA3} + {EA0EA1BA-AC4C-4D6C-839F-BF0F60A40346} = {4012738B-4956-416F-AC49-28E5F00297B3} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {7B79E244-ED98-4357-89F3-0E9586941E8B} diff --git a/src/YuckQi.Domain.Services/Abstract/ITypeEntityService.cs b/src/YuckQi.Domain.Services/Abstract/ITypeEntityService.cs index 5e95658..f247889 100644 --- a/src/YuckQi.Domain.Services/Abstract/ITypeEntityService.cs +++ b/src/YuckQi.Domain.Services/Abstract/ITypeEntityService.cs @@ -1,4 +1,5 @@ using System; +using System.Threading; using System.Threading.Tasks; using YuckQi.Domain.Aspects.Abstract; using YuckQi.Domain.Entities.Abstract; @@ -6,14 +7,12 @@ using YuckQi.Domain.Validation; using YuckQi.Domain.ValueObjects.Abstract; -namespace YuckQi.Domain.Services.Abstract +namespace YuckQi.Domain.Services.Abstract; + +public interface ITypeEntityService where TTypeEntity : IEntity, IType where TIdentifier : IEquatable { - public interface ITypeEntityService where TTypeEntity : IEntity, IType where TKey : struct - { - Task> CreateAsync(TTypeEntity entity); - Task> GetAsync(Guid identifier); - Task> GetAsync(TKey key); - Task> ModifyAsync(TTypeEntity entity); - Task>> SearchAsync(TypeSearchCriteria criteria = null); - } + Task> Create(TTypeEntity entity, CancellationToken cancellationToken = default); + Task> Get(TIdentifier identifier, CancellationToken cancellationToken = default); + Task> Modify(TTypeEntity entity, CancellationToken cancellationToken = default); + Task>> Search(TypeSearchCriteria? criteria = null, CancellationToken cancellationToken = default); } diff --git a/src/YuckQi.Domain.Services/Models/TypeSearchCriteria.cs b/src/YuckQi.Domain.Services/Models/TypeSearchCriteria.cs index 96a772a..914cf3a 100644 --- a/src/YuckQi.Domain.Services/Models/TypeSearchCriteria.cs +++ b/src/YuckQi.Domain.Services/Models/TypeSearchCriteria.cs @@ -1,12 +1,11 @@ using System; using YuckQi.Domain.ValueObjects.Abstract; -namespace YuckQi.Domain.Services.Models +namespace YuckQi.Domain.Services.Models; + +public class TypeSearchCriteria : IPage { - public class TypeSearchCriteria : IPage - { - public String Name { get; set; } - public Int32 PageNumber { get; set; } - public Int32 PageSize { get; set; } - } + public String Name { get; set; } + public Int32 PageNumber { get; set; } + public Int32 PageSize { get; set; } } diff --git a/src/YuckQi.Domain.Services/YuckQi.Domain.Services.csproj b/src/YuckQi.Domain.Services/YuckQi.Domain.Services.csproj index d8ec536..0189c88 100644 --- a/src/YuckQi.Domain.Services/YuckQi.Domain.Services.csproj +++ b/src/YuckQi.Domain.Services/YuckQi.Domain.Services.csproj @@ -1,12 +1,13 @@ - + - netstandard2.0 + net6.0 true Kevin J Lambert - 1.3.1 + 6.2.0 LICENSE A .NET library for bootstrapping a domain services project. + enable diff --git a/src/YuckQi.Domain.Validation/Exceptions/DomainValidationException.cs b/src/YuckQi.Domain.Validation/Exceptions/DomainValidationException.cs deleted file mode 100644 index baf4fd6..0000000 --- a/src/YuckQi.Domain.Validation/Exceptions/DomainValidationException.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Linq; - -namespace YuckQi.Domain.Validation.Exceptions -{ - public class DomainValidationException : ApplicationException - { - #region Constants - - private const String DefaultErrorMessage = "Something went wrong."; - - #endregion - - - #region Properties - - public Result Result { get; } - - #endregion - - - #region Constructors - - public DomainValidationException(Result result) : base(GetErrorMessage(result)) - { - Result = result; - } - - #endregion - - - #region Supporting Methods - - private static String GetErrorMessage(Result result) - { - if (result == null) - return DefaultErrorMessage; - - var count = result.Detail.Count(t => t.Type == ResultType.Error); - var noun = count == 1 ? "error" : "errors"; - var message = $"Domain model has {count} {noun} after validation."; - - return message; - } - - #endregion - } -} diff --git a/src/YuckQi.Domain.Validation/Extensions/AbstractValidatorExtensions.cs b/src/YuckQi.Domain.Validation/Extensions/AbstractValidatorExtensions.cs index e4b1c9c..43fe4c2 100644 --- a/src/YuckQi.Domain.Validation/Extensions/AbstractValidatorExtensions.cs +++ b/src/YuckQi.Domain.Validation/Extensions/AbstractValidatorExtensions.cs @@ -1,44 +1,50 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using FluentValidation; using FluentValidation.Results; -namespace YuckQi.Domain.Validation.Extensions +namespace YuckQi.Domain.Validation.Extensions; + +public static class AbstractValidatorExtensions { - public static class AbstractValidatorExtensions + public static Result GetResult(this AbstractValidator validator, T item) { - public static Result GetResult(this AbstractValidator validator, T item, String failedValidationMessageId) - { - var validationResult = validator.Validate(item); - var result = BuildResult(validationResult, item, failedValidationMessageId); + if (validator == null) + throw new ArgumentNullException(nameof(validator)); - return result; - } + var validationResult = validator.Validate(item); + var result = BuildResult(validationResult, item); - public static async Task> GetResultAsync(this AbstractValidator validator, T item, String failedValidationMessageId) - { - var validationResult = await validator.ValidateAsync(item); - var result = BuildResult(validationResult, item, failedValidationMessageId); + return result; + } - return result; - } + public static async Task> GetResult(this AbstractValidator validator, T item, CancellationToken cancellationToken) + { + if (validator == null) + throw new ArgumentNullException(nameof(validator)); - private static Result BuildResult(ValidationResult validationResult, T item, String failedValidationMessageId) - { - if (validationResult == null) - throw new ArgumentNullException(nameof(validationResult)); + var validationResult = await validator.ValidateAsync(item, cancellationToken); + var result = BuildResult(validationResult, item); - if (validationResult.IsValid) - return new Result(item); + return result; + } - return new Result(default, GetResultDetail(validationResult, failedValidationMessageId)); - } + private static Result BuildResult(ValidationResult validationResult, T item) + { + if (validationResult == null) + throw new ArgumentNullException(nameof(validationResult)); - private static IReadOnlyCollection GetResultDetail(ValidationResult result, String failedValidationMessageId) - { - return result?.Errors.Select(t => new ResultDetail(ResultCode.InvalidRequestDetail, new ResultMessage(failedValidationMessageId, t.ErrorMessage), t.PropertyName)).ToList(); - } + if (validationResult.IsValid) + return new Result(item); + + return new Result(default, GetResultDetail(validationResult)); + } + + private static IReadOnlyCollection GetResultDetail(ValidationResult result) + { + return result.Errors.Select(t => new ResultDetail(new ResultMessage(t.ErrorMessage), ResultCode.InvalidRequestDetail, t.PropertyName)).ToList(); } } diff --git a/src/YuckQi.Domain.Validation/Result.cs b/src/YuckQi.Domain.Validation/Result.cs index 796ce3b..b5dd54c 100644 --- a/src/YuckQi.Domain.Validation/Result.cs +++ b/src/YuckQi.Domain.Validation/Result.cs @@ -2,60 +2,36 @@ using System.Collections.Generic; using System.Linq; -namespace YuckQi.Domain.Validation -{ - public class Result - { - #region Properties - - public IReadOnlyCollection Detail { get; } - - public Boolean IsValid => Detail.All(t => t.Type != ResultType.Error); - - #endregion - +namespace YuckQi.Domain.Validation; - #region Constructors - - public Result(IReadOnlyCollection detail) - { - Detail = detail ?? Array.Empty(); - } +public class Result +{ + public IReadOnlyCollection Detail { get; } - #endregion - } + public Boolean IsValid => Detail.All(t => t.Type != ResultType.Error); - public class Result : Result + public Result(IReadOnlyCollection? detail) { - #region Properties - - public T Payload { get; } - - #endregion - - - #region Constructors - - public Result(ResultDetail detail) : this(new List { detail }) { } - - public Result(IReadOnlyCollection detail) : base(detail) { } - - public Result(T payload, IReadOnlyCollection detail = null) : base(detail) - { - Payload = payload; - } + Detail = detail ?? Array.Empty(); + } +} - #endregion +public class Result : Result +{ + public T? Payload { get; } + public Result(ResultDetail detail) : this(new List { detail }) { } - #region Public Methods + public Result(IReadOnlyCollection detail) : base(detail) { } - public static Result ConstraintViolation(TKey key, String message = null) where TKey : struct => new Result(ResultDetail.ConstraintViolation(key, message)); + public Result(T? payload, IReadOnlyCollection? detail = null) : base(detail) + { + Payload = payload; + } - public Boolean HasResultCode(ResultCode resultCode) => Detail.Any(t => t.Code == resultCode); + public static Result ConstraintViolation(TIdentifier identifier, String? message = null) where TIdentifier : IEquatable => new(ResultDetail.ConstraintViolation(identifier, message)); - public static Result NotFound(TKey key, String message = null) where TKey : struct => new Result(ResultDetail.NotFound(key, message)); + public Boolean HasResultCode(ResultCode resultCode) => Detail.Any(t => t.Code == resultCode); - #endregion - } + public static Result NotFound(TIdentifier identifier, String? message = null) where TIdentifier : IEquatable => new(ResultDetail.NotFound(identifier, message)); } diff --git a/src/YuckQi.Domain.Validation/ResultCode.cs b/src/YuckQi.Domain.Validation/ResultCode.cs index 561a410..f8126d1 100644 --- a/src/YuckQi.Domain.Validation/ResultCode.cs +++ b/src/YuckQi.Domain.Validation/ResultCode.cs @@ -1,50 +1,35 @@ using System; -namespace YuckQi.Domain.Validation -{ - public readonly struct ResultCode - { - #region Private Members - - private readonly String _code; - - #endregion - +namespace YuckQi.Domain.Validation; - #region Implicit Operators - - public static implicit operator String(ResultCode resultCode) => resultCode._code; - - #endregion - - - #region Constants +public readonly struct ResultCode +{ + private readonly String _code; - public static readonly ResultCode ConstraintViolation = new ResultCode(nameof(ConstraintViolation)); - public static readonly ResultCode InvalidRequestDetail = new ResultCode(nameof(InvalidRequestDetail)); - public static readonly ResultCode NotFound = new ResultCode(nameof(NotFound)); + public static implicit operator String(ResultCode code) => code._code; - #endregion + public static readonly ResultCode ConstraintViolation = new(nameof(ConstraintViolation)); + public static readonly ResultCode InvalidRequestDetail = new(nameof(InvalidRequestDetail)); + public static readonly ResultCode NotFound = new(nameof(NotFound)); + public ResultCode() : this(Guid.NewGuid().ToString()) { } - #region Constructors + public ResultCode(String code) + { + _code = code; + } - public ResultCode(String code) + public override Boolean Equals(Object? obj) + { + return obj switch { - _code = code; - } - - #endregion - - - #region Public Methods - - public override Boolean Equals(Object obj) => obj != null && String.Equals(this, (ResultCode) obj); - - public override Int32 GetHashCode() => _code.GetHashCode(); + ResultCode other => String.Equals(this, other), + String other => String.Equals(this, other), + _ => false + }; + } - public override String ToString() => _code; + public override Int32 GetHashCode() => _code.GetHashCode(); - #endregion - } + public override String ToString() => _code; } diff --git a/src/YuckQi.Domain.Validation/ResultDetail.cs b/src/YuckQi.Domain.Validation/ResultDetail.cs index a192760..36d2ab3 100644 --- a/src/YuckQi.Domain.Validation/ResultDetail.cs +++ b/src/YuckQi.Domain.Validation/ResultDetail.cs @@ -1,46 +1,24 @@ using System; -namespace YuckQi.Domain.Validation -{ - public class ResultDetail - { - #region Private Members - - private readonly ResultCode _code; - - #endregion - - - #region Constants - - public static ResultDetail ConstraintViolation(TKey key, String message = null) where TKey : struct => new ResultDetail(ResultCode.ConstraintViolation, ResultMessage.ConstraintConflict(key, message)); - public static ResultDetail NotFound(TKey key, String message = null) where TKey : struct => new ResultDetail(ResultCode.NotFound, ResultMessage.NotFound(key, message)); - - #endregion - +namespace YuckQi.Domain.Validation; - #region Properties - - public ResultMessage Message { get; } - public String Property { get; } - public ResultType Type { get; } - - public String Code => _code; - - #endregion - - - #region Constructors - - public ResultDetail(ResultCode code, ResultMessage message, String property = null, ResultType type = ResultType.Error) - { - _code = code; +public class ResultDetail +{ + public static ResultDetail ConstraintViolation(TIdentifier identifier, String? message = null) where TIdentifier : IEquatable => new(ResultMessage.ConstraintConflict(identifier, message), ResultCode.ConstraintViolation); + public static ResultDetail NotFound(TIdentifier identifier, String? message = null) where TIdentifier : IEquatable => new(ResultMessage.NotFound(identifier, message), ResultCode.NotFound); - Message = message; - Property = property; - Type = type; - } + public ResultCode? Code { get; } + public ResultMessage Message { get; } + public String? Property { get; } + public ResultType Type { get; } - #endregion + public ResultDetail(ResultMessage message, ResultCode? code = null, String? property = null, ResultType type = ResultType.Error) + { + Code = code; + Message = message; + Property = property; + Type = type; } + + public ResultDetail(String message, ResultCode? code = null, String? property = null, ResultType type = ResultType.Error) : this(new ResultMessage(message), code, property, type) { } } diff --git a/src/YuckQi.Domain.Validation/ResultMessage.cs b/src/YuckQi.Domain.Validation/ResultMessage.cs index 673be00..95819cd 100644 --- a/src/YuckQi.Domain.Validation/ResultMessage.cs +++ b/src/YuckQi.Domain.Validation/ResultMessage.cs @@ -1,33 +1,23 @@ using System; -namespace YuckQi.Domain.Validation -{ - public readonly struct ResultMessage - { - #region Properties - - public String Id { get; } - public String Text { get; } - - #endregion - +namespace YuckQi.Domain.Validation; - #region Constructors +public readonly struct ResultMessage +{ + private readonly String _message; - public ResultMessage(String id, String text = null) - { - Id = id; - Text = text; - } + public static implicit operator String(ResultMessage message) => message._message; - #endregion + public ResultMessage() : this(String.Empty) { } + public ResultMessage(String message) + { + _message = message; + } - #region Public Methods + public static ResultMessage ConstraintConflict(TIdentifier identifier, String? message = null) where TIdentifier : IEquatable => new(message ?? $"'{typeof(T).Name}' '{identifier}' already exists."); - public static ResultMessage ConstraintConflict(TKey key, String message = null) where TKey : struct => new ResultMessage($"{ResultCode.ConstraintViolation.GetHashCode()}", message ?? $"'{typeof(T).Name}' '{key}' already exists."); - public static ResultMessage NotFound(TKey key, String message = null) where TKey : struct => new ResultMessage($"{ResultCode.NotFound.GetHashCode()}", message ?? $"'{typeof(T).Name}' '{key}' could not be found."); + public static ResultMessage NotFound(TIdentifier identifier, String? message = null) where TIdentifier : IEquatable => new(message ?? $"'{typeof(T).Name}' '{identifier}' could not be found."); - #endregion - } + public override String ToString() => _message; } diff --git a/src/YuckQi.Domain.Validation/ResultType.cs b/src/YuckQi.Domain.Validation/ResultType.cs index f2519a0..3aa6980 100644 --- a/src/YuckQi.Domain.Validation/ResultType.cs +++ b/src/YuckQi.Domain.Validation/ResultType.cs @@ -1,9 +1,8 @@ -namespace YuckQi.Domain.Validation +namespace YuckQi.Domain.Validation; + +public enum ResultType { - public enum ResultType - { - Unknown = 0, - Warning = 1, - Error = 2 - } + Unknown = 0, + Warning = 1, + Error = 2 } diff --git a/src/YuckQi.Domain.Validation/YuckQi.Domain.Validation.csproj b/src/YuckQi.Domain.Validation/YuckQi.Domain.Validation.csproj index eea7979..0497bae 100644 --- a/src/YuckQi.Domain.Validation/YuckQi.Domain.Validation.csproj +++ b/src/YuckQi.Domain.Validation/YuckQi.Domain.Validation.csproj @@ -1,12 +1,13 @@ - + - netstandard2.0 + net6.0 true Kevin J Lambert - 1.3.1 + 6.2.0 LICENSE A .NET library providing domain validation fundamentals. + enable @@ -17,7 +18,7 @@ - + diff --git a/src/YuckQi.Domain/Aspects/Abstract/IActivated.cs b/src/YuckQi.Domain/Aspects/Abstract/IActivated.cs index f622f0d..4615402 100644 --- a/src/YuckQi.Domain/Aspects/Abstract/IActivated.cs +++ b/src/YuckQi.Domain/Aspects/Abstract/IActivated.cs @@ -1,9 +1,8 @@ using System; -namespace YuckQi.Domain.Aspects.Abstract +namespace YuckQi.Domain.Aspects.Abstract; + +public interface IActivated { - public interface IActivated - { - DateTime? ActivationMomentUtc { get; set; } - } + DateTime? ActivationMomentUtc { get; set; } } diff --git a/src/YuckQi.Domain/Aspects/Abstract/IAudited.cs b/src/YuckQi.Domain/Aspects/Abstract/IAudited.cs index 1466339..14ef1c5 100644 --- a/src/YuckQi.Domain/Aspects/Abstract/IAudited.cs +++ b/src/YuckQi.Domain/Aspects/Abstract/IAudited.cs @@ -1,8 +1,7 @@ -namespace YuckQi.Domain.Aspects.Abstract +namespace YuckQi.Domain.Aspects.Abstract; + +public interface IAudited : ICreated, IRevised { - public interface IAudited : ICreated, IRevised - { - TIdentity CreatedBy { get; set; } - TIdentity RevisedBy { get; set; } - } + TIdentity CreatedBy { get; set; } + TIdentity RevisedBy { get; set; } } diff --git a/src/YuckQi.Domain/Aspects/Abstract/ICreated.cs b/src/YuckQi.Domain/Aspects/Abstract/ICreated.cs index 3f7f2d4..63bed96 100644 --- a/src/YuckQi.Domain/Aspects/Abstract/ICreated.cs +++ b/src/YuckQi.Domain/Aspects/Abstract/ICreated.cs @@ -1,9 +1,8 @@ using System; -namespace YuckQi.Domain.Aspects.Abstract +namespace YuckQi.Domain.Aspects.Abstract; + +public interface ICreated { - public interface ICreated - { - DateTime CreationMomentUtc { get; set; } - } + DateTime CreationMomentUtc { get; set; } } diff --git a/src/YuckQi.Domain/Aspects/Abstract/IDeleted.cs b/src/YuckQi.Domain/Aspects/Abstract/IDeleted.cs index d29fe24..fcd3bb2 100644 --- a/src/YuckQi.Domain/Aspects/Abstract/IDeleted.cs +++ b/src/YuckQi.Domain/Aspects/Abstract/IDeleted.cs @@ -1,9 +1,8 @@ using System; -namespace YuckQi.Domain.Aspects.Abstract +namespace YuckQi.Domain.Aspects.Abstract; + +public interface IDeleted { - public interface IDeleted - { - DateTime? DeletionMomentUtc { get; set; } - } + DateTime? DeletionMomentUtc { get; set; } } diff --git a/src/YuckQi.Domain/Aspects/Abstract/IRevised.cs b/src/YuckQi.Domain/Aspects/Abstract/IRevised.cs index 9713f4d..9600a09 100644 --- a/src/YuckQi.Domain/Aspects/Abstract/IRevised.cs +++ b/src/YuckQi.Domain/Aspects/Abstract/IRevised.cs @@ -1,9 +1,8 @@ using System; -namespace YuckQi.Domain.Aspects.Abstract +namespace YuckQi.Domain.Aspects.Abstract; + +public interface IRevised { - public interface IRevised - { - DateTime RevisionMomentUtc { get; set; } - } + DateTime RevisionMomentUtc { get; set; } } diff --git a/src/YuckQi.Domain/Aspects/Abstract/IType.cs b/src/YuckQi.Domain/Aspects/Abstract/IType.cs index 5a07671..0e0259f 100644 --- a/src/YuckQi.Domain/Aspects/Abstract/IType.cs +++ b/src/YuckQi.Domain/Aspects/Abstract/IType.cs @@ -1,11 +1,9 @@ using System; -namespace YuckQi.Domain.Aspects.Abstract +namespace YuckQi.Domain.Aspects.Abstract; + +public interface IType { - public interface IType - { - Guid Identifier { get; set; } - String Name { get; set; } - String ShortName { get; set; } - } + String Name { get; set; } + String ShortName { get; set; } } diff --git a/src/YuckQi.Domain/Entities/Abstract/EntityBase.cs b/src/YuckQi.Domain/Entities/Abstract/EntityBase.cs index c6a7efa..6a4a044 100644 --- a/src/YuckQi.Domain/Entities/Abstract/EntityBase.cs +++ b/src/YuckQi.Domain/Entities/Abstract/EntityBase.cs @@ -1,7 +1,8 @@ -namespace YuckQi.Domain.Entities.Abstract +using System; + +namespace YuckQi.Domain.Entities.Abstract; + +public abstract class EntityBase : IEntity where TIdentifier : IEquatable { - public abstract class EntityBase : IEntity where TKey : struct - { - public TKey Key { get; set; } - } + public TIdentifier? Identifier { get; set; } } diff --git a/src/YuckQi.Domain/Entities/Abstract/IEntity.cs b/src/YuckQi.Domain/Entities/Abstract/IEntity.cs index fec07d6..27d4aaa 100644 --- a/src/YuckQi.Domain/Entities/Abstract/IEntity.cs +++ b/src/YuckQi.Domain/Entities/Abstract/IEntity.cs @@ -1,7 +1,8 @@ -namespace YuckQi.Domain.Entities.Abstract +using System; + +namespace YuckQi.Domain.Entities.Abstract; + +public interface IEntity where TIdentifier : IEquatable { - public interface IEntity where TKey : struct - { - TKey Key { get; set; } - } + TIdentifier? Identifier { get; set; } } diff --git a/src/YuckQi.Domain/Entities/MultiTenant/Abstract/IMultiTenantEntity.cs b/src/YuckQi.Domain/Entities/MultiTenant/Abstract/IMultiTenantEntity.cs index c9b2657..f057c52 100644 --- a/src/YuckQi.Domain/Entities/MultiTenant/Abstract/IMultiTenantEntity.cs +++ b/src/YuckQi.Domain/Entities/MultiTenant/Abstract/IMultiTenantEntity.cs @@ -1,12 +1,11 @@ using System; using YuckQi.Domain.Entities.Abstract; -namespace YuckQi.Domain.Entities.MultiTenant.Abstract +namespace YuckQi.Domain.Entities.MultiTenant.Abstract; + +public interface IMultiTenantEntity : IEntity where TIdentifier : IEquatable where TTenantIdentifier : IEquatable { - public interface IMultiTenantEntity : IEntity where TKey : struct where TTenantKey : struct - { - TTenantKey TenantId { get; set; } + TTenantIdentifier? TenantIdentifier { get; set; } - Boolean IsValidTenant(TTenantKey? tenantId); - } + Boolean IsValidTenant(TTenantIdentifier? tenantIdentifier); } diff --git a/src/YuckQi.Domain/Entities/MultiTenant/Abstract/MultiTenantEntityBase.cs b/src/YuckQi.Domain/Entities/MultiTenant/Abstract/MultiTenantEntityBase.cs index 0530eab..fc93617 100644 --- a/src/YuckQi.Domain/Entities/MultiTenant/Abstract/MultiTenantEntityBase.cs +++ b/src/YuckQi.Domain/Entities/MultiTenant/Abstract/MultiTenantEntityBase.cs @@ -1,12 +1,11 @@ using System; using YuckQi.Domain.Entities.Abstract; -namespace YuckQi.Domain.Entities.MultiTenant.Abstract +namespace YuckQi.Domain.Entities.MultiTenant.Abstract; + +public abstract class MultiTenantEntityBase : EntityBase, IMultiTenantEntity where TIdentifier : IEquatable where TTenantIdentifier : IEquatable { - public abstract class MultiTenantEntityBase : EntityBase, IMultiTenantEntity where TKey : struct where TTenantKey : struct - { - public TTenantKey TenantId { get; set; } + public TTenantIdentifier? TenantIdentifier { get; set; } - public Boolean IsValidTenant(TTenantKey? tenantId) => TenantId.Equals(tenantId); - } + public Boolean IsValidTenant(TTenantIdentifier? tenantIdentifier) => Equals(TenantIdentifier, tenantIdentifier); } diff --git a/src/YuckQi.Domain/ValueObjects/Abstract/IPage.cs b/src/YuckQi.Domain/ValueObjects/Abstract/IPage.cs index fc27dd8..23ac801 100644 --- a/src/YuckQi.Domain/ValueObjects/Abstract/IPage.cs +++ b/src/YuckQi.Domain/ValueObjects/Abstract/IPage.cs @@ -1,17 +1,16 @@ using System; using System.Collections.Generic; -namespace YuckQi.Domain.ValueObjects.Abstract +namespace YuckQi.Domain.ValueObjects.Abstract; + +public interface IPage { - public interface IPage - { - Int32 PageNumber { get; } - Int32 PageSize { get; } - } + Int32 PageNumber { get; } + Int32 PageSize { get; } +} - public interface IPage : IPage - { - IReadOnlyCollection Items { get; } - Int32 TotalCount { get; } - } +public interface IPage : IPage +{ + IReadOnlyCollection Items { get; } + Int32 TotalCount { get; } } diff --git a/src/YuckQi.Domain/ValueObjects/Date.cs b/src/YuckQi.Domain/ValueObjects/Date.cs deleted file mode 100644 index 4f7e60e..0000000 --- a/src/YuckQi.Domain/ValueObjects/Date.cs +++ /dev/null @@ -1,199 +0,0 @@ -/* -The MIT License (MIT) - -Copyright (c) 2015 Clay Anderson - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -using System; -using System.Globalization; -using System.Runtime.Serialization; - -namespace YuckQi.Domain.ValueObjects -{ - [Serializable] - public readonly struct Date : IComparable, IFormattable, ISerializable, IComparable, IEquatable - { - private readonly DateTime _value; - - public static readonly Date MaxValue = new Date(DateTime.MaxValue); - public static readonly Date MinValue = new Date(DateTime.MinValue); - - public Date(Int32 year, Int32 month, Int32 day) - { - _value = new DateTime(year, month, day); - } - - public Date(DateTime dateTime) - { - _value = dateTime.AddTicks(-dateTime.Ticks % TimeSpan.TicksPerDay); - } - - public Date(DateTimeOffset dateTimeOffset) : this(dateTimeOffset.DateTime) { } - - private Date(SerializationInfo info, StreamingContext context) - { - _value = DateTime.FromFileTime(info.GetInt64("ticks")); - } - - public static TimeSpan operator -(Date d1, Date d2) => d1._value - d2._value; - - public static Date operator -(Date d, TimeSpan t) => new Date(d._value - t); - - public static Boolean operator !=(Date d1, Date d2) => d1._value != d2._value; - - public static Date operator +(Date d, TimeSpan t) => new Date(d._value + t); - - public static Boolean operator <(Date d1, Date d2) => d1._value < d2._value; - - public static Boolean operator <=(Date d1, Date d2) => d1._value <= d2._value; - - public static Boolean operator ==(Date d1, Date d2) => d1._value == d2._value; - - public static Boolean operator >(Date d1, Date d2) => d1._value > d2._value; - - public static Boolean operator >=(Date d1, Date d2) => d1._value >= d2._value; - - public static implicit operator DateTime(Date d) => d._value; - - public static explicit operator Date(DateTime d) => new Date(d); - - public static implicit operator DateTimeOffset(Date d) => d._value; - - public static explicit operator Date(DateTimeOffset d) => new Date(d); - - public Int32 Day => _value.Day; - - public DayOfWeek DayOfWeek => _value.DayOfWeek; - - public Int32 DayOfYear => _value.DayOfYear; - - public Int32 Month => _value.Month; - - public static Date Today => new Date(DateTime.Today); - - public Int32 Year => _value.Year; - - public Int64 Ticks => _value.Ticks; - - public Date AddDays(Int32 value) => new Date(_value.AddDays(value)); - - public Date AddMonths(Int32 value) => new Date(_value.AddMonths(value)); - - public Date AddYears(Int32 value) => new Date(_value.AddYears(value)); - - public static Int32 Compare(Date d1, Date d2) => d1.CompareTo(d2); - - public Int32 CompareTo(Date value) => _value.CompareTo(value._value); - - public Int32 CompareTo(Object value) => _value.CompareTo(value); - - public static Int32 DaysInMonth(Int32 year, Int32 month) => DateTime.DaysInMonth(year, month); - - public Boolean Equals(Date value) => _value.Equals(value._value); - - public override Boolean Equals(Object value) => value is Date date && _value.Equals(date._value); - - public override Int32 GetHashCode() => _value.GetHashCode(); - - public static Boolean Equals(Date d1, Date d2) => d1._value.Equals(d2._value); - - void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) - { - info.AddValue("ticks", _value.Ticks); - } - - public static Boolean IsLeapYear(Int32 year) => DateTime.IsLeapYear(year); - - public static Date Parse(String s) => new Date(DateTime.Parse(s)); - - public static Date Parse(String s, IFormatProvider provider) => new Date(DateTime.Parse(s, provider)); - - public static Date Parse(String s, IFormatProvider provider, DateTimeStyles style) => new Date(DateTime.Parse(s, provider, style)); - - public static Date ParseExact(String s, String format, IFormatProvider provider) => new Date(DateTime.ParseExact(s, format, provider)); - - public static Date ParseExact(String s, String format, IFormatProvider provider, DateTimeStyles style) => new Date(DateTime.ParseExact(s, format, provider, style)); - - public static Date ParseExact(String s, String[] formats, IFormatProvider provider, DateTimeStyles style) => new Date(DateTime.ParseExact(s, formats, provider, style)); - - public TimeSpan Subtract(Date value) => this - value; - - public Date Subtract(TimeSpan value) => this - value; - - public static Date ToDate(DateTime dateTime) => new Date(dateTime); - - public static Date ToDate(DateTimeOffset dateTimeOffset) => new Date(dateTimeOffset); - - public String ToLongString() => _value.ToLongDateString(); - - public String ToShortString() => _value.ToShortDateString(); - - public override String ToString() => ToShortString(); - - public String ToString(IFormatProvider provider) => _value.ToString(provider); - - public String ToString(String format) - { - if (format == "O" || format == "o" || format == "s") - return ToString("yyyy-MM-dd"); - - return _value.ToString(format); - } - - public String ToString(String format, IFormatProvider provider) => _value.ToString(format, provider); - - public static Boolean TryParse(String s, out Date result) - { - var success = DateTime.TryParse(s, out var d); - - result = new Date(d); - - return success; - } - - public static Boolean TryParse(String s, IFormatProvider provider, DateTimeStyles style, out Date result) - { - var success = DateTime.TryParse(s, provider, style, out var d); - - result = new Date(d); - - return success; - } - - public static Boolean TryParseExact(String s, String format, IFormatProvider provider, DateTimeStyles style, out Date result) - { - var success = DateTime.TryParseExact(s, format, provider, style, out var d); - - result = new Date(d); - - return success; - } - - public static Boolean TryParseExact(String s, String[] formats, IFormatProvider provider, DateTimeStyles style, out Date result) - { - var success = DateTime.TryParseExact(s, formats, provider, style, out var d); - - result = new Date(d); - - return success; - } - } -} diff --git a/src/YuckQi.Domain/ValueObjects/Page.cs b/src/YuckQi.Domain/ValueObjects/Page.cs index 549abd4..5e4b738 100644 --- a/src/YuckQi.Domain/ValueObjects/Page.cs +++ b/src/YuckQi.Domain/ValueObjects/Page.cs @@ -2,51 +2,50 @@ using System.Collections.Generic; using YuckQi.Domain.ValueObjects.Abstract; -namespace YuckQi.Domain.ValueObjects -{ - public readonly struct Page : IPage - { - #region Properties +namespace YuckQi.Domain.ValueObjects; - public Int32 PageNumber { get; } - public Int32 PageSize { get; } +public readonly struct Page : IPage +{ + #region Properties - #endregion + public Int32 PageNumber { get; } + public Int32 PageSize { get; } + #endregion - #region Constructors - public Page(Int32 page, Int32 size) - { - PageNumber = page; - PageSize = size; - } + #region Constructors - #endregion + public Page(Int32 page, Int32 size) + { + PageNumber = page; + PageSize = size; } - public readonly struct Page : IPage - { - #region Properties + #endregion +} - public IReadOnlyCollection Items { get; } - public Int32 PageNumber { get; } - public Int32 PageSize { get; } - public Int32 TotalCount { get; } +public readonly struct Page : IPage +{ + #region Properties - #endregion + public IReadOnlyCollection Items { get; } + public Int32 PageNumber { get; } + public Int32 PageSize { get; } + public Int32 TotalCount { get; } + #endregion - #region Constructors - public Page(IReadOnlyCollection items, Int32 total, Int32 page, Int32 size) - { - Items = items ?? new List(); - PageNumber = page; - PageSize = size; - TotalCount = total; - } + #region Constructors - #endregion + public Page(IReadOnlyCollection items, Int32 total, Int32 page, Int32 size) + { + Items = items; + PageNumber = page; + PageSize = size; + TotalCount = total; } + + #endregion } diff --git a/src/YuckQi.Domain/YuckQi.Domain.csproj b/src/YuckQi.Domain/YuckQi.Domain.csproj index 90a9c6c..81d575f 100644 --- a/src/YuckQi.Domain/YuckQi.Domain.csproj +++ b/src/YuckQi.Domain/YuckQi.Domain.csproj @@ -1,12 +1,13 @@ - + - netstandard2.0 + net6.0 true Kevin J Lambert - 1.3.1 + 6.2.0 LICENSE A .NET library for bootstrapping a domain model project. + enable diff --git a/test/YuckQi.Domain.UnitTests/Entities/Abstract/EntityBaseTests.cs b/test/YuckQi.Domain.UnitTests/Entities/Abstract/EntityBaseTests.cs new file mode 100644 index 0000000..f28ba45 --- /dev/null +++ b/test/YuckQi.Domain.UnitTests/Entities/Abstract/EntityBaseTests.cs @@ -0,0 +1,22 @@ +using System; +using NUnit.Framework; +using YuckQi.Domain.Entities.Abstract; + +namespace YuckQi.Domain.UnitTests.Entities.Abstract; + +public class EntityBaseTests +{ + private class Entity : EntityBase { } + + [SetUp] + public void Setup() { } + + [Test] + public void EntityBase_GetIdentifier_HasExpectedValue() + { + var identifier = Guid.NewGuid(); + var entity = new Entity { Identifier = identifier }; + + Assert.That(entity.Identifier, Is.EqualTo(identifier)); + } +} diff --git a/test/YuckQi.Domain.UnitTests/Entities/MultiTenant/Abstract/MultiTenantEntityBaseTests.cs b/test/YuckQi.Domain.UnitTests/Entities/MultiTenant/Abstract/MultiTenantEntityBaseTests.cs new file mode 100644 index 0000000..1d6c8ae --- /dev/null +++ b/test/YuckQi.Domain.UnitTests/Entities/MultiTenant/Abstract/MultiTenantEntityBaseTests.cs @@ -0,0 +1,40 @@ +using System; +using NUnit.Framework; +using YuckQi.Domain.Entities.MultiTenant.Abstract; + +namespace YuckQi.Domain.UnitTests.Entities.MultiTenant.Abstract; + +public class MultiTenantEntityBaseTests +{ + private class MultiTenantEntity : MultiTenantEntityBase { } + + [SetUp] + public void Setup() { } + + [Test] + public void MultiTenantEntityBase_GetTenantIdentifier_HasExpectedValue() + { + var identifier = Guid.NewGuid().ToString("D").ToUpperInvariant(); + var entity = new MultiTenantEntity { Identifier = Guid.NewGuid(), TenantIdentifier = identifier }; + + Assert.That(entity.TenantIdentifier, Is.EqualTo(identifier)); + } + + [Test] + public void MultiTenantEntityBase_WithDifferentTenantIdentifier_IsNotValid() + { + var identifier = Guid.NewGuid().ToString("D").ToUpperInvariant(); + var entity = new MultiTenantEntity(); + + Assert.That(entity.IsValidTenant(identifier), Is.False); + } + + [Test] + public void MultiTenantEntityBase_WithSameTenantIdentifier_IsValid() + { + var identifier = Guid.NewGuid().ToString("D").ToUpperInvariant(); + var entity = new MultiTenantEntity { Identifier = Guid.NewGuid(), TenantIdentifier = identifier }; + + Assert.That(entity.IsValidTenant(identifier), Is.True); + } +} diff --git a/test/YuckQi.Domain.UnitTests/ValueObjects/PageTests.cs b/test/YuckQi.Domain.UnitTests/ValueObjects/PageTests.cs new file mode 100644 index 0000000..e8da6e5 --- /dev/null +++ b/test/YuckQi.Domain.UnitTests/ValueObjects/PageTests.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using NUnit.Framework; +using YuckQi.Domain.ValueObjects; + +namespace YuckQi.Domain.UnitTests.ValueObjects; + +public class PageTests +{ + [SetUp] + public void Setup() { } + + [Test] + public void Page_Properties_HaveExpectedValues() + { + var page = new Page(1, 10); + + Assert.That(page.PageNumber, Is.EqualTo(1)); + Assert.That(page.PageSize, Is.EqualTo(10)); + } + + [Test] + public void PageOfString_Properties_HaveExpectedValues() + { + var items = new HashSet { "abc", "def", "ghi" }; + var page = new Page(items, items.Count, 1, 10); + + Assert.That(page.Items, Contains.Item("abc")); + Assert.That(page.Items, Contains.Item("def")); + Assert.That(page.Items, Contains.Item("ghi")); + Assert.That(page.PageNumber, Is.EqualTo(1)); + Assert.That(page.PageSize, Is.EqualTo(10)); + Assert.That(page.TotalCount, Is.EqualTo(3)); + } +} diff --git a/test/YuckQi.Domain.UnitTests/YuckQi.Domain.UnitTests.csproj b/test/YuckQi.Domain.UnitTests/YuckQi.Domain.UnitTests.csproj new file mode 100644 index 0000000..f4f3444 --- /dev/null +++ b/test/YuckQi.Domain.UnitTests/YuckQi.Domain.UnitTests.csproj @@ -0,0 +1,24 @@ + + + + net6.0 + enable + + false + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/test/YuckQi.Domain.Validation.UnitTests/Extensions/AbstractValidatorExtensionsTests.cs b/test/YuckQi.Domain.Validation.UnitTests/Extensions/AbstractValidatorExtensionsTests.cs new file mode 100644 index 0000000..1777421 --- /dev/null +++ b/test/YuckQi.Domain.Validation.UnitTests/Extensions/AbstractValidatorExtensionsTests.cs @@ -0,0 +1,62 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using FluentValidation; +using NUnit.Framework; +using YuckQi.Domain.Validation.Extensions; + +namespace YuckQi.Domain.Validation.UnitTests.Extensions; + +public class AbstractValidatorExtensionsTests +{ + public class StringValidator : AbstractValidator + { + public StringValidator() + { + RuleFor(t => t.Length).GreaterThan(1).WithMessage("it is too short"); + } + } + + [SetUp] + public void Setup() { } + + [Test] + public void AbstractValidator_GetResultWithValidItem_IsValid() + { + var validator = new StringValidator(); + var result = validator.GetResult("hello"); + + Assert.That(result.IsValid, Is.True); + } + + [Test] + public async Task AbstractValidator_GetResultAsyncWithValidItem_IsValid() + { + var validator = new StringValidator(); + var result = await validator.GetResult("hello", CancellationToken.None); + + Assert.That(result.IsValid, Is.True); + } + + [Test] + public void AbstractValidator_GetResultWithInvalidItem_HasDetail() + { + var validator = new StringValidator(); + var result = validator.GetResult(String.Empty); + + Assert.That(result.IsValid, Is.False); + Assert.That(result.Detail, Is.Not.Empty); + } + + [Test] + public void AbstractValidator_GetResultWithNullReference_ThrowsException() + { + Assert.That(() => AbstractValidatorExtensions.GetResult(null!, String.Empty), Throws.ArgumentNullException); + } + + [Test] + public void AbstractValidator_GetResultAsyncWithNullReference_ThrowsException() + { + Assert.That(() => AbstractValidatorExtensions.GetResult(null!, String.Empty, CancellationToken.None), Throws.ArgumentNullException); + } +} diff --git a/test/YuckQi.Domain.Validation.UnitTests/ResultCodeTests.cs b/test/YuckQi.Domain.Validation.UnitTests/ResultCodeTests.cs index 43fe625..073344b 100644 --- a/test/YuckQi.Domain.Validation.UnitTests/ResultCodeTests.cs +++ b/test/YuckQi.Domain.Validation.UnitTests/ResultCodeTests.cs @@ -10,11 +10,40 @@ public void Setup() { } [Test] public void ResultCode_WithSameCode_HasSameHashCode() { - var resultCodeA = new ResultCode("test"); + var resultCodeA = new ResultCode(); var hashCodeA = resultCodeA.GetHashCode(); - var resultCodeB = new ResultCode("test"); + var resultCodeB = new ResultCode(resultCodeA); var hashCodeB = resultCodeB.GetHashCode(); - Assert.AreEqual(hashCodeA, hashCodeB); + Assert.That(hashCodeA, Is.EqualTo(hashCodeB)); + } + + [Test] + public void ResultCode_StringConversion_IsAsExpected() + { + var resultCode = new ResultCode("test"); + + Assert.That(resultCode.ToString(), Is.EquivalentTo("test")); + } + + [Test] + public void ResultCode_Equality_IsAsExpected() + { + var resultCodeA = new ResultCode("test"); + var resultCodeB = new ResultCode("test"); + + // ReSharper disable SuspiciousTypeConversion.Global + Assert.That(resultCodeA.Equals("test"), Is.True); + Assert.That(resultCodeA.Equals(resultCodeB), Is.True); + Assert.That(resultCodeA.Equals(1234), Is.False); + // ReSharper restore SuspiciousTypeConversion.Global + } + + [Test] + public void ResultCode_ToString_IsAsExpected() + { + var resultCode = new ResultCode("test"); + + Assert.That(resultCode.ToString(), Is.EqualTo("test")); } } diff --git a/test/YuckQi.Domain.Validation.UnitTests/ResultDetailTests.cs b/test/YuckQi.Domain.Validation.UnitTests/ResultDetailTests.cs new file mode 100644 index 0000000..5458ab3 --- /dev/null +++ b/test/YuckQi.Domain.Validation.UnitTests/ResultDetailTests.cs @@ -0,0 +1,35 @@ +using System; +using NUnit.Framework; + +namespace YuckQi.Domain.Validation.UnitTests; + +public class ResultDetailTests +{ + [SetUp] + public void Setup() { } + + [Test] + public void ResultDetail_NotFound_HasNotFoundResultCode() + { + var detail = ResultDetail.NotFound(Guid.NewGuid()); + + Assert.That(detail.Code, Is.EqualTo(ResultCode.NotFound)); + } + + [Test] + public void ResultDetail_WithProperty_HasMatchingPropertyName() + { + var detail = new ResultDetail("thing missing", property: "property"); + + Assert.That(detail.Property, Is.EqualTo("property")); + } + + [Test] + public void ResultDetail_Message_HasMatchingValue() + { + var message = "this is a problem"; + var detail = new ResultDetail(message); + + Assert.That((String) detail.Message, Is.EqualTo(message)); + } +} diff --git a/test/YuckQi.Domain.Validation.UnitTests/ResultMessageTests.cs b/test/YuckQi.Domain.Validation.UnitTests/ResultMessageTests.cs new file mode 100644 index 0000000..0590fa9 --- /dev/null +++ b/test/YuckQi.Domain.Validation.UnitTests/ResultMessageTests.cs @@ -0,0 +1,25 @@ +using NUnit.Framework; + +namespace YuckQi.Domain.Validation.UnitTests; + +public class ResultMessageTests +{ + [SetUp] + public void Setup() { } + + [Test] + public void ResultMessage_ToString_MatchesOriginalMessage() + { + var message = new ResultMessage("this is a test"); + + Assert.That(message.ToString(), Is.EqualTo("this is a test")); + } + + [Test] + public void ResultMessage_WithNoMessage_IsNotNull() + { + var message = new ResultMessage(); + + Assert.That(message.ToString(), Is.Not.Null); + } +} diff --git a/test/YuckQi.Domain.Validation.UnitTests/ResultTests.cs b/test/YuckQi.Domain.Validation.UnitTests/ResultTests.cs index 527196c..3c3bfce 100644 --- a/test/YuckQi.Domain.Validation.UnitTests/ResultTests.cs +++ b/test/YuckQi.Domain.Validation.UnitTests/ResultTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using NUnit.Framework; namespace YuckQi.Domain.Validation.UnitTests; @@ -14,37 +15,63 @@ public void Result_NotFound_HasNotFoundResultCode() { var detail = new List { ResultDetail.NotFound(1), ResultDetail.ConstraintViolation(1) }.AsReadOnly(); var result = new Result(detail); - var hasNotFoundResultCode = result.HasResultCode(ResultCode.NotFound); - Assert.IsTrue(hasNotFoundResultCode); + Assert.That(result.HasResultCode(ResultCode.NotFound), Is.True); } [Test] public void Result_WithErrors_IsNotValid() { - var detail = new List { new(new ResultCode("test"), new ResultMessage("id")) }; + var detail = new List { new("test") }; var result = new Result("test", detail); - var isValid = result.IsValid; - Assert.IsFalse(isValid); + Assert.That(result.IsValid, Is.False); } [Test] public void Result_WithNoDetail_IsValid() { var result = new Result("test"); - var isValid = result.IsValid; - Assert.IsTrue(isValid); + Assert.That(result.IsValid, Is.True); } [Test] public void Result_WithOnlyWarnings_IsValid() { - var detail = new List { new(new ResultCode("test"), new ResultMessage("id"), type: ResultType.Warning) }; + var detail = new List { new(new ResultMessage("test"), type: ResultType.Warning) }; var result = new Result("test", detail); - var isValid = result.IsValid; - Assert.IsTrue(isValid); + Assert.That(result.IsValid, Is.True); + } + + [Test] + public void Result_Payload_IsValid() + { + var payload = Guid.NewGuid().ToString(); + var result = new Result(payload); + + Assert.That(result.IsValid, Is.True); + Assert.That(result.Payload, Is.SameAs(payload)); + } + + [Test] + public void Result_ConstraintViolation_IsValid() + { + var identifier = Guid.NewGuid().ToString(); + var result = Result.ConstraintViolation(identifier); + var errors = result.Detail.Where(t => t.Code == ResultCode.ConstraintViolation); + + Assert.That(errors.Count(), Is.EqualTo(1)); + } + + [Test] + public void Result_NotFound_IsValid() + { + var identifier = Guid.NewGuid().ToString(); + var result = Result.NotFound(identifier); + var errors = result.Detail.Where(t => t.Code == ResultCode.NotFound); + + Assert.That(errors.Count(), Is.EqualTo(1)); } } diff --git a/test/YuckQi.Domain.Validation.UnitTests/YuckQi.Domain.Validation.UnitTests.csproj b/test/YuckQi.Domain.Validation.UnitTests/YuckQi.Domain.Validation.UnitTests.csproj index f55e89e..1c9be1e 100644 --- a/test/YuckQi.Domain.Validation.UnitTests/YuckQi.Domain.Validation.UnitTests.csproj +++ b/test/YuckQi.Domain.Validation.UnitTests/YuckQi.Domain.Validation.UnitTests.csproj @@ -8,10 +8,13 @@ - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive +