Files
monorepo/LCU.WebApps.Indirect.ReserveManagementSystem/Api/ReserveManagementSystemApi.Tests/Features/ImportReadServiceSteps.cs
T
2026-03-17 08:54:34 -05:00

434 lines
17 KiB
C#

using Microsoft.EntityFrameworkCore;
using Moq;
using System.Globalization;
using System.Text;
using TechTalk.SpecFlow;
using TechTalk.SpecFlow.Assist;
using TechTalk.SpecFlow.Assist.ValueRetrievers;
using Xunit;
using ReserveManagementSystemApi.ServiceClients;
using ReserveManagementSystemApi.Services;
using ReserveManagementSystemLib.Configuration;
using ReserveManagementSystemLib.Models;
using ReserveManagementSystemLib.Persistence;
using ReserveManagementSystemLib.Repositories;
using LCU.Library.Internal.ApiSecurity.Enums;
using LCU.Library.Internal.ApiSecurity.Models;
using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.IndirectLoan;
using LCU.Library.Internal.LcuHttpClient.HttpRequest;
namespace ReserveManagementSystemApi.Tests.Features
{
[Binding]
public sealed class ImportReadServiceSteps
{
// For additional details on SpecFlow step definitions see https://go.specflow.org/doc-stepdef
private readonly ScenarioContext _scenarioContext;
private ApiSecurityConfiguration _apiSecurityConfiguration;
private ImportReadService _importReadService;
private LoanRepository _loanRepository;
private LoanTypeRepository _loanTypeRepository;
private DealerRepository _dealerRepository;
private DealerService _dealerService;
private Mock<IAuditHistoryRepository> _mockAuditHistRepo;
private Mock<IExportService> _mockExportService;
private LoanService _loanService;
private ImportRepository _importRepository;
private ImportService _importService;
private AppDbContext _appDbContext;
private Import _importResult;
private Exception _exception;
private string _importFileName;
private StreamReader _importStreamReader;
private List<Loan> _loansResult;
private List<Dealer> _dealersResult;
private List<IndirectLoanDetail> _loanDetailsFromDNA;
private List<ClosedIndirectLoan> _closedLoansFromDNA;
private Mock<CoreApiConfiguration> _mockCoreApiConfiguration;
private Mock<IGetRequest> _mockgetRequest;
private Mock<IPostRequest> _mockpostRequest;
private Mock<IPutRequest> _mockputRequest;
public ImportReadServiceSteps(ScenarioContext scenarioContext)
{
_scenarioContext = scenarioContext;
Service.Instance.ValueRetrievers.Register(new NullValueRetriever("<null>"));
}
[BeforeScenario]
public void CreateDatabase()
{
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseInMemoryDatabase(Guid.NewGuid().ToString())
.Options;
_apiSecurityConfiguration = new ApiSecurityConfiguration(ApiKeyAuthenticationFailureBehavior.Warn);
_mockCoreApiConfiguration = new Mock<CoreApiConfiguration>();
_mockCoreApiConfiguration.Object.ApiTimeOutInSeconds = "420";
_mockpostRequest = new Mock<IPostRequest>();
_mockputRequest = new Mock<IPutRequest>();
_mockgetRequest = new Mock<IGetRequest>();
_appDbContext = new AppDbContext(options);
_loanRepository = new LoanRepository(_appDbContext);
_loanTypeRepository = new LoanTypeRepository(_appDbContext);
_dealerRepository = new DealerRepository(_appDbContext);
_importRepository = new ImportRepository(_appDbContext);
_mockAuditHistRepo = new Mock<IAuditHistoryRepository>();
_mockExportService = new Mock<IExportService>();
_dealerService = new DealerService(_dealerRepository);
_loanService = new LoanService(_loanRepository, _loanTypeRepository, new AuditHistoryService(_mockAuditHistRepo.Object),
new Mock<ICoreApiServiceClient>().Object);
_importService = new ImportService(_importRepository);
_importReadService = new ImportReadService(
_loanService, _importService,
_dealerService,
_mockExportService.Object,
new CoreApiServiceClient(_apiSecurityConfiguration, _mockCoreApiConfiguration.Object, _mockgetRequest.Object, _mockpostRequest.Object, _mockputRequest.Object),
new Mock<RmsApiConfiguration>().Object
);
}
[AfterScenario]
public void DisposeAppDbContext()
{
_appDbContext.Database.EnsureDeleted();
_appDbContext.Dispose();
}
[Given(@"an import file named ""(.*)"" that contains")]
public void GivenAnImportFileNamedThatContains(string fileName, string fileContent)
{
_importFileName = fileName;
var byteArray = Encoding.UTF8.GetBytes(fileContent);
var stream = new MemoryStream(byteArray);
_importStreamReader = new StreamReader(stream);
}
[Given(@"that I get these closed loans back from DNA")]
public void GivenThatIGetTheseClosedLoansBackFromDNA(Table table)
{
_closedLoansFromDNA = table.CreateSet<ClosedIndirectLoan>().ToList();
}
[Given(@"an import from DNA that contains")]
public void GivenAnImportFromDNAThatContains(Table table)
{
_loanDetailsFromDNA = table.CreateSet<IndirectLoanDetail>().ToList();
}
[Given(@"a loan table consisting of")]
public void GivenALoanTableConsistingOf(Table table)
{
var loans = table.CreateSet<Loan>().ToList();
_appDbContext.Loans.AddRange(loans);
_appDbContext.SaveChanges();
}
[Given(@"a loan type table consisting of")]
public void GivenALoanTypeTableConsistingOf(Table table)
{
var types = table.CreateSet<LoanType>().ToList();
_appDbContext.LoanTypes.AddRange(types);
_appDbContext.SaveChanges();
}
[Given(@"dealers that look like")]
public void GivenDealersThatLookLike(Table table)
{
var dealers = table.CreateSet<Dealer>().ToList();
_appDbContext.Dealers.AddRange(dealers);
_appDbContext.SaveChanges();
}
[Given(@"the current vehicle for loanId (.*) is")]
public void GivenTheCurrentVehicleForLoanIdIs(int loanId, Table table)
{
var vehicle = table.CreateInstance<Vehicle>();
vehicle.LoanId = loanId;
_appDbContext.Vehicles.Add(vehicle);
_appDbContext.SaveChanges();
}
[When(@"I read this new loan import file at ""(.*)""")]
public async void WhenIReadThisNewLoanImportFileAt(DateTime currentTime)
{
try
{
_importResult = await _importReadService.ReadNewLoanImportFile(_importStreamReader, _importFileName, currentTime);
}
catch (Exception ex)
{
_exception = ex;
}
}
[When(@"I process this DNA new/updated loan import at ""(.*)""")]
public async void WhenIReadThisNewDNALoanImportFileAt(DateTime currentTime)
{
try
{
_importResult = await _importReadService.ProcessActiveLoanImport(_loanDetailsFromDNA, currentTime);
}
catch (Exception ex)
{
_exception = ex;
}
}
[When(@"I process this DNA new/updated loan import at ""(.*)"" and skip the export")]
public async void WhenIProcessThisDNANewUpdatedLoanImportAtAndSkipTheExport(DateTime currentTime)
{
try
{
_importResult = await _importReadService.ProcessActiveLoanImport(_loanDetailsFromDNA, currentTime, true);
}
catch (Exception ex)
{
_exception = ex;
}
}
[When(@"I process the closed loan import from DNA at ""(.*)""")]
public async void WhenIReadTheClosedLoanImportFromDNAAt(DateTime currentTime)
{
try
{
_importResult = await _importReadService.ProcessClosedLoanImport(_closedLoansFromDNA, currentTime, string.Empty);
}
catch (Exception ex)
{
_exception = ex;
}
}
[When(@"I process the closed loan import with missing loan ""(.*)"" with date from DNA at ""(.*)"" and select from ""(.*)""")]
public async void WhenIProcessTheClosedLoanImportWithMissingLoanWithDateFromDNAAt(string missingLoanNumber, DateTime currentTime, DateTime newerThan)
{
try
{
var stringDate = newerThan.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
_importResult = await _importReadService.ProcessClosedLoanImport(_closedLoansFromDNA.Where(l => l.LoanNumber != missingLoanNumber).ToList(),
currentTime, stringDate);
}
catch (Exception ex)
{
_exception = ex;
}
}
[When(@"I process the missing active loans with detail from DNA at ""(.*)"" and export")]
public async void WhenIProcessTheMissingActiveLoansWithDetailFromDNAAtAndExport(DateTime currentTime)
{
try
{
_importResult = await _importReadService.ProcessClosedLoansWithUpdates(_loanDetailsFromDNA, currentTime, false);
}
catch (Exception ex)
{
_exception = ex;
}
}
[When(@"I process the closed loan import with detail from DNA at ""(.*)""")]
public async void WhenIReadTheInitialClosedLoanImportFromDNAAt(DateTime currentTime)
{
try
{
_importResult = await _importReadService.ProcessClosedLoansWithUpdates(_loanDetailsFromDNA, currentTime, false);
}
catch (Exception ex)
{
_exception = ex;
}
}
[When(@"I process the closed loan import with detail from DNA at ""(.*)"" and skip the export")]
public async void WhenIReadTheInitialClosedLoanImportFromDNAAtAndSkipTheExport(DateTime currentTime)
{
try
{
_importResult = await _importReadService.ProcessClosedLoansWithUpdates(_loanDetailsFromDNA, currentTime, true);
}
catch (Exception ex)
{
_exception = ex;
}
}
[When(@"I read this closed loan import file at ""(.*)""")]
public async void WhenIReadThisClosedLoanImportFileAt(DateTime currentTime)
{
try
{
_importResult = await _importReadService.ReadClosedLoanImportFile(_importStreamReader, _importFileName, currentTime);
}
catch (Exception ex)
{
_exception = ex;
}
}
[When(@"I get the record from the ImportTable")]
public async void WhenIGetTheRecordFromTheImportTable()
{
_importResult = (await _importRepository.GetAll().ToListAsync()).First();
}
[Then(@"the import has start date ""(.*)""")]
public void ThenTheImportHasStartDate(DateTime startDate)
{
Assert.Equal(startDate, _importResult.StartDate);
}
[Then(@"the import has an end date that is greater or equal to the start date")]
public void ThenTheImportHasAnEndDateThatIsGreaterOrEqualToTheStartDate()
{
Assert.True(_importResult.EndDate >= _importResult.StartDate);
}
[Then(@"the import has record count (.*)")]
public void ThenTheImportHasRecordCount(int recordCount)
{
Assert.Equal(recordCount, _importResult.RecordCount);
}
[Then(@"the import has success ""(.*)""")]
public void ThenTheImportHasSuccess(bool success)
{
Assert.Equal(success, _importResult.Success);
}
[Then(@"the import has file name ""(.*)""")]
public void ThenTheImportHasFileName(string fileName)
{
Assert.Equal(fileName, _importResult.FileName);
}
[Then(@"an exception is thrown")]
public void ThenAnExceptionIsThrown()
{
Assert.NotNull(_exception);
}
[Then(@"the import looks like")]
public void ThenTheImportLooksLike(Table table)
{
table.CompareToInstance(_importResult);
}
[Then(@"there is a record added to the Audit History table")]
public void ThenThereIsARecordAddedToTheAuditHistoryTable()
{
_mockAuditHistRepo.Verify(x => x.AddHistoriesAsync(It.IsAny<List<AuditHistory>>()));
}
[Then(@"no audit history record is added")]
public void ThenNoAuditHistoryRecordIsAdded()
{
_mockAuditHistRepo.Verify(x => x.AddHistoriesAsync(It.IsAny<List<AuditHistory>>()), Times.Never);
}
[Then(@"AddHistoriesAsync is called with (.*) history/ies having OldValue ""(.*)"" and NewValue ""(.*)""")]
public void ThenAddHistoriesAsyncIsCalledWithHistoryIesHavingOldValueAndNewValue(int number, string oldValue, string newValue)
{
_mockAuditHistRepo.Verify(x =>
x.AddHistoriesAsync(It.Is<List<AuditHistory>>(a => a.Count(x => x.NewValue == newValue && x.OldValue == oldValue) == number)));
}
[Then(@"AddHistoriesAsync is called with (.*) history/ies having ActivityType ""(.*)"" and AuditDescription ""(.*)""")]
public void ThenAddHistoriesAsyncIsCalledWithHistoryHavingActivityTypeAndAuditDescription(int number, string type, string description)
{
_mockAuditHistRepo.Verify(x =>
x.AddHistoriesAsync(It.Is<List<AuditHistory>>(a => a.Count(x => x.ActivityType == type && x.AuditDescription == description) == number)));
}
[Then(@"AddHistoriesAsync is called with (.*) history/ies having LoanNumber ""(.*)"" and MemberNumber ""(.*)""")]
public void ThenAddHistoriesAsyncIsCalledWithHistoryHavingLoanNumberAndMemberNumber(int number, string loanNumber, string memberNumber)
{
_mockAuditHistRepo.Verify(x =>
x.AddHistoriesAsync(It.Is<List<AuditHistory>>(a => a.Count(x => x.MemberNumber == memberNumber && x.LoanNumber == loanNumber) == number)));
}
[Then(@"ExportChargebacksAsync is called")]
public void ThenExportChargebacksAsyncIsCalled()
{
_mockExportService.Verify(x => x.ExportChargebacksAsync(It.IsAny<DateTime>()));
}
[Then(@"ExportChargebacksAsync is not called")]
public void ThenExportChargebacksAsyncIsNotCalled()
{
_mockExportService.Verify(x => x.ExportChargebacksAsync(It.IsAny<DateTime>()), Times.Never);
}
[Then(@"MarkReservesAndChargebacksAsExportedAsync is called")]
public void ThenMarkReservesAndChargebacksAsExportedAsyncIsCalled()
{
_mockExportService.Verify(x => x.MarkReservesAndChargebacksAsExportedAsync(It.IsAny<List<Loan>>(), It.IsAny<DateTime>()));
}
[Then(@"all loans have non-null ExportedChargebackDate")]
public void ThenAllLoansHaveNon_NullExportedChargebackDate()
{
Assert.DoesNotContain(_loansResult, l => l.ExportedChargebackDate == null);
}
[Then(@"ExportReservesAsync is called")]
public void ThenExportReservesAsyncIsCalled()
{
_mockExportService.Verify(x => x.ExportReservesAsync(It.IsAny<DateTime>()));
}
[Then(@"ExportReservesAsync is not called")]
public void ThenExportReservesAsyncIsNotCalled()
{
_mockExportService.Verify(x => x.ExportReservesAsync(It.IsAny<DateTime>()), Times.Never);
}
[Then(@"MarkReservesAsExportedAsync is called")]
public void ThenMarkReservesAsExportedAsyncIsCalled()
{
_mockExportService.Verify(x => x.MarkReservesAsExportedAsync(It.IsAny<List<Loan>>(), It.IsAny<DateTime>()));
}
[Then(@"all loans have non-null ExportedReserveDate")]
public void ThenAllLoansHaveNon_NullExportedReserveDate()
{
Assert.DoesNotContain(_loansResult, l => l.ExportedReserveDate == null);
}
[Then(@"the loans now look like")]
public async void ThenTheLoansNowLookLike(Table table)
{
_loansResult = await _loanRepository.GetAll().AsNoTracking().ToListAsync();
table.CompareToSet(_loansResult);
}
[Then(@"the dealers now look like")]
public async void ThenTheDealersNowLookLike(Table table)
{
_dealersResult = await _dealerRepository.GetAll().ToListAsync();
table.CompareToSet(_dealersResult);
}
[Then(@"the vehicle for LoanId (.*) looks like this")]
public void ThenTheVehicleForLoanIdLooksLikeThis(int loanId, Table table)
{
var result = _loansResult.FirstOrDefault(v => v.LoanId == loanId)?.Vehicle;
table.CompareToInstance<Vehicle>(result);
}
[Then(@"the vehicle for LoanId (.*) is null")]
public void ThenTheVehicleForLoanIdIsNull(int loanId)
{
Assert.Null(_loansResult.FirstOrDefault(v => v.LoanId == loanId).Vehicle);
}
[Then(@"the loans with details now look like")]
public void ThenTheLoansWithDetailsNowLookLike(Table table)
{
var loans = table.CreateInstance<Loan>();
_loansResult.Add(loans);
}
}
}