mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-10-04 12:32:10 +00:00
test: verify team member commit and rollback
This commit is contained in:
parent
5aa3a6f820
commit
fddb7b7909
1 changed files with 99 additions and 22 deletions
|
|
@ -35,6 +35,85 @@ public sealed class TeamMemberCreateTransactionTests
|
||||||
await using (var setup = new SqliteTeamMemberTestDbContext(options))
|
await using (var setup = new SqliteTeamMemberTestDbContext(options))
|
||||||
await setup.Database.EnsureCreatedAsync();
|
await setup.Database.EnsureCreatedAsync();
|
||||||
|
|
||||||
|
await using var serviceProvider = BuildServiceProvider(connection, injectFailure: true);
|
||||||
|
ThrowingAfterPersistPermissionDataService failingPermissionData;
|
||||||
|
await using (var createScope = serviceProvider.CreateAsyncScope())
|
||||||
|
{
|
||||||
|
var service = createScope.ServiceProvider.GetRequiredService<ITeamMemberService>();
|
||||||
|
failingPermissionData = (ThrowingAfterPersistPermissionDataService)createScope.ServiceProvider
|
||||||
|
.GetRequiredService<ITeamPermissionOverrideDataService>();
|
||||||
|
var failure = await Record.ExceptionAsync(() => service.CreateAsync(
|
||||||
|
ValidRequest(),
|
||||||
|
Admin(),
|
||||||
|
CancellationToken.None));
|
||||||
|
|
||||||
|
Assert.IsType<InvalidOperationException>(failure);
|
||||||
|
Assert.Equal("injected mid-sequence failure", failure!.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.NotNull(failingPermissionData.RowsAtFailure);
|
||||||
|
var rowsAtFailure = failingPermissionData.RowsAtFailure!.Value;
|
||||||
|
Assert.Equal(1, rowsAtFailure.Users);
|
||||||
|
Assert.Equal(1, rowsAtFailure.Roles);
|
||||||
|
Assert.Equal(1, rowsAtFailure.UserRoles);
|
||||||
|
Assert.Equal(2, rowsAtFailure.ServiceAreas);
|
||||||
|
Assert.Equal(1, rowsAtFailure.PermissionOverrides);
|
||||||
|
|
||||||
|
await using var verifyScope = serviceProvider.CreateAsyncScope();
|
||||||
|
var verify = verifyScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
||||||
|
Assert.Empty(await verify.Users.AsNoTracking().ToListAsync());
|
||||||
|
Assert.Empty(await verify.Roles.AsNoTracking().ToListAsync());
|
||||||
|
Assert.Empty(await verify.UserRoles.AsNoTracking().ToListAsync());
|
||||||
|
Assert.Empty(await verify.UserServiceAreas.AsNoTracking().ToListAsync());
|
||||||
|
Assert.Empty(await verify.UserPermissionOverrides.AsNoTracking().ToListAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Create_SuccessfulTransaction_CommitsPendingMemberAndAssociations()
|
||||||
|
{
|
||||||
|
await using var connection = new SqliteConnection("Data Source=:memory:;Foreign Keys=True");
|
||||||
|
await connection.OpenAsync();
|
||||||
|
|
||||||
|
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
|
||||||
|
.UseSqlite(connection)
|
||||||
|
.Options;
|
||||||
|
|
||||||
|
await using (var setup = new SqliteTeamMemberTestDbContext(options))
|
||||||
|
await setup.Database.EnsureCreatedAsync();
|
||||||
|
|
||||||
|
await using var serviceProvider = BuildServiceProvider(connection);
|
||||||
|
await using (var createScope = serviceProvider.CreateAsyncScope())
|
||||||
|
{
|
||||||
|
var service = createScope.ServiceProvider.GetRequiredService<ITeamMemberService>();
|
||||||
|
var outcome = await service.CreateAsync(ValidRequest(), Admin(), CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.True(outcome.Success);
|
||||||
|
Assert.True(outcome.Member!.PendingRegistration);
|
||||||
|
Assert.Equal("taylor@example.com", outcome.Member.Email);
|
||||||
|
}
|
||||||
|
|
||||||
|
await using var verifyScope = serviceProvider.CreateAsyncScope();
|
||||||
|
var verify = verifyScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
||||||
|
var user = await verify.Users.AsNoTracking().SingleAsync(user => user.Email == "taylor@example.com");
|
||||||
|
Assert.True(user.PendingRegistration);
|
||||||
|
|
||||||
|
var role = await verify.Roles.AsNoTracking().SingleAsync(role => role.Name == "Dispatcher");
|
||||||
|
Assert.Contains(await verify.UserRoles.AsNoTracking().ToListAsync(), row => row.UserId == user.Id && row.RoleId == role.Id);
|
||||||
|
|
||||||
|
var areas = await verify.UserServiceAreas.AsNoTracking()
|
||||||
|
.Where(area => area.UserId == user.Id)
|
||||||
|
.Select(area => area.Area)
|
||||||
|
.OrderBy(area => area)
|
||||||
|
.ToListAsync();
|
||||||
|
Assert.Equal(new[] { "East", "West" }, areas);
|
||||||
|
|
||||||
|
var permissionOverride = await verify.UserPermissionOverrides.AsNoTracking()
|
||||||
|
.SingleAsync(permission => permission.UserId == user.Id);
|
||||||
|
Assert.Equal("deleteSites", permissionOverride.PermissionKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ServiceProvider BuildServiceProvider(SqliteConnection connection, bool injectFailure = false)
|
||||||
|
{
|
||||||
var configuration = new ConfigurationBuilder().Build();
|
var configuration = new ConfigurationBuilder().Build();
|
||||||
var services = new ServiceCollection();
|
var services = new ServiceCollection();
|
||||||
services.AddLogging();
|
services.AddLogging();
|
||||||
|
|
@ -47,31 +126,17 @@ public sealed class TeamMemberCreateTransactionTests
|
||||||
.AddDefaultTokenProviders();
|
.AddDefaultTokenProviders();
|
||||||
services.AddDataServices();
|
services.AddDataServices();
|
||||||
services.AddBusinessServices(configuration);
|
services.AddBusinessServices(configuration);
|
||||||
services.AddScoped<TeamPermissionOverrideDataService>();
|
|
||||||
services.AddScoped<ITeamPermissionOverrideDataService>(provider =>
|
|
||||||
new ThrowingAfterPersistPermissionDataService(
|
|
||||||
provider.GetRequiredService<TeamPermissionOverrideDataService>()));
|
|
||||||
|
|
||||||
await using var serviceProvider = services.BuildServiceProvider();
|
if (injectFailure)
|
||||||
await using (var createScope = serviceProvider.CreateAsyncScope())
|
|
||||||
{
|
{
|
||||||
var service = createScope.ServiceProvider.GetRequiredService<ITeamMemberService>();
|
services.AddScoped<TeamPermissionOverrideDataService>();
|
||||||
var failure = await Record.ExceptionAsync(() => service.CreateAsync(
|
services.AddScoped<ITeamPermissionOverrideDataService>(provider =>
|
||||||
ValidRequest(),
|
new ThrowingAfterPersistPermissionDataService(
|
||||||
Admin(),
|
provider.GetRequiredService<TeamPermissionOverrideDataService>(),
|
||||||
CancellationToken.None));
|
provider.GetRequiredService<ApplicationDbContext>()));
|
||||||
|
|
||||||
Assert.IsType<InvalidOperationException>(failure);
|
|
||||||
Assert.Equal("injected mid-sequence failure", failure!.Message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await using var verifyScope = serviceProvider.CreateAsyncScope();
|
return services.BuildServiceProvider();
|
||||||
var verify = verifyScope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
|
||||||
Assert.Empty(await verify.Users.AsNoTracking().ToListAsync());
|
|
||||||
Assert.Empty(await verify.Roles.AsNoTracking().ToListAsync());
|
|
||||||
Assert.Empty(await verify.UserRoles.AsNoTracking().ToListAsync());
|
|
||||||
Assert.Empty(await verify.UserServiceAreas.AsNoTracking().ToListAsync());
|
|
||||||
Assert.Empty(await verify.UserPermissionOverrides.AsNoTracking().ToListAsync());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CreateTeamMemberRequestDTO ValidRequest() => new()
|
private static CreateTeamMemberRequestDTO ValidRequest() => new()
|
||||||
|
|
@ -121,12 +186,18 @@ public sealed class TeamMemberCreateTransactionTests
|
||||||
private sealed class ThrowingAfterPersistPermissionDataService : ITeamPermissionOverrideDataService
|
private sealed class ThrowingAfterPersistPermissionDataService : ITeamPermissionOverrideDataService
|
||||||
{
|
{
|
||||||
private readonly ITeamPermissionOverrideDataService _inner;
|
private readonly ITeamPermissionOverrideDataService _inner;
|
||||||
|
private readonly ApplicationDbContext _context;
|
||||||
|
|
||||||
public ThrowingAfterPersistPermissionDataService(ITeamPermissionOverrideDataService inner)
|
public ThrowingAfterPersistPermissionDataService(
|
||||||
|
ITeamPermissionOverrideDataService inner,
|
||||||
|
ApplicationDbContext context)
|
||||||
{
|
{
|
||||||
_inner = inner;
|
_inner = inner;
|
||||||
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public (int Users, int Roles, int UserRoles, int ServiceAreas, int PermissionOverrides)? RowsAtFailure { get; private set; }
|
||||||
|
|
||||||
public Task<TeamPermissionUserData?> GetUserAsync(string userId, CancellationToken cancellationToken) =>
|
public Task<TeamPermissionUserData?> GetUserAsync(string userId, CancellationToken cancellationToken) =>
|
||||||
_inner.GetUserAsync(userId, cancellationToken);
|
_inner.GetUserAsync(userId, cancellationToken);
|
||||||
|
|
||||||
|
|
@ -143,6 +214,12 @@ public sealed class TeamMemberCreateTransactionTests
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
await _inner.SetOverridesAsync(userId, overrides, cancellationToken);
|
await _inner.SetOverridesAsync(userId, overrides, cancellationToken);
|
||||||
|
RowsAtFailure = (
|
||||||
|
await _context.Users.CountAsync(cancellationToken),
|
||||||
|
await _context.Roles.CountAsync(cancellationToken),
|
||||||
|
await _context.UserRoles.CountAsync(cancellationToken),
|
||||||
|
await _context.UserServiceAreas.CountAsync(cancellationToken),
|
||||||
|
await _context.UserPermissionOverrides.CountAsync(cancellationToken));
|
||||||
throw new InvalidOperationException("injected mid-sequence failure");
|
throw new InvalidOperationException("injected mid-sequence failure");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue