Remove unused fat
This commit is contained in:
@@ -4,7 +4,6 @@
|
|||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageVersion Include="Ardalis.GuardClauses" Version="4.2.0" />
|
|
||||||
<PackageVersion Include="AutoMapper" Version="13.0.1" />
|
<PackageVersion Include="AutoMapper" Version="13.0.1" />
|
||||||
<PackageVersion Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.0" />
|
<PackageVersion Include="Azure.Extensions.AspNetCore.Configuration.Secrets" Version="1.3.0" />
|
||||||
<PackageVersion Include="Azure.Identity" Version="1.12.0" />
|
<PackageVersion Include="Azure.Identity" Version="1.12.0" />
|
||||||
@@ -16,7 +15,6 @@
|
|||||||
<PackageVersion Include="FluentValidation.DependencyInjectionExtensions" Version="11.8.1" />
|
<PackageVersion Include="FluentValidation.DependencyInjectionExtensions" Version="11.8.1" />
|
||||||
<PackageVersion Include="Google.Apis.Oauth2.v2" Version="1.67.0.1869" />
|
<PackageVersion Include="Google.Apis.Oauth2.v2" Version="1.67.0.1869" />
|
||||||
<PackageVersion Include="JetBrains.Annotations" Version="2024.2.0" />
|
<PackageVersion Include="JetBrains.Annotations" Version="2024.2.0" />
|
||||||
<PackageVersion Include="MediatR" Version="12.2.0" />
|
|
||||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Facebook" Version="8.0.4" />
|
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Facebook" Version="8.0.4" />
|
||||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Google" Version="8.0.4" />
|
<PackageVersion Include="Microsoft.AspNetCore.Authentication.Google" Version="8.0.4" />
|
||||||
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6" />
|
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.6" />
|
||||||
|
|||||||
37
Hutopy.sln
37
Hutopy.sln
@@ -3,18 +3,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.0.31903.59
|
VisualStudioVersion = 17.0.31903.59
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Domain", "src\Domain\Domain.csproj", "{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application", "src\Application\Application.csproj", "{34C0FACD-F3D9-400C-8945-554DD6B0819A}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure", "src\Infrastructure\Infrastructure.csproj", "{117DA02F-5274-4565-ACC6-DA9B6E568B09}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure", "src\Infrastructure\Infrastructure.csproj", "{117DA02F-5274-4565-ACC6-DA9B6E568B09}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6ED356A7-8B47-4613-AD01-C85CF28491BD}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{6ED356A7-8B47-4613-AD01-C85CF28491BD}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{664D406C-2F83-48F0-BFC3-408D5CB53C65}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Domain.UnitTests", "tests\Domain.UnitTests\Domain.UnitTests.csproj", "{DC37FD87-552C-4613-9F16-1537CA522898}"
|
|
||||||
EndProject
|
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E2DA20AA-28D1-455C-BF50-C49A8F831633}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{E2DA20AA-28D1-455C-BF50-C49A8F831633}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
.editorconfig = .editorconfig
|
.editorconfig = .editorconfig
|
||||||
@@ -30,56 +22,27 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "src\Web\Web.csproj", "{4E4EE20C-F06A-4A1B-851F-C5577796941C}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Web", "src\Web\Web.csproj", "{4E4EE20C-F06A-4A1B-851F-C5577796941C}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Application.FunctionalTests", "tests\Application.FunctionalTests\Application.FunctionalTests.csproj", "{EA6127A5-94C9-4C31-AD11-E6811B92B520}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Infrastructure.IntegrationTests", "tests\Infrastructure.IntegrationTests\Infrastructure.IntegrationTests.csproj", "{01FA6786-921D-4CE8-8C50-4FDA66C9477D}"
|
|
||||||
EndProject
|
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{34C0FACD-F3D9-400C-8945-554DD6B0819A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{34C0FACD-F3D9-400C-8945-554DD6B0819A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{34C0FACD-F3D9-400C-8945-554DD6B0819A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{34C0FACD-F3D9-400C-8945-554DD6B0819A}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{117DA02F-5274-4565-ACC6-DA9B6E568B09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{117DA02F-5274-4565-ACC6-DA9B6E568B09}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{117DA02F-5274-4565-ACC6-DA9B6E568B09}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{117DA02F-5274-4565-ACC6-DA9B6E568B09}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.Build.0 = Release|Any CPU
|
{117DA02F-5274-4565-ACC6-DA9B6E568B09}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{DC37FD87-552C-4613-9F16-1537CA522898}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{DC37FD87-552C-4613-9F16-1537CA522898}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{DC37FD87-552C-4613-9F16-1537CA522898}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{DC37FD87-552C-4613-9F16-1537CA522898}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{4E4EE20C-F06A-4A1B-851F-C5577796941C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{4E4EE20C-F06A-4A1B-851F-C5577796941C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{4E4EE20C-F06A-4A1B-851F-C5577796941C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{4E4EE20C-F06A-4A1B-851F-C5577796941C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{4E4EE20C-F06A-4A1B-851F-C5577796941C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{4E4EE20C-F06A-4A1B-851F-C5577796941C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{4E4EE20C-F06A-4A1B-851F-C5577796941C}.Release|Any CPU.Build.0 = Release|Any CPU
|
{4E4EE20C-F06A-4A1B-851F-C5577796941C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{EA6127A5-94C9-4C31-AD11-E6811B92B520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{EA6127A5-94C9-4C31-AD11-E6811B92B520}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{EA6127A5-94C9-4C31-AD11-E6811B92B520}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{EA6127A5-94C9-4C31-AD11-E6811B92B520}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{01FA6786-921D-4CE8-8C50-4FDA66C9477D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{01FA6786-921D-4CE8-8C50-4FDA66C9477D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{01FA6786-921D-4CE8-8C50-4FDA66C9477D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{01FA6786-921D-4CE8-8C50-4FDA66C9477D}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(NestedProjects) = preSolution
|
GlobalSection(NestedProjects) = preSolution
|
||||||
{C7E89A3E-A631-4760-8D61-BD1EAB1C4E69} = {6ED356A7-8B47-4613-AD01-C85CF28491BD}
|
|
||||||
{34C0FACD-F3D9-400C-8945-554DD6B0819A} = {6ED356A7-8B47-4613-AD01-C85CF28491BD}
|
|
||||||
{117DA02F-5274-4565-ACC6-DA9B6E568B09} = {6ED356A7-8B47-4613-AD01-C85CF28491BD}
|
{117DA02F-5274-4565-ACC6-DA9B6E568B09} = {6ED356A7-8B47-4613-AD01-C85CF28491BD}
|
||||||
{DC37FD87-552C-4613-9F16-1537CA522898} = {664D406C-2F83-48F0-BFC3-408D5CB53C65}
|
|
||||||
{4E4EE20C-F06A-4A1B-851F-C5577796941C} = {6ED356A7-8B47-4613-AD01-C85CF28491BD}
|
{4E4EE20C-F06A-4A1B-851F-C5577796941C} = {6ED356A7-8B47-4613-AD01-C85CF28491BD}
|
||||||
{EA6127A5-94C9-4C31-AD11-E6811B92B520} = {664D406C-2F83-48F0-BFC3-408D5CB53C65}
|
|
||||||
{01FA6786-921D-4CE8-8C50-4FDA66C9477D} = {664D406C-2F83-48F0-BFC3-408D5CB53C65}
|
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {3CB609D9-5D54-4C11-A371-DAAC8B74E430}
|
SolutionGuid = {3CB609D9-5D54-4C11-A371-DAAC8B74E430}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
## Patterns / strategy used
|
## Patterns / strategy used
|
||||||
- Clean Architecture ( with Infrastructure, Domain, Application and Web layers )
|
- Clean Architecture ( with Infrastructure, Domain, Application and Web layers )
|
||||||
- Minimal API endpoints.
|
- Minimal API endpoints.
|
||||||
- Guards ( Fail fast ) : https://github.com/ardalis/GuardClauses
|
|
||||||
|
|
||||||
## Tools
|
## Tools
|
||||||
- Install Docker : https://www.docker.com/get-started/
|
- Install Docker : https://www.docker.com/get-started/
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<RootNamespace>Hutopy.Application</RootNamespace>
|
|
||||||
<AssemblyName>Hutopy.Application</AssemblyName>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Ardalis.GuardClauses" />
|
|
||||||
<PackageReference Include="AutoMapper" />
|
|
||||||
<PackageReference Include="FluentValidation.DependencyInjectionExtensions" />
|
|
||||||
<PackageReference Include="Google.Apis.Oauth2.v2" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore" />
|
|
||||||
<PackageReference Include="MinimalApis.Extensions" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Domain\Domain.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
namespace Hutopy.Domain.Common;
|
|
||||||
|
|
||||||
public abstract class BaseAuditableEntity : BaseEntity
|
|
||||||
{
|
|
||||||
public DateTimeOffset CreatedAt { get; set; }
|
|
||||||
|
|
||||||
public Guid? CreatedBy { get; set; }
|
|
||||||
|
|
||||||
public DateTimeOffset LastModifiedAt { get; set; }
|
|
||||||
|
|
||||||
public Guid? LastModifiedBy { get; set; }
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace Hutopy.Domain.Common;
|
|
||||||
|
|
||||||
public abstract class BaseEntity
|
|
||||||
{
|
|
||||||
// This can easily be modified to be BaseEntity<T> and public T Id to support different key types.
|
|
||||||
// Using non-generic integer types for simplicity
|
|
||||||
public Guid Id { get; set; }
|
|
||||||
|
|
||||||
private readonly List<BaseEvent> _domainEvents = [];
|
|
||||||
|
|
||||||
[NotMapped]
|
|
||||||
public IEnumerable<BaseEvent> DomainEvents => _domainEvents.AsReadOnly();
|
|
||||||
|
|
||||||
public void AddDomainEvent(BaseEvent domainEvent)
|
|
||||||
{
|
|
||||||
_domainEvents.Add(domainEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveDomainEvent(BaseEvent domainEvent)
|
|
||||||
{
|
|
||||||
_domainEvents.Remove(domainEvent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void ClearDomainEvents()
|
|
||||||
{
|
|
||||||
_domainEvents.Clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
using MediatR;
|
|
||||||
|
|
||||||
namespace Hutopy.Domain.Common;
|
|
||||||
|
|
||||||
public abstract class BaseEvent : INotification
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
namespace Hutopy.Domain.Common;
|
|
||||||
|
|
||||||
// Learn more: https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/implement-value-objects
|
|
||||||
public abstract class ValueObject
|
|
||||||
{
|
|
||||||
private static bool EqualOperator(ValueObject left, ValueObject right)
|
|
||||||
{
|
|
||||||
if (left is null ^ right is null)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return left?.Equals(right!) != false;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static bool NotEqualOperator(ValueObject left, ValueObject right)
|
|
||||||
{
|
|
||||||
return !(EqualOperator(left, right));
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract IEnumerable<object> GetEqualityComponents();
|
|
||||||
|
|
||||||
public override bool Equals(object? obj)
|
|
||||||
{
|
|
||||||
if (obj == null || obj.GetType() != GetType())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var other = (ValueObject)obj;
|
|
||||||
return GetEqualityComponents().SequenceEqual(other.GetEqualityComponents());
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
var hash = new HashCode();
|
|
||||||
|
|
||||||
foreach (var component in GetEqualityComponents())
|
|
||||||
{
|
|
||||||
hash.Add(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash.ToHashCode();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
namespace Hutopy.Domain.Constants;
|
|
||||||
|
|
||||||
public abstract class Policies
|
|
||||||
{
|
|
||||||
public const string CanPurge = nameof(CanPurge);
|
|
||||||
public const string CanDelete = nameof(CanDelete);
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<RootNamespace>Hutopy.Domain</RootNamespace>
|
|
||||||
<AssemblyName>Hutopy.Domain</AssemblyName>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Google.Apis.Oauth2.v2" />
|
|
||||||
<PackageReference Include="MediatR" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
namespace Hutopy.Domain.Enums;
|
|
||||||
|
|
||||||
public enum PriorityLevel
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
Low = 1,
|
|
||||||
Medium = 2,
|
|
||||||
High = 3
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
namespace Hutopy.Domain.Exceptions;
|
|
||||||
|
|
||||||
public class UnsupportedColourException(
|
|
||||||
string code) : Exception($"Colour \"{code}\" is unsupported.");
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
global using Hutopy.Domain.Common;
|
|
||||||
global using Hutopy.Domain.Exceptions;
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
namespace Hutopy.Domain.ValueObjects;
|
|
||||||
|
|
||||||
public class Colour(string code) : ValueObject
|
|
||||||
{
|
|
||||||
public static Colour From(string code)
|
|
||||||
{
|
|
||||||
var colour = new Colour(code);
|
|
||||||
|
|
||||||
if (!SupportedColours.Contains(colour))
|
|
||||||
{
|
|
||||||
throw new UnsupportedColourException(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
return colour;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Colour White => new("#FFFFFF");
|
|
||||||
|
|
||||||
public static Colour Red => new("#FF5733");
|
|
||||||
|
|
||||||
public static Colour Orange => new("#FFC300");
|
|
||||||
|
|
||||||
public static Colour Yellow => new("#FFFF66");
|
|
||||||
|
|
||||||
public static Colour Green => new("#CCFF99");
|
|
||||||
|
|
||||||
public static Colour Blue => new("#6666FF");
|
|
||||||
|
|
||||||
public static Colour Purple => new("#9966CC");
|
|
||||||
|
|
||||||
public static Colour Grey => new("#999999");
|
|
||||||
|
|
||||||
public string Code { get; private set; } = string.IsNullOrWhiteSpace(code)?"#000000":code;
|
|
||||||
|
|
||||||
public static implicit operator string(Colour colour)
|
|
||||||
{
|
|
||||||
return colour.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static explicit operator Colour(string code)
|
|
||||||
{
|
|
||||||
return From(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Code;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IEnumerable<Colour> SupportedColours
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
yield return White;
|
|
||||||
yield return Red;
|
|
||||||
yield return Orange;
|
|
||||||
yield return Yellow;
|
|
||||||
yield return Green;
|
|
||||||
yield return Blue;
|
|
||||||
yield return Purple;
|
|
||||||
yield return Grey;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IEnumerable<object> GetEqualityComponents()
|
|
||||||
{
|
|
||||||
yield return Code;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -4,7 +4,7 @@ using Azure.Storage.Blobs.Models;
|
|||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
namespace Hutopy.Infrastructure.AzureBlob;
|
namespace Hutopy.Infrastructure.BlobStorage;
|
||||||
|
|
||||||
public class AzureBlobStorage
|
public class AzureBlobStorage
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Hutopy.Application.AzureBlobStorage.Constants;
|
namespace Hutopy.Infrastructure.BlobStorage;
|
||||||
|
|
||||||
public static class CommonFileNames
|
public static class CommonFileNames
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Hutopy.Application.AzureBlobStorage.Constants;
|
namespace Hutopy.Infrastructure.BlobStorage;
|
||||||
|
|
||||||
public static class ContainerNames
|
public static class ContainerNames
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Hutopy.Infrastructure.AzureBlob;
|
namespace Hutopy.Infrastructure.BlobStorage;
|
||||||
|
|
||||||
public static class ContentTypes
|
public static class ContentTypes
|
||||||
{
|
{
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Hutopy.Application.AzureBlobStorage.Constants;
|
namespace Hutopy.Infrastructure.BlobStorage;
|
||||||
|
|
||||||
public static class SubDirectoryNames
|
public static class SubDirectoryNames
|
||||||
{
|
{
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
using Hutopy.Domain.Constants;
|
using Hutopy.Infrastructure.Identity;
|
||||||
using Hutopy.Infrastructure.Identity;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
@@ -55,13 +54,13 @@ public class ApplicationDbContextInitializer(
|
|||||||
|
|
||||||
private async Task TrySeedAsync()
|
private async Task TrySeedAsync()
|
||||||
{
|
{
|
||||||
var administratorRole = new ApplicationRole(Roles.Administrator);
|
var administratorRole = new ApplicationRole(KnownRoles.Administrator);
|
||||||
if (roleManager.Roles.All(r => r.Name != administratorRole.Name))
|
if (roleManager.Roles.All(r => r.Name != administratorRole.Name))
|
||||||
{
|
{
|
||||||
await roleManager.CreateAsync(administratorRole);
|
await roleManager.CreateAsync(administratorRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
var roleCreator = new ApplicationRole(Roles.Creator);
|
var roleCreator = new ApplicationRole(KnownRoles.Creator);
|
||||||
if (roleManager.Roles.All(r => r.Name != roleCreator.Name))
|
if (roleManager.Roles.All(r => r.Name != roleCreator.Name))
|
||||||
{
|
{
|
||||||
await roleManager.CreateAsync(roleCreator);
|
await roleManager.CreateAsync(roleCreator);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Hutopy.Domain.Constants;
|
using Hutopy.Infrastructure.BlobStorage;
|
||||||
using Hutopy.Infrastructure.AzureBlob;
|
|
||||||
using Hutopy.Infrastructure.Data;
|
using Hutopy.Infrastructure.Data;
|
||||||
using Hutopy.Infrastructure.Identity;
|
using Hutopy.Infrastructure.Identity;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
@@ -49,9 +48,6 @@ public static class DependencyInjection
|
|||||||
// Scoped services
|
// Scoped services
|
||||||
services.AddScoped<IdentityService>();
|
services.AddScoped<IdentityService>();
|
||||||
|
|
||||||
services.AddAuthorization(options =>
|
|
||||||
options.AddPolicy(Policies.CanPurge, policy => policy.RequireRole(Roles.Administrator)));
|
|
||||||
|
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
namespace Hutopy.Domain.Constants;
|
namespace Hutopy.Infrastructure.Identity;
|
||||||
|
|
||||||
public abstract class Roles
|
public static class KnownRoles
|
||||||
{
|
{
|
||||||
public const string Administrator = nameof(Administrator);
|
public const string Administrator = nameof(Administrator);
|
||||||
public const string Creator = nameof(Creator);
|
public const string Creator = nameof(Creator);
|
||||||
@@ -18,9 +18,6 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools"/>
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools"/>
|
||||||
<PackageReference Include="Stripe.net"/>
|
<PackageReference Include="Stripe.net"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\Application\Application.csproj"/>
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Migrations\"/>
|
<Folder Include="Migrations\"/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Hutopy.Application.AzureBlobStorage.Constants;
|
using Hutopy.Infrastructure.BlobStorage;
|
||||||
using Hutopy.Infrastructure.AzureBlob;
|
|
||||||
using Hutopy.Web.Features.Contents.Data;
|
using Hutopy.Web.Features.Contents.Data;
|
||||||
|
|
||||||
namespace Hutopy.Web.Features.Contents.Handlers;
|
namespace Hutopy.Web.Features.Contents.Handlers;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Hutopy.Application.AzureBlobStorage.Constants;
|
using Hutopy.Infrastructure.BlobStorage;
|
||||||
using Hutopy.Infrastructure.AzureBlob;
|
|
||||||
using Hutopy.Web.Features.Contents.Data;
|
using Hutopy.Web.Features.Contents.Data;
|
||||||
|
|
||||||
namespace Hutopy.Web.Features.Contents.Handlers;
|
namespace Hutopy.Web.Features.Contents.Handlers;
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using Hutopy.Application.AzureBlobStorage.Constants;
|
using Hutopy.Infrastructure.BlobStorage;
|
||||||
using Hutopy.Infrastructure.AzureBlob;
|
|
||||||
using Hutopy.Web.Common;
|
using Hutopy.Web.Common;
|
||||||
using Hutopy.Web.Features.Contents.Data;
|
using Hutopy.Web.Features.Contents.Data;
|
||||||
using Hutopy.Web.Features.Contents.Handlers.Models;
|
using Hutopy.Web.Features.Contents.Handlers.Models;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Hutopy.Application.AzureBlobStorage.Constants;
|
using Hutopy.Infrastructure.BlobStorage;
|
||||||
using Hutopy.Infrastructure.AzureBlob;
|
|
||||||
using Hutopy.Infrastructure.Identity;
|
using Hutopy.Infrastructure.Identity;
|
||||||
using Hutopy.Web.Common;
|
using Hutopy.Web.Common;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Hutopy.Application.AzureBlobStorage.Constants;
|
using Hutopy.Infrastructure.BlobStorage;
|
||||||
using Hutopy.Infrastructure.AzureBlob;
|
|
||||||
using Hutopy.Infrastructure.Identity;
|
using Hutopy.Infrastructure.Identity;
|
||||||
|
|
||||||
namespace Hutopy.Web.Features.Users.Handlers;
|
namespace Hutopy.Web.Features.Users.Handlers;
|
||||||
|
|||||||
@@ -30,8 +30,7 @@ public class GoogleUserInfo
|
|||||||
|
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public record LoginWithGoogleRequest(
|
public record LoginWithGoogleRequest(
|
||||||
string Token)
|
string Token);
|
||||||
: IRequest<LoginWithGoogleResponse>;
|
|
||||||
|
|
||||||
public record LoginWithGoogleResponse(
|
public record LoginWithGoogleResponse(
|
||||||
string AccessToken,
|
string AccessToken,
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
global using Ardalis.GuardClauses;
|
|
||||||
global using FastEndpoints;
|
global using FastEndpoints;
|
||||||
global using FluentValidation;
|
global using FluentValidation;
|
||||||
global using JetBrains.Annotations;
|
global using JetBrains.Annotations;
|
||||||
global using MediatR;
|
|
||||||
global using Microsoft.EntityFrameworkCore;
|
global using Microsoft.EntityFrameworkCore;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Azure.Identity;
|
using Azure.Identity;
|
||||||
using Hutopy.Application;
|
|
||||||
using Hutopy.Infrastructure;
|
using Hutopy.Infrastructure;
|
||||||
using Hutopy.Infrastructure.Data;
|
using Hutopy.Infrastructure.Data;
|
||||||
using Hutopy.Infrastructure.Identity;
|
using Hutopy.Infrastructure.Identity;
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using Hutopy.Domain.Constants;
|
using Hutopy.Infrastructure.Identity;
|
||||||
using Hutopy.Infrastructure.Identity;
|
|
||||||
using Hutopy.Web.Common;
|
using Hutopy.Web.Common;
|
||||||
using Hutopy.Web.Features.Contents.Data;
|
using Hutopy.Web.Features.Contents.Data;
|
||||||
using Hutopy.Web.Features.Messages.Data;
|
using Hutopy.Web.Features.Messages.Data;
|
||||||
@@ -34,7 +33,7 @@ internal class TestDataSeeder(
|
|||||||
{
|
{
|
||||||
if (contentContext.Contents.Any()) return;
|
if (contentContext.Contents.Any()) return;
|
||||||
|
|
||||||
_users.Add(await CreateUserAsync("admin", null, Roles.Administrator));
|
_users.Add(await CreateUserAsync("admin", null, KnownRoles.Administrator));
|
||||||
var userA = await CreateUserAsync("userA", null);
|
var userA = await CreateUserAsync("userA", null);
|
||||||
_users.Add(userA);
|
_users.Add(userA);
|
||||||
_users.Add(await CreateUserAsync("userB", null));
|
_users.Add(await CreateUserAsync("userB", null));
|
||||||
@@ -44,7 +43,7 @@ internal class TestDataSeeder(
|
|||||||
var creatorUser = await CreateUserAsync(
|
var creatorUser = await CreateUserAsync(
|
||||||
creator.Name,
|
creator.Name,
|
||||||
creator.Images.Logo,
|
creator.Images.Logo,
|
||||||
Roles.Creator);
|
KnownRoles.Creator);
|
||||||
|
|
||||||
creator.Id = creatorUser.Id;
|
creator.Id = creatorUser.Id;
|
||||||
creator.CreatedBy = creator.Id;
|
creator.CreatedBy = creator.Id;
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Application\Application.csproj" />
|
|
||||||
<ProjectReference Include="..\Infrastructure\Infrastructure.csproj" />
|
<ProjectReference Include="..\Infrastructure\Infrastructure.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<RootNamespace>Hutopy.Application.FunctionalTests</RootNamespace>
|
|
||||||
<AssemblyName>Hutopy.Application.FunctionalTests</AssemblyName>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Remove="appsettings.json" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Include="appsettings.json">
|
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
|
||||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
|
||||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
|
||||||
</Content>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" />
|
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
|
||||||
<PackageReference Include="nunit" />
|
|
||||||
<PackageReference Include="NUnit.Analyzers">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="NUnit3TestAdapter" />
|
|
||||||
<PackageReference Include="coverlet.collector" />
|
|
||||||
<PackageReference Include="FluentAssertions" />
|
|
||||||
<PackageReference Include="Moq" />
|
|
||||||
<PackageReference Include="Respawn" />
|
|
||||||
<PackageReference Include="Testcontainers.MsSql" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\src\Web\Web.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
namespace Hutopy.Application.FunctionalTests;
|
|
||||||
|
|
||||||
using static Testing;
|
|
||||||
|
|
||||||
[TestFixture]
|
|
||||||
public abstract class BaseTestFixture
|
|
||||||
{
|
|
||||||
[SetUp]
|
|
||||||
public async Task TestSetUp()
|
|
||||||
{
|
|
||||||
await ResetState();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
using System.Data.Common;
|
|
||||||
using Hutopy.Infrastructure.Data;
|
|
||||||
using Hutopy.Web;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Mvc.Testing;
|
|
||||||
using Microsoft.AspNetCore.TestHost;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
|
||||||
|
|
||||||
namespace Hutopy.Application.FunctionalTests;
|
|
||||||
|
|
||||||
using static Testing;
|
|
||||||
|
|
||||||
public class CustomWebApplicationFactory(
|
|
||||||
DbConnection connection)
|
|
||||||
: WebApplicationFactory<Program>
|
|
||||||
{
|
|
||||||
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
|
||||||
{
|
|
||||||
builder.ConfigureTestServices(services =>
|
|
||||||
{
|
|
||||||
services
|
|
||||||
.RemoveAll<DbContextOptions<ApplicationDbContext>>()
|
|
||||||
.AddDbContext<ApplicationDbContext>((sp, options) =>
|
|
||||||
{
|
|
||||||
options.AddInterceptors(sp.GetServices<ISaveChangesInterceptor>());
|
|
||||||
options.UseSqlServer(connection);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
global using Ardalis.GuardClauses;
|
|
||||||
global using FluentAssertions;
|
|
||||||
global using Moq;
|
|
||||||
global using NUnit.Framework;
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using System.Data.Common;
|
|
||||||
|
|
||||||
namespace Hutopy.Application.FunctionalTests;
|
|
||||||
|
|
||||||
public interface ITestDatabase
|
|
||||||
{
|
|
||||||
Task InitialiseAsync();
|
|
||||||
|
|
||||||
DbConnection GetConnection();
|
|
||||||
|
|
||||||
Task ResetAsync();
|
|
||||||
|
|
||||||
Task DisposeAsync();
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
using System.Data.Common;
|
|
||||||
using Hutopy.Infrastructure.Data;
|
|
||||||
using Microsoft.Data.SqlClient;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Respawn;
|
|
||||||
|
|
||||||
namespace Hutopy.Application.FunctionalTests;
|
|
||||||
|
|
||||||
public class SqlServerTestDatabase : ITestDatabase
|
|
||||||
{
|
|
||||||
private readonly string _connectionString = null!;
|
|
||||||
private SqlConnection _connection = null!;
|
|
||||||
private Respawner _respawner = null!;
|
|
||||||
|
|
||||||
public SqlServerTestDatabase()
|
|
||||||
{
|
|
||||||
var configuration = new ConfigurationBuilder()
|
|
||||||
.AddJsonFile("appsettings.json")
|
|
||||||
.AddEnvironmentVariables()
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
var connectionString = configuration.GetConnectionString("MssqlConnection");
|
|
||||||
|
|
||||||
Guard.Against.Null(connectionString);
|
|
||||||
|
|
||||||
_connectionString = connectionString;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task InitialiseAsync()
|
|
||||||
{
|
|
||||||
_connection = new SqlConnection(_connectionString);
|
|
||||||
|
|
||||||
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
|
|
||||||
.UseSqlServer(_connectionString)
|
|
||||||
.Options;
|
|
||||||
|
|
||||||
var context = new ApplicationDbContext(options);
|
|
||||||
|
|
||||||
context.Database.Migrate();
|
|
||||||
|
|
||||||
_respawner = await Respawner.CreateAsync(_connectionString, new RespawnerOptions
|
|
||||||
{
|
|
||||||
TablesToIgnore = new Respawn.Graph.Table[] { "__EFMigrationsHistory" }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public DbConnection GetConnection()
|
|
||||||
{
|
|
||||||
return _connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ResetAsync()
|
|
||||||
{
|
|
||||||
await _respawner.ResetAsync(_connectionString);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DisposeAsync()
|
|
||||||
{
|
|
||||||
await _connection.DisposeAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
namespace Hutopy.Application.FunctionalTests;
|
|
||||||
|
|
||||||
public static class TestDatabaseFactory
|
|
||||||
{
|
|
||||||
public static async Task<ITestDatabase> CreateAsync()
|
|
||||||
{
|
|
||||||
var database = new TestcontainersTestDatabase();
|
|
||||||
|
|
||||||
await database.InitialiseAsync();
|
|
||||||
|
|
||||||
return database;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
using System.Data.Common;
|
|
||||||
using Hutopy.Infrastructure.Data;
|
|
||||||
using Microsoft.Data.SqlClient;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Respawn;
|
|
||||||
using Testcontainers.MsSql;
|
|
||||||
|
|
||||||
namespace Hutopy.Application.FunctionalTests;
|
|
||||||
|
|
||||||
public class TestcontainersTestDatabase : ITestDatabase
|
|
||||||
{
|
|
||||||
private readonly MsSqlContainer _container;
|
|
||||||
private DbConnection _connection = null!;
|
|
||||||
private string _connectionString = null!;
|
|
||||||
private Respawner _respawner = null!;
|
|
||||||
|
|
||||||
public TestcontainersTestDatabase()
|
|
||||||
{
|
|
||||||
_container = new MsSqlBuilder()
|
|
||||||
.WithAutoRemove(true)
|
|
||||||
.Build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task InitialiseAsync()
|
|
||||||
{
|
|
||||||
await _container.StartAsync();
|
|
||||||
|
|
||||||
_connectionString = _container.GetConnectionString();
|
|
||||||
|
|
||||||
_connection = new SqlConnection(_connectionString);
|
|
||||||
|
|
||||||
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
|
|
||||||
.UseSqlServer(_connectionString)
|
|
||||||
.Options;
|
|
||||||
|
|
||||||
var context = new ApplicationDbContext(options);
|
|
||||||
|
|
||||||
await context.Database.MigrateAsync();
|
|
||||||
|
|
||||||
_respawner = await Respawner.CreateAsync(_connectionString, new RespawnerOptions
|
|
||||||
{
|
|
||||||
TablesToIgnore = ["__EFMigrationsHistory"]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public DbConnection GetConnection()
|
|
||||||
{
|
|
||||||
return _connection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task ResetAsync()
|
|
||||||
{
|
|
||||||
await _respawner.ResetAsync(_connectionString);
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task DisposeAsync()
|
|
||||||
{
|
|
||||||
await _connection.DisposeAsync();
|
|
||||||
await _container.DisposeAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,155 +0,0 @@
|
|||||||
using Hutopy.Domain.Constants;
|
|
||||||
using Hutopy.Infrastructure.Data;
|
|
||||||
using Hutopy.Infrastructure.Identity;
|
|
||||||
using MediatR;
|
|
||||||
using Microsoft.AspNetCore.Identity;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace Hutopy.Application.FunctionalTests;
|
|
||||||
|
|
||||||
[SetUpFixture]
|
|
||||||
public partial class Testing
|
|
||||||
{
|
|
||||||
private static ITestDatabase _database;
|
|
||||||
private static CustomWebApplicationFactory _factory = null!;
|
|
||||||
private static IServiceScopeFactory _scopeFactory = null!;
|
|
||||||
private static Guid _userId;
|
|
||||||
|
|
||||||
[OneTimeSetUp]
|
|
||||||
public async Task RunBeforeAnyTests()
|
|
||||||
{
|
|
||||||
_database = await TestDatabaseFactory.CreateAsync();
|
|
||||||
|
|
||||||
_factory = new CustomWebApplicationFactory(_database.GetConnection());
|
|
||||||
|
|
||||||
_scopeFactory = _factory.Services.GetRequiredService<IServiceScopeFactory>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<TResponse> SendAsync<TResponse>(IRequest<TResponse> request)
|
|
||||||
{
|
|
||||||
using var scope = _scopeFactory.CreateScope();
|
|
||||||
|
|
||||||
var mediator = scope.ServiceProvider.GetRequiredService<ISender>();
|
|
||||||
|
|
||||||
return await mediator.Send(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task SendAsync(IBaseRequest request)
|
|
||||||
{
|
|
||||||
using var scope = _scopeFactory.CreateScope();
|
|
||||||
|
|
||||||
var mediator = scope.ServiceProvider.GetRequiredService<ISender>();
|
|
||||||
|
|
||||||
await mediator.Send(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Guid GetUserId()
|
|
||||||
{
|
|
||||||
return _userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<Guid> RunAsDefaultUserAsync()
|
|
||||||
{
|
|
||||||
return await RunAsUserAsync(
|
|
||||||
"test@local",
|
|
||||||
"Testing1234!",
|
|
||||||
[]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<Guid> RunAsAdministratorAsync()
|
|
||||||
{
|
|
||||||
return await RunAsUserAsync(
|
|
||||||
"administrator@local",
|
|
||||||
"Administrator1234!",
|
|
||||||
[Roles.Administrator]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<Guid> RunAsUserAsync(string userName, string password, string[] roles)
|
|
||||||
{
|
|
||||||
using var scope = _scopeFactory.CreateScope();
|
|
||||||
|
|
||||||
var userManager = scope.ServiceProvider.GetRequiredService<ApplicationUserManager>();
|
|
||||||
|
|
||||||
var user = new ApplicationUser
|
|
||||||
{
|
|
||||||
UserName = userName, Email = userName, Firstname = "FirstName", Lastname = "LastName"
|
|
||||||
};
|
|
||||||
|
|
||||||
var result = await userManager.CreateAsync(user, password);
|
|
||||||
|
|
||||||
if (roles.Any())
|
|
||||||
{
|
|
||||||
var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
|
|
||||||
|
|
||||||
foreach (var role in roles)
|
|
||||||
{
|
|
||||||
await roleManager.CreateAsync(new IdentityRole(role));
|
|
||||||
}
|
|
||||||
|
|
||||||
await userManager.AddToRolesAsync(user, roles);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result.Succeeded)
|
|
||||||
{
|
|
||||||
_userId = user.Id;
|
|
||||||
|
|
||||||
return _userId;
|
|
||||||
}
|
|
||||||
|
|
||||||
var errors = string.Join(Environment.NewLine, result.ToApplicationResult().Errors);
|
|
||||||
|
|
||||||
throw new Exception($"Unable to create {userName}.{Environment.NewLine}{errors}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task ResetState()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _database.ResetAsync();
|
|
||||||
}
|
|
||||||
catch (Exception)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
_userId = Guid.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<TEntity?> FindAsync<TEntity>(params object[] keyValues)
|
|
||||||
where TEntity : class
|
|
||||||
{
|
|
||||||
using var scope = _scopeFactory.CreateScope();
|
|
||||||
|
|
||||||
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
|
||||||
|
|
||||||
return await context.FindAsync<TEntity>(keyValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task AddAsync<TEntity>(TEntity entity)
|
|
||||||
where TEntity : class
|
|
||||||
{
|
|
||||||
using var scope = _scopeFactory.CreateScope();
|
|
||||||
|
|
||||||
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
|
||||||
|
|
||||||
context.Add(entity);
|
|
||||||
|
|
||||||
await context.SaveChangesAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static async Task<int> CountAsync<TEntity>() where TEntity : class
|
|
||||||
{
|
|
||||||
using var scope = _scopeFactory.CreateScope();
|
|
||||||
|
|
||||||
var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
|
||||||
|
|
||||||
return await context.Set<TEntity>().CountAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
[OneTimeTearDown]
|
|
||||||
public async Task RunAfterAnyTests()
|
|
||||||
{
|
|
||||||
await _database.DisposeAsync();
|
|
||||||
await _factory.DisposeAsync();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"ConnectionStrings": {
|
|
||||||
"MssqlConnection": "Server=(localdb)\\mssqllocaldb;Database=HutopyTestDb;Trusted_Connection=True;MultipleActiveResultSets=true"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<RootNamespace>Hutopy.Domain.UnitTests</RootNamespace>
|
|
||||||
<AssemblyName>Hutopy.Domain.UnitTests</AssemblyName>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
|
||||||
<PackageReference Include="nunit" />
|
|
||||||
<PackageReference Include="NUnit.Analyzers">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="NUnit3TestAdapter" />
|
|
||||||
<PackageReference Include="coverlet.collector" />
|
|
||||||
<PackageReference Include="FluentAssertions" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\src\Domain\Domain.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
using Hutopy.Domain.Exceptions;
|
|
||||||
using Hutopy.Domain.ValueObjects;
|
|
||||||
using FluentAssertions;
|
|
||||||
using NUnit.Framework;
|
|
||||||
|
|
||||||
namespace Hutopy.Domain.UnitTests.ValueObjects;
|
|
||||||
|
|
||||||
public class ColourTests
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void ShouldReturnCorrectColourCode()
|
|
||||||
{
|
|
||||||
var code = "#FFFFFF";
|
|
||||||
|
|
||||||
var colour = Colour.From(code);
|
|
||||||
|
|
||||||
colour.Code.Should().Be(code);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ToStringReturnsCode()
|
|
||||||
{
|
|
||||||
var colour = Colour.White;
|
|
||||||
|
|
||||||
colour.ToString().Should().Be(colour.Code);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ShouldPerformImplicitConversionToColourCodeString()
|
|
||||||
{
|
|
||||||
string code = Colour.White;
|
|
||||||
|
|
||||||
code.Should().Be("#FFFFFF");
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ShouldPerformExplicitConversionGivenSupportedColourCode()
|
|
||||||
{
|
|
||||||
var colour = (Colour)"#FFFFFF";
|
|
||||||
|
|
||||||
colour.Should().Be(Colour.White);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void ShouldThrowUnsupportedColourExceptionGivenNotSupportedColourCode()
|
|
||||||
{
|
|
||||||
FluentActions.Invoking(() => Colour.From("##FF33CC"))
|
|
||||||
.Should().Throw<UnsupportedColourException>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
global using NUnit.Framework;
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<RootNamespace>Hutopy.Infrastructure.IntegrationTests</RootNamespace>
|
|
||||||
<AssemblyName>Hutopy.Infrastructure.IntegrationTests</AssemblyName>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" />
|
|
||||||
<PackageReference Include="NUnit" />
|
|
||||||
<PackageReference Include="NUnit3TestAdapter" />
|
|
||||||
<PackageReference Include="NUnit.Analyzers">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="coverlet.collector" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
Reference in New Issue
Block a user