mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 07:13:12 +00:00
Align the second test project with the site data-service contract
- Recording fake forwards the new site-code and open-work-order queries - Drop the LocalDB hard-delete test; sites are now tombstoned
This commit is contained in:
parent
c3865e56ac
commit
60b1afd8e0
2 changed files with 14 additions and 147 deletions
|
|
@ -5,7 +5,6 @@ using Microsoft.Data.SqlClient;
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using SeaHaven.DataServices.Implementation;
|
||||
|
||||
namespace SeaHavenIndustries.Tests;
|
||||
|
||||
|
|
@ -84,150 +83,6 @@ public class SH138SiteContactsSqlServerTests
|
|||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task SH138_LocationDelete_DetachesSoftDeletedContacts_WithRestrictFk_WhenLocalDbAvailable()
|
||||
{
|
||||
var masterConnectionString = await ResolveMasterConnectionStringAsync();
|
||||
if (masterConnectionString == null)
|
||||
return;
|
||||
|
||||
var dbName = $"SH138LocationDelete_{Guid.NewGuid():N}";
|
||||
var connectionString = WithDatabase(masterConnectionString, dbName);
|
||||
|
||||
try
|
||||
{
|
||||
await CreateDatabaseAsync(masterConnectionString, dbName);
|
||||
|
||||
await using var connection = new SqlConnection(connectionString);
|
||||
await connection.OpenAsync();
|
||||
|
||||
await using (var createTables = connection.CreateCommand())
|
||||
{
|
||||
createTables.CommandText =
|
||||
"""
|
||||
CREATE TABLE Locations (
|
||||
Id int NOT NULL IDENTITY PRIMARY KEY,
|
||||
AccountId int NULL,
|
||||
Title nvarchar(max) NULL,
|
||||
Name nvarchar(max) NULL,
|
||||
Latitude nvarchar(max) NULL,
|
||||
Longitude nvarchar(max) NULL,
|
||||
Address1 nvarchar(max) NULL,
|
||||
Address2 nvarchar(max) NULL,
|
||||
City nvarchar(max) NULL,
|
||||
State nvarchar(max) NULL,
|
||||
Zip nvarchar(max) NULL,
|
||||
PhoneNumber nvarchar(max) NULL,
|
||||
Email nvarchar(max) NULL,
|
||||
Status nvarchar(max) NULL,
|
||||
ExternalSource nvarchar(max) NULL,
|
||||
ExternalLocationId nvarchar(max) NULL,
|
||||
IsDeleted bit NULL,
|
||||
createdby nvarchar(max) NULL,
|
||||
DeleterUserId nvarchar(max) NULL,
|
||||
DeletionTime datetime2 NULL,
|
||||
CreatedDate datetime2 NULL,
|
||||
LastModificationTime datetime2 NULL,
|
||||
LastModifierUserId int NULL
|
||||
);
|
||||
CREATE TABLE Contacts (
|
||||
Id int NOT NULL IDENTITY PRIMARY KEY,
|
||||
AccountId int NULL,
|
||||
LocationId int NULL,
|
||||
Title nvarchar(max) NULL,
|
||||
Owner nvarchar(max) NULL,
|
||||
FirstName nvarchar(max) NULL,
|
||||
MiddleName nvarchar(max) NULL,
|
||||
LastName nvarchar(max) NULL,
|
||||
ContactType nvarchar(max) NULL,
|
||||
PhoneNumber nvarchar(max) NULL,
|
||||
Email nvarchar(max) NULL,
|
||||
Address1 nvarchar(max) NULL,
|
||||
Address2 nvarchar(max) NULL,
|
||||
City nvarchar(max) NULL,
|
||||
State nvarchar(max) NULL,
|
||||
Zip nvarchar(max) NULL,
|
||||
FacebookUrl nvarchar(max) NULL,
|
||||
LinkedInUrl nvarchar(max) NULL,
|
||||
TwitterUrl nvarchar(max) NULL,
|
||||
IsDeleted bit NULL,
|
||||
createdby nvarchar(max) NULL,
|
||||
DeleterUserId nvarchar(max) NULL,
|
||||
DeletionTime datetime2 NULL,
|
||||
CreatedDate datetime2 NULL,
|
||||
LastModificationTime datetime2 NULL,
|
||||
LastModifierUserId int NULL,
|
||||
SiteContactOrder int NULL,
|
||||
CONSTRAINT FK_Contacts_Locations_LocationId FOREIGN KEY (LocationId) REFERENCES Locations (Id) ON DELETE NO ACTION
|
||||
);
|
||||
SET IDENTITY_INSERT Locations ON;
|
||||
INSERT INTO Locations (Id, Name) VALUES (11, 'Depot');
|
||||
SET IDENTITY_INSERT Locations OFF;
|
||||
INSERT INTO Contacts (LocationId, FirstName, PhoneNumber, SiteContactOrder) VALUES (11, 'Alice Cooper', '555-0100', 0);
|
||||
INSERT INTO Contacts (LocationId, FirstName, PhoneNumber, IsDeleted, DeleterUserId, DeletionTime) VALUES (11, 'Bob Dillon', '555-0200', 1, 'actor-1', '2026-01-01T00:00:00');
|
||||
""";
|
||||
await createTables.ExecuteNonQueryAsync();
|
||||
}
|
||||
|
||||
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
|
||||
.UseSqlServer(connection)
|
||||
.Options;
|
||||
|
||||
await using var context = new ApplicationDbContext(options);
|
||||
var service = new LocationDataService(context);
|
||||
var deleted = await service.DeleteByIdAsync(11, CancellationToken.None);
|
||||
|
||||
Assert.True(deleted);
|
||||
|
||||
await using (var locationCmd = connection.CreateCommand())
|
||||
{
|
||||
locationCmd.CommandText = "SELECT COUNT(*) FROM Locations;";
|
||||
var locationCount = await locationCmd.ExecuteScalarAsync();
|
||||
Assert.Equal(0, Convert.ToInt32(locationCount));
|
||||
}
|
||||
|
||||
await using (var activeCmd = connection.CreateCommand())
|
||||
{
|
||||
activeCmd.CommandText =
|
||||
"""
|
||||
SELECT FirstName, PhoneNumber, LocationId, IsDeleted, DeleterUserId, DeletionTime
|
||||
FROM Contacts
|
||||
WHERE FirstName = N'Alice Cooper';
|
||||
""";
|
||||
await using var reader = await activeCmd.ExecuteReaderAsync();
|
||||
Assert.True(await reader.ReadAsync());
|
||||
Assert.Equal("Alice Cooper", reader.GetString(0));
|
||||
Assert.Equal("555-0100", reader.GetString(1));
|
||||
Assert.True(reader.IsDBNull(2));
|
||||
Assert.True(reader.GetBoolean(3));
|
||||
Assert.True(reader.IsDBNull(4), "delete carries no audit actor");
|
||||
Assert.False(reader.IsDBNull(5));
|
||||
Assert.False(await reader.ReadAsync());
|
||||
}
|
||||
|
||||
await using (var previouslyDeletedCmd = connection.CreateCommand())
|
||||
{
|
||||
previouslyDeletedCmd.CommandText =
|
||||
"""
|
||||
SELECT LocationId, IsDeleted, DeleterUserId, DeletionTime
|
||||
FROM Contacts
|
||||
WHERE FirstName = N'Bob Dillon';
|
||||
""";
|
||||
await using var reader = await previouslyDeletedCmd.ExecuteReaderAsync();
|
||||
Assert.True(await reader.ReadAsync());
|
||||
Assert.True(reader.IsDBNull(0), "already soft-deleted rows detach so the restrict FK cannot block the delete");
|
||||
Assert.True(reader.GetBoolean(1));
|
||||
Assert.Equal("actor-1", reader.GetString(2));
|
||||
Assert.Equal(new DateTime(2026, 1, 1), reader.GetDateTime(3));
|
||||
Assert.False(await reader.ReadAsync());
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
await DropDatabaseAsync(masterConnectionString, dbName);
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task ApplyMigrationUpAsync(ApplicationDbContext context, Migration migration)
|
||||
{
|
||||
var builder = new MigrationBuilder(context.Database.ProviderName!);
|
||||
|
|
|
|||
|
|
@ -849,7 +849,19 @@ public class WorkOrderAccountScopeTests
|
|||
=> _inner.AddAsync(location, cancellationToken);
|
||||
public Task UpdateAsync(Locations location, CancellationToken cancellationToken)
|
||||
=> _inner.UpdateAsync(location, cancellationToken);
|
||||
public Task<bool> DeleteByIdAsync(int id, CancellationToken cancellationToken)
|
||||
=> _inner.DeleteByIdAsync(id, cancellationToken);
|
||||
public Task<bool> SiteCodeExistsAsync(
|
||||
string siteCode,
|
||||
int? accountId,
|
||||
int? excludeLocationId,
|
||||
CancellationToken cancellationToken)
|
||||
=> _inner.SiteCodeExistsAsync(siteCode, accountId, excludeLocationId, cancellationToken);
|
||||
public Task<(int Count, IReadOnlyList<int> Ids)> GetOpenWorkOrderIdsAsync(
|
||||
int locationId,
|
||||
string? siteCode,
|
||||
int? siteAccountId,
|
||||
int? callerAccountId,
|
||||
int maxIds,
|
||||
CancellationToken cancellationToken)
|
||||
=> _inner.GetOpenWorkOrderIdsAsync(locationId, siteCode, siteAccountId, callerAccountId, maxIds, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue