using FluentAssertions; using Strata.ContinuousImprovement.Biz.Exploration; using Strata.ContinuousImprovement.Biz.Exploration.CaseTypeFamilies; using Strata.ContinuousImprovement.Biz.Exploration.Filters; using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities; using System.Diagnostics.CodeAnalysis; namespace Strata.ContinuousImprovement.Biz.Test.Integration.SnowflakeIntegrationTests { [ExcludeFromCodeCoverage] [TestFixture, Category("Integration"), Category("CCI")] public class FlexibleExplorationSummaryDetailTest : IntegrationTestBase { private static readonly Guid _configurationGuid = Guid.Parse("aa4cba4f-2506-462c-8e34-c45b21653988"); [OneTimeSetUp] public async Task SetupExploration() { var explorationInfo = CreateExplorationInfo(); var summaries = await ExplorationService.GetCaseTypeFamilySummariesAsync(explorationInfo, CancellationToken.None); if (!summaries.Any()) throw new InvalidOperationException("No Case Type Family summaries returned for setup."); } [Test] public async Task GetCaseTypeFamilySummaryDetails_WhenNoFilters_IsEquivalent() { // arrange var explorationInfo = CreateExplorationInfo(); // act var summaries = await ExplorationService.GetCaseTypeFamilySummariesAsync(explorationInfo, CancellationToken.None); var testSummary = summaries.OrderByDescending(x => x.Data.TotalEncounters).First(); explorationInfo.CaseTypeFamilyId = testSummary.Data.Id; var testDetails = await ExplorationService.GetCaseTypeFamilySummaryDetailsAsync(explorationInfo, CancellationToken.None); var testDetail = testDetails.First(); // assert testDetail.Data.Should().BeEquivalentTo(testSummary.Data, options => options .Using(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, 0.001)) .WhenTypeIs()); } [TestCaseSource(nameof(ExclusionCriteriaTestCases))] public async Task GetCaseTypeFamilySummaries_WithExclusions(ExclusionCriteria exclusions) { await RunExclusionSummaryTests(exclusions); } [Test] public async Task GetCaseTypeFamilySummaryDetails_WithFilters_IsEquivalent() { // arrange - filtering on mortality (IsSelected = true => MortalityRate = 1) var booleanFilter = CreateBooleanFilter(ChipKey.Mortality); var explorationInfo = CreateExplorationInfo(booleanFilter); // act var summaries = await ExplorationService.GetCaseTypeFamilySummariesAsync(explorationInfo, CancellationToken.None); var testSummary = summaries.OrderByDescending(x => x.Data.TotalEncounters).First(); explorationInfo.CaseTypeFamilyId = testSummary.Data.Id; var testDetails = await ExplorationService.GetCaseTypeFamilySummaryDetailsAsync(explorationInfo, CancellationToken.None); var testDetail = testDetails.First(); // assert testDetail.Data.Should().BeEquivalentTo(testSummary.Data, options => options .Using(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, 0.001)) .WhenTypeIs()); } [Test] public async Task GetCaseTypeFamilySummaryDetails_WithFiltersAndExclusions_IsEquivalent() { // arrange - iqr + mad exclusion combo with a boolean filter var booleanFilter = CreateBooleanFilter(ChipKey.Mortality); var exclusions = new ExclusionCriteria { CostExclusionType = ExclusionCriteriaType.Iqr, CostExclusionValue = 1.5, LosExclusionType = ExclusionCriteriaType.Mad, LosExclusionValue = 2 }; var explorationInfo = CreateExplorationInfo(booleanFilter, exclusions); // act var summaries = await ExplorationService.GetCaseTypeFamilySummariesAsync(explorationInfo, CancellationToken.None); var testSummary = summaries.OrderByDescending(x => x.Data.TotalEncounters).First(); explorationInfo.CaseTypeFamilyId = testSummary.Data.Id; var testDetails = await ExplorationService.GetCaseTypeFamilySummaryDetailsAsync(explorationInfo, CancellationToken.None); var testDetail = testDetails.First(); // assert testDetail.Data.Should().BeEquivalentTo(testSummary.Data, options => options .Using(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, 0.001)) .WhenTypeIs()); } private FilterChipItem CreateDischargeDateFilter() => new() { ChipType = ChipType.DateRange, Filters = [], DateRange = [new DateTime(2024, 1, 1), new DateTime(2025, 1, 1)] }; private FilterChipItem CreateBooleanFilter(ChipKey key) { if (key is ChipKey.Mortality) { return new FilterChipItem { ChipType = ChipType.Boolean, GlobalId = "Mortality", IsSelected = true, // determines true/false of filter Key = ChipKey.Mortality, Operator = OperatorType.In, Filters = new List() { new TreeNode { DisplayText = "Yes" }}, }; } throw new ArgumentException($"Unsupported boolean filter: {key}", nameof(key)); } private ExplorationCostDriverInfo CreateExplorationInfo(FilterChipItem? additionalFilter = null, ExclusionCriteria? exclusion = null) { var dischargeDateFilter = CreateDischargeDateFilter(); var filterChipItems = additionalFilter != null ? new List { dischargeDateFilter, additionalFilter } : new List { dischargeDateFilter }; return new ExplorationCostDriverInfo { ConfigurationGuid = _configurationGuid, ExclusionCriteria = exclusion ?? new ExclusionCriteria(), Filters = new Biz.Exploration.Filters.Filter { DischargeDateStart = dischargeDateFilter.DateRange.First(), DischargeDateEnd = dischargeDateFilter.DateRange.Last(), FilterChipItems = filterChipItems } }; } private async Task RunExclusionSummaryTests(ExclusionCriteria exclusions) { // arrange var explorationInfo = CreateExplorationInfo(null, exclusions); // act var summaries = await ExplorationService.GetCaseTypeFamilySummariesAsync(explorationInfo, CancellationToken.None); var testSummary = summaries.OrderByDescending(x => x.Data.TotalEncounters).First(); explorationInfo.CaseTypeFamilyId = testSummary.Data.Id; var testDetails = await ExplorationService.GetCaseTypeFamilySummaryDetailsAsync(explorationInfo, CancellationToken.None); var testDetail = testDetails.First(); // assert testDetail.Data.Should().BeEquivalentTo(testSummary.Data, options => options .Using(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, 0.001)) .WhenTypeIs()); } private static IEnumerable ExclusionCriteriaTestCases() { yield return new TestCaseData( new ExclusionCriteria { CostExclusionType = ExclusionCriteriaType.Mad, CostExclusionValue = 2, LosExclusionType = ExclusionCriteriaType.Mad, LosExclusionValue = 2 } ).SetName("GetCaseTypeFamilySummaryDetails_WithMADExclusions_IsEquivalent"); yield return new TestCaseData( new ExclusionCriteria { CostExclusionType = ExclusionCriteriaType.Iqr, CostExclusionValue = 1.5, LosExclusionType = ExclusionCriteriaType.Iqr, LosExclusionValue = 1.5 } ).SetName("GetCaseTypeFamilySummaryDetails_WithIQRExclusions_IsEquivalent"); } } }