Move dotnet api into new directory

This commit is contained in:
Aaron Po
2026-04-27 15:59:17 -04:00
parent e8c5b8a80c
commit 189bce040b
132 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,258 @@
using Apps72.Dev.Data.DbMocker;
using FluentAssertions;
using Infrastructure.Repository.Auth;
using Infrastructure.Repository.Tests.Database;
namespace Infrastructure.Repository.Tests.Auth;
public class AuthRepositoryTest
{
private static AuthRepository CreateRepo(MockDbConnection conn) =>
new(new TestConnectionFactory(conn));
[Fact]
public async Task RegisterUserAsync_CreatesUserWithCredential_ReturnsUserAccount()
{
var expectedUserId = Guid.NewGuid();
var conn = new MockDbConnection();
conn.Mocks.When(cmd => cmd.CommandText == "USP_RegisterUser")
.ReturnsScalar(expectedUserId);
// Mock the subsequent read for the newly created user by id
conn.Mocks.When(cmd => cmd.CommandText == "usp_GetUserAccountById")
.ReturnsTable(
MockTable
.WithColumns(
("UserAccountId", typeof(Guid)),
("Username", typeof(string)),
("FirstName", typeof(string)),
("LastName", typeof(string)),
("Email", typeof(string)),
("CreatedAt", typeof(DateTime)),
("UpdatedAt", typeof(DateTime?)),
("DateOfBirth", typeof(DateTime)),
("Timer", typeof(byte[]))
)
.AddRow(
expectedUserId,
"testuser",
"Test",
"User",
"test@example.com",
DateTime.UtcNow,
null,
new DateTime(1990, 1, 1),
null
)
);
var repo = CreateRepo(conn);
var result = await repo.RegisterUserAsync(
username: "testuser",
firstName: "Test",
lastName: "User",
email: "test@example.com",
dateOfBirth: new DateTime(1990, 1, 1),
passwordHash: "hashedpassword123"
);
result.Should().NotBeNull();
result.UserAccountId.Should().Be(expectedUserId);
result.Username.Should().Be("testuser");
result.FirstName.Should().Be("Test");
result.LastName.Should().Be("User");
result.Email.Should().Be("test@example.com");
result.DateOfBirth.Should().Be(new DateTime(1990, 1, 1));
}
[Fact]
public async Task GetUserByEmailAsync_ReturnsUser_WhenExists()
{
var userId = Guid.NewGuid();
var conn = new MockDbConnection();
conn.Mocks.When(cmd => cmd.CommandText == "usp_GetUserAccountByEmail")
.ReturnsTable(
MockTable
.WithColumns(
("UserAccountId", typeof(Guid)),
("Username", typeof(string)),
("FirstName", typeof(string)),
("LastName", typeof(string)),
("Email", typeof(string)),
("CreatedAt", typeof(DateTime)),
("UpdatedAt", typeof(DateTime?)),
("DateOfBirth", typeof(DateTime)),
("Timer", typeof(byte[]))
)
.AddRow(
userId,
"emailuser",
"Email",
"User",
"emailuser@example.com",
DateTime.UtcNow,
null,
new DateTime(1990, 5, 15),
null
)
);
var repo = CreateRepo(conn);
var result = await repo.GetUserByEmailAsync("emailuser@example.com");
result.Should().NotBeNull();
result!.UserAccountId.Should().Be(userId);
result.Username.Should().Be("emailuser");
result.Email.Should().Be("emailuser@example.com");
result.FirstName.Should().Be("Email");
result.LastName.Should().Be("User");
}
[Fact]
public async Task GetUserByEmailAsync_ReturnsNull_WhenNotExists()
{
var conn = new MockDbConnection();
conn.Mocks.When(cmd => cmd.CommandText == "usp_GetUserAccountByEmail")
.ReturnsTable(MockTable.Empty());
var repo = CreateRepo(conn);
var result = await repo.GetUserByEmailAsync("nonexistent@example.com");
result.Should().BeNull();
}
[Fact]
public async Task GetUserByUsernameAsync_ReturnsUser_WhenExists()
{
var userId = Guid.NewGuid();
var conn = new MockDbConnection();
conn.Mocks.When(cmd =>
cmd.CommandText == "usp_GetUserAccountByUsername"
)
.ReturnsTable(
MockTable
.WithColumns(
("UserAccountId", typeof(Guid)),
("Username", typeof(string)),
("FirstName", typeof(string)),
("LastName", typeof(string)),
("Email", typeof(string)),
("CreatedAt", typeof(DateTime)),
("UpdatedAt", typeof(DateTime?)),
("DateOfBirth", typeof(DateTime)),
("Timer", typeof(byte[]))
)
.AddRow(
userId,
"usernameuser",
"Username",
"User",
"username@example.com",
DateTime.UtcNow,
null,
new DateTime(1985, 8, 20),
null
)
);
var repo = CreateRepo(conn);
var result = await repo.GetUserByUsernameAsync("usernameuser");
result.Should().NotBeNull();
result!.UserAccountId.Should().Be(userId);
result.Username.Should().Be("usernameuser");
result.Email.Should().Be("username@example.com");
}
[Fact]
public async Task GetUserByUsernameAsync_ReturnsNull_WhenNotExists()
{
var conn = new MockDbConnection();
conn.Mocks.When(cmd =>
cmd.CommandText == "usp_GetUserAccountByUsername"
)
.ReturnsTable(MockTable.Empty());
var repo = CreateRepo(conn);
var result = await repo.GetUserByUsernameAsync("nonexistent");
result.Should().BeNull();
}
[Fact]
public async Task GetActiveCredentialByUserAccountIdAsync_ReturnsCredential_WhenExists()
{
var userId = Guid.NewGuid();
var credentialId = Guid.NewGuid();
var conn = new MockDbConnection();
conn.Mocks.When(cmd =>
cmd.CommandText == "USP_GetActiveUserCredentialByUserAccountId"
)
.ReturnsTable(
MockTable
.WithColumns(
("UserCredentialId", typeof(Guid)),
("UserAccountId", typeof(Guid)),
("Hash", typeof(string)),
("CreatedAt", typeof(DateTime)),
("Timer", typeof(byte[]))
)
.AddRow(
credentialId,
userId,
"hashed_password_value",
DateTime.UtcNow,
null
)
);
var repo = CreateRepo(conn);
var result = await repo.GetActiveCredentialByUserAccountIdAsync(userId);
result.Should().NotBeNull();
result!.UserCredentialId.Should().Be(credentialId);
result.UserAccountId.Should().Be(userId);
result.Hash.Should().Be("hashed_password_value");
}
[Fact]
public async Task GetActiveCredentialByUserAccountIdAsync_ReturnsNull_WhenNotExists()
{
var userId = Guid.NewGuid();
var conn = new MockDbConnection();
conn.Mocks.When(cmd =>
cmd.CommandText == "USP_GetActiveUserCredentialByUserAccountId"
)
.ReturnsTable(MockTable.Empty());
var repo = CreateRepo(conn);
var result = await repo.GetActiveCredentialByUserAccountIdAsync(userId);
result.Should().BeNull();
}
[Fact]
public async Task RotateCredentialAsync_ExecutesSuccessfully()
{
var userId = Guid.NewGuid();
var newPasswordHash = "new_hashed_password";
var conn = new MockDbConnection();
conn.Mocks.When(cmd => cmd.CommandText == "USP_RotateUserCredential")
.ReturnsScalar(1);
var repo = CreateRepo(conn);
// Should not throw
var act = async () =>
await repo.RotateCredentialAsync(userId, newPasswordHash);
await act.Should().NotThrowAsync();
}
}

View File

@@ -0,0 +1,108 @@
using Apps72.Dev.Data.DbMocker;
using FluentAssertions;
using Infrastructure.Repository.Breweries;
using Infrastructure.Repository.Tests.Database;
using Domain.Entities;
namespace Infrastructure.Repository.Tests.Breweries;
public class BreweryRepositoryTest
{
private static BreweryRepository CreateRepo(MockDbConnection conn) =>
new(new TestConnectionFactory(conn));
[Fact]
public async Task GetByIdAsync_ReturnsBrewery_WhenExists()
{
var breweryId = Guid.NewGuid();
var conn = new MockDbConnection();
// Repository calls the stored procedure
const string getByIdSql = "USP_GetBreweryById";
var locationId = Guid.NewGuid();
conn.Mocks.When(cmd => cmd.CommandText == getByIdSql)
.ReturnsTable(
MockTable
.WithColumns(
("BreweryPostId", typeof(Guid)),
("PostedById", typeof(Guid)),
("BreweryName", typeof(string)),
("Description", typeof(string)),
("CreatedAt", typeof(DateTime)),
("UpdatedAt", typeof(DateTime?)),
("Timer", typeof(byte[])),
("BreweryPostLocationId", typeof(Guid)),
("CityId", typeof(Guid)),
("AddressLine1", typeof(string)),
("AddressLine2", typeof(string)),
("PostalCode", typeof(string)),
("Coordinates", typeof(byte[]))
)
.AddRow(
breweryId,
Guid.NewGuid(),
"Test Brewery",
"A test brewery description",
DateTime.UtcNow,
null,
null,
locationId,
Guid.NewGuid(),
"123 Main St",
null,
"12345",
null
)
);
var repo = CreateRepo(conn);
var result = await repo.GetByIdAsync(breweryId);
result.Should().NotBeNull();
result!.BreweryPostId.Should().Be(breweryId);
result.Location.Should().NotBeNull();
result.Location!.BreweryPostLocationId.Should().Be(locationId);
}
[Fact]
public async Task GetByIdAsync_ReturnsNull_WhenNotExists()
{
var conn = new MockDbConnection();
conn.Mocks.When(cmd => cmd.CommandText == "USP_GetBreweryById")
.ReturnsTable(MockTable.Empty());
var repo = CreateRepo(conn);
var result = await repo.GetByIdAsync(Guid.NewGuid());
result.Should().BeNull();
}
[Fact]
public async Task CreateAsync_ExecutesSuccessfully()
{
var conn = new MockDbConnection();
conn.Mocks.When(cmd => cmd.CommandText == "USP_CreateBrewery")
.ReturnsScalar(1);
var repo = CreateRepo(conn);
var brewery = new BreweryPost
{
BreweryPostId = Guid.NewGuid(),
PostedById = Guid.NewGuid(),
BreweryName = "Test Brewery",
Description = "A test brewery description",
CreatedAt = DateTime.UtcNow,
Location = new BreweryPostLocation
{
BreweryPostLocationId = Guid.NewGuid(),
CityId = Guid.NewGuid(),
AddressLine1 = "123 Main St",
PostalCode = "12345",
Coordinates = [0x00, 0x01]
}
};
// Should not throw
var act = async () => await repo.CreateAsync(brewery);
await act.Should().NotThrowAsync();
}
}

View File

@@ -0,0 +1,11 @@
using System.Data.Common;
using Infrastructure.Repository.Sql;
namespace Infrastructure.Repository.Tests.Database;
internal class TestConnectionFactory(DbConnection conn) : ISqlConnectionFactory
{
private readonly DbConnection _conn = conn;
public DbConnection CreateConnection() => _conn;
}

View File

@@ -0,0 +1,16 @@
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["Domain/Domain.Entities/Domain.Entities.csproj", "Domain.Entities/"]
COPY ["Domain/Domain.Exceptions/Domain.Exceptions.csproj", "Domain.Exceptions/"]
COPY ["Infrastructure/Infrastructure.Repository/Infrastructure.Repository.csproj", "Infrastructure/Infrastructure.Repository/"]
COPY ["Infrastructure/Infrastructure.Repository.Tests/Infrastructure.Repository.Tests.csproj", "Infrastructure/Infrastructure.Repository.Tests/"]
RUN dotnet restore "Infrastructure/Infrastructure.Repository.Tests/Infrastructure.Repository.Tests.csproj"
COPY . .
WORKDIR "/src/Infrastructure/Infrastructure.Repository.Tests"
RUN dotnet build "./Infrastructure.Repository.Tests.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS final
RUN mkdir -p /app/test-results/repository-tests
WORKDIR /src/Infrastructure/Infrastructure.Repository.Tests
ENTRYPOINT ["dotnet", "test", "./Infrastructure.Repository.Tests.csproj", "-c", "Release", "--logger", "trx;LogFileName=/app/test-results/repository-tests/results.trx"]

View File

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<RootNamespace>Infrastructure.Repository.Tests</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="xunit" Version="2.9.2" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2" />
<PackageReference Include="FluentAssertions" Version="6.9.0" />
<PackageReference Include="DbMocker" Version="1.26.0" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.1.4" />
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Infrastructure.Repository\Infrastructure.Repository.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,180 @@
using Apps72.Dev.Data.DbMocker;
using FluentAssertions;
using Infrastructure.Repository.Tests.Database;
using Infrastructure.Repository.UserAccount;
namespace Infrastructure.Repository.Tests.UserAccount;
public class UserAccountRepositoryTest
{
private static UserAccountRepository CreateRepo(MockDbConnection conn) =>
new(new TestConnectionFactory(conn));
[Fact]
public async Task GetByIdAsync_ReturnsRow_Mapped()
{
var conn = new MockDbConnection();
conn.Mocks.When(cmd => cmd.CommandText == "usp_GetUserAccountById")
.ReturnsTable(
MockTable
.WithColumns(
("UserAccountId", typeof(Guid)),
("Username", typeof(string)),
("FirstName", typeof(string)),
("LastName", typeof(string)),
("Email", typeof(string)),
("CreatedAt", typeof(DateTime)),
("UpdatedAt", typeof(DateTime?)),
("DateOfBirth", typeof(DateTime)),
("Timer", typeof(byte[]))
)
.AddRow(
Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"),
"yerb",
"Aaron",
"Po",
"aaronpo@example.com",
new DateTime(2020, 1, 1),
null,
new DateTime(1990, 1, 1),
null
)
);
var repo = CreateRepo(conn);
var result = await repo.GetByIdAsync(
Guid.Parse("aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa")
);
result.Should().NotBeNull();
result!.Username.Should().Be("yerb");
result.Email.Should().Be("aaronpo@example.com");
}
[Fact]
public async Task GetAllAsync_ReturnsMultipleRows()
{
var conn = new MockDbConnection();
conn.Mocks.When(cmd => cmd.CommandText == "usp_GetAllUserAccounts")
.ReturnsTable(
MockTable
.WithColumns(
("UserAccountId", typeof(Guid)),
("Username", typeof(string)),
("FirstName", typeof(string)),
("LastName", typeof(string)),
("Email", typeof(string)),
("CreatedAt", typeof(DateTime)),
("UpdatedAt", typeof(DateTime?)),
("DateOfBirth", typeof(DateTime)),
("Timer", typeof(byte[]))
)
.AddRow(
Guid.NewGuid(),
"a",
"A",
"A",
"a@example.com",
DateTime.UtcNow,
null,
DateTime.UtcNow.Date,
null
)
.AddRow(
Guid.NewGuid(),
"b",
"B",
"B",
"b@example.com",
DateTime.UtcNow,
null,
DateTime.UtcNow.Date,
null
)
);
var repo = CreateRepo(conn);
var results = (await repo.GetAllAsync(null, null)).ToList();
results.Should().HaveCount(2);
results
.Select(r => r.Username)
.Should()
.BeEquivalentTo(new[] { "a", "b" });
}
[Fact]
public async Task GetByUsername_ReturnsRow()
{
var conn = new MockDbConnection();
conn.Mocks.When(cmd =>
cmd.CommandText == "usp_GetUserAccountByUsername"
)
.ReturnsTable(
MockTable
.WithColumns(
("UserAccountId", typeof(Guid)),
("Username", typeof(string)),
("FirstName", typeof(string)),
("LastName", typeof(string)),
("Email", typeof(string)),
("CreatedAt", typeof(DateTime)),
("UpdatedAt", typeof(DateTime?)),
("DateOfBirth", typeof(DateTime)),
("Timer", typeof(byte[]))
)
.AddRow(
Guid.NewGuid(),
"lookupuser",
"L",
"U",
"lookup@example.com",
DateTime.UtcNow,
null,
DateTime.UtcNow.Date,
null
)
);
var repo = CreateRepo(conn);
var result = await repo.GetByUsernameAsync("lookupuser");
result.Should().NotBeNull();
result!.Email.Should().Be("lookup@example.com");
}
[Fact]
public async Task GetByEmail_ReturnsRow()
{
var conn = new MockDbConnection();
conn.Mocks.When(cmd => cmd.CommandText == "usp_GetUserAccountByEmail")
.ReturnsTable(
MockTable
.WithColumns(
("UserAccountId", typeof(Guid)),
("Username", typeof(string)),
("FirstName", typeof(string)),
("LastName", typeof(string)),
("Email", typeof(string)),
("CreatedAt", typeof(DateTime)),
("UpdatedAt", typeof(DateTime?)),
("DateOfBirth", typeof(DateTime)),
("Timer", typeof(byte[]))
)
.AddRow(
Guid.NewGuid(),
"byemail",
"B",
"E",
"byemail@example.com",
DateTime.UtcNow,
null,
DateTime.UtcNow.Date,
null
)
);
var repo = CreateRepo(conn);
var result = await repo.GetByEmailAsync("byemail@example.com");
result.Should().NotBeNull();
result!.Username.Should().Be("byemail");
}
}