using FluentAssertions; using Microsoft.Extensions.Logging; using Moq; using NUnit.Framework; using Strata.ContinuousImprovement.Biz.Configuration; using Strata.ContinuousImprovement.Biz.DbContexts.Snowflake; using Strata.ContinuousImprovement.Biz.QualityVariation.QVI; using CIConfiguration = Strata.ContinuousImprovement.Biz.Configuration.Configuration; using System; using System.Threading; using System.Threading.Tasks; namespace Strata.ContinuousImprovement.Biz.Test.Unit.QualityVariation.QVI { [TestFixture, Category("Unit")] public class QviLineItemSavingsServiceTest { private Mock _snowflakeDatabaseContextMock; private Mock _configurationServiceMock; private Mock> _loggerMock; private QviLineItemSavingsService _service; [SetUp] public void SetUp() { _snowflakeDatabaseContextMock = new Mock(); _configurationServiceMock = new Mock(); _loggerMock = new Mock>(); _service = new QviLineItemSavingsService( _snowflakeDatabaseContextMock.Object, _configurationServiceMock.Object, _loggerMock.Object); } [Test] public async Task GetCaseTypeFamilyInfoAsync_WhenNoEntityIds_ReturnsEmpty() { var configurationGuid = Guid.NewGuid(); _configurationServiceMock .Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny())) .ReturnsAsync(new CIConfiguration { EntityIdsCSV = string.Empty, SourceSystemIdsCSV = "1" }); var result = await _service.GetCaseTypeFamilyInfoAsync(configurationGuid, true, CancellationToken.None); result.Should().BeEmpty(); _snowflakeDatabaseContextMock.Verify( s => s.QueryAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } [Test] public async Task GetCaseTypeFamilyInfoAsync_WhenNoSourceSystemIds_ReturnsEmpty() { var configurationGuid = Guid.NewGuid(); _configurationServiceMock .Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny())) .ReturnsAsync(new CIConfiguration { EntityIdsCSV = "1", SourceSystemIdsCSV = string.Empty }); var result = await _service.GetCaseTypeFamilyInfoAsync(configurationGuid, true, CancellationToken.None); result.Should().BeEmpty(); _snowflakeDatabaseContextMock.Verify( s => s.QueryAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } [Test] public async Task GetCaseTypeFamilyInfoAsync_WhenEntitiesExist_QueriesSnowflake() { var configurationGuid = Guid.NewGuid(); var expected = new[] { new QviLineItemCaseTypeFamilyInfo { QualityVariationEventId = 42, CaseTypeFamilyId = 7 } }; _configurationServiceMock .Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny())) .ReturnsAsync(new CIConfiguration { EntityIdsCSV = "1", SourceSystemIdsCSV = "1", DepartmentRollupGlobalId = string.Empty, QualityVariationEndDate = new DateTime(2024, 12, 31) }); _snowflakeDatabaseContextMock .Setup(s => s.QueryAsync( It.IsAny(), nameof(QviLineItemSavingsService.GetCaseTypeFamilyInfoAsync), It.IsAny(), It.IsAny())) .ReturnsAsync(expected); var result = await _service.GetCaseTypeFamilyInfoAsync(configurationGuid, true, CancellationToken.None); result.Should().BeEquivalentTo(expected); _snowflakeDatabaseContextMock.Verify( s => s.QueryAsync( It.IsAny(), nameof(QviLineItemSavingsService.GetCaseTypeFamilyInfoAsync), It.IsAny(), It.IsAny()), Times.Once); } [Test] public async Task GetDrgTypeInfoAsync_WhenNoEntityIds_ReturnsEmpty() { var configurationGuid = Guid.NewGuid(); _configurationServiceMock .Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny())) .ReturnsAsync(new CIConfiguration { EntityIdsCSV = string.Empty, SourceSystemIdsCSV = "1" }); var result = await _service.GetDrgTypeInfoAsync(configurationGuid, true, CancellationToken.None); result.Should().BeEmpty(); _snowflakeDatabaseContextMock.Verify( s => s.QueryAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } [Test] public async Task GetDrgTypeInfoAsync_WhenNoSourceSystemIds_ReturnsEmpty() { var configurationGuid = Guid.NewGuid(); _configurationServiceMock .Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny())) .ReturnsAsync(new CIConfiguration { EntityIdsCSV = "1", SourceSystemIdsCSV = string.Empty }); var result = await _service.GetDrgTypeInfoAsync(configurationGuid, true, CancellationToken.None); result.Should().BeEmpty(); _snowflakeDatabaseContextMock.Verify( s => s.QueryAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } [Test] public async Task GetDrgTypeInfoAsync_WhenEntitiesExist_QueriesSnowflake() { var configurationGuid = Guid.NewGuid(); var expected = new[] { new QviLineItemDrgTypeInfo { DrgType = "APR" } }; _configurationServiceMock .Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny())) .ReturnsAsync(new CIConfiguration { EntityIdsCSV = "1", SourceSystemIdsCSV = "1", DepartmentRollupGlobalId = string.Empty, QualityVariationEndDate = new DateTime(2024, 12, 31) }); _snowflakeDatabaseContextMock .Setup(s => s.QueryAsync( It.IsAny(), nameof(QviLineItemSavingsService.GetDrgTypeInfoAsync), It.IsAny(), It.IsAny())) .ReturnsAsync(expected); var result = await _service.GetDrgTypeInfoAsync(configurationGuid, true, CancellationToken.None); result.Should().BeEquivalentTo(expected); _snowflakeDatabaseContextMock.Verify( s => s.QueryAsync( It.IsAny(), nameof(QviLineItemSavingsService.GetDrgTypeInfoAsync), It.IsAny(), It.IsAny()), Times.Once); } [Test] public async Task GetEncounterSavingInfoAsync_UsesConfigurationGuidParameter() { var configurationGuid = Guid.NewGuid(); var expected = new[] { new QviLineItemEncounterSavingInfo { EncounterRecordNumber = "enc-1" } }; _configurationServiceMock .Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny())) .ReturnsAsync(new CIConfiguration()); _snowflakeDatabaseContextMock .Setup(s => s.QueryAsync( It.IsAny(), nameof(QviLineItemSavingsService.GetEncounterSavingInfoAsync), It.IsAny(), It.IsAny())) .ReturnsAsync(expected); var result = await _service.GetEncounterSavingInfoAsync(configurationGuid, null, null, CancellationToken.None); result.Should().BeEquivalentTo(expected); _snowflakeDatabaseContextMock.Verify( s => s.QueryAsync( It.IsAny(), nameof(QviLineItemSavingsService.GetEncounterSavingInfoAsync), It.Is(o => o.GetType().GetProperty("ConfigurationGUID") != null && (Guid)o.GetType().GetProperty("ConfigurationGUID").GetValue(o)! == configurationGuid), It.IsAny()), Times.Once); } [Test] public async Task GetEncounterSavingInfoAsync_WhenOpportunityGuidAndIsBaselineProvided_FiltersQuery() { var configurationGuid = Guid.NewGuid(); var opportunityGuid = Guid.NewGuid(); var expected = new[] { new QviLineItemEncounterSavingInfo { EncounterRecordNumber = "enc-1" } }; _configurationServiceMock .Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny())) .ReturnsAsync(new CIConfiguration()); _snowflakeDatabaseContextMock .Setup(s => s.QueryAsync( It.Is(q => q.Contains(":OpportunityGUID") && q.Contains(":IsBaseline")), nameof(QviLineItemSavingsService.GetEncounterSavingInfoAsync), It.IsAny(), It.IsAny())) .ReturnsAsync(expected); var result = await _service.GetEncounterSavingInfoAsync(configurationGuid, opportunityGuid, true, CancellationToken.None); result.Should().BeEquivalentTo(expected); } [Test] public async Task GetEncounterSavingInfoAsync_WhenSnowflakeThrows_Rethrows() { var configurationGuid = Guid.NewGuid(); _configurationServiceMock .Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny())) .ReturnsAsync(new CIConfiguration()); _snowflakeDatabaseContextMock .Setup(s => s.QueryAsync( It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .ThrowsAsync(new InvalidOperationException("boom")); var action = async () => await _service.GetEncounterSavingInfoAsync(configurationGuid, null, null, CancellationToken.None); await action.Should().ThrowAsync(); } } }