using GB5Shared.DTO.Framework.Login;
using GB5Shared.EventLogPublish;
using Microsoft.Extensions.Logging.Abstractions;
using Moq;
using SwBLL.ChangeRequest;
using SwBLL.ClientDatabase;
using SwBLL.DbServer;
using SwBLL.DdlScript;
using SwBLL.Provisioning;
using SwBLL.UserResourceRole;
using SwDAL.CustomCode.ChangeRequest;
using SwDAL.DTO.ChangeRequest;
using SwDAL.DTO.DdlScript;
using SwDAL.Enums;
using Xunit;
namespace SwTests;
///
/// Covers ChangeRequestBLL.GetById's real-time DDL progress enrichment (tracker §37 Decision 2)
/// — ScriptsDone/ScriptsTotal are only ever computed for Category == ClientProvisioning, since
/// that's the only category anyone polls for live provisioning status.
///
public class ChangeRequestBLLProgressTests
{
private static (ChangeRequestBLL Svc, Mock Dal, Mock DdlScriptBLL) BuildService()
{
var dal = new Mock();
var ddlScriptBLL = new Mock();
var eventLogPublish = new EventLogPublish(null!, NullLogger.Instance);
var svc = new ChangeRequestBLL(
dal.Object, new Mock().Object, new Mock().Object,
new Mock().Object, ddlScriptBLL.Object, new Mock().Object,
new Mock().Object, eventLogPublish, NullLogger.Instance);
return (svc, dal, ddlScriptBLL);
}
private static LoginDTO TestLogin() => new() { ClientId = 1, UserId = -1 };
[Fact]
public async Task Test_GetById_ClientProvisioningCategory_EnrichesScriptsDoneTotal()
{
var (svc, dal, ddlScriptBLL) = BuildService();
var cr = new ChangeRequestDTO { ChangeRequestId = 100, ClientDatabaseId = 5, Category = ChangeRequestCategory.ClientProvisioning };
dal.Setup(d => d.GetById(100, It.IsAny(), It.IsAny())).ReturnsAsync(cr);
dal.Setup(d => d.GetLinkedApprovedDdlScripts(100, It.IsAny(), It.IsAny()))
.ReturnsAsync(new List
{
new() { DdlScriptId = 1, SqlScript = "S1" },
new() { DdlScriptId = 2, SqlScript = "S2" },
new() { DdlScriptId = 3, SqlScript = "S3" },
});
ddlScriptBLL.Setup(d => d.CountExecutedScriptsAsync(5, It.IsAny>(), It.IsAny(), It.IsAny()))
.ReturnsAsync(2);
var result = await svc.GetById(100, TestLogin(), CancellationToken.None);
Assert.Equal(3, result!.ScriptsTotal);
Assert.Equal(2, result.ScriptsDone);
ddlScriptBLL.Verify(d => d.CountExecutedScriptsAsync(5,
It.Is>(ids => ids.SequenceEqual(new[] { 1, 2, 3 })),
It.IsAny(), It.IsAny()), Times.Once);
}
[Fact]
public async Task Test_GetById_NonClientProvisioningCategory_DoesNotEnrich_NeverCallsDdlScriptBLL()
{
var (svc, dal, ddlScriptBLL) = BuildService();
var cr = new ChangeRequestDTO { ChangeRequestId = 101, ClientDatabaseId = 5, Category = ChangeRequestCategory.SchemaChange };
dal.Setup(d => d.GetById(101, It.IsAny(), It.IsAny())).ReturnsAsync(cr);
var result = await svc.GetById(101, TestLogin(), CancellationToken.None);
Assert.Null(result!.ScriptsTotal);
Assert.Null(result.ScriptsDone);
dal.Verify(d => d.GetLinkedApprovedDdlScripts(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never);
ddlScriptBLL.Verify(d => d.CountExecutedScriptsAsync(
It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny()), Times.Never);
}
[Fact]
public async Task Test_GetById_ClientProvisioningCategory_NoLinkedScripts_ReportsZeroZero_NoCountCall()
{
var (svc, dal, ddlScriptBLL) = BuildService();
var cr = new ChangeRequestDTO { ChangeRequestId = 102, ClientDatabaseId = 5, Category = ChangeRequestCategory.ClientProvisioning };
dal.Setup(d => d.GetById(102, It.IsAny(), It.IsAny())).ReturnsAsync(cr);
dal.Setup(d => d.GetLinkedApprovedDdlScripts(102, It.IsAny(), It.IsAny()))
.ReturnsAsync(new List());
var result = await svc.GetById(102, TestLogin(), CancellationToken.None);
Assert.Equal(0, result!.ScriptsTotal);
Assert.Equal(0, result.ScriptsDone);
ddlScriptBLL.Verify(d => d.CountExecutedScriptsAsync(
It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny()), Times.Never);
}
}