Template
chore: deploy initial code base
This commit is contained in:
+642
@@ -0,0 +1,642 @@
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.All.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.All.Opportunities.Filters;
|
||||
using Strata.ContinuousImprovement.Biz.Configuration;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.Encounter;
|
||||
using Strata.ContinuousImprovement.Biz.Filter;
|
||||
using Strata.ContinuousImprovement.Biz.Generics;
|
||||
using Strata.ContinuousImprovement.Biz.Initiatives;
|
||||
using Strata.ContinuousImprovement.Biz.Pagination;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.Hangfire.Jazz.Client;
|
||||
using Strata.Hangfire.Jazz.Client.Models;
|
||||
using Strata.Schema.Client;
|
||||
using Strata.Schema.Client.Dtos;
|
||||
using Strata.Schema.Client.Dtos.Info;
|
||||
using Strata.SqlTools.Configuration.Common.AsyncFactory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.All.Opportunities
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class AllOpportunityServiceTest
|
||||
{
|
||||
private IAllOpportunityService _allOpportunityService;
|
||||
private Mock<IAsyncDbContextFactory<JazzDbContext>> _dbContextFactoryMock;
|
||||
private Mock<IJazzDbContext> _jazzDbContextMock;
|
||||
private Mock<ISchemaServiceClient> _schemaServiceMock;
|
||||
private Mock<IJazzHangfireServiceClient> _hangfireServiceMock;
|
||||
private Mock<IConfigurationService> _configurationMock;
|
||||
private IInitiativeService _initiativeService;
|
||||
private IUpdateFactOpportunitySavingsService _updateFactOpportunitySavingsService;
|
||||
private static readonly ResourceFileExtractor _extractor = new ResourceFileExtractor(".Resource.");
|
||||
private List<Biz.Configuration.Configuration> _configurations;
|
||||
internal static List<Guid> ConfigGuids = new() { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
|
||||
internal static List<string> ConfigNames = new() { "FY2021", "FY2022", "FY2023", "FY2024" };
|
||||
private ScoreDimensionInfoDto _dimension;
|
||||
private List<ScoreHierarchyDto> _hierarchies;
|
||||
private List<HierarchyNodeDto> _hierarchyNodes;
|
||||
private List<FilterHelper> _filterHelpers;
|
||||
private JobEnqueuedResponse _jobResponse;
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
_dbContextFactoryMock = new Mock<IAsyncDbContextFactory<JazzDbContext>>();
|
||||
_jazzDbContextMock = new Mock<IJazzDbContext>();
|
||||
_schemaServiceMock = new Mock<ISchemaServiceClient>();
|
||||
_hangfireServiceMock = new Mock<IJazzHangfireServiceClient>();
|
||||
_configurationMock = new Mock<IConfigurationService>();
|
||||
_initiativeService = Mock.Of<IInitiativeService>();
|
||||
_updateFactOpportunitySavingsService = Mock.Of<IUpdateFactOpportunitySavingsService>();
|
||||
Mock.Get(_initiativeService)
|
||||
.Setup(s => s.DeleteAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(true));
|
||||
Mock.Get(_updateFactOpportunitySavingsService)
|
||||
.Setup(s => s.UpdateFactOpportunitySavings(It.IsAny<CancellationToken>()));
|
||||
_allOpportunityService = new AllOpportunityService(_dbContextFactoryMock.Object, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
_configurations = new List<Biz.Configuration.Configuration>
|
||||
{
|
||||
new()
|
||||
{
|
||||
ConfigurationGuid = ConfigGuids[0],
|
||||
Name = ConfigNames.First(),
|
||||
DepartmentRollupGlobalId = string.Empty,
|
||||
ServiceLineDimensionGuid = Guid.NewGuid()
|
||||
},
|
||||
new()
|
||||
{
|
||||
ConfigurationGuid = ConfigGuids[1],
|
||||
Name = ConfigNames[1],
|
||||
DepartmentRollupGlobalId = "Department",
|
||||
ServiceLineDimensionGuid = Guid.NewGuid()
|
||||
},
|
||||
new()
|
||||
{
|
||||
ConfigurationGuid = ConfigGuids[2],
|
||||
Name = ConfigNames[2],
|
||||
DepartmentRollupGlobalId = string.Empty,
|
||||
ServiceLineDimensionGuid = Guid.NewGuid()
|
||||
},
|
||||
new()
|
||||
{
|
||||
ConfigurationGuid = ConfigGuids[3],
|
||||
Name = ConfigNames.Last(),
|
||||
DepartmentRollupGlobalId = string.Empty,
|
||||
ServiceLineDimensionGuid = Guid.NewGuid()
|
||||
}
|
||||
};
|
||||
_dimension = new ScoreDimensionInfoDto
|
||||
{
|
||||
FriendlyName = "test",
|
||||
DimensionGuid = Guid.NewGuid(),
|
||||
DefaultHierarchyGuid = Guid.NewGuid()
|
||||
};
|
||||
_hierarchies = new List<ScoreHierarchyDto>
|
||||
{
|
||||
new ScoreHierarchyDto
|
||||
{
|
||||
FriendlyName = "test",
|
||||
HierarchyGuid = _dimension.DefaultHierarchyGuid
|
||||
}
|
||||
};
|
||||
_hierarchyNodes = new List<HierarchyNodeDto>
|
||||
{
|
||||
new HierarchyNodeDto
|
||||
{
|
||||
Name = "Case Type",
|
||||
Path = "CaseType|CaseType|1"
|
||||
}
|
||||
};
|
||||
_jobResponse = new JobEnqueuedResponse
|
||||
{
|
||||
JobId = Guid.NewGuid()
|
||||
};
|
||||
_filterHelpers = new List<FilterHelper>
|
||||
{
|
||||
new FilterHelper
|
||||
{
|
||||
Text = "Case Type",
|
||||
Id = "CaseType|CaseType|1"
|
||||
}
|
||||
};
|
||||
|
||||
_hangfireServiceMock.Setup(moq =>
|
||||
moq.EnqueueJobAsync(It.IsAny<EnqueueJobDto>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_jobResponse));
|
||||
|
||||
_configurationMock.Setup(moq => moq.GetConfigurationAsync(It.Is<Guid>(c => c == ConfigGuids[0]), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_configurations[0]));
|
||||
_configurationMock.Setup(moq => moq.GetConfigurationAsync(It.Is<Guid>(c => c == ConfigGuids[1]), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_configurations[1]));
|
||||
_configurationMock.Setup(moq => moq.GetConfigurationAsync(It.Is<Guid>(c => c == ConfigGuids[2]), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_configurations[2]));
|
||||
_configurationMock.Setup(moq => moq.GetConfigurationAsync(It.Is<Guid>(c => c == _configurations.Last().ConfigurationGuid), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_configurations.Last()));
|
||||
|
||||
_schemaServiceMock.Setup(moq => moq.GetDimensionByGlobalIdAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_dimension));
|
||||
_schemaServiceMock.Setup(moq => moq.GetDimensionByIdAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_dimension));
|
||||
_schemaServiceMock.Setup(moq => moq.GetScoreHierarchiesByGlobalIdAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_hierarchies.AsEnumerable()));
|
||||
_schemaServiceMock.Setup(moq => moq.GetHierarchyNodesByHierarchyGuidAsync(It.IsAny<Guid>(),
|
||||
It.IsAny<HierarchyNodeParametersDto>(), It.IsAny<List<ExtraFilterDto>>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_hierarchyNodes.AsEnumerable()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Asc()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var allOpportunityService = new AllOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
var filters = new AllFilters()
|
||||
{
|
||||
OpportunityTypes = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
|
||||
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions("IdentifiedSavings", SortOrder.Asc);
|
||||
|
||||
// act
|
||||
var taskResult = await allOpportunityService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<AllOpportunity>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().IdentifiedSavings
|
||||
.Should().BeLessThan(taskResult.Data.Last().IdentifiedSavings);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Desc()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var allOpportunityService = new AllOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
var filters = new AllFilters()
|
||||
{
|
||||
OpportunityTypes = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
|
||||
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions("IdentifiedSavings", SortOrder.Desc);
|
||||
|
||||
// act
|
||||
var taskResult = await allOpportunityService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<AllOpportunity>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().IdentifiedSavings
|
||||
.Should().BeGreaterThan(taskResult.Data.Last().IdentifiedSavings);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFilterData))]
|
||||
public void TestValidateFilters(AllFilters filters)
|
||||
{
|
||||
if (filters == null) return;
|
||||
if (filters.OpportunityTypes.Any())
|
||||
filters.OpportunityTypes.Should()
|
||||
.AllBeOfType<string>()
|
||||
.And.NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetExcelWorkbook()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opp = framework.ENOpportunities.First();
|
||||
var filters = new AllFilters()
|
||||
{
|
||||
ConfigurationGuid = framework.Configurations.First().ConfigurationGuid,
|
||||
OpportunityTypes = new[] {$"{(int)OpportunityTypes.Variation}",
|
||||
$"{(int)OpportunityTypes.QualityVariation}",
|
||||
$"{(int)OpportunityTypes.FreeForm}",
|
||||
$"{(int)OpportunityTypes.GeneralLedger}",
|
||||
$"{(int)OpportunityTypes.Payroll}",
|
||||
$"{(int)OpportunityTypes.Encounter}" },
|
||||
};
|
||||
var service = new AllOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var wb = await service.ExportAsync(new SortOptions(), filters, CancellationToken.None);
|
||||
#pragma warning disable S125 // Sections of code should not be commented out
|
||||
//wb.SaveAs(System.IO.Path.Combine(@"C:\Git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "AllExcelFilter.xlsx"));
|
||||
#pragma warning restore S125 // Sections of code should not be commented out
|
||||
|
||||
// assert
|
||||
wb.Worksheets.Should().HaveCount(1);
|
||||
var ws = wb.Worksheet(1);
|
||||
ws.Should().NotBeNull();
|
||||
|
||||
var expected = @"Examples.AllOpportunity.ExcelFilter.xlsx";
|
||||
using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected))
|
||||
using (var actualStream = new MemoryStream())
|
||||
{
|
||||
wb.SaveAs(actualStream);
|
||||
actualStream.Compare(expectedStream, out var message).Should().BeTrue(message);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetExcelWorkbookNullFilter()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var service = new AllOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var wb = await service.ExportAsync(null, null, CancellationToken.None);
|
||||
#pragma warning disable S125 // Sections of code should not be commented out
|
||||
//wb.SaveAs(System.IO.Path.Combine(@"C:\Git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "AllExcelNullFilter.xlsx"));
|
||||
#pragma warning restore S125 // Sections of code should not be commented out
|
||||
|
||||
// assert
|
||||
wb.Worksheets.Should().HaveCount(1);
|
||||
var ws = wb.Worksheet(1);
|
||||
ws.Should().NotBeNull();
|
||||
|
||||
var expected = @"Examples.AllOpportunity.ExcelNullFilter.xlsx";
|
||||
using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected))
|
||||
using (var actualStream = new MemoryStream())
|
||||
{
|
||||
wb.SaveAs(actualStream);
|
||||
actualStream.Compare(expectedStream, out var message).Should().BeTrue(message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetFilterOptionsAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunityService = new AllOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await opportunityService
|
||||
.GetFilterOptionsAsync(new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
return;
|
||||
}
|
||||
taskResult.Should()
|
||||
.BeOfType<AllFilterOptions>()
|
||||
.And.NotBeNull();
|
||||
taskResult.OpportunityTypes.Should().AllBeOfType<FilterMember>().And.NotBeNullOrEmpty()
|
||||
.And.NotContain(cd => string.IsNullOrEmpty(cd.Id))
|
||||
.And.NotContain(cd => string.IsNullOrEmpty(cd.Text));
|
||||
}
|
||||
catch (NotImplementedException nie)
|
||||
{
|
||||
nie.Should().BeOfType<NotImplementedException>();
|
||||
}
|
||||
catch (AssertionException ae)
|
||||
{
|
||||
ae.Should().BeOfType<AssertionException>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test, Ignore("Handled by the other services")]
|
||||
public async Task TestSetHidden()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunities = framework.ENOpportunities;
|
||||
var opportunity = opportunities.First(vo => !vo.IsHidden);
|
||||
var isHidden = opportunity.IsHidden;
|
||||
var service = new AllOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
await service.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
result.IsHidden.Should().Be(!isHidden);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var allOpportunityService = new AllOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
try
|
||||
{
|
||||
var opportunities = allOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;
|
||||
|
||||
//act
|
||||
await allOpportunityService.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden,
|
||||
|
||||
cancellationToken);
|
||||
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return;
|
||||
|
||||
var result = allOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result;
|
||||
|
||||
result.IsHidden.Should().Be(!isHidden);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
switch (e.GetType().Name)
|
||||
{
|
||||
case "AggregateException":
|
||||
case "OperationCanceledException":
|
||||
return;
|
||||
}
|
||||
e.Should().NotBeOfType<Exception>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.ENOpportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;
|
||||
var allOpportunityService = new AllOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await allOpportunityService.SetHiddenAsync(Guid.Empty, !isHidden,
|
||||
cancellationToken);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var allOpportunityService = new AllOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
try
|
||||
{
|
||||
var opportunities = allOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
|
||||
if (opportunity == null) return;
|
||||
|
||||
var note = "new test note";
|
||||
// act
|
||||
await allOpportunityService.SetNoteAsync(opportunity.OpportunityGuid, note,
|
||||
CancellationToken.None);
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return;
|
||||
var result = allOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result;
|
||||
result.Note.Should().Be(note);
|
||||
|
||||
// assert
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
switch (e.GetType().Name)
|
||||
{
|
||||
case "AggregateException":
|
||||
case "OperationCanceledException":
|
||||
return;
|
||||
}
|
||||
e.Should().NotBeOfType<Exception>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test, Ignore("Handled by the other services")]
|
||||
public async Task TestSetNote()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunities = framework.ENOpportunities;
|
||||
var opportunity = opportunities.First(vo => string.IsNullOrEmpty(vo.Note));
|
||||
var note = opportunity.Note;
|
||||
var expected = "Now is the time for all good engineers to write great code!";
|
||||
var service = new AllOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
await service.SetNoteAsync(opportunity.OpportunityGuid, expected, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
result.Note.Should().NotBeNullOrEmpty()
|
||||
.And.NotBe(note)
|
||||
.And.Be(expected);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.ENOpportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
if (opportunity == null) return;
|
||||
var note = "new test note";
|
||||
var allOpportunityService = new AllOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await allOpportunityService.SetNoteAsync(Guid.Empty, note, cancellationToken);
|
||||
|
||||
// assert
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetAllAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var allOpportunityService = new AllOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var taskResult = await allOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetById(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var allOpportunityService = new AllOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var tempResult = await allOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var taskResult =
|
||||
await allOpportunityService.GetById(tempResult.FirstOrDefault()?.OpportunityGuid ?? Guid.Empty, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<AllOpportunity>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetByIds(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var allOpportunityService = new AllOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var tempResult = await allOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var ids = tempResult.Select(o => o.OpportunityGuid);
|
||||
var taskResult = await allOpportunityService.GetByIds(ids, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<AllOpportunity>()
|
||||
.And.HaveCount(ids.Count());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
|
||||
#region TestCaseData
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFilterData()
|
||||
{
|
||||
yield return new TestCaseData(new AllFilters { ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("No Filters");
|
||||
yield return new TestCaseData(new AllFilters { ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("View Visible");
|
||||
yield return new TestCaseData(new AllFilters { ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Not View Visible");
|
||||
yield return new TestCaseData(new AllFilters { IdentifiedSavings = 1999, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings");
|
||||
yield return new TestCaseData(new AllFilters { IdentifiedSavings = 999, ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings Not ViewVisible");
|
||||
yield return new TestCaseData(new AllFilters { OpportunityTypes = new[] { "Entity" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By OpportunityTypes");
|
||||
yield return new TestCaseData(new AllFilters { OpportunityTypes = new[] { "Provider" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), ViewVisible = false })
|
||||
.SetName("By OpportunityTypes Not ViewVisible");
|
||||
yield return new TestCaseData(new AllFilters { OpportunitySearch = "EN - 101", ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Search By Id");
|
||||
yield return new TestCaseData(new AllFilters { ExcludeInitiatives = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Exclude Opportunities with Initiatives");
|
||||
}
|
||||
|
||||
//public static IEnumerable<TestCaseData> GetAllOpportunityDataModel()
|
||||
//{
|
||||
// return from configGuid in ConfigGuids
|
||||
// from EncounterGroup encounterGroup in Enum.GetValues(typeof(EncounterGroup))
|
||||
// where encounterGroup != EncounterGroup.Both
|
||||
// from EncounterOpportunityLevel encounterOpportunityLevel in Enum.GetValues(typeof(EncounterOpportunityLevel))
|
||||
// from encounterGroups in new[] { true, false }
|
||||
// from OpportunityTypes in new[] { true, false }
|
||||
// select new TestCaseData(new AllOpportunityDataModel
|
||||
// {
|
||||
// ConfigurationGuid = configGuid,
|
||||
// EncounterGroup = (int)encounterGroup,
|
||||
// EncounterOpportunityLevel = encounterOpportunityLevel,
|
||||
// HasAllEncounterGroups = encounterGroups,
|
||||
// CaseTypes = encounterGroup == EncounterGroup.CaseType
|
||||
// ? new List<FilterHelper>
|
||||
// {
|
||||
// new() {Text = $"{encounterGroup}", Id = "Id"}
|
||||
// }
|
||||
// : new List<FilterHelper>(),
|
||||
// PatientPopulations = encounterGroup == EncounterGroup.PatientPopulation
|
||||
// ? new List<FilterHelper>
|
||||
// {
|
||||
// new () {Text = $"{encounterGroup}", Id = "Id"}
|
||||
// }
|
||||
// : new List<FilterHelper>(),
|
||||
// HasAllOpportunityTypes = OpportunityTypes,
|
||||
// Entities = encounterOpportunityLevel == EncounterOpportunityLevel.Entity
|
||||
// ? new List<FilterHelper>
|
||||
// {
|
||||
// new () {Text = $"{encounterOpportunityLevel}", Id = "Id"}
|
||||
// }
|
||||
// : new List<FilterHelper>(),
|
||||
// ServiceLines = encounterOpportunityLevel == EncounterOpportunityLevel.ServiceLine
|
||||
// ? new List<FilterHelper>
|
||||
// {
|
||||
// new () {Text = $"{encounterOpportunityLevel}", Id = "Id"}
|
||||
// }
|
||||
// : new List<FilterHelper>(),
|
||||
// Specialties = encounterOpportunityLevel == EncounterOpportunityLevel.Specialty
|
||||
// ? new List<FilterHelper>
|
||||
// {
|
||||
// new () {Text = $"{encounterOpportunityLevel}", Id = "Id"}
|
||||
// }
|
||||
// : new List<FilterHelper>(),
|
||||
// Providers = encounterOpportunityLevel == EncounterOpportunityLevel.Provider
|
||||
// ? new List<FilterHelper>
|
||||
// {
|
||||
// new () {Text = $"{encounterOpportunityLevel}", Id = "Id"}
|
||||
// }
|
||||
// : new List<FilterHelper>()
|
||||
// }).SetName($"{nameof(TestCreateAsync)} {ConfigNames[ConfigGuids.IndexOf(configGuid)]} IsUsingCustomEntityDim: {(ConfigGuids.IndexOf(configGuid) == 1)} IsUsingSg2: {(ConfigGuids.IndexOf(configGuid) == 3)} {encounterGroup} {encounterOpportunityLevel}");
|
||||
//}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
using Strata.ContinuousImprovement.Biz.Generics;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Test.Unit.Biz.All
|
||||
{
|
||||
public static class OpportunityTypesExtensions
|
||||
{
|
||||
public static string OpportunityTypeName(this OpportunityTypes opportunityType)
|
||||
{
|
||||
switch (opportunityType)
|
||||
{
|
||||
case OpportunityTypes.Variation:
|
||||
return "Utilization Variation";
|
||||
case OpportunityTypes.StaffingToDemand:
|
||||
return "Staffing To Demand";
|
||||
case OpportunityTypes.QualityVariation:
|
||||
return "Quality Variation";
|
||||
case OpportunityTypes.FreeForm:
|
||||
return "Free Form";
|
||||
case OpportunityTypes.GeneralLedger:
|
||||
return "General Ledger";
|
||||
case OpportunityTypes.Payroll:
|
||||
return "Payroll";
|
||||
case OpportunityTypes.Encounter:
|
||||
return "Encounter";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.ChargeCode;
|
||||
using Strata.ContinuousImprovement.Biz.ChargeCode.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.Schema.Client.Dtos;
|
||||
using Strata.SqlTools.Configuration.Common.AsyncFactory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.ChargeCode.Opportunities
|
||||
{
|
||||
[TestFixture()]
|
||||
public class CCOpportunityServiceTests : OpportunityServiceTests
|
||||
{
|
||||
public IJazzDbContext DbContext { get; set; }
|
||||
private IAsyncDbContextFactory<JazzDbContext> _dbContextFactory { get; set; }
|
||||
public ICCOpportunityService CCOpportunityService { get; set; }
|
||||
public IOptions<ChargeCodeOpportunityValidationSection> SectionAccessor { get; set; }
|
||||
public ILogger<CCOpportunityService> Logger { get; set; }
|
||||
|
||||
[SetUp]
|
||||
public void TestSetup()
|
||||
{
|
||||
var chargeCodeDimensionGuid = Guid.NewGuid();
|
||||
var caseTypeDimensionGuid = Guid.NewGuid();
|
||||
Mock.Get(SchemaServiceClient)
|
||||
.Setup(s => s.GetDimensionByGlobalIdAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.Returns<string, CancellationToken>((globalId, token) =>
|
||||
globalId switch
|
||||
{
|
||||
"Charge Code" => Task.FromResult(new Schema.Client.Dtos.Info.ScoreDimensionInfoDto { DimensionGuid = chargeCodeDimensionGuid }),
|
||||
"Case Type" => Task.FromResult(new Schema.Client.Dtos.Info.ScoreDimensionInfoDto { DimensionGuid = caseTypeDimensionGuid }),
|
||||
_ => Task.FromResult(new Schema.Client.Dtos.Info.ScoreDimensionInfoDto { DimensionGuid = Guid.NewGuid() })
|
||||
});
|
||||
Mock.Get(SchemaServiceClient)
|
||||
.Setup(x => x.GetHierarchyNodesFromHierarchyPathsAsync(It.IsAny<Guid>(), It.IsAny<IEnumerable<string>>(), It.IsAny<CancellationToken>()))
|
||||
.Returns<Guid, IEnumerable<string>, CancellationToken>((dimensionGuid, codeHpaths, token)
|
||||
=> Task.FromResult(new List<HierarchyNodeDto> {
|
||||
new HierarchyNodeDto{
|
||||
Path = "Path",
|
||||
PathDisplay = "PathDisplay",
|
||||
Name = "Name",
|
||||
Count = 10,
|
||||
IsLeaf= false
|
||||
}
|
||||
}.AsEnumerable()));
|
||||
Mock.Get(SchemaServiceClient)
|
||||
.Setup(x => x.GetDimensionMembersFromHierarchyPathsAsync(It.IsAny<Guid>(), It.IsAny<IEnumerable<string>>(), It.IsAny<CancellationToken>()))
|
||||
.Returns<Guid, IEnumerable<string>, CancellationToken>((dimensionGuid, codeHpaths, token)
|
||||
=> Task.FromResult(new List<MemberDto> {
|
||||
new MemberDto
|
||||
{
|
||||
Name ="Name",
|
||||
Id = "02"
|
||||
}
|
||||
}.AsEnumerable()));
|
||||
Mock.Get(SchemaServiceClient)
|
||||
.Setup(x => x.GetFilteredDimensionMembersByGlobalIdAsync<ChargeCodePickerModel>(It.IsAny<string>(), It.IsAny<List<int>>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(new List<ChargeCodePickerModel> {
|
||||
new ChargeCodePickerModel(){
|
||||
ChargeCodeId = 99,
|
||||
Name = "TestName",
|
||||
CostDriver = "TestCostDriver",
|
||||
Rollup = "TestRollup"
|
||||
}
|
||||
}.AsEnumerable()));
|
||||
var principal = TestUtilities.GetClaimsPrincipalAccessor();
|
||||
var defaultUser = principal.GetCurrentClaimsPrincipal();
|
||||
Mock.Get(ClaimsPrincipalAccessor)
|
||||
.Setup(x => x.GetCurrentClaimsPrincipal())
|
||||
.Returns(defaultUser);
|
||||
|
||||
SectionAccessor = Mock.Of<IOptions<ChargeCodeOpportunityValidationSection>>();
|
||||
Mock.Get(SectionAccessor)
|
||||
.Setup(x => x.Value)
|
||||
.Returns(new ChargeCodeOpportunityValidationSection
|
||||
{
|
||||
MaxChargeCodeSelections = 10,
|
||||
MaxOpportunityLevelSelections = 10,
|
||||
});
|
||||
Logger = Mock.Of<ILogger<CCOpportunityService>>();
|
||||
|
||||
CCOpportunityService = new CCOpportunityService(DbContextFactory,
|
||||
null, // CentralDbContext,
|
||||
ClaimsPrincipalAccessor,
|
||||
ConfigurationService,
|
||||
AuthorizationServiceClient,
|
||||
IdServiceClient,
|
||||
FiscalMonthResolver,
|
||||
SchemaServiceClient,
|
||||
BackgroundJobClient,
|
||||
NotificationHubContext,
|
||||
SectionAccessor,
|
||||
InitiativeService,
|
||||
SnowflakeDatabaseContext,
|
||||
UpdateFactOpportunitySavingsService,
|
||||
Logger);
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public async Task CCOpportunityServiceTest()
|
||||
{
|
||||
await Verifier.Verify(CCOpportunityService, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public async Task GetDbContextAsyncTest()
|
||||
{
|
||||
var dbContext = await CCOpportunityService.GetDbContext(CancellationToken.None);
|
||||
var names = dbContext.AllOpportunities.Select(opp => $"All - {opp.Name} {opp.OpportunityId}").ToList();
|
||||
names.AddRange(dbContext.ChargeCodeOpportunities.Select(opp => opp.Name ?? ""));
|
||||
names.AddRange(dbContext.EncounterOpportunities.Select(opp => opp.Name ?? ""));
|
||||
names.AddRange(dbContext.FFOpportunities.Select(opp => opp.Name ?? ""));
|
||||
names.AddRange(dbContext.GeneralLedgerOpportunities.Select(opp => opp.Name ?? ""));
|
||||
names.AddRange(dbContext.Initiatives.Select(opp => $"Initiative - {opp.Name} {opp.OpportunityId}"));
|
||||
names.AddRange(dbContext.PayrollOpportunities.Select(opp => opp.Name ?? ""));
|
||||
names.AddRange(dbContext.VariationOpportunities.Where(opp => opp.OpportunityKey.StartsWith("UV"))
|
||||
.Select(opp => $"{opp.CostDriver ?? ""} {opp.ServiceLineName ?? ""} {opp.EntityName ?? ""} {opp.OpportunityId}"));
|
||||
await Verifier.Verify(new
|
||||
{
|
||||
names = names.Distinct().OrderBy(x => x),
|
||||
counts = new[] {
|
||||
dbContext.Configurations.Count(),
|
||||
dbContext.AllOpportunities.Count(opp => !opp.OpportunityKey.StartsWith("FE")),
|
||||
dbContext.ChargeCodeOpportunities.Count(),
|
||||
dbContext.EncounterOpportunities.Count(),
|
||||
dbContext.FFOpportunities.Count(),
|
||||
dbContext.GeneralLedgerOpportunities.Count(),
|
||||
dbContext.Initiatives.Count(),
|
||||
dbContext.PayrollOpportunities.Count(),
|
||||
dbContext.VariationOpportunities.Count(opp => opp.OpportunityKey.StartsWith("UV"))
|
||||
}
|
||||
}, VerifySettings)
|
||||
.IgnoreInstance<Guid>((x) => true)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public async Task GetChargeCodeCustomPickerMembersAsyncTest()
|
||||
{
|
||||
var result = await CCOpportunityService.GetChargeCodePickerModelMembers(new List<string>
|
||||
{
|
||||
"CC 1"
|
||||
}, CancellationToken.None);
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public async Task ValidateOpportunityLevelsAsyncTest()
|
||||
{
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public async Task CreateAsyncTest()
|
||||
{
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
|
||||
[Test(), Ignore("Still working on this")]
|
||||
public async Task UpdateAsyncTest()
|
||||
{
|
||||
var dbGuid = JazzEntityFrameworkFactory.DatabaseGuid;
|
||||
var opportunities = JAZZ_Framework.ChargeCodeOpportunities;
|
||||
var opportunity = opportunities.FirstOrDefault();
|
||||
opportunity.Name += " Updated";
|
||||
|
||||
var result = await CCOpportunityService.UpdateAsync(dbGuid, opportunity, CancellationToken.None);
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.DontScrubGuids()
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public async Task GetByIdTest()
|
||||
{
|
||||
var opportunities = JAZZ_Framework.CCOpportunities;
|
||||
var opportunity = opportunities.FirstOrDefault();
|
||||
|
||||
var result = await CCOpportunityService.GetById(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
result.Configuration = null;
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.DontScrubGuids()
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public async Task DeleteAsyncTest()
|
||||
{
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public async Task GetInitiativeInfoAsyncTest()
|
||||
{
|
||||
var opportunities = JAZZ_Framework.CCOpportunities;
|
||||
var opportunity = opportunities.FirstOrDefault();
|
||||
|
||||
var result = await CCOpportunityService.GetInitiativeInfoAsync(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.DontScrubGuids()
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public async Task RefreshOpportunityTrackingDataTest()
|
||||
{
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
|
||||
[Test(), Ignore("Still working on this")]
|
||||
public async Task ExportAsyncTest()
|
||||
{
|
||||
var opportunities = JAZZ_Framework.CCOpportunities;
|
||||
var opportunity = opportunities.FirstOrDefault();
|
||||
|
||||
var export = await CCOpportunityService.ExportAsync(opportunity.OpportunityGuid, new string[] { "CC 1" }, "", CancellationToken.None);
|
||||
var result = export.GetDataTables();
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.DontScrubGuids()
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public async Task UpdateGoalTotalUnitsOfServiceAsyncTest()
|
||||
{
|
||||
var opportunities = JAZZ_Framework.CCOpportunities;
|
||||
var opportunity = opportunities.FirstOrDefault();
|
||||
|
||||
var result = await CCOpportunityService.UpdateGoalTotalUnitsOfServiceAsync(opportunity.OpportunityGuid, "|CC 1|", 100, CancellationToken.None);
|
||||
//await Verifier.Verify(result, VerifySettings)
|
||||
// .DontScrubGuids()
|
||||
// .UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test()]
|
||||
public async Task UpdateGoalCostPerUnitAsyncTest()
|
||||
{
|
||||
Assert.Inconclusive();
|
||||
}
|
||||
}
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.ChargeCode.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.Shared;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
using VerifyTests;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.ChargeCode.Opportunities
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class OpportunityDetailLevelQueryTests
|
||||
{
|
||||
private VerifySettings _verifySettings;
|
||||
|
||||
[SetUp]
|
||||
public void TestSetup()
|
||||
{
|
||||
_verifySettings = TestExtensions.TestSettings();
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(OpportunityDetailLevelQueryTestCases))]
|
||||
public async Task OpportunityDetailLevelQueryTest(OpportunityLevel opportunityLevel, QueryHelper encounterQueryHelper,
|
||||
QueryHelper opportunityLevelQueryHelper)
|
||||
{
|
||||
var query = new OpportunityDetailLevelQuery(opportunityLevel, encounterQueryHelper, opportunityLevelQueryHelper);
|
||||
var result = query.GetQuery();
|
||||
await Verifier.Verify(result, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> OpportunityDetailLevelQueryTestCases()
|
||||
{
|
||||
var configuration = Mock.Of<Biz.Configuration.Configuration>();
|
||||
configuration.DepartmentRollupGlobalId = "";
|
||||
var sqlParameters = new SqlParameter[] {
|
||||
new SqlParameter("@chargeCodeIds", new List<int> { 1, 2, 3 }),
|
||||
new SqlParameter("@caseTypeIds", new List<int> { 1, 2, 3 }),
|
||||
new SqlParameter("@startDate", new DateTime(2023,1,1)),
|
||||
new SqlParameter("@endDate", new DateTime(2024,1,1)),
|
||||
new SqlParameter("@isBaseline", true)
|
||||
};
|
||||
|
||||
foreach (var parameterName in new[] { "@caseTypeIds", "@indicatorIds" })
|
||||
{
|
||||
sqlParameters[1].ParameterName = parameterName;
|
||||
foreach (var isUsingSnowflake in new[] { true, false })
|
||||
{
|
||||
foreach (var oppLevel in Enum.GetValues<OpportunityLevel>())
|
||||
{
|
||||
switch (oppLevel)
|
||||
{
|
||||
case OpportunityLevel.ServiceLine:
|
||||
foreach (var serviceLine in new[] { "Sg2 Service Line Crosswalk", "Service Line" })
|
||||
{
|
||||
yield return new TestCaseData(oppLevel,
|
||||
new EncounterGroupQueryHelper(sqlParameters),
|
||||
new OpportunityLevelQueryHelper(oppLevel, configuration, serviceLine, $"{(serviceLine.Replace(" ", ""))}Id"))
|
||||
.SetName($"{{m}} {Enum.GetName<OpportunityLevel>(oppLevel)} {parameterName.Substring(1)} {serviceLine} {(isUsingSnowflake ? "Snowflake" : "")}");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
yield return new TestCaseData(oppLevel,
|
||||
new EncounterGroupQueryHelper(sqlParameters),
|
||||
new OpportunityLevelQueryHelper(oppLevel, configuration, "", ""))
|
||||
.SetName($"{{m}} {Enum.GetName<OpportunityLevel>(oppLevel)} {parameterName.Substring(1)} Default {(isUsingSnowflake ? "Snowflake" : "")}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.ChargeCode.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts.Snowflake;
|
||||
using Strata.ContinuousImprovement.Biz.Shared;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.ContinuousImprovement.Biz.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
using VerifyTests;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.ChargeCode.Opportunities
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class OpportunityDetailQueryTests
|
||||
{
|
||||
private VerifySettings _verifySettings;
|
||||
private Biz.Configuration.Configuration _configuration;
|
||||
|
||||
[SetUp]
|
||||
public void TestSetup()
|
||||
{
|
||||
_configuration = Mock.Of<Biz.Configuration.Configuration>();
|
||||
_verifySettings = TestExtensions.TestSettings();
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(OpportunityDetailQueryTestCases))]
|
||||
public async Task OpportunityDetailQueryTest(OpportunityLevel opportunityLevel, IEnumerable<SqlParameter> sqlParameters, QueryHelper encounterQueryHelper, QueryHelper opportunityLevelQueryHelper, bool isUsingSnowflake)
|
||||
{
|
||||
var query = new OpportunityDetailQuery(opportunityLevel, encounterQueryHelper, opportunityLevelQueryHelper, isUsingSnowflake);
|
||||
var result = isUsingSnowflake
|
||||
? query.GetQuery().ConvertSqlToSnowflakeParameterSyntax()
|
||||
: query.GetQuery().InterpolateQueryArrayValues(ref sqlParameters);
|
||||
await Verifier.Verify(result, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> OpportunityDetailQueryTestCases()
|
||||
{
|
||||
var configuration = Mock.Of<Biz.Configuration.Configuration>();
|
||||
configuration.DepartmentRollupGlobalId = "";
|
||||
var sqlParameters = new SqlParameter[] {
|
||||
new SqlParameter("@chargeCodeIds", new List<int> { 1, 2, 3 }),
|
||||
new SqlParameter("@caseTypeIds", new List<int> { 7, 8, 9 }),
|
||||
new SqlParameter("@oppLevelIds", new List<int>{ 4, 5, 6 }),
|
||||
new SqlParameter("@startDate", new DateTime(2023,1,1)),
|
||||
new SqlParameter("@endDate", new DateTime(2024,1,1)),
|
||||
new SqlParameter("@isBaseline", true)
|
||||
};
|
||||
|
||||
foreach (var parameterName in new[] { "@caseTypeIds", "@indicatorIds" })
|
||||
{
|
||||
sqlParameters[1].ParameterName = parameterName;
|
||||
foreach (var isUsingSnowflake in new[] { true, false })
|
||||
{
|
||||
foreach (var oppLevel in Enum.GetValues<OpportunityLevel>())
|
||||
{
|
||||
switch (oppLevel)
|
||||
{
|
||||
case OpportunityLevel.ServiceLine:
|
||||
foreach (var serviceLine in new[] { "Sg2 Service Line Crosswalk", "Service Line" })
|
||||
{
|
||||
yield return new TestCaseData(oppLevel, sqlParameters,
|
||||
new EncounterGroupQueryHelper(sqlParameters),
|
||||
new OpportunityLevelQueryHelper(oppLevel, configuration, serviceLine, $"{(serviceLine.Replace(" ", ""))}Id"), isUsingSnowflake)
|
||||
.SetName($"{{m}} {Enum.GetName<OpportunityLevel>(oppLevel)} {parameterName.Substring(1)} {serviceLine} {(isUsingSnowflake ? "Snowflake" : "")}");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
yield return new TestCaseData(oppLevel, sqlParameters,
|
||||
new EncounterGroupQueryHelper(sqlParameters),
|
||||
new OpportunityLevelQueryHelper(oppLevel, configuration, "", ""), isUsingSnowflake)
|
||||
.SetName($"{{m}} {Enum.GetName<OpportunityLevel>(oppLevel)} {parameterName.Substring(1)} Default {(isUsingSnowflake ? "Snowflake" : "")}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.Configuration;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.FiscalMonths;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.SqlTools.Configuration.Common.AsyncFactory;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Configuration
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class ConfigurationServiceTest
|
||||
{
|
||||
|
||||
private Mock<IConfigurationService> _configurationServiceMock;
|
||||
private Mock<IAsyncDbContextFactory<JazzDbContext>> _dbContextFactoryMock;
|
||||
private Mock<IJazzDbContext> _jazzDbContextMock;
|
||||
private Mock<IFiscalMonthResolver> _fiscalMonthResolverMock;
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
_configurationServiceMock = new Mock<IConfigurationService>();
|
||||
_dbContextFactoryMock = new Mock<IAsyncDbContextFactory<JazzDbContext>>();
|
||||
_jazzDbContextMock = new Mock<IJazzDbContext>();
|
||||
_fiscalMonthResolverMock = new Mock<IFiscalMonthResolver>();
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetDefaultConfigurationMock(JazzEntityFrameworkFactory framework, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var dfltConfiguration = framework.Configurations.OrderBy(c => c.DisplayOrder).First();
|
||||
_configurationServiceMock
|
||||
.Setup(vos => vos
|
||||
.GetDefaultConfigurationAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(dfltConfiguration);
|
||||
var logger = Mock.Of<ILogger<ConfigurationService>>();
|
||||
var _configurationService = new ConfigurationService(framework, null, null, logger, _fiscalMonthResolverMock.Object);
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await _configurationService.GetDefaultConfigurationAsync(cancellationToken);
|
||||
|
||||
// assert
|
||||
if (taskResult == null)
|
||||
{
|
||||
framework.JazzDbContext.Should().BeNull();
|
||||
return;
|
||||
}
|
||||
taskResult.Should().BeOfType<Biz.Configuration.Configuration>();
|
||||
taskResult.Name.Should().Be(dfltConfiguration.Name);
|
||||
taskResult.DisplayOrder.Should().Be(dfltConfiguration.DisplayOrder);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
cancellationToken.Should().NotBe(CancellationToken.None);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Intentionally left empty
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetDefaultConfiguration(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
// arrange
|
||||
var logger = Mock.Of<ILogger<ConfigurationService>>();
|
||||
await jazzEntityFrameworkFactory.CreateDbContextAsync(CancellationToken.None);
|
||||
var configurationService = new ConfigurationService(jazzEntityFrameworkFactory, null, null, logger, _fiscalMonthResolverMock.Object);
|
||||
|
||||
// act
|
||||
var taskResult = await configurationService.GetDefaultConfigurationAsync(cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<Biz.Configuration.Configuration>();
|
||||
taskResult.QVIOpportunityBreakdownName.Should().NotBeNullOrEmpty();
|
||||
taskResult.QVIOpportunityBreakdownNamePlural.Should().NotBeNullOrEmpty();
|
||||
taskResult.QVIOpportunityBreakdownEnum.Should()
|
||||
.Be((int)taskResult.QVIOpportunityBreakdown);
|
||||
}
|
||||
}
|
||||
catch (AggregateException ae)
|
||||
{
|
||||
ae.Should().NotBeOfType<AggregateException>();
|
||||
}
|
||||
catch (InvalidOperationException ioe)
|
||||
{
|
||||
ioe.Should().NotBeOfType<InvalidOperationException>();
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
cancellationToken.Should().NotBe(CancellationToken.None);
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Intentionally left blank
|
||||
}
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.FiscalMonths;
|
||||
using Strata.ContinuousImprovement.Biz.Generics;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using config = Strata.ContinuousImprovement.Biz.Configuration;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Configuration
|
||||
{
|
||||
|
||||
[TestFixture, Category("Unit")]
|
||||
public class ConfigurationTest
|
||||
{
|
||||
private IEnumerable<OpportunityTypes> excludedOpportTypes = new List<OpportunityTypes>()
|
||||
{
|
||||
OpportunityTypes.Blank,
|
||||
OpportunityTypes.Network
|
||||
};
|
||||
private IEnumerable<OpportunityTypes> OpportTypes { get; set; }
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void OneTimeSetup()
|
||||
{
|
||||
OpportTypes = Enum.GetValues(typeof(OpportunityTypes))
|
||||
.Cast<OpportunityTypes>()
|
||||
.Where(x => !excludedOpportTypes.Contains(x));
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(ConfigTestCases))]
|
||||
public void TestConfiguration(string rollup, string ids, int breakdown,
|
||||
IEnumerable<int> configuredIds, string name, string plural)
|
||||
{
|
||||
var config = new config.Configuration
|
||||
{
|
||||
DepartmentRollupGlobalId = rollup,
|
||||
EntityIdsCSV = string.IsNullOrEmpty(rollup) ? "" : ids,
|
||||
CustomEntityIdsCSV = string.IsNullOrEmpty(rollup) ? ids : "",
|
||||
QVIOpportunityBreakdown = (Biz.Configuration.Configuration.QVIOpportunityBreakdowns)breakdown
|
||||
};
|
||||
config.ConfiguredEntityIds.Should().AllBeEquivalentTo(configuredIds);
|
||||
config.QVIOpportunityBreakdownEnum.Should().Be(breakdown);
|
||||
config.QVIOpportunityBreakdownName.Should().Be(name);
|
||||
config.QVIOpportunityBreakdownNamePlural.Should().Be(plural);
|
||||
config.ServiceLineDimensionGuid.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(StartEndDateTestCases))]
|
||||
public void TestGetBaselineStartDate(DateTime expectedStartDate, DateTime endDate)
|
||||
{
|
||||
var configuration = GetConfigurationByDate(endDate);
|
||||
var opportunityTypeIds = Enum.GetValues<OpportunityTypes>().Cast<byte>().ToList();
|
||||
foreach (var opType in OpportTypes.Where(t => opportunityTypeIds.Contains((byte)t)))
|
||||
{
|
||||
var actualStartDate = configuration.GetBaselineStartDate(opType);
|
||||
actualStartDate.Should().Be(expectedStartDate);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(StartEndDateTestCases))]
|
||||
public void TestGetLastFiscalYearStartDate(DateTime expectedStartDate, DateTime endDate)
|
||||
{
|
||||
var configuration = GetConfigurationByDate(endDate, true);
|
||||
|
||||
var actualStartDate = configuration.GetLastFiscalYearStartDate();
|
||||
expectedStartDate = expectedStartDate.AddYears(-1);
|
||||
actualStartDate.Should().Be(expectedStartDate);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(StartEndDateTestCases))]
|
||||
public void TestGetFiscalYearStartDate(DateTime expectedStartDate, DateTime endDate)
|
||||
{
|
||||
var configuration = GetConfigurationByDate(endDate, true);
|
||||
|
||||
var actualStartDate = configuration.GetFiscalYearStartDate();
|
||||
actualStartDate.Should().Be(expectedStartDate);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(TrackingCurrentMonthEndDateTestCases))]
|
||||
public void TestTrackingCurrentMonthEndDate(
|
||||
OpportunityTypes opportunityType,
|
||||
DateTime trackingCurrentMonth,
|
||||
DateTime expectedEndDate)
|
||||
{
|
||||
var configuration = GetConfigurationWithTrackingMonth(trackingCurrentMonth, opportunityType);
|
||||
|
||||
var actualEndDate = configuration.TrackingCurrentMonthEndDate(opportunityType);
|
||||
|
||||
actualEndDate.Should().Be(expectedEndDate);
|
||||
actualEndDate.Hour.Should().Be(0);
|
||||
actualEndDate.Minute.Should().Be(0);
|
||||
actualEndDate.Second.Should().Be(0);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(TrackingCurrentMonthEndDateTestCases))]
|
||||
public void TestGetTrackingCurrentMonthEndDate(
|
||||
OpportunityTypes opportunityType,
|
||||
DateTime trackingCurrentMonth,
|
||||
DateTime expectedEndDate)
|
||||
{
|
||||
var configuration = GetConfigurationWithTrackingMonth(trackingCurrentMonth, opportunityType);
|
||||
|
||||
var actualEndDate = configuration.GetTrackingCurrentMonthEndDate(opportunityType);
|
||||
|
||||
actualEndDate.Should().Be(expectedEndDate.AddDays(-1));
|
||||
}
|
||||
|
||||
#region Configuration Test Cases
|
||||
|
||||
private static IEnumerable<TestCaseData> ConfigTestCases()
|
||||
{
|
||||
yield return new TestCaseData("Rollup", "1,2,3,4", 4,
|
||||
new[] { 1, 2, 3, 4 }, "Breakdown", "Breakdowns")
|
||||
.SetName("Default With Rollup");
|
||||
yield return new TestCaseData("", "1,2,3,4", 4,
|
||||
new[] { 1, 2, 3, 4 }, "Breakdown", "Breakdowns")
|
||||
.SetName("Default w/o Rollup");
|
||||
yield return new TestCaseData("Rollup", "1,2,3,4",
|
||||
(int)config.Configuration.QVIOpportunityBreakdowns.Entity,
|
||||
new[] { 1, 2, 3, 4 }, "Entity", "Entities")
|
||||
.SetName("Entity With Rollup");
|
||||
yield return new TestCaseData("", "1,2,3,4",
|
||||
(int)config.Configuration.QVIOpportunityBreakdowns.Entity,
|
||||
new[] { 1, 2, 3, 4 }, "Entity", "Entities")
|
||||
.SetName("Entity w/o Rollup");
|
||||
yield return new TestCaseData("Rollup", "1,2,3,4",
|
||||
(int)config.Configuration.QVIOpportunityBreakdowns.ServiceLine,
|
||||
new[] { 1, 2, 3, 4 }, "Service Line", "Service Lines")
|
||||
.SetName("Service Line With Rollup");
|
||||
yield return new TestCaseData("", "1,2,3,4",
|
||||
(int)config.Configuration.QVIOpportunityBreakdowns.ServiceLine,
|
||||
new[] { 1, 2, 3, 4 }, "Service Line", "Service Lines")
|
||||
.SetName("Service Line w/o Rollup");
|
||||
yield return new TestCaseData("Rollup", "1,2,3,4",
|
||||
(int)config.Configuration.QVIOpportunityBreakdowns.PhysicianSpecialty,
|
||||
new[] { 1, 2, 3, 4 }, "Physician Specialty", "Physician Specialties")
|
||||
.SetName("Physician Specialty With Rollup");
|
||||
yield return new TestCaseData("", "1,2,3,4",
|
||||
(int)config.Configuration.QVIOpportunityBreakdowns.PhysicianSpecialty,
|
||||
new[] { 1, 2, 3, 4 }, "Physician Specialty", "Physician Specialties")
|
||||
.SetName("Physician Specialty w/o Rollup");
|
||||
}
|
||||
|
||||
private static IEnumerable<TestCaseData> StartEndDateTestCases()
|
||||
{
|
||||
yield return new TestCaseData(new DateTime(2023, 3, 1), new DateTime(2024, 2, 29));
|
||||
yield return new TestCaseData(new DateTime(2024, 3, 1), new DateTime(2025, 2, 28));
|
||||
}
|
||||
|
||||
private static IEnumerable<TestCaseData> TrackingCurrentMonthEndDateTestCases()
|
||||
{
|
||||
yield return new TestCaseData(
|
||||
OpportunityTypes.ChargeCode,
|
||||
new DateTime(2024, 3, 15),
|
||||
new DateTime(2024, 4, 1))
|
||||
.SetName("ChargeCode - March 2024");
|
||||
|
||||
yield return new TestCaseData(
|
||||
OpportunityTypes.QualityVariation,
|
||||
new DateTime(2024, 6, 20),
|
||||
new DateTime(2024, 7, 1))
|
||||
.SetName("QualityVariation - June 2024");
|
||||
|
||||
yield return new TestCaseData(
|
||||
OpportunityTypes.Variation,
|
||||
new DateTime(2024, 12, 5),
|
||||
new DateTime(2025, 1, 1))
|
||||
.SetName("Variation - December 2024");
|
||||
|
||||
yield return new TestCaseData(
|
||||
OpportunityTypes.OrgDefined,
|
||||
new DateTime(2024, 2, 10),
|
||||
new DateTime(2024, 3, 1))
|
||||
.SetName("OrgDefined - February 2024");
|
||||
|
||||
yield return new TestCaseData(
|
||||
OpportunityTypes.Exploration,
|
||||
new DateTime(2024, 1, 31),
|
||||
new DateTime(2024, 2, 1))
|
||||
.SetName("Exploration - January 2024");
|
||||
|
||||
yield return new TestCaseData(
|
||||
OpportunityTypes.ChargeCode,
|
||||
new DateTime(2024, 2, 29),
|
||||
new DateTime(2024, 3, 1))
|
||||
.SetName("ChargeCode - Leap Year February");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Utils
|
||||
|
||||
private static config.Configuration GetConfigurationByDate(DateTime date, bool isFiscalMonthResolver = false)
|
||||
{
|
||||
var configuration = new config.Configuration
|
||||
{
|
||||
FiscalYearID = (short)date.Year,
|
||||
OrgDefinedEndDate = date,
|
||||
VariationEndDate = date,
|
||||
QualityVariationEndDate = date
|
||||
};
|
||||
|
||||
if (isFiscalMonthResolver)
|
||||
{
|
||||
var lastFiscalMonth = new FiscalMonth
|
||||
{
|
||||
FiscalMonthId = (byte)date.Month
|
||||
};
|
||||
var fmr = Mock.Of<IFiscalMonthResolver>();
|
||||
Mock.Get(fmr)
|
||||
.Setup(s => s.LastFiscalMonth())
|
||||
.Returns(() => lastFiscalMonth);
|
||||
configuration.FiscalMonthResolver = fmr;
|
||||
}
|
||||
return configuration;
|
||||
}
|
||||
|
||||
private static config.Configuration GetConfigurationWithTrackingMonth(
|
||||
DateTime trackingCurrentMonth,
|
||||
OpportunityTypes opportunityType)
|
||||
{
|
||||
var configuration = new config.Configuration();
|
||||
|
||||
switch (opportunityType)
|
||||
{
|
||||
case OpportunityTypes.ChargeCode:
|
||||
configuration.OrgDefinedTrackingCurrentMonth = trackingCurrentMonth;
|
||||
break;
|
||||
case OpportunityTypes.QualityVariation:
|
||||
configuration.QualityVariationTrackingCurrentMonth = trackingCurrentMonth;
|
||||
break;
|
||||
default:
|
||||
configuration.VariationTrackingCurrentMonth = trackingCurrentMonth;
|
||||
break;
|
||||
}
|
||||
|
||||
return configuration;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moq;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.DbContexts
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
public static class DbSetExtensions
|
||||
{
|
||||
public static DbSet<T> GetQueryableMockDbSet<T>(List<T> sourceList) where T : class
|
||||
{
|
||||
var queryable = sourceList.AsQueryable();
|
||||
var dbSet = new Mock<DbSet<T>>();
|
||||
dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
|
||||
dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
|
||||
dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
|
||||
dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());
|
||||
dbSet.Setup(d => d.Add(It.IsAny<T>())).Callback<T>((s) => sourceList.Add(s));
|
||||
return dbSet.Object;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.FreeForm.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.Generics;
|
||||
using Strata.ContinuousImprovement.Biz.QualityVariation.Opportunities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.DbContexts
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class JazzDbContextTests
|
||||
{
|
||||
private JazzDbContext _context;
|
||||
private DbContextOptions<JazzDbContext> _options;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void OneTimeSetUp()
|
||||
{
|
||||
_options = new DbContextOptionsBuilder<JazzDbContext>()
|
||||
.UseInMemoryDatabase($"TestDb_{Guid.NewGuid()}")
|
||||
.ConfigureWarnings(x => x.Ignore(InMemoryEventId.TransactionIgnoredWarning))
|
||||
.Options;
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_context = new JazzDbContext(_options);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
_context?.Dispose();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConfigureConventions_ShouldSetDecimalPrecision_ForAllDecimalProperties()
|
||||
{
|
||||
// Act
|
||||
var model = _context.Model;
|
||||
|
||||
// Assert - Get all decimal properties from all entities
|
||||
var decimalProperties = model.GetEntityTypes()
|
||||
.SelectMany(e => e.GetProperties())
|
||||
.Where(p => p.ClrType == typeof(decimal) || p.ClrType == typeof(decimal?))
|
||||
.ToList();
|
||||
|
||||
// Verify that we have decimal properties to test
|
||||
decimalProperties.Should().NotBeEmpty("There should be decimal properties in the model to test");
|
||||
|
||||
// Check that all decimal properties have the expected precision and scale
|
||||
var foregroundColor = Console.ForegroundColor;
|
||||
foreach (var property in decimalProperties)
|
||||
{
|
||||
var className = ((IEntityType)property.DeclaringType).ClrType.Name;
|
||||
var propertyName = property.Name;
|
||||
var precision = property.GetPrecision();
|
||||
var scale = property.GetScale();
|
||||
|
||||
if (precision == null || scale == null)
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine($"Property {className}.{propertyName} does not have precision/scale configured.");
|
||||
}
|
||||
else if (className == "QVIOpportunity" && propertyName == "QVIRate")
|
||||
{
|
||||
precision.Should().Be(19, $"Property {className}.{propertyName} should have precision 19");
|
||||
scale.Should().Be(4, $"Property {className}.{propertyName} should have scale 4");
|
||||
}
|
||||
else if (propertyName.StartsWith("Month"))
|
||||
{
|
||||
precision.Should().Be(15, $"Property {className}.{propertyName} should have precision 15");
|
||||
scale.Should().Be(4, $"Property {className}.{propertyName} should have scale 4");
|
||||
}
|
||||
else if (propertyName.StartsWith("QVI"))
|
||||
{
|
||||
precision.Should().Be(29, $"Property {className}.{propertyName} should have precision 29");
|
||||
scale.Should().Be(11, $"Property {className}.{propertyName} should have scale 11");
|
||||
}
|
||||
}
|
||||
Console.ForegroundColor = foregroundColor;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ConfigureConventions_ShouldNotAffectNonDecimalProperties()
|
||||
{
|
||||
// Act
|
||||
var model = _context.Model;
|
||||
|
||||
// Assert - Check that non-decimal properties are not affected
|
||||
var nonDecimalProperties = model.GetEntityTypes()
|
||||
.SelectMany(e => e.GetProperties())
|
||||
.Where(p => p.ClrType != typeof(decimal) && p.ClrType != typeof(decimal?))
|
||||
.ToList();
|
||||
|
||||
nonDecimalProperties.Should().NotBeEmpty("There should be non-decimal properties to verify they're not affected");
|
||||
|
||||
foreach (var property in nonDecimalProperties)
|
||||
{
|
||||
var precision = property.GetPrecision();
|
||||
var scale = property.GetScale();
|
||||
|
||||
if (property.ClrType == typeof(string))
|
||||
{
|
||||
precision.Should().BeNull($"String property {((IEntityType)property.DeclaringType).ClrType.Name}.{property.Name} should not have precision");
|
||||
scale.Should().BeNull($"String property {((IEntityType)property.DeclaringType).ClrType.Name}.{property.Name} should not have scale");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task DatabaseCreation_ShouldSucceed_WithDecimalPrecisionConfiguration()
|
||||
{
|
||||
// Act & Assert
|
||||
var canConnect = await _context.Database.CanConnectAsync();
|
||||
canConnect.Should().BeTrue("Database should be accessible with decimal precision configuration");
|
||||
|
||||
await _context.Database.EnsureCreatedAsync();
|
||||
var created = await _context.Database.CanConnectAsync();
|
||||
created.Should().BeTrue("Database should be created successfully with decimal precision configuration");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ModelValidation_ShouldPass_WithDecimalPrecisionConfiguration()
|
||||
{
|
||||
// Arrange & Act
|
||||
Action validateModel = () =>
|
||||
{
|
||||
// Accessing the model is enough to trigger validation in EF Core.
|
||||
// No explicit FinalizeModel method exists on IModel.
|
||||
var _ = _context.Model.GetEntityTypes().ToList();
|
||||
};
|
||||
|
||||
// Assert
|
||||
validateModel.Should().NotThrow("Model should validate successfully with decimal precision configuration");
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> OpportunityTestCases()
|
||||
{
|
||||
yield return new TestCaseData(new QVIOpportunity
|
||||
{
|
||||
OpportunityGuid = Guid.NewGuid(),
|
||||
ConfigurationGuid = Guid.NewGuid(),
|
||||
IdentifiedSavings = (double)98765.432102m,
|
||||
QVIRate = (decimal)98765.432102d,
|
||||
OpportunityKey = "TEST-004"
|
||||
}, (double)98765.4321m, (decimal)98765.4321d);
|
||||
}
|
||||
|
||||
private void AddOpportunityToContext(Opportunity opportunity)
|
||||
{
|
||||
switch (opportunity)
|
||||
{
|
||||
case QVIOpportunity qviOpportunity:
|
||||
_context.QualityVariationItemOpportunities.Add(qviOpportunity);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException($"Unsupported opportunity type: {opportunity.GetType().Name}");
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<object> GetSavedOpportunityAsync(Opportunity opportunity)
|
||||
{
|
||||
return opportunity switch
|
||||
{
|
||||
QVIOpportunity qviOpportunity => await _context.QualityVariationItemOpportunities
|
||||
.FirstOrDefaultAsync(o => o.OpportunityGuid == qviOpportunity.OpportunityGuid),
|
||||
_ => throw new ArgumentException($"Unsupported opportunity type: {opportunity.GetType().Name}")
|
||||
};
|
||||
}
|
||||
|
||||
[Test, TestCaseSource(nameof(OpportunityTestCases))]
|
||||
public async Task DecimalProperty_ShouldHandlePrecisionCorrectly_InDatabase(Opportunity testOpportunity, double expectedIdentifiedSavings, decimal? expectedQVIRate = null)
|
||||
{
|
||||
// This test verifies that the precision works in practice with the InMemory provider
|
||||
// Note: InMemory provider doesn't enforce precision/scale, but this tests the configuration doesn't break anything
|
||||
|
||||
// Arrange
|
||||
await _context.Database.EnsureCreatedAsync();
|
||||
|
||||
// Act
|
||||
if (testOpportunity == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(testOpportunity), "Test opportunity cannot be null");
|
||||
}
|
||||
|
||||
AddOpportunityToContext(testOpportunity);
|
||||
|
||||
// Assert
|
||||
Func<Task> saveAction = async () => await _context.SaveChangesAsync();
|
||||
await saveAction.Should().NotThrowAsync("Saving with configured decimal precision should work");
|
||||
|
||||
var savedOpportunity = await GetSavedOpportunityAsync(testOpportunity);
|
||||
|
||||
savedOpportunity.Should().NotBeNull();
|
||||
const double ToleranceForDecimalComparison = 19d;
|
||||
|
||||
if (savedOpportunity is FFOpportunityDataModel ffOppTest)
|
||||
{
|
||||
ffOppTest.IdentifiedSavings.Should().BeApproximately(expectedIdentifiedSavings, ToleranceForDecimalComparison);
|
||||
}
|
||||
else
|
||||
{
|
||||
((Opportunity)savedOpportunity).IdentifiedSavings.Should().BeApproximately(expectedIdentifiedSavings, ToleranceForDecimalComparison);
|
||||
if (savedOpportunity is QVIOpportunity qviOppTest && expectedQVIRate.HasValue)
|
||||
{
|
||||
qviOppTest.QVIRate.Should().BeApproximately(expectedQVIRate.Value, (decimal)ToleranceForDecimalComparison);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BaseMethod_ShouldBeCalled_InConfigureConventions()
|
||||
{
|
||||
// This test ensures that base.ConfigureConventions() is still called
|
||||
// We can't directly test this, but we can verify that EF Core's base conventions are applied
|
||||
|
||||
var model = _context.Model;
|
||||
|
||||
// Verify that base EF Core conventions are still working
|
||||
var stringProperties = model.GetEntityTypes()
|
||||
.SelectMany(e => e.GetProperties())
|
||||
.Where(p => p.ClrType == typeof(string))
|
||||
.ToList();
|
||||
|
||||
stringProperties.Should().NotBeEmpty("Should have string properties to verify base conventions work");
|
||||
|
||||
// EF Core base conventions should still work for string properties
|
||||
foreach (var property in stringProperties.Take(5)) // Just check a few
|
||||
{
|
||||
// Base conventions should still be applied (this varies by property, so we just ensure no exceptions)
|
||||
Action getAnnotations = () => { var _ = property.GetAnnotations(); };
|
||||
getAnnotations.Should().NotThrow($"Base conventions should work for {((IEntityType)property.DeclaringType).ClrType.Name}.{property.Name}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.Dtos;
|
||||
using Strata.ContinuousImprovement.Biz.Encounter.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.Mappers;
|
||||
using Strata.ContinuousImprovement.Biz.Shared;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Encounter
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class EncounterOpportunityMetricTest
|
||||
{
|
||||
private ENOpportunityDto opportunity;
|
||||
private ENOpportunityDataModelWithFilters model;
|
||||
|
||||
[SetUp]
|
||||
public void TestSetup()
|
||||
{
|
||||
opportunity = new ENOpportunityDto
|
||||
{
|
||||
ConfigurationGuid = Guid.NewGuid(),
|
||||
Name = "Test Encounter Opportunity",
|
||||
EncounterGroup = 0,
|
||||
OpportunityLevel = 1,
|
||||
EncounterGroups = new List<string>
|
||||
{
|
||||
"CaseType|CaseType|1"
|
||||
},
|
||||
OpportunityLevels = new List<string>()
|
||||
{
|
||||
"ENT|ENT|1"
|
||||
},
|
||||
IsBaseline = true
|
||||
};
|
||||
model = opportunity.MapToDataModel(null);
|
||||
model.OpportunityGuid = Guid.NewGuid();
|
||||
model.AuthorGuid = Guid.NewGuid();
|
||||
model.AuthorName = "Someones Name";
|
||||
model.DateCreated = DateTime.Today;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestENOpportunityDataModel()
|
||||
{
|
||||
var data = opportunity.MapToDataModel(null);
|
||||
data.ConfigurationGuid.Should().NotBe(Guid.Empty)
|
||||
.And.Be(opportunity.ConfigurationGuid);
|
||||
data.EncounterGroup.Should().Be(opportunity.EncounterGroup);
|
||||
data.OpportunityLevel.Should().Be(Enum.GetName(typeof(OpportunityLevel), opportunity.OpportunityLevel));
|
||||
data.EncounterOpportunityLevel.Should().Be((OpportunityLevel)opportunity.OpportunityLevel);
|
||||
data.CaseTypes.Should().NotBeEmpty()
|
||||
.And.Contain(ct => opportunity.EncounterGroups.Select(x => x).Contains(ct.Id));
|
||||
data.IsSeasonal.Should().Be(opportunity.IsSeasonal);
|
||||
data.IsBaseline.Should().Be(opportunity.IsBaseline);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEncounterOpportunityMetric()
|
||||
{
|
||||
var metric = model.MapFromDataModel();
|
||||
metric.OpportunityGuid.Should().Be(model.OpportunityGuid);
|
||||
metric.ConfigurationGuid.Should().Be(model.ConfigurationGuid);
|
||||
metric.AuthorName.Should().Be(model.AuthorName);
|
||||
metric.AuthorGuid.Should().Be(model.AuthorGuid);
|
||||
metric.Name.Should().Be(model.Name);
|
||||
metric.EncounterOpportunityLevel.Should().Be(model.EncounterOpportunityLevel);
|
||||
metric.EncounterGroup.Should().Be(model.EncounterGroup);
|
||||
metric.CaseTypes.Should().NotBeEmpty()
|
||||
.And.Contain(ct => opportunity.EncounterGroups.Select(x => x).Contains(ct.Id));
|
||||
var filter = opportunity.EncounterGroups.First().MapToFilterHelper();
|
||||
metric.CaseTypes.First().GetHashCode().Equals(filter.GetHashCode());
|
||||
metric.PatientPopulations.Should().BeEmpty();
|
||||
metric.Entities.Should().NotBeEmpty()
|
||||
.And.Contain(ct => opportunity.OpportunityLevels.Select(x => x).Contains(ct.Id));
|
||||
metric.ServiceLines.Should().BeEmpty();
|
||||
metric.Specialties.Should().BeEmpty();
|
||||
metric.Providers.Should().BeEmpty();
|
||||
metric.IsBaseline.Should().Be(opportunity.IsBaseline);
|
||||
metric.ConfigurationGuid.Should().NotBe(Guid.Empty);
|
||||
metric.IsSeasonal.Should().Be(opportunity.IsSeasonal);
|
||||
metric.IsBaseline.Should().Be(opportunity.IsBaseline);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetEncounterOpportunityMetricTests))]
|
||||
public void TestEncounterOpportunityMetric(ENOpportunityDto enOpportunity)
|
||||
{
|
||||
var dataModel = opportunity.MapToDataModel(null);
|
||||
var metric = dataModel.MapFromDataModel();
|
||||
metric.OpportunityGuid.Should().Be(dataModel.OpportunityGuid);
|
||||
metric.ConfigurationGuid.Should().Be(dataModel.ConfigurationGuid);
|
||||
metric.AuthorName.Should().Be(dataModel.AuthorName);
|
||||
metric.AuthorGuid.Should().Be(dataModel.AuthorGuid);
|
||||
metric.Name.Should().Be(dataModel.Name);
|
||||
metric.EncounterOpportunityLevel.Should().Be(dataModel.EncounterOpportunityLevel);
|
||||
metric.EncounterGroup.Should().Be(dataModel.EncounterGroup);
|
||||
switch ((EncounterGroup)metric.EncounterGroup)
|
||||
{
|
||||
case EncounterGroup.CaseType:
|
||||
metric.CaseTypes.Should().NotBeEmpty()
|
||||
.And.Contain(ct => opportunity.EncounterGroups.Select(x => x).Contains(ct.Id));
|
||||
var filter = opportunity.EncounterGroups.First().MapToFilterHelper();
|
||||
metric.CaseTypes.First().GetHashCode().Equals(filter.GetHashCode());
|
||||
break;
|
||||
case EncounterGroup.PatientPopulation:
|
||||
metric.PatientPopulations.Should().NotBeEmpty()
|
||||
.And.Contain(ct => opportunity.EncounterGroups.Select(x => x).Contains(ct.Id));
|
||||
var filter1 = opportunity.EncounterGroups.First().MapToFilterHelper();
|
||||
metric.PatientPopulations.First().GetHashCode().Equals(filter1.GetHashCode());
|
||||
break;
|
||||
}
|
||||
metric.PatientPopulations.Should().BeEmpty();
|
||||
switch (metric.EncounterOpportunityLevel)
|
||||
{
|
||||
case OpportunityLevel.Organization:
|
||||
metric.Entities.Should().BeEmpty();
|
||||
metric.ServiceLines.Should().BeEmpty();
|
||||
metric.Specialties.Should().BeEmpty();
|
||||
metric.Providers.Should().BeEmpty();
|
||||
break;
|
||||
case OpportunityLevel.Entity:
|
||||
metric.Entities.Should().NotBeEmpty()
|
||||
.And.Contain(ct => opportunity.OpportunityLevels.Select(x => x).Contains(ct.Id));
|
||||
metric.ServiceLines.Should().BeEmpty();
|
||||
metric.Specialties.Should().BeEmpty();
|
||||
metric.Providers.Should().BeEmpty();
|
||||
break;
|
||||
case OpportunityLevel.ServiceLine:
|
||||
metric.ServiceLines.Should().NotBeEmpty()
|
||||
.And.Contain(ct => opportunity.OpportunityLevels.Select(x => x).Contains(ct.Id));
|
||||
metric.Entities.Should().BeEmpty();
|
||||
metric.Specialties.Should().BeEmpty();
|
||||
metric.Providers.Should().BeEmpty();
|
||||
break;
|
||||
case OpportunityLevel.Specialty:
|
||||
metric.Specialties.Should().NotBeEmpty()
|
||||
.And.Contain(ct => opportunity.OpportunityLevels.Select(x => x).Contains(ct.Id));
|
||||
metric.Entities.Should().BeEmpty();
|
||||
metric.ServiceLines.Should().BeEmpty();
|
||||
metric.Providers.Should().BeEmpty();
|
||||
break;
|
||||
case OpportunityLevel.Provider:
|
||||
metric.Providers.Should().NotBeEmpty()
|
||||
.And.Contain(ct => opportunity.OpportunityLevels.Select(x => x).Contains(ct.Id));
|
||||
metric.Entities.Should().BeEmpty();
|
||||
metric.ServiceLines.Should().BeEmpty();
|
||||
metric.Specialties.Should().BeEmpty();
|
||||
break;
|
||||
}
|
||||
metric.IsBaseline.Should().Be(opportunity.IsBaseline);
|
||||
metric.ConfigurationGuid.Should().NotBe(Guid.Empty);
|
||||
metric.IsSeasonal.Should().Be(opportunity.IsSeasonal);
|
||||
metric.IsBaseline.Should().Be(opportunity.IsBaseline);
|
||||
}
|
||||
public static IEnumerable<TestCaseData> GetEncounterOpportunityMetricTests()
|
||||
{
|
||||
foreach (EncounterGroup encounterGroup in Enum.GetValues(typeof(EncounterGroup)))
|
||||
{
|
||||
if (encounterGroup == EncounterGroup.Both) continue;
|
||||
foreach (OpportunityLevel oppLevel in Enum.GetValues(typeof(OpportunityLevel)))
|
||||
{
|
||||
yield return new TestCaseData(new ENOpportunityDto
|
||||
{
|
||||
ConfigurationGuid = Guid.NewGuid(),
|
||||
Name = "Test Encounter Opportunity",
|
||||
EncounterGroup = (int)encounterGroup,
|
||||
OpportunityLevel = (int)oppLevel,
|
||||
EncounterGroups = new List<string>
|
||||
{
|
||||
"CaseType|CaseType|1"
|
||||
},
|
||||
OpportunityLevels = new List<string>()
|
||||
{
|
||||
"ENT|ENT|1"
|
||||
},
|
||||
IsBaseline = true
|
||||
}).SetName($"TestEncounterOpportunityMetric {encounterGroup} {oppLevel}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+813
@@ -0,0 +1,813 @@
|
||||
using FluentAssertions;
|
||||
using Hangfire;
|
||||
using Hangfire.Common;
|
||||
using Hangfire.States;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.Authorization;
|
||||
using Strata.ContinuousImprovement.Biz.Configuration;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.Encounter;
|
||||
using Strata.ContinuousImprovement.Biz.Encounter.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.Encounter.Opportunities.Filters;
|
||||
using Strata.ContinuousImprovement.Biz.Filter;
|
||||
using Strata.ContinuousImprovement.Biz.FiscalMonths;
|
||||
using Strata.ContinuousImprovement.Biz.Generics;
|
||||
using Strata.ContinuousImprovement.Biz.Initiatives;
|
||||
using Strata.ContinuousImprovement.Biz.Notification;
|
||||
using Strata.ContinuousImprovement.Biz.Pagination;
|
||||
using Strata.ContinuousImprovement.Biz.Shared;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.Hangfire.Jazz.Client;
|
||||
using Strata.Hangfire.Jazz.Client.Models;
|
||||
using Strata.Id.Client;
|
||||
using Strata.Schema.Client;
|
||||
using Strata.Schema.Client.Dtos;
|
||||
using Strata.Schema.Client.Dtos.Info;
|
||||
using Strata.SqlTools.Configuration.Common.AsyncFactory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Encounter.Opportunities
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class ENOpportunityServiceTests
|
||||
{
|
||||
|
||||
private IENOpportunityService _encounterOpportunityService;
|
||||
private Mock<IAsyncDbContextFactory<JazzDbContext>> _dbContextFactoryMock;
|
||||
private Mock<IJazzDbContext> _jazzDbContextMock;
|
||||
private Mock<ISchemaServiceClient> _schemaServiceMock;
|
||||
private Mock<IJazzHangfireServiceClient> _hangfireServiceMock;
|
||||
private Mock<IConfigurationService> _configurationMock;
|
||||
private Mock<IFiscalMonthResolver> _fiscalMonthResolverMock;
|
||||
private Mock<IBackgroundJobClient> _backgroundJobClient;
|
||||
private Mock<IIdServiceClient> _idServiceClient;
|
||||
private Mock<IAuthorizationServiceClient> _authorizationServiceClient;
|
||||
private Mock<IHubContext<NotificationHub, INotificationHub>> _notificationHubContext;
|
||||
private IInitiativeService _initiativeService;
|
||||
private IUpdateFactOpportunitySavingsService _updateFactOpportunitySavingsService;
|
||||
private static readonly ResourceFileExtractor _extractor = new ResourceFileExtractor(".Resource.");
|
||||
private List<Biz.Configuration.Configuration> _configurations;
|
||||
internal static List<Guid> ConfigGuids = new() { Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid(), Guid.NewGuid() };
|
||||
internal static List<string> ConfigNames = new() { "FY2021", "FY2022", "FY2023", "FY2024" };
|
||||
private ScoreDimensionInfoDto _dimension;
|
||||
private List<ScoreHierarchyDto> _hierarchies;
|
||||
private List<HierarchyNodeDto> _hierarchyNodes;
|
||||
private List<FilterHelper> _filterHelpers;
|
||||
private JobEnqueuedResponse _jobResponse;
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
_dbContextFactoryMock = new Mock<IAsyncDbContextFactory<JazzDbContext>>();
|
||||
_jazzDbContextMock = new Mock<IJazzDbContext>();
|
||||
_schemaServiceMock = new Mock<ISchemaServiceClient>();
|
||||
_hangfireServiceMock = new Mock<IJazzHangfireServiceClient>();
|
||||
_configurationMock = new Mock<IConfigurationService>();
|
||||
_fiscalMonthResolverMock = new Mock<IFiscalMonthResolver>();
|
||||
_updateFactOpportunitySavingsService = Mock.Of<IUpdateFactOpportunitySavingsService>();
|
||||
_initiativeService = Mock.Of<IInitiativeService>();
|
||||
_authorizationServiceClient = new Mock<IAuthorizationServiceClient>();
|
||||
_notificationHubContext = new Mock<IHubContext<NotificationHub, INotificationHub>>();
|
||||
_notificationHubContext.Setup(s => s.Clients)
|
||||
.Returns(new Mock<IHubClients<INotificationHub>>().Object);
|
||||
Mock.Get(_updateFactOpportunitySavingsService)
|
||||
.Setup(s => s.UpdateFactOpportunitySavings(It.IsAny<CancellationToken>()));
|
||||
Mock.Get(_initiativeService)
|
||||
.Setup(s => s.DeleteAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(true));
|
||||
_backgroundJobClient = new Mock<IBackgroundJobClient>();
|
||||
_idServiceClient = new Mock<IIdServiceClient>();
|
||||
_encounterOpportunityService = new ENOpportunityService(_dbContextFactoryMock.Object, null, null,
|
||||
_schemaServiceMock.Object, _hangfireServiceMock.Object, _configurationMock.Object, _fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService, _backgroundJobClient.Object, _idServiceClient.Object, _notificationHubContext.Object, _authorizationServiceClient.Object);
|
||||
|
||||
_configurations = new List<Biz.Configuration.Configuration>
|
||||
{
|
||||
new()
|
||||
{
|
||||
ConfigurationGuid = ConfigGuids[0],
|
||||
Name = ConfigNames.First(),
|
||||
DepartmentRollupGlobalId = string.Empty,
|
||||
ServiceLineDimensionGuid = Guid.NewGuid()
|
||||
},
|
||||
new()
|
||||
{
|
||||
ConfigurationGuid = ConfigGuids[1],
|
||||
Name = ConfigNames[1],
|
||||
DepartmentRollupGlobalId = "Department",
|
||||
ServiceLineDimensionGuid = Guid.NewGuid()
|
||||
},
|
||||
new()
|
||||
{
|
||||
ConfigurationGuid = ConfigGuids[2],
|
||||
Name = ConfigNames[2],
|
||||
DepartmentRollupGlobalId = string.Empty,
|
||||
ServiceLineDimensionGuid = Guid.NewGuid()
|
||||
},
|
||||
new()
|
||||
{
|
||||
ConfigurationGuid = ConfigGuids[3],
|
||||
Name = ConfigNames.Last(),
|
||||
DepartmentRollupGlobalId = string.Empty,
|
||||
ServiceLineDimensionGuid = Guid.NewGuid()
|
||||
}
|
||||
};
|
||||
_dimension = new ScoreDimensionInfoDto
|
||||
{
|
||||
FriendlyName = "test",
|
||||
DimensionGuid = Guid.NewGuid(),
|
||||
DefaultHierarchyGuid = Guid.NewGuid()
|
||||
};
|
||||
_hierarchies = new List<ScoreHierarchyDto>
|
||||
{
|
||||
new ScoreHierarchyDto
|
||||
{
|
||||
FriendlyName = "test",
|
||||
HierarchyGuid = _dimension.DefaultHierarchyGuid
|
||||
}
|
||||
};
|
||||
_hierarchyNodes = new List<HierarchyNodeDto>
|
||||
{
|
||||
new HierarchyNodeDto
|
||||
{
|
||||
Name = "Case Type",
|
||||
Path = "CaseType|CaseType|1"
|
||||
}
|
||||
};
|
||||
_jobResponse = new JobEnqueuedResponse
|
||||
{
|
||||
JobId = Guid.NewGuid()
|
||||
};
|
||||
_filterHelpers = new List<FilterHelper>
|
||||
{
|
||||
new FilterHelper
|
||||
{
|
||||
Id = "CaseType|CaseType|1"
|
||||
}
|
||||
};
|
||||
|
||||
_hangfireServiceMock.Setup(moq =>
|
||||
moq.EnqueueJobAsync(It.IsAny<EnqueueJobDto>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_jobResponse));
|
||||
|
||||
_configurationMock.Setup(moq => moq.GetConfigurationAsync(It.Is<Guid>(c => c == ConfigGuids[0]), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_configurations[0]));
|
||||
_configurationMock.Setup(moq => moq.GetConfigurationAsync(It.Is<Guid>(c => c == ConfigGuids[1]), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_configurations[1]));
|
||||
_configurationMock.Setup(moq => moq.GetConfigurationAsync(It.Is<Guid>(c => c == ConfigGuids[2]), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_configurations[2]));
|
||||
_configurationMock.Setup(moq => moq.GetConfigurationAsync(It.Is<Guid>(c => c == _configurations.Last().ConfigurationGuid), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_configurations.Last()));
|
||||
|
||||
_schemaServiceMock.Setup(moq => moq.GetDimensionByGlobalIdAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_dimension));
|
||||
_schemaServiceMock.Setup(moq => moq.GetDimensionByIdAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_dimension));
|
||||
_schemaServiceMock.Setup(moq => moq.GetScoreHierarchiesByGlobalIdAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_hierarchies.AsEnumerable()));
|
||||
_schemaServiceMock.Setup(moq => moq.GetHierarchyNodesByHierarchyGuidAsync(It.IsAny<Guid>(),
|
||||
It.IsAny<HierarchyNodeParametersDto>(), It.IsAny<List<ExtraFilterDto>>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_hierarchyNodes.AsEnumerable()));
|
||||
_schemaServiceMock.Setup(moq => moq.GetHierarchyNodesFromHierarchyPathsAsync(It.IsAny<Guid>(),
|
||||
It.IsAny<IEnumerable<string>>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(_hierarchyNodes.AsEnumerable()));
|
||||
|
||||
_backgroundJobClient.Setup(moq => moq.Create(It.IsAny<Job>(), It.IsAny<IState>()))
|
||||
.Returns(Guid.NewGuid().ToString());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Asc()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var encounterOpportunityService = new ENOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
var filters = new ENFilters()
|
||||
{
|
||||
Cases = 0,
|
||||
OpportunityLevels = new List<string>(),
|
||||
EncounterGroups = EncounterGroup.Both,
|
||||
Seasonality = SeasonalityType.WithAndWithout,
|
||||
IdentifiedSavings = 0,
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
|
||||
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions("IdentifiedSavings", SortOrder.Asc);
|
||||
|
||||
// act
|
||||
var taskResult = await encounterOpportunityService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<ENOpportunity>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().IdentifiedSavings
|
||||
.Should().BeLessThan(taskResult.Data.Last().IdentifiedSavings);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Desc()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var encounterOpportunityService = new ENOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
var filters = new ENFilters()
|
||||
{
|
||||
Cases = 0,
|
||||
OpportunityLevels = new List<string>(),
|
||||
EncounterGroups = EncounterGroup.Both,
|
||||
Seasonality = SeasonalityType.WithAndWithout,
|
||||
IdentifiedSavings = 0,
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
|
||||
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions("IdentifiedSavings", SortOrder.Desc);
|
||||
|
||||
// act
|
||||
var taskResult = await encounterOpportunityService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<ENOpportunity>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().IdentifiedSavings
|
||||
.Should().BeGreaterThan(taskResult.Data.Last().IdentifiedSavings);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFilterData))]
|
||||
public void TestValidateFilters(ENFilters filters)
|
||||
{
|
||||
if (filters == null) return;
|
||||
if (filters.OpportunityLevels.Any())
|
||||
filters.OpportunityLevels.Should()
|
||||
.AllBeOfType<string>()
|
||||
.And.NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetExcelWorkbook()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opp = framework.ENOpportunities.First();
|
||||
var filters = new ENFilters()
|
||||
{
|
||||
ConfigurationGuid = framework.Configurations.First().ConfigurationGuid,
|
||||
OpportunityLevels = new[] { opp.OpportunityLevel },
|
||||
};
|
||||
var service = new ENOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var wb = await service.ExportAsync(new SortOptions(), filters, CancellationToken.None);
|
||||
#pragma warning disable S125 // Sections of code should not be commented out
|
||||
//wb.SaveAs(System.IO.Path.Combine(@"C:\Git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "ExcelFilter.xlsx"));
|
||||
#pragma warning restore S125 // Sections of code should not be commented out
|
||||
|
||||
// assert
|
||||
wb.Worksheets.Should().HaveCount(1);
|
||||
var ws = wb.Worksheet(1);
|
||||
ws.Should().NotBeNull();
|
||||
|
||||
var expected = @"Examples.EncounterOpportunity.ExcelFilter.xlsx";
|
||||
using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected))
|
||||
using (var actualStream = new MemoryStream())
|
||||
{
|
||||
wb.SaveAs(actualStream);
|
||||
actualStream.Compare(expectedStream, out var message).Should().BeTrue(message);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetExcelWorkbookNullFilter()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var service = new ENOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var wb = await service.ExportAsync(null, null, CancellationToken.None);
|
||||
#pragma warning disable S125 // Sections of code should not be commented out
|
||||
//wb.SaveAs(System.IO.Path.Combine(@"C:\Git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "ExcelNullFilter.xlsx"));
|
||||
#pragma warning restore S125 // Sections of code should not be commented out
|
||||
|
||||
// assert
|
||||
wb.Worksheets.Should().HaveCount(1);
|
||||
var ws = wb.Worksheet(1);
|
||||
ws.Should().NotBeNull();
|
||||
|
||||
var expected = @"Examples.EncounterOpportunity.ExcelNullFilter.xlsx";
|
||||
using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected))
|
||||
using (var actualStream = new MemoryStream())
|
||||
{
|
||||
wb.SaveAs(actualStream);
|
||||
actualStream.Compare(expectedStream, out var message).Should().BeTrue(message);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestCreateAsyncCaseTypesOrganization()
|
||||
{
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunity = new ENOpportunityDataModelWithFilters
|
||||
{
|
||||
EncounterGroup = 0,
|
||||
CaseTypes = new List<FilterHelper>
|
||||
{
|
||||
new FilterHelper
|
||||
{
|
||||
Id = "CaseType|CaseType|1"
|
||||
}
|
||||
},
|
||||
EncounterOpportunityLevel = OpportunityLevel.Organization
|
||||
};
|
||||
opportunity.ConfigurationGuid = framework.Configurations.FirstOrDefault().ConfigurationGuid;
|
||||
var service = new ENOpportunityService(framework, null, null,
|
||||
_schemaServiceMock.Object, _hangfireServiceMock.Object, _configurationMock.Object, _fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService, _backgroundJobClient.Object, _idServiceClient.Object, _notificationHubContext.Object, _authorizationServiceClient.Object);
|
||||
|
||||
var results = await service.CreateAsync(opportunity.MapToDataModel(null), Guid.Empty, true, CancellationToken.None);
|
||||
results.Should().NotBe(Guid.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestCreateAsyncAllCaseTypesOrganization()
|
||||
{
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunity = new ENOpportunityDataModelWithFilters
|
||||
{
|
||||
EncounterGroup = 0,
|
||||
EncounterOpportunityLevel = OpportunityLevel.Organization
|
||||
};
|
||||
opportunity.ConfigurationGuid = framework.Configurations.FirstOrDefault().ConfigurationGuid;
|
||||
var service = new ENOpportunityService(framework, null, null,
|
||||
_schemaServiceMock.Object, _hangfireServiceMock.Object, _configurationMock.Object, _fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService, _backgroundJobClient.Object, _idServiceClient.Object, _notificationHubContext.Object, _authorizationServiceClient.Object);
|
||||
var results = await service.CreateAsync(opportunity.MapToDataModel(null), Guid.Empty, true, CancellationToken.None);
|
||||
results.Should().NotBe(Guid.Empty);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetENOpportunityDataModel))]
|
||||
public async Task TestCreateAsync(ENOpportunityDataModelWithFilters opportunity)
|
||||
{
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
opportunity.ConfigurationGuid = framework.Configurations.FirstOrDefault().ConfigurationGuid;
|
||||
var service = new ENOpportunityService(framework, null, null,
|
||||
_schemaServiceMock.Object, _hangfireServiceMock.Object, _configurationMock.Object, _fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService, _backgroundJobClient.Object, _idServiceClient.Object, _notificationHubContext.Object, _authorizationServiceClient.Object);
|
||||
var results = await service.CreateAsync(opportunity.MapToDataModel(null), Guid.Empty, true, CancellationToken.None);
|
||||
results.Should().NotBe(Guid.Empty);
|
||||
}
|
||||
|
||||
[Test, Ignore("Problem moq'ing GetEntityNodes")]
|
||||
public async Task TestCreateAsyncAllCaseTypesAllEntities()
|
||||
{
|
||||
var serviceMock = new Mock<ENOpportunityService>(_dbContextFactoryMock.Object, null, null,
|
||||
_schemaServiceMock.Object, _hangfireServiceMock.Object, _configurationMock.Object, _fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService, _backgroundJobClient.Object, _idServiceClient.Object, _notificationHubContext.Object, _authorizationServiceClient.Object);
|
||||
var service = serviceMock.Object;
|
||||
var opportunity = new ENOpportunityDataModelWithFilters
|
||||
{
|
||||
EncounterGroup = 0,
|
||||
EncounterOpportunityLevel = OpportunityLevel.Entity
|
||||
};
|
||||
var results = await service.CreateAsync(opportunity.MapToDataModel(null), Guid.Empty, true, CancellationToken.None);
|
||||
results.Should().NotBe(Guid.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetEntityNodes()
|
||||
{
|
||||
var service = new ENOpportunityService(_dbContextFactoryMock.Object, null, null,
|
||||
_schemaServiceMock.Object, _hangfireServiceMock.Object, _configurationMock.Object, _fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService, _backgroundJobClient.Object, _idServiceClient.Object, _notificationHubContext.Object, _authorizationServiceClient.Object);
|
||||
var configuration = new Biz.Configuration.Configuration
|
||||
{
|
||||
DepartmentRollupGlobalId = ""
|
||||
};
|
||||
|
||||
var results = await service.GetEntityNodes(configuration, CancellationToken.None);
|
||||
results.Should().NotBeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetServiceLineNodesBySg2()
|
||||
{
|
||||
var service = new ENOpportunityService(_dbContextFactoryMock.Object, null, null,
|
||||
_schemaServiceMock.Object, _hangfireServiceMock.Object, _configurationMock.Object, _fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService, _backgroundJobClient.Object, _idServiceClient.Object, _notificationHubContext.Object, _authorizationServiceClient.Object);
|
||||
var configuration = new Biz.Configuration.Configuration
|
||||
{
|
||||
ServiceLineDimensionGuid = Guid.Empty
|
||||
};
|
||||
|
||||
var results = await service.GetServiceLineNodes(configuration, new List<string>(), CancellationToken.None);
|
||||
results.Should().NotBeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetServiceLineNodes()
|
||||
{
|
||||
var service = new ENOpportunityService(_dbContextFactoryMock.Object, null, null,
|
||||
_schemaServiceMock.Object, _hangfireServiceMock.Object, _configurationMock.Object, _fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService, _backgroundJobClient.Object, _idServiceClient.Object, _notificationHubContext.Object, _authorizationServiceClient.Object);
|
||||
var configuration = new Biz.Configuration.Configuration
|
||||
{
|
||||
ServiceLineDimensionGuid = Guid.NewGuid()
|
||||
};
|
||||
|
||||
var results = await service.GetServiceLineNodes(configuration, new List<string>(), CancellationToken.None);
|
||||
results.Should().NotBeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetNodesByGlobalId()
|
||||
{
|
||||
var service = new ENOpportunityService(_dbContextFactoryMock.Object, null, null,
|
||||
_schemaServiceMock.Object, _hangfireServiceMock.Object, _configurationMock.Object, _fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService, _backgroundJobClient.Object, _idServiceClient.Object, _notificationHubContext.Object, _authorizationServiceClient.Object);
|
||||
var results = await service.GetNodesByGlobalId("entity", CancellationToken.None);
|
||||
results.Should().NotBeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetNodesByHierarchyGuid()
|
||||
{
|
||||
var service = new ENOpportunityService(_dbContextFactoryMock.Object, null, null,
|
||||
_schemaServiceMock.Object, _hangfireServiceMock.Object, _configurationMock.Object, _fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService, _backgroundJobClient.Object, _idServiceClient.Object, _notificationHubContext.Object, _authorizationServiceClient.Object);
|
||||
var results = await service.GetNodesByHierarchyGuid(Guid.NewGuid(), CancellationToken.None);
|
||||
results.Should().NotBeEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSetHidden()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunities = framework.ENOpportunities;
|
||||
var opportunity = opportunities.First(vo => !vo.IsHidden);
|
||||
var isHidden = opportunity.IsHidden;
|
||||
var service = new ENOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
await service.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
result.IsHidden.Should().Be(!isHidden);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetFilterOptionsAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunityService = new ENOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await opportunityService
|
||||
.GetFilterOptionsAsync(new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
return;
|
||||
}
|
||||
taskResult.Should()
|
||||
.BeOfType<ENFilterOptions>()
|
||||
.And.NotBeNull();
|
||||
taskResult.OpportunityLevels.Should().AllBeOfType<FilterMember>().And.NotBeNullOrEmpty()
|
||||
.And.NotContain(cd => string.IsNullOrEmpty(cd.Id))
|
||||
.And.NotContain(cd => string.IsNullOrEmpty(cd.Text));
|
||||
}
|
||||
catch (NotImplementedException nie)
|
||||
{
|
||||
nie.Should().BeOfType<NotImplementedException>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var encounterOpportunityService = new ENOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
try
|
||||
{
|
||||
var opportunities = encounterOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;
|
||||
|
||||
//act
|
||||
await encounterOpportunityService.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden,
|
||||
|
||||
cancellationToken);
|
||||
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return;
|
||||
|
||||
var result = encounterOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result;
|
||||
|
||||
result.IsHidden.Should().Be(!isHidden);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
switch (e.GetType().Name)
|
||||
{
|
||||
case "AggregateException":
|
||||
case "OperationCanceledException":
|
||||
return;
|
||||
}
|
||||
e.Should().NotBeOfType<Exception>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.ENOpportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;
|
||||
var encounterOpportunityService = new ENOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await encounterOpportunityService.SetHiddenAsync(Guid.Empty, !isHidden,
|
||||
cancellationToken);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var encounterOpportunityService = new ENOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
try
|
||||
{
|
||||
var opportunities = encounterOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
|
||||
if (opportunity == null) return;
|
||||
|
||||
var note = "new test note";
|
||||
// act
|
||||
await encounterOpportunityService.SetNoteAsync(opportunity.OpportunityGuid, note,
|
||||
CancellationToken.None);
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return;
|
||||
var result = encounterOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result;
|
||||
result.Note.Should().Be(note);
|
||||
|
||||
// assert
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
switch (e.GetType().Name)
|
||||
{
|
||||
case "AggregateException":
|
||||
case "OperationCanceledException":
|
||||
return;
|
||||
}
|
||||
e.Should().NotBeOfType<Exception>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSetNote()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunities = framework.ENOpportunities;
|
||||
var opportunity = opportunities.First(vo => string.IsNullOrEmpty(vo.Note));
|
||||
var note = opportunity.Note;
|
||||
var expected = "Now is the time for all good engineers to write great code!";
|
||||
var service = new ENOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
await service.SetNoteAsync(opportunity.OpportunityGuid, expected, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
result.Note.Should().NotBeNullOrEmpty()
|
||||
.And.NotBe(note)
|
||||
.And.Be(expected);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.ENOpportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
if (opportunity == null) return;
|
||||
var note = "new test note";
|
||||
var encounterOpportunityService = new ENOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await encounterOpportunityService.SetNoteAsync(Guid.Empty, note, cancellationToken);
|
||||
|
||||
// assert
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetAllAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var encounterOpportunityService = new ENOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var taskResult = await encounterOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetById(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var encounterOpportunityService = new ENOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var tempResult = await encounterOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var taskResult =
|
||||
await encounterOpportunityService.GetById(tempResult.FirstOrDefault()?.OpportunityGuid ?? Guid.Empty, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<ENOpportunity>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetByIds(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var encounterOpportunityService = new ENOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var tempResult = await encounterOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var ids = tempResult.Select(o => o.OpportunityGuid);
|
||||
var taskResult = await encounterOpportunityService.GetByIds(ids, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<ENOpportunity>()
|
||||
.And.HaveCount(ids.Count());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
|
||||
#region TestCaseData
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFilterData()
|
||||
{
|
||||
yield return new TestCaseData(new ENFilters { ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("No Filters");
|
||||
yield return new TestCaseData(new ENFilters { ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("View Visible");
|
||||
yield return new TestCaseData(new ENFilters { ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Not View Visible");
|
||||
yield return new TestCaseData(new ENFilters { IdentifiedSavings = 1999, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings");
|
||||
yield return new TestCaseData(new ENFilters { IdentifiedSavings = 999, ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings Not ViewVisible");
|
||||
yield return new TestCaseData(new ENFilters { OpportunityLevels = new[] { "Entity" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By OpportunityLevels");
|
||||
yield return new TestCaseData(new ENFilters { OpportunityLevels = new[] { "Provider" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), ViewVisible = false })
|
||||
.SetName("By OpportunityLevels Not ViewVisible");
|
||||
yield return new TestCaseData(new ENFilters { EncounterGroups = EncounterGroup.CaseType, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By EncounterGroups");
|
||||
yield return new TestCaseData(new ENFilters { EncounterGroups = EncounterGroup.PatientPopulation, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), ViewVisible = false })
|
||||
.SetName("By EncounterGroups Not ViewVisible");
|
||||
yield return new TestCaseData(new ENFilters { Seasonality = SeasonalityType.With, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By Seaonality");
|
||||
yield return new TestCaseData(new ENFilters { OpportunitySearch = "EN - 101", ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Search By Id");
|
||||
yield return new TestCaseData(new ENFilters { ExcludeInitiatives = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Exclude Opportunities with Initiatives");
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> GetENOpportunityDataModel()
|
||||
{
|
||||
return from configGuid in ConfigGuids
|
||||
from EncounterGroup encounterGroup in Enum.GetValues(typeof(EncounterGroup))
|
||||
where encounterGroup != EncounterGroup.Both
|
||||
from OpportunityLevel encounterOpportunityLevel in Enum.GetValues(typeof(OpportunityLevel))
|
||||
from encounterGroups in new[] { true, false }
|
||||
from opportunityLevels in new[] { true, false }
|
||||
select new TestCaseData(new ENOpportunityDataModelWithFilters
|
||||
{
|
||||
ConfigurationGuid = configGuid,
|
||||
EncounterGroup = (int)encounterGroup,
|
||||
EncounterOpportunityLevel = encounterOpportunityLevel,
|
||||
CaseTypes = encounterGroup == EncounterGroup.CaseType
|
||||
? new List<FilterHelper>
|
||||
{
|
||||
new() {Id = "Id"}
|
||||
}
|
||||
: new List<FilterHelper>(),
|
||||
PatientPopulations = encounterGroup == EncounterGroup.PatientPopulation
|
||||
? new List<FilterHelper>
|
||||
{
|
||||
new () {Id = "Id"}
|
||||
}
|
||||
: new List<FilterHelper>(),
|
||||
Entities = encounterOpportunityLevel == OpportunityLevel.Entity
|
||||
? new List<FilterHelper>
|
||||
{
|
||||
new () {Id = "Id"}
|
||||
}
|
||||
: new List<FilterHelper>(),
|
||||
ServiceLines = encounterOpportunityLevel == OpportunityLevel.ServiceLine
|
||||
? new List<FilterHelper>
|
||||
{
|
||||
new () {Id = "Id"}
|
||||
}
|
||||
: new List<FilterHelper>(),
|
||||
Specialties = encounterOpportunityLevel == OpportunityLevel.Specialty
|
||||
? new List<FilterHelper>
|
||||
{
|
||||
new () {Id = "Id"}
|
||||
}
|
||||
: new List<FilterHelper>(),
|
||||
Providers = encounterOpportunityLevel == OpportunityLevel.Provider
|
||||
? new List<FilterHelper>
|
||||
{
|
||||
new () {Id = "Id"}
|
||||
}
|
||||
: new List<FilterHelper>()
|
||||
}).SetName($"{nameof(TestCreateAsync)} {ConfigNames[ConfigGuids.IndexOf(configGuid)]} IsUsingCustomEntityDim: {ConfigGuids.IndexOf(configGuid) == 1} IsUsingSg2: {ConfigGuids.IndexOf(configGuid) == 3} {encounterGroup} {encounterOpportunityLevel}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+297
@@ -0,0 +1,297 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts.Snowflake;
|
||||
using Strata.ContinuousImprovement.Biz.Exploration;
|
||||
using Strata.ContinuousImprovement.Biz.Exploration.CaseTypeFamilies;
|
||||
using Strata.ContinuousImprovement.Biz.Exploration.Filters;
|
||||
using Strata.ContinuousImprovement.Biz.FiscalMonths;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.ContinuousImprovement.Biz.Utilities;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.CoreLib.Claims;
|
||||
using Strata.StrataSphereCompare.Client;
|
||||
using Strata.StrataSphereCompare.Client.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using static Strata.ContinuousImprovement.Biz.Exploration.ExplorationService;
|
||||
using ExplorationFilter = Strata.ContinuousImprovement.Biz.Exploration.Filters.Filter;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Exploration
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class ExplorationServiceBenchmarkingUnitTests
|
||||
{
|
||||
private const string FeatureFlagKey = "cibenchmarkingenabled";
|
||||
private const string CaseTypeFamilyName = "Sample CTF";
|
||||
|
||||
private Mock<ISnowflakeDatabaseContext> _snowflakeDatabaseContextMock;
|
||||
private Mock<IFiscalMonthResolver> _fiscalMonthResolverMock;
|
||||
private Mock<IClaimsPrincipalAccessor> _claimsPrincipalAccessorMock;
|
||||
private Mock<IStrataSphereCompareService> _strataSphereCompareServiceMock;
|
||||
private Mock<ILogger<ExplorationService>> _explorationServiceLoggerMock;
|
||||
private Mock<IExplorationFilterService> _explorationFilterServiceMock;
|
||||
|
||||
private ExplorationInfo _explorationInfo;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void OneTimeSetUp()
|
||||
{
|
||||
_snowflakeDatabaseContextMock = new Mock<ISnowflakeDatabaseContext>();
|
||||
_fiscalMonthResolverMock = new Mock<IFiscalMonthResolver>();
|
||||
_explorationServiceLoggerMock = new Mock<ILogger<ExplorationService>>();
|
||||
|
||||
var principal = TestUtilities.GetClaimsPrincipalAccessor();
|
||||
var defaultUser = principal.GetCurrentClaimsPrincipal();
|
||||
_claimsPrincipalAccessorMock = new Mock<IClaimsPrincipalAccessor>();
|
||||
_claimsPrincipalAccessorMock.Setup(a => a.GetCurrentClaimsPrincipal()).Returns(defaultUser);
|
||||
|
||||
_strataSphereCompareServiceMock = new Mock<IStrataSphereCompareService>();
|
||||
_explorationFilterServiceMock = new Mock<IExplorationFilterService>();
|
||||
|
||||
// Setup ExplorationFilterService mock
|
||||
_explorationFilterServiceMock
|
||||
.Setup(s => s.GetFilterStringsAsync(It.IsAny<IEnumerable<FilterChipItem>>(), It.IsAny<IQueryParamBase>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(("", ""));
|
||||
_explorationFilterServiceMock
|
||||
.Setup(s => s.BuildDataFiltersAsync(It.IsAny<CaseTypeFamily>(), It.IsAny<string>(), It.IsAny<ExplorationFilter>(), It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new CostDetailsFilterDto());
|
||||
|
||||
// Setup 1: For GetCaseTypeFamilySummariesAsync (no drill down filter)
|
||||
_strataSphereCompareServiceMock
|
||||
.Setup(s => s.GetCostDetailsAsync(
|
||||
It.IsAny<BaseComparisonParams>(),
|
||||
It.Is<CostDetailsFilterDto>(filter => filter.CostDetailsFilterDrillDown == null),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new[]
|
||||
{
|
||||
new CostDetailsDto
|
||||
{
|
||||
AprDrgCaseTypeFamilyName = CaseTypeFamilyName,
|
||||
P50th_VariableDirectCost = 250.75m,
|
||||
P50th_Alos = 5.2m
|
||||
}
|
||||
});
|
||||
|
||||
// Setup 2: For GetCaseTypeFamilySummaryDetailsAsync (with drill down filter)
|
||||
_strataSphereCompareServiceMock
|
||||
.Setup(s => s.GetCostDetailsAsync(
|
||||
It.IsAny<BaseComparisonParams>(),
|
||||
It.Is<CostDetailsFilterDto>(filter => filter.CostDetailsFilterDrillDown != null),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new[]
|
||||
{
|
||||
new CostDetailsDto
|
||||
{
|
||||
SphChargeCodeCostDriver = "LOS",
|
||||
P50th_VariableDirectCost = 150.50m,
|
||||
P50th_Alos = 3.2m
|
||||
},
|
||||
new CostDetailsDto
|
||||
{
|
||||
SphChargeCodeCostDriver = "Surgery",
|
||||
P50th_VariableDirectCost = 300.25m,
|
||||
P50th_Alos = 4.8m
|
||||
}
|
||||
});
|
||||
|
||||
// Summary Mock Data
|
||||
_snowflakeDatabaseContextMock
|
||||
.Setup(s => s.QueryAsync<CaseTypeFamilySummaryInfo>(
|
||||
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<object>(), It.IsAny<TimeSpan>()))
|
||||
.ReturnsAsync(new[]
|
||||
{
|
||||
new CaseTypeFamilySummaryInfo { CaseTypeFamilyName = CaseTypeFamilyName }
|
||||
});
|
||||
|
||||
// Summary Detail Mock Data - for GetCaseTypeFamilySummaryDetailsAsync
|
||||
_snowflakeDatabaseContextMock
|
||||
.Setup(s => s.QueryAsync<CaseTypeFamilyEncounterInfo>(
|
||||
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<object>(), It.IsAny<TimeSpan>()))
|
||||
.ReturnsAsync(new[]
|
||||
{
|
||||
new CaseTypeFamilyEncounterInfo
|
||||
{
|
||||
CaseTypeFamilyName = CaseTypeFamilyName,
|
||||
CostDriver = "LOS"
|
||||
},
|
||||
new CaseTypeFamilyEncounterInfo
|
||||
{
|
||||
CaseTypeFamilyName = CaseTypeFamilyName,
|
||||
CostDriver = "Surgery"
|
||||
}
|
||||
});
|
||||
|
||||
_explorationInfo = new ExplorationCostDriverInfo
|
||||
{
|
||||
CaseTypeFamilyId = 1,
|
||||
PeerGroupId = 1,
|
||||
ExclusionCriteria = new ExclusionCriteria
|
||||
{
|
||||
LosExclusionType = ExclusionCriteriaType.None,
|
||||
CostExclusionType = ExclusionCriteriaType.None
|
||||
},
|
||||
Filters = new ExplorationFilter // Use the alias
|
||||
{
|
||||
FilterChipItems = new List<FilterChipItem>
|
||||
{
|
||||
new FilterChipItem
|
||||
{
|
||||
ChipType = ChipType.DateRange,
|
||||
Key = ChipKey.DischargeDateID,
|
||||
DateRange = new List<DateTime>
|
||||
{
|
||||
new DateTime(2024, 1, 1),
|
||||
new DateTime(2024, 12, 31)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetCaseTypeFamilySummariesAsync_FeatureFlagOn_PopulatesPeerMetrics()
|
||||
{
|
||||
// Arrange
|
||||
var jazzFactory = new JazzEntityFrameworkFactory();
|
||||
await jazzFactory.CreateDbContextAsync(CancellationToken.None);
|
||||
|
||||
var featureFlagWrapper = Mock.Of<IFeatureFlagWrapper>();
|
||||
Mock.Get(featureFlagWrapper)
|
||||
.Setup(f => f.IsCiBenchmarkingEnabled(It.IsAny<bool>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
var service = new ExplorationService(
|
||||
jazzFactory,
|
||||
_snowflakeDatabaseContextMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
featureFlagWrapper,
|
||||
_strataSphereCompareServiceMock.Object,
|
||||
_explorationFilterServiceMock.Object,
|
||||
_explorationServiceLoggerMock.Object);
|
||||
|
||||
// Act
|
||||
var summaries = await service.GetCaseTypeFamilySummariesAsync(_explorationInfo, CancellationToken.None);
|
||||
var summary = summaries.Single(s => s.Name == CaseTypeFamilyName);
|
||||
|
||||
// Assert
|
||||
Assert.That(summary.Data.PeerMedianCost, Is.EqualTo(250.75d));
|
||||
Assert.That(summary.Data.PeerMedianALos, Is.EqualTo(5.2d));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetCaseTypeFamilySummariesAsync_FeatureFlagOff_DefaultPeerMetrics()
|
||||
{
|
||||
// Arrange
|
||||
var jazzFactory = new JazzEntityFrameworkFactory();
|
||||
await jazzFactory.CreateDbContextAsync(CancellationToken.None);
|
||||
|
||||
var featureFlagWrapper = Mock.Of<IFeatureFlagWrapper>();
|
||||
Mock.Get(featureFlagWrapper)
|
||||
.Setup(f => f.IsCiBenchmarkingEnabled(It.IsAny<bool>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
var service = new ExplorationService(
|
||||
jazzFactory,
|
||||
_snowflakeDatabaseContextMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
featureFlagWrapper,
|
||||
_strataSphereCompareServiceMock.Object,
|
||||
_explorationFilterServiceMock.Object,
|
||||
_explorationServiceLoggerMock.Object);
|
||||
|
||||
// Act
|
||||
var summaries = await service.GetCaseTypeFamilySummariesAsync(_explorationInfo, CancellationToken.None);
|
||||
var summary = summaries.Single(s => s.Name == CaseTypeFamilyName);
|
||||
|
||||
// Assert
|
||||
Assert.That(summary.Data.PeerMedianCost, Is.EqualTo(0d));
|
||||
Assert.That(summary.Data.PeerMedianALos, Is.EqualTo(0d));
|
||||
}
|
||||
|
||||
[Test, Ignore("Feature flag is not enabled, this might need additional refactoring")]
|
||||
public async Task GetCaseTypeFamilySummaryDetailsAsync_FeatureFlagOn_PopulatesPeerMetrics()
|
||||
{
|
||||
// Arrange
|
||||
var jazzFactory = new JazzEntityFrameworkFactory();
|
||||
await jazzFactory.CreateDbContextAsync(CancellationToken.None);
|
||||
|
||||
var featureFlagWrapper = Mock.Of<IFeatureFlagWrapper>();
|
||||
Mock.Get(featureFlagWrapper)
|
||||
.Setup(f => f.IsCiBenchmarkingEnabled(It.IsAny<bool>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
var service = new ExplorationService(
|
||||
jazzFactory,
|
||||
_snowflakeDatabaseContextMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
featureFlagWrapper,
|
||||
_strataSphereCompareServiceMock.Object,
|
||||
_explorationFilterServiceMock.Object,
|
||||
_explorationServiceLoggerMock.Object);
|
||||
|
||||
// Act
|
||||
var summaries = await service.GetCaseTypeFamilySummaryDetailsAsync(_explorationInfo, CancellationToken.None);
|
||||
var summary = summaries.Single();
|
||||
|
||||
// Assert
|
||||
Assert.That(summary, Is.Not.Null);
|
||||
Assert.That(summary.Name, Is.EqualTo(CaseTypeFamilyName));
|
||||
Assert.That(summary.Children, Is.Not.Null.And.Not.Empty);
|
||||
|
||||
var losChild = summary.Children.FirstOrDefault(c => c.Name == "LOS");
|
||||
if (losChild != null)
|
||||
{
|
||||
Assert.That(losChild.Data.PeerMedianCost, Is.EqualTo(150.50d));
|
||||
}
|
||||
|
||||
var surgeryChild = summary.Children.FirstOrDefault(c => c.Name == "Surgery");
|
||||
if (surgeryChild != null)
|
||||
{
|
||||
Assert.That(surgeryChild.Data.PeerMedianCost, Is.EqualTo(300.25d));
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetCaseTypeFamilySummaryDetailsAsync_FeatureFlagOff_DefaultPeerMetrics()
|
||||
{
|
||||
// Arrange
|
||||
var jazzFactory = new JazzEntityFrameworkFactory();
|
||||
await jazzFactory.CreateDbContextAsync(CancellationToken.None);
|
||||
|
||||
var featureFlagWrapper = Mock.Of<IFeatureFlagWrapper>();
|
||||
Mock.Get(featureFlagWrapper)
|
||||
.Setup(f => f.IsCiBenchmarkingEnabled(It.IsAny<bool>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
var service = new ExplorationService(
|
||||
jazzFactory,
|
||||
_snowflakeDatabaseContextMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
featureFlagWrapper,
|
||||
_strataSphereCompareServiceMock.Object,
|
||||
_explorationFilterServiceMock.Object,
|
||||
_explorationServiceLoggerMock.Object);
|
||||
|
||||
// Act
|
||||
var summaries = await service.GetCaseTypeFamilySummaryDetailsAsync(_explorationInfo as ExplorationCostDriverInfo, CancellationToken.None);
|
||||
var summary = summaries.Single();
|
||||
|
||||
// Assert
|
||||
Assert.That(summary, Is.Not.Null);
|
||||
Assert.That(summary.Name, Is.EqualTo(CaseTypeFamilyName));
|
||||
if (summary.Children != null && summary.Children.Any())
|
||||
{
|
||||
foreach (var child in summary.Children)
|
||||
{
|
||||
Assert.That(child.Data.PeerMedianCost, Is.EqualTo(0d));
|
||||
Assert.That(child.Data.PeerMedianALos, Is.EqualTo(0d));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+316
@@ -0,0 +1,316 @@
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using MoreLinq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.Configuration;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts.Snowflake;
|
||||
using Strata.ContinuousImprovement.Biz.Exploration;
|
||||
using Strata.ContinuousImprovement.Biz.Exploration.CaseTypeFamilies;
|
||||
using Strata.ContinuousImprovement.Biz.Exploration.Filters;
|
||||
using Strata.ContinuousImprovement.Biz.FiscalMonths;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.ContinuousImprovement.Biz.Utilities;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.SqlTools.Configuration.Common.AsyncFactory;
|
||||
using Strata.StrataSphereCompare.Client;
|
||||
using Strata.StrataSphereCompare.Client.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
using VerifyTests;
|
||||
using static Strata.ContinuousImprovement.Biz.Exploration.ExplorationService;
|
||||
using ExplorationFilter = Strata.ContinuousImprovement.Biz.Exploration.Filters.Filter;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Exploration
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class ExplorationServiceTest
|
||||
{
|
||||
private const string SourceFilePath = @"Exploration/source/";
|
||||
|
||||
public IAsyncDbContextFactory<JazzDbContext> DbContextFactory { get; set; }
|
||||
public JazzEntityFrameworkFactory JAZZ_Framework { get; set; }
|
||||
public JazzDbContext JazzDbContext { get; set; }
|
||||
public ISqlGridReaderWrapper SqlGridReader { get; set; }
|
||||
public ISnowflakeDatabaseContext SnowflakeDatabaseContext { get; set; }
|
||||
public IConfigurationService ConfigurationService { get; set; }
|
||||
public IFiscalMonthResolver FiscalMonthResolver { get; set; }
|
||||
public ILogger<ExplorationService> Logger { get; set; }
|
||||
public VerifySettings VerifySettings { get; set; }
|
||||
public IFeatureFlagWrapper FeatureFlagWrapper { get; set; }
|
||||
public IStrataSphereCompareService StrataSphereCompareService { get; set; }
|
||||
public IExplorationFilterService ExplorationFilterService { get; set; }
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void ExplorationServiceTestOneTimeSetUp()
|
||||
{
|
||||
DbContextFactory = Mock.Of<IAsyncDbContextFactory<JazzDbContext>>();
|
||||
JAZZ_Framework = new JazzEntityFrameworkFactory();
|
||||
|
||||
Mock.Get(DbContextFactory)
|
||||
.Setup(s => s.CreateDbContextAsync(It.IsAny<CancellationToken>()))
|
||||
.Returns(async () =>
|
||||
{
|
||||
JazzDbContext = await JAZZ_Framework.CreateDbContextAsync(CancellationToken.None);
|
||||
return JazzDbContext;
|
||||
});
|
||||
|
||||
SqlGridReader = Mock.Of<ISqlGridReaderWrapper>();
|
||||
Mock.Get(SqlGridReader)
|
||||
.Setup(s => s.Read(It.IsAny<bool>()))
|
||||
.Returns(Enumerable.Empty<dynamic>());
|
||||
SnowflakeDatabaseContext = Mock.Of<ISnowflakeDatabaseContext>();
|
||||
Mock.Get(SnowflakeDatabaseContext)
|
||||
.Setup(s => s.QueryMultipleAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<object>(), It.IsAny<TimeSpan>()))
|
||||
.Returns(Task.FromResult(SqlGridReader));
|
||||
|
||||
ConfigurationService = Mock.Of<IConfigurationService>();
|
||||
FiscalMonthResolver = Mock.Of<IFiscalMonthResolver>();
|
||||
Logger = Mock.Of<ILogger<ExplorationService>>();
|
||||
VerifySettings = TestExtensions.TestSettings();
|
||||
FeatureFlagWrapper = Mock.Of<IFeatureFlagWrapper>();
|
||||
StrataSphereCompareService = Mock.Of<IStrataSphereCompareService>();
|
||||
ExplorationFilterService = Mock.Of<IExplorationFilterService>();
|
||||
|
||||
// Setup the mock to return empty results
|
||||
Mock.Get(ExplorationFilterService)
|
||||
.Setup(s => s.GetFilterStringsAsync(It.IsAny<IEnumerable<FilterChipItem>>(), It.IsAny<IQueryParamBase>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(("", ""));
|
||||
Mock.Get(ExplorationFilterService)
|
||||
.Setup(s => s.BuildDataFiltersAsync(It.IsAny<CaseTypeFamily>(), It.IsAny<string>(), It.IsAny<ExplorationFilter>(), It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new CostDetailsFilterDto());
|
||||
Mock.Get(ExplorationFilterService)
|
||||
.Setup(s => s.CreateCostDriverFilter())
|
||||
.Returns(new FilterChipItem());
|
||||
Mock.Get(FeatureFlagWrapper)
|
||||
.Setup(f => f.IsCiBenchmarkingEnabled(It.IsAny<bool>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetCaseTypeFamilyDetailsTestCases))]
|
||||
public async Task GetCaseTypeFamilyDetailsTest(GetCaseTypeFamilyDetailsTestData data)
|
||||
{
|
||||
// arrange
|
||||
Mock.Get(SqlGridReader)
|
||||
.Setup(s => s.Read<CTFGroupCalcs>(It.IsAny<bool>()))
|
||||
.Returns(data.CTFGroupCalcsList);
|
||||
Mock.Get(SqlGridReader)
|
||||
.Setup(s => s.Read<EntityGroupCalcs>(It.IsAny<bool>()))
|
||||
.Returns(data.EntityGroupCalcsList);
|
||||
Mock.Get(SqlGridReader)
|
||||
.Setup(s => s.Read<EntityCodeGroupCalcs>(It.IsAny<bool>()))
|
||||
.Returns(data.EntityCodeGroupCalcsList);
|
||||
Mock.Get(SqlGridReader)
|
||||
.Setup(s => s.Read<EntityCodePhysicianGroupCalcs>(It.IsAny<bool>()))
|
||||
.Returns(data.EntityCodePhysicianGroupCalcsList);
|
||||
Mock.Get(SqlGridReader)
|
||||
.Setup(s => s.Read<CTFEncounterDetail>(It.IsAny<bool>()))
|
||||
.Returns(data.CTFEncounterDetailList);
|
||||
|
||||
var explorationService = new ExplorationService(
|
||||
DbContextFactory,
|
||||
SnowflakeDatabaseContext,
|
||||
FiscalMonthResolver,
|
||||
FeatureFlagWrapper,
|
||||
StrataSphereCompareService,
|
||||
ExplorationFilterService,
|
||||
Logger);
|
||||
|
||||
// act
|
||||
var taskResult = await explorationService.GetCaseTypeFamilyDetailsAsync(data.ExplorationDetailInfoData, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
await Verifier.Verify(taskResult, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetEncountersTestCases))]
|
||||
public async Task GetEncountersTest(GetEncountersTestData data)
|
||||
{
|
||||
// arrange
|
||||
Mock.Get(SqlGridReader)
|
||||
.Setup(s => s.Read<PhysicianInfo>(It.IsAny<bool>()))
|
||||
.Returns(data.PhysicianInfoList);
|
||||
Mock.Get(SqlGridReader)
|
||||
.Setup(s => s.Read<EncounterInfoBase>(It.IsAny<bool>()))
|
||||
.Returns(data.EncounterInfoBaseList);
|
||||
var configurationGuid = Guid.Empty;
|
||||
|
||||
var explorationService = new ExplorationService(
|
||||
DbContextFactory,
|
||||
SnowflakeDatabaseContext,
|
||||
FiscalMonthResolver,
|
||||
FeatureFlagWrapper,
|
||||
StrataSphereCompareService,
|
||||
ExplorationFilterService,
|
||||
Logger);
|
||||
|
||||
// act
|
||||
var taskResult = await explorationService.GetEncountersAsync(data.ExplorationDetailInfoData, configurationGuid, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
await Verifier.Verify(taskResult, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
private static IEnumerable<TestCaseData> GetCaseTypeFamilyDetailsTestCases()
|
||||
{
|
||||
var testName = "GetCaseTypeFamilyDetailsTest";
|
||||
|
||||
var explorationDetailInfoDataJson = GetSourceFile("ExplorationDetailInfo.txt");
|
||||
var ctfGroupCalcsListJson = GetSourceFile("CTFGroupCalcs.txt");
|
||||
var entityGroupCalcsListJson = GetSourceFile("EntityGroupCalcs.txt");
|
||||
var entityCodeGroupCalcsListJson = GetSourceFile("EntityCodeGroupCalcs.txt");
|
||||
var entityCodePhysicianGroupCalcsListJson = GetSourceFile("EntityCodePhysicianGroupCalcs.txt");
|
||||
var ctfEncounterDetailListJson = GetSourceFile("CTFEncounterDetail.txt");
|
||||
|
||||
var dataAllMatch = new GetCaseTypeFamilyDetailsTestData()
|
||||
{
|
||||
ExplorationDetailInfoData = JsonSerializer.Deserialize<ExplorationDetailInfo>(explorationDetailInfoDataJson),
|
||||
CTFGroupCalcsList = JsonSerializer.Deserialize<IEnumerable<CTFGroupCalcs>>(ctfGroupCalcsListJson),
|
||||
EntityGroupCalcsList = JsonSerializer.Deserialize<IEnumerable<EntityGroupCalcs>>(entityGroupCalcsListJson),
|
||||
EntityCodeGroupCalcsList = JsonSerializer.Deserialize<IEnumerable<EntityCodeGroupCalcs>>(entityCodeGroupCalcsListJson),
|
||||
EntityCodePhysicianGroupCalcsList = JsonSerializer.Deserialize<IEnumerable<EntityCodePhysicianGroupCalcs>>(entityCodePhysicianGroupCalcsListJson),
|
||||
CTFEncounterDetailList = JsonSerializer.Deserialize<IEnumerable<CTFEncounterDetail>>(ctfEncounterDetailListJson)
|
||||
};
|
||||
dataAllMatch.ExplorationDetailInfoData.Filters = new ExplorationFilter() // FIXED: Changed from Biz.Exploration.Filters.Filter to ExplorationFilter
|
||||
{
|
||||
FilterChipItems = new List<FilterChipItem>()
|
||||
{
|
||||
new FilterChipItem {
|
||||
ChipType = ChipType.DateRange, Key = ChipKey.DischargeDateID,
|
||||
DateRange = new List<DateTime>()
|
||||
{
|
||||
new DateTime(2024, 1, 1),
|
||||
new DateTime(2024, 12, 31)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
yield return new TestCaseData(dataAllMatch)
|
||||
.SetName($"{testName} All Match");
|
||||
|
||||
var dataPhysicianIdNotMatch = new GetCaseTypeFamilyDetailsTestData()
|
||||
{
|
||||
ExplorationDetailInfoData = dataAllMatch.ExplorationDetailInfoData,
|
||||
CTFGroupCalcsList = dataAllMatch.CTFGroupCalcsList,
|
||||
EntityGroupCalcsList = dataAllMatch.EntityGroupCalcsList,
|
||||
EntityCodeGroupCalcsList = dataAllMatch.EntityCodeGroupCalcsList,
|
||||
EntityCodePhysicianGroupCalcsList = JsonSerializer.Deserialize<IEnumerable<EntityCodePhysicianGroupCalcs>>(entityCodePhysicianGroupCalcsListJson),
|
||||
CTFEncounterDetailList = dataAllMatch.CTFEncounterDetailList
|
||||
};
|
||||
dataPhysicianIdNotMatch.EntityCodePhysicianGroupCalcsList.First().PhysicianId = 0;
|
||||
yield return new TestCaseData(dataPhysicianIdNotMatch)
|
||||
.SetName($"{testName} PhysicianId Not Match");
|
||||
|
||||
var dataCodeNotMatch = new GetCaseTypeFamilyDetailsTestData()
|
||||
{
|
||||
ExplorationDetailInfoData = dataAllMatch.ExplorationDetailInfoData,
|
||||
CTFGroupCalcsList = dataAllMatch.CTFGroupCalcsList,
|
||||
EntityGroupCalcsList = dataAllMatch.EntityGroupCalcsList,
|
||||
EntityCodeGroupCalcsList = JsonSerializer.Deserialize<IEnumerable<EntityCodeGroupCalcs>>(entityCodeGroupCalcsListJson),
|
||||
EntityCodePhysicianGroupCalcsList = dataAllMatch.EntityCodePhysicianGroupCalcsList,
|
||||
CTFEncounterDetailList = dataAllMatch.CTFEncounterDetailList
|
||||
};
|
||||
dataCodeNotMatch.EntityCodeGroupCalcsList.First().Code = "";
|
||||
yield return new TestCaseData(dataCodeNotMatch)
|
||||
.SetName($"{testName} Code Not Match");
|
||||
|
||||
var dataEntityNotMatch = new GetCaseTypeFamilyDetailsTestData()
|
||||
{
|
||||
ExplorationDetailInfoData = dataAllMatch.ExplorationDetailInfoData,
|
||||
CTFGroupCalcsList = dataAllMatch.CTFGroupCalcsList,
|
||||
EntityGroupCalcsList = JsonSerializer.Deserialize<IEnumerable<EntityGroupCalcs>>(entityGroupCalcsListJson),
|
||||
EntityCodeGroupCalcsList = dataAllMatch.EntityCodeGroupCalcsList,
|
||||
EntityCodePhysicianGroupCalcsList = dataAllMatch.EntityCodePhysicianGroupCalcsList,
|
||||
CTFEncounterDetailList = dataAllMatch.CTFEncounterDetailList
|
||||
};
|
||||
dataEntityNotMatch.EntityGroupCalcsList.First().EntityId = 0;
|
||||
yield return new TestCaseData(dataEntityNotMatch)
|
||||
.SetName($"{testName} Entity Not Match");
|
||||
}
|
||||
|
||||
private static IEnumerable<TestCaseData> GetEncountersTestCases()
|
||||
{
|
||||
var testName = "GetEncountersTest";
|
||||
|
||||
var explorationDetailInfoDataJson = GetSourceFile("ExplorationDetailInfo.txt");
|
||||
var physicianInfoJson = GetSourceFile("PhysicianInfo.txt");
|
||||
var encounterInfoBaseJson = GetSourceFile("EncounterInfoBase.txt");
|
||||
|
||||
var dataAllMatch = new GetEncountersTestData()
|
||||
{
|
||||
ExplorationDetailInfoData = JsonSerializer.Deserialize<ExplorationDetailInfo>(explorationDetailInfoDataJson),
|
||||
PhysicianInfoList = JsonSerializer.Deserialize<IEnumerable<PhysicianInfo>>(physicianInfoJson),
|
||||
EncounterInfoBaseList = JsonSerializer.Deserialize<IEnumerable<EncounterInfoBase>>(encounterInfoBaseJson)
|
||||
};
|
||||
|
||||
dataAllMatch.ExplorationDetailInfoData.Filters = new ExplorationFilter() // FIXED: Changed from Biz.Exploration.Filters.Filter to ExplorationFilter
|
||||
{
|
||||
FilterChipItems = new List<FilterChipItem>()
|
||||
{
|
||||
new FilterChipItem {
|
||||
ChipType = ChipType.DateRange, Key = ChipKey.DischargeDateID,
|
||||
DateRange = new List<DateTime>()
|
||||
{
|
||||
new DateTime(2024, 1, 1),
|
||||
new DateTime(2024, 12, 31)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
yield return new TestCaseData(dataAllMatch)
|
||||
.SetName($"{testName} All Match");
|
||||
|
||||
var dataPhysicianIdNotMatch = new GetEncountersTestData()
|
||||
{
|
||||
ExplorationDetailInfoData = dataAllMatch.ExplorationDetailInfoData,
|
||||
PhysicianInfoList = JsonSerializer.Deserialize<IEnumerable<PhysicianInfo>>(physicianInfoJson),
|
||||
EncounterInfoBaseList = dataAllMatch.EncounterInfoBaseList,
|
||||
};
|
||||
dataPhysicianIdNotMatch.PhysicianInfoList.First().PhysicianID = 0;
|
||||
yield return new TestCaseData(dataPhysicianIdNotMatch)
|
||||
.SetName($"{testName} PhysicianId Not Match");
|
||||
}
|
||||
|
||||
private static string GetSourceFile(string file)
|
||||
{
|
||||
string filePath = Path.Combine(TestHelper.TestsRootDirectory, SourceFilePath, file);
|
||||
string jsonData = File.ReadAllText(filePath);
|
||||
return jsonData;
|
||||
}
|
||||
|
||||
public class GetCaseTypeFamilySummariesTestData
|
||||
{
|
||||
public ExplorationInfo ExplorationInfoData { get; set; }
|
||||
public IEnumerable<CaseTypeFamilyEncounterInfo> CaseTypeFamilyEncounterInfoList { get; set; }
|
||||
|
||||
}
|
||||
|
||||
public class GetCaseTypeFamilyDetailsTestData
|
||||
{
|
||||
public ExplorationDetailInfo ExplorationDetailInfoData { get; set; }
|
||||
public IEnumerable<CTFGroupCalcs> CTFGroupCalcsList { get; set; }
|
||||
public IEnumerable<EntityGroupCalcs> EntityGroupCalcsList { get; set; }
|
||||
public IEnumerable<EntityCodeGroupCalcs> EntityCodeGroupCalcsList { get; set; }
|
||||
public IEnumerable<EntityCodePhysicianGroupCalcs> EntityCodePhysicianGroupCalcsList { get; set; }
|
||||
public IEnumerable<CTFEncounterDetail> CTFEncounterDetailList { get; set; }
|
||||
}
|
||||
|
||||
public class GetEncountersTestData
|
||||
{
|
||||
public ExplorationDetailInfo ExplorationDetailInfoData { get; set; }
|
||||
public IEnumerable<PhysicianInfo> PhysicianInfoList { get; set; }
|
||||
public IEnumerable<EncounterInfoBase> EncounterInfoBaseList { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
[
|
||||
{
|
||||
"EncounterId": 24375411,
|
||||
"EncounterRecordNumber": "1024375411",
|
||||
"CTFType": 0,
|
||||
"EntityId": 93,
|
||||
"Code": "880",
|
||||
"PhysicianId": 3339,
|
||||
"LengthOfStay": 5,
|
||||
"VariableDirectCost": 208.1365,
|
||||
"IdentifiedVariation": 148.89435,
|
||||
"Charges": 4045.0814,
|
||||
"IsExpired": 0,
|
||||
"IsExcluded": false,
|
||||
"DischargeStatusCode": "06",
|
||||
"DischargeStatusDescription": "Discharged/transferred to home under care of an organized home health service organization in anticipation of covered skilled care"
|
||||
},
|
||||
{
|
||||
"EncounterId": 26713064,
|
||||
"EncounterRecordNumber": "1026713064",
|
||||
"CTFType": 0,
|
||||
"EntityId": 93,
|
||||
"Code": "880",
|
||||
"PhysicianId": 3474,
|
||||
"LengthOfStay": 3,
|
||||
"VariableDirectCost": 71.8018,
|
||||
"IdentifiedVariation": 12.559649999999998,
|
||||
"Charges": 985.8658,
|
||||
"IsExpired": 0,
|
||||
"IsExcluded": false,
|
||||
"DischargeStatusCode": "01",
|
||||
"DischargeStatusDescription": "Discharged to home or self care (routine discharge)"
|
||||
},
|
||||
{
|
||||
"EncounterId": 27090900,
|
||||
"EncounterRecordNumber": "1027090900",
|
||||
"CTFType": 0,
|
||||
"EntityId": 93,
|
||||
"Code": "880",
|
||||
"PhysicianId": 794,
|
||||
"LengthOfStay": 15,
|
||||
"VariableDirectCost": 5.0037,
|
||||
"IdentifiedVariation": -54.23845,
|
||||
"Charges": 384.65,
|
||||
"IsExpired": 0,
|
||||
"IsExcluded": true,
|
||||
"DischargeStatusCode": "03",
|
||||
"DischargeStatusDescription": "Discharged/transferred to Skilled Nursing Facility (SNF) with Medicare certification"
|
||||
},
|
||||
{
|
||||
"EncounterId": 28432227,
|
||||
"EncounterRecordNumber": "1028432227",
|
||||
"CTFType": 0,
|
||||
"EntityId": 93,
|
||||
"Code": "880",
|
||||
"PhysicianId": 3896,
|
||||
"LengthOfStay": 7,
|
||||
"VariableDirectCost": 46.6825,
|
||||
"IdentifiedVariation": -12.559650000000005,
|
||||
"Charges": 996.8704,
|
||||
"IsExpired": 0,
|
||||
"IsExcluded": true,
|
||||
"DischargeStatusCode": "03",
|
||||
"DischargeStatusDescription": "Discharged/transferred to Skilled Nursing Facility (SNF) with Medicare certification"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,7 @@
|
||||
[
|
||||
{
|
||||
"CTFId": 206,
|
||||
"CTFName": "Acute Adjustment Reaction And Psychosocial Dysfunction",
|
||||
"MedianVDC": 59.24215
|
||||
}
|
||||
]
|
||||
+596
@@ -0,0 +1,596 @@
|
||||
[
|
||||
{
|
||||
"CaseTypeFamilyId": 6654,
|
||||
"CaseTypeFamilyName": "Endoscopy Procedures on the Mediastinum",
|
||||
"Vdc": 2038.5242,
|
||||
"MedianVdc": 1931.0259,
|
||||
"TwentyFivePercentileVdc": 1877.27675,
|
||||
"SeventyFivePercentileVdc": 1984.77505,
|
||||
"TwentyFivePercentileLos": 0,
|
||||
"SeventyFivePercentileLos": 0,
|
||||
"CostDriver": "Laboratory",
|
||||
"EncounterId": 2562780,
|
||||
"DischargeDateTime": "2023-01-17T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": 270.5061,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 0,
|
||||
"MedianLengthOfStay": 0,
|
||||
"MedianVariableDirectCost": 283.5443,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 554.0504,
|
||||
"Charges": 11265.2698,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 0,
|
||||
"IqrVdc": 107.4983,
|
||||
"MadLos": 0,
|
||||
"MadVdc": 159.37698,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 6654,
|
||||
"CaseTypeFamilyName": "Endoscopy Procedures on the Mediastinum",
|
||||
"Vdc": 2038.5242,
|
||||
"MedianVdc": 1931.0259,
|
||||
"TwentyFivePercentileVdc": 1877.27675,
|
||||
"SeventyFivePercentileVdc": 1984.77505,
|
||||
"TwentyFivePercentileLos": 0,
|
||||
"SeventyFivePercentileLos": 0,
|
||||
"CostDriver": "Excluded",
|
||||
"EncounterId": 2562780,
|
||||
"DischargeDateTime": "2023-01-17T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": 0,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 0,
|
||||
"MedianLengthOfStay": 0,
|
||||
"MedianVariableDirectCost": 0.2644,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 0.2644,
|
||||
"Charges": 49.0752,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 0,
|
||||
"IqrVdc": 107.4983,
|
||||
"MadLos": 0,
|
||||
"MadVdc": 159.37698,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 6654,
|
||||
"CaseTypeFamilyName": "Endoscopy Procedures on the Mediastinum",
|
||||
"Vdc": 2038.5242,
|
||||
"MedianVdc": 1931.0259,
|
||||
"TwentyFivePercentileVdc": 1877.27675,
|
||||
"SeventyFivePercentileVdc": 1984.77505,
|
||||
"TwentyFivePercentileLos": 0,
|
||||
"SeventyFivePercentileLos": 0,
|
||||
"CostDriver": "OR Time",
|
||||
"EncounterId": 2562780,
|
||||
"DischargeDateTime": "2023-01-17T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": -15.31945,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 0,
|
||||
"MedianLengthOfStay": 0,
|
||||
"MedianVariableDirectCost": 1066.93575,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 1051.6163,
|
||||
"Charges": 17348.9676,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 0,
|
||||
"IqrVdc": 107.4983,
|
||||
"MadLos": 0,
|
||||
"MadVdc": 159.37698,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 6654,
|
||||
"CaseTypeFamilyName": "Endoscopy Procedures on the Mediastinum",
|
||||
"Vdc": 2038.5242,
|
||||
"MedianVdc": 1931.0259,
|
||||
"TwentyFivePercentileVdc": 1877.27675,
|
||||
"SeventyFivePercentileVdc": 1984.77505,
|
||||
"TwentyFivePercentileLos": 0,
|
||||
"SeventyFivePercentileLos": 0,
|
||||
"CostDriver": "Supplies",
|
||||
"EncounterId": 2562780,
|
||||
"DischargeDateTime": "2023-01-17T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": -74.0283,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 0,
|
||||
"MedianLengthOfStay": 0,
|
||||
"MedianVariableDirectCost": 275.0648,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 201.0365,
|
||||
"Charges": 908.8934,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 0,
|
||||
"IqrVdc": 107.4983,
|
||||
"MadLos": 0,
|
||||
"MadVdc": 159.37698,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 6654,
|
||||
"CaseTypeFamilyName": "Endoscopy Procedures on the Mediastinum",
|
||||
"Vdc": 2038.5242,
|
||||
"MedianVdc": 1931.0259,
|
||||
"TwentyFivePercentileVdc": 1877.27675,
|
||||
"SeventyFivePercentileVdc": 1984.77505,
|
||||
"TwentyFivePercentileLos": 0,
|
||||
"SeventyFivePercentileLos": 0,
|
||||
"CostDriver": "Pharmacy",
|
||||
"EncounterId": 2562780,
|
||||
"DischargeDateTime": "2023-01-17T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": -15.66025,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 0,
|
||||
"MedianLengthOfStay": 0,
|
||||
"MedianVariableDirectCost": 120.94545,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 105.2852,
|
||||
"Charges": 1801.1414,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 0,
|
||||
"IqrVdc": 107.4983,
|
||||
"MadLos": 0,
|
||||
"MadVdc": 159.37698,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 6654,
|
||||
"CaseTypeFamilyName": "Endoscopy Procedures on the Mediastinum",
|
||||
"Vdc": 2038.5242,
|
||||
"MedianVdc": 1931.0259,
|
||||
"TwentyFivePercentileVdc": 1877.27675,
|
||||
"SeventyFivePercentileVdc": 1984.77505,
|
||||
"TwentyFivePercentileLos": 0,
|
||||
"SeventyFivePercentileLos": 0,
|
||||
"CostDriver": "",
|
||||
"EncounterId": 2562780,
|
||||
"DischargeDateTime": "2023-01-17T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": 0,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 0,
|
||||
"MedianLengthOfStay": 0,
|
||||
"MedianVariableDirectCost": 0,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 0,
|
||||
"Charges": 0,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 0,
|
||||
"IqrVdc": 107.4983,
|
||||
"MadLos": 0,
|
||||
"MadVdc": 159.37698,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 6654,
|
||||
"CaseTypeFamilyName": "Endoscopy Procedures on the Mediastinum",
|
||||
"Vdc": 2038.5242,
|
||||
"MedianVdc": 1931.0259,
|
||||
"TwentyFivePercentileVdc": 1877.27675,
|
||||
"SeventyFivePercentileVdc": 1984.77505,
|
||||
"TwentyFivePercentileLos": 0,
|
||||
"SeventyFivePercentileLos": 0,
|
||||
"CostDriver": "Cardiovascular",
|
||||
"EncounterId": 2562780,
|
||||
"DischargeDateTime": "2023-01-17T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": 0,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 0,
|
||||
"MedianLengthOfStay": 0,
|
||||
"MedianVariableDirectCost": 5.0037,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 5.0037,
|
||||
"Charges": 393.3321,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 0,
|
||||
"IqrVdc": 107.4983,
|
||||
"MadLos": 0,
|
||||
"MadVdc": 159.37698,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 6654,
|
||||
"CaseTypeFamilyName": "Endoscopy Procedures on the Mediastinum",
|
||||
"Vdc": 2038.5242,
|
||||
"MedianVdc": 1931.0259,
|
||||
"TwentyFivePercentileVdc": 1877.27675,
|
||||
"SeventyFivePercentileVdc": 1984.77505,
|
||||
"TwentyFivePercentileLos": 0,
|
||||
"SeventyFivePercentileLos": 0,
|
||||
"CostDriver": "Therapeutic Services",
|
||||
"EncounterId": 2562780,
|
||||
"DischargeDateTime": "2023-01-17T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": -60.63385,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 0,
|
||||
"MedianLengthOfStay": 0,
|
||||
"MedianVariableDirectCost": 181.90155,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 121.2677,
|
||||
"Charges": 320.4913,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 0,
|
||||
"IqrVdc": 107.4983,
|
||||
"MadLos": 0,
|
||||
"MadVdc": 159.37698,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 592,
|
||||
"CaseTypeFamilyName": "Skin Debridement",
|
||||
"Vdc": 4353.6024,
|
||||
"MedianVdc": 4353.6024,
|
||||
"TwentyFivePercentileVdc": 2983.74705,
|
||||
"SeventyFivePercentileVdc": 4525.49485,
|
||||
"TwentyFivePercentileLos": 4.5,
|
||||
"SeventyFivePercentileLos": 9.5,
|
||||
"CostDriver": "Pharmacy",
|
||||
"EncounterId": 2565425,
|
||||
"DischargeDateTime": "2023-02-02T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": 0,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 12,
|
||||
"MedianLengthOfStay": 7,
|
||||
"MedianVariableDirectCost": 373.0302,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 373.0302,
|
||||
"Charges": 11782.8149,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 5,
|
||||
"IqrVdc": 1541.7478,
|
||||
"MadLos": 7.413,
|
||||
"MadVdc": 509.6955,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 592,
|
||||
"CaseTypeFamilyName": "Skin Debridement",
|
||||
"Vdc": 4353.6024,
|
||||
"MedianVdc": 4353.6024,
|
||||
"TwentyFivePercentileVdc": 2983.74705,
|
||||
"SeventyFivePercentileVdc": 4525.49485,
|
||||
"TwentyFivePercentileLos": 4.5,
|
||||
"SeventyFivePercentileLos": 9.5,
|
||||
"CostDriver": "Supplies",
|
||||
"EncounterId": 2565425,
|
||||
"DischargeDateTime": "2023-02-02T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": -19.7357,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 12,
|
||||
"MedianLengthOfStay": 7,
|
||||
"MedianVariableDirectCost": 87.3104,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 67.5747,
|
||||
"Charges": 254.2575,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 5,
|
||||
"IqrVdc": 1541.7478,
|
||||
"MadLos": 7.413,
|
||||
"MadVdc": 509.6955,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 592,
|
||||
"CaseTypeFamilyName": "Skin Debridement",
|
||||
"Vdc": 4353.6024,
|
||||
"MedianVdc": 4353.6024,
|
||||
"TwentyFivePercentileVdc": 2983.74705,
|
||||
"SeventyFivePercentileVdc": 4525.49485,
|
||||
"TwentyFivePercentileLos": 4.5,
|
||||
"SeventyFivePercentileLos": 9.5,
|
||||
"CostDriver": "OR Time",
|
||||
"EncounterId": 2565425,
|
||||
"DischargeDateTime": "2023-02-02T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": 0,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 12,
|
||||
"MedianLengthOfStay": 7,
|
||||
"MedianVariableDirectCost": 680.5711,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 680.5711,
|
||||
"Charges": 12771.463,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 5,
|
||||
"IqrVdc": 1541.7478,
|
||||
"MadLos": 7.413,
|
||||
"MadVdc": 509.6955,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 592,
|
||||
"CaseTypeFamilyName": "Skin Debridement",
|
||||
"Vdc": 4353.6024,
|
||||
"MedianVdc": 4353.6024,
|
||||
"TwentyFivePercentileVdc": 2983.74705,
|
||||
"SeventyFivePercentileVdc": 4525.49485,
|
||||
"TwentyFivePercentileLos": 4.5,
|
||||
"SeventyFivePercentileLos": 9.5,
|
||||
"CostDriver": "LOS",
|
||||
"EncounterId": 2565425,
|
||||
"DischargeDateTime": "2023-02-02T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": 357.1267,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 12,
|
||||
"MedianLengthOfStay": 7,
|
||||
"MedianVariableDirectCost": 1747.5269,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 2104.6536,
|
||||
"Charges": 29186.0674,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 5,
|
||||
"IqrVdc": 1541.7478,
|
||||
"MadLos": 7.413,
|
||||
"MadVdc": 509.6955,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 592,
|
||||
"CaseTypeFamilyName": "Skin Debridement",
|
||||
"Vdc": 4353.6024,
|
||||
"MedianVdc": 4353.6024,
|
||||
"TwentyFivePercentileVdc": 2983.74705,
|
||||
"SeventyFivePercentileVdc": 4525.49485,
|
||||
"TwentyFivePercentileLos": 4.5,
|
||||
"SeventyFivePercentileLos": 9.5,
|
||||
"CostDriver": "Other Diagnostic Services",
|
||||
"EncounterId": 2565425,
|
||||
"DischargeDateTime": "2023-02-02T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": 37.18375,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 12,
|
||||
"MedianLengthOfStay": 7,
|
||||
"MedianVariableDirectCost": 113.54845,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 150.7322,
|
||||
"Charges": 3224.1159,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 5,
|
||||
"IqrVdc": 1541.7478,
|
||||
"MadLos": 7.413,
|
||||
"MadVdc": 509.6955,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 592,
|
||||
"CaseTypeFamilyName": "Skin Debridement",
|
||||
"Vdc": 4353.6024,
|
||||
"MedianVdc": 4353.6024,
|
||||
"TwentyFivePercentileVdc": 2983.74705,
|
||||
"SeventyFivePercentileVdc": 4525.49485,
|
||||
"TwentyFivePercentileLos": 4.5,
|
||||
"SeventyFivePercentileLos": 9.5,
|
||||
"CostDriver": "",
|
||||
"EncounterId": 2565425,
|
||||
"DischargeDateTime": "2023-02-02T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": 0,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 12,
|
||||
"MedianLengthOfStay": 7,
|
||||
"MedianVariableDirectCost": 0,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 0,
|
||||
"Charges": 0,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 5,
|
||||
"IqrVdc": 1541.7478,
|
||||
"MadLos": 7.413,
|
||||
"MadVdc": 509.6955,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 592,
|
||||
"CaseTypeFamilyName": "Skin Debridement",
|
||||
"Vdc": 4353.6024,
|
||||
"MedianVdc": 4353.6024,
|
||||
"TwentyFivePercentileVdc": 2983.74705,
|
||||
"SeventyFivePercentileVdc": 4525.49485,
|
||||
"TwentyFivePercentileLos": 4.5,
|
||||
"SeventyFivePercentileLos": 9.5,
|
||||
"CostDriver": "Laboratory",
|
||||
"EncounterId": 2565425,
|
||||
"DischargeDateTime": "2023-02-02T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": 0,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 12,
|
||||
"MedianLengthOfStay": 7,
|
||||
"MedianVariableDirectCost": 123.2207,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 123.2207,
|
||||
"Charges": 5503.8051,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 5,
|
||||
"IqrVdc": 1541.7478,
|
||||
"MadLos": 7.413,
|
||||
"MadVdc": 509.6955,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 592,
|
||||
"CaseTypeFamilyName": "Skin Debridement",
|
||||
"Vdc": 4353.6024,
|
||||
"MedianVdc": 4353.6024,
|
||||
"TwentyFivePercentileVdc": 2983.74705,
|
||||
"SeventyFivePercentileVdc": 4525.49485,
|
||||
"TwentyFivePercentileLos": 4.5,
|
||||
"SeventyFivePercentileLos": 9.5,
|
||||
"CostDriver": "Therapeutic Services",
|
||||
"EncounterId": 2565425,
|
||||
"DischargeDateTime": "2023-02-02T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": 245.3111,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 12,
|
||||
"MedianLengthOfStay": 7,
|
||||
"MedianVariableDirectCost": 473.0037,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 718.3148,
|
||||
"Charges": 7026.8907,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 5,
|
||||
"IqrVdc": 1541.7478,
|
||||
"MadLos": 7.413,
|
||||
"MadVdc": 509.6955,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 592,
|
||||
"CaseTypeFamilyName": "Skin Debridement",
|
||||
"Vdc": 4353.6024,
|
||||
"MedianVdc": 4353.6024,
|
||||
"TwentyFivePercentileVdc": 2983.74705,
|
||||
"SeventyFivePercentileVdc": 4525.49485,
|
||||
"TwentyFivePercentileLos": 4.5,
|
||||
"SeventyFivePercentileLos": 9.5,
|
||||
"CostDriver": "Imaging",
|
||||
"EncounterId": 2565425,
|
||||
"DischargeDateTime": "2023-02-02T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": 0,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 12,
|
||||
"MedianLengthOfStay": 7,
|
||||
"MedianVariableDirectCost": 37.5413,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 37.5413,
|
||||
"Charges": 690.5777,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 5,
|
||||
"IqrVdc": 1541.7478,
|
||||
"MadLos": 7.413,
|
||||
"MadVdc": 509.6955,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
},
|
||||
{
|
||||
"CaseTypeFamilyId": 592,
|
||||
"CaseTypeFamilyName": "Skin Debridement",
|
||||
"Vdc": 4353.6024,
|
||||
"MedianVdc": 4353.6024,
|
||||
"TwentyFivePercentileVdc": 2983.74705,
|
||||
"SeventyFivePercentileVdc": 4525.49485,
|
||||
"TwentyFivePercentileLos": 4.5,
|
||||
"SeventyFivePercentileLos": 9.5,
|
||||
"CostDriver": "Excluded",
|
||||
"EncounterId": 2565425,
|
||||
"DischargeDateTime": "2023-02-02T00:00:00Z",
|
||||
"EncounterRecordNumber": null,
|
||||
"EntityId": 0,
|
||||
"IdentifiedVariation": -49.1141,
|
||||
"IsExpired": 0,
|
||||
"LengthOfStay": 12,
|
||||
"MedianLengthOfStay": 7,
|
||||
"MedianVariableDirectCost": 147.0779,
|
||||
"MedianGrossCharges": 0,
|
||||
"VariableDirectCost": 97.9638,
|
||||
"Charges": 1718.5171,
|
||||
"IsExcluded": false,
|
||||
"IqrLos": 5,
|
||||
"IqrVdc": 1541.7478,
|
||||
"MadLos": 7.413,
|
||||
"MadVdc": 509.6955,
|
||||
"DischargeStatusCode": null,
|
||||
"DischargeStatusDescription": null,
|
||||
"MortalityRate": 0,
|
||||
"ROM": 0,
|
||||
"SOI": 0
|
||||
}
|
||||
]
|
||||
+170
@@ -0,0 +1,170 @@
|
||||
[
|
||||
{
|
||||
"EncounterId": 3490618,
|
||||
"EncounterRecordNumber": "1003490618",
|
||||
"PhysicianID": 3845,
|
||||
"AgeCohortID": 3,
|
||||
"EntityID": 2,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 15,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-02-18T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
},
|
||||
{
|
||||
"EncounterId": 21268418,
|
||||
"EncounterRecordNumber": "1021268418",
|
||||
"PhysicianID": 3939,
|
||||
"AgeCohortID": 4,
|
||||
"EntityID": 2,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 2,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-04-07T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
},
|
||||
{
|
||||
"EncounterId": 21269053,
|
||||
"EncounterRecordNumber": "1021269053",
|
||||
"PhysicianID": 2986,
|
||||
"AgeCohortID": 3,
|
||||
"EntityID": 2,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 14,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-01-28T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
},
|
||||
{
|
||||
"EncounterId": 21366384,
|
||||
"EncounterRecordNumber": "1021366384",
|
||||
"PhysicianID": 1370,
|
||||
"AgeCohortID": 4,
|
||||
"EntityID": 2,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 12,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-03-01T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
},
|
||||
{
|
||||
"EncounterId": 21549774,
|
||||
"EncounterRecordNumber": "1021549774",
|
||||
"PhysicianID": 3153,
|
||||
"AgeCohortID": 3,
|
||||
"EntityID": 13,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 1,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-02-15T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
},
|
||||
{
|
||||
"EncounterId": 22931559,
|
||||
"EncounterRecordNumber": "1022931559",
|
||||
"PhysicianID": 4446,
|
||||
"AgeCohortID": 4,
|
||||
"EntityID": 2,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 11,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-05-21T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
},
|
||||
{
|
||||
"EncounterId": 23497650,
|
||||
"EncounterRecordNumber": "1023497650",
|
||||
"PhysicianID": 842,
|
||||
"AgeCohortID": 4,
|
||||
"EntityID": 2,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 8,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-05-14T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
},
|
||||
{
|
||||
"EncounterId": 24240851,
|
||||
"EncounterRecordNumber": "1024240851",
|
||||
"PhysicianID": 720,
|
||||
"AgeCohortID": 3,
|
||||
"EntityID": 2,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 3,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-06-24T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
},
|
||||
{
|
||||
"EncounterId": 25272685,
|
||||
"EncounterRecordNumber": "1025272685",
|
||||
"PhysicianID": 3481,
|
||||
"AgeCohortID": 4,
|
||||
"EntityID": 2,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 3,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-07-13T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
},
|
||||
{
|
||||
"EncounterId": 25954564,
|
||||
"EncounterRecordNumber": "1025954564",
|
||||
"PhysicianID": 842,
|
||||
"AgeCohortID": 3,
|
||||
"EntityID": 2,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 2,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-08-04T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
},
|
||||
{
|
||||
"EncounterId": 25971328,
|
||||
"EncounterRecordNumber": "1025971328",
|
||||
"PhysicianID": 3343,
|
||||
"AgeCohortID": 3,
|
||||
"EntityID": 2,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 2,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-07-25T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
},
|
||||
{
|
||||
"EncounterId": 27006329,
|
||||
"EncounterRecordNumber": "1027006329",
|
||||
"PhysicianID": 4269,
|
||||
"AgeCohortID": 3,
|
||||
"EntityID": 2,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 2,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-10-01T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
},
|
||||
{
|
||||
"EncounterId": 29625457,
|
||||
"EncounterRecordNumber": "1029625457",
|
||||
"PhysicianID": 842,
|
||||
"AgeCohortID": 4,
|
||||
"EntityID": 2,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 9,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-11-24T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
},
|
||||
{
|
||||
"EncounterId": 30059663,
|
||||
"EncounterRecordNumber": "1030059663",
|
||||
"PhysicianID": 24764,
|
||||
"AgeCohortID": 4,
|
||||
"EntityID": 13,
|
||||
"ServiceLineID": 13,
|
||||
"LengthOfStay": 6,
|
||||
"IsQVIEncounter": false,
|
||||
"DischargeDateTime": "2023-11-19T00:00:00Z",
|
||||
"IsExcluded": false
|
||||
}
|
||||
]
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
[
|
||||
{
|
||||
"EntityId": 93,
|
||||
"Code": "880",
|
||||
"CodeName": "880 - ACUTE ADJUSTMENT REACTION AND PSYCHOSOCIAL DYSFUNCTION",
|
||||
"MedianVDC": 59.24215,
|
||||
"MedianLOS": 6,
|
||||
"MedianCharges": 991.3681,
|
||||
"Id": "880",
|
||||
"Name": "880 - ACUTE ADJUSTMENT REACTION AND PSYCHOSOCIAL DYSFUNCTION"
|
||||
}
|
||||
]
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
[
|
||||
{
|
||||
"EntityId": 93,
|
||||
"Code": "880",
|
||||
"PhysicianId": 3474,
|
||||
"PhysicianName": "KLAPPERICH CORDELL",
|
||||
"MedianVDC": 71.8018,
|
||||
"MedianLOS": 3,
|
||||
"MedianCharges": 985.8658,
|
||||
"Id": "3474",
|
||||
"Name": "KLAPPERICH CORDELL"
|
||||
},
|
||||
{
|
||||
"EntityId": 93,
|
||||
"Code": "880",
|
||||
"PhysicianId": 3896,
|
||||
"PhysicianName": "HARTSE FRANKIE",
|
||||
"MedianVDC": 46.6825,
|
||||
"MedianLOS": 7,
|
||||
"MedianCharges": 996.8704,
|
||||
"Id": "3896",
|
||||
"Name": "HARTSE FRANKIE"
|
||||
},
|
||||
{
|
||||
"EntityId": 93,
|
||||
"Code": "880",
|
||||
"PhysicianId": 794,
|
||||
"PhysicianName": "DIAZDELEON HIPOLITO",
|
||||
"MedianVDC": 5.0037,
|
||||
"MedianLOS": 15,
|
||||
"MedianCharges": 384.65,
|
||||
"Id": "794",
|
||||
"Name": "DIAZDELEON HIPOLITO"
|
||||
},
|
||||
{
|
||||
"EntityId": 93,
|
||||
"Code": "880",
|
||||
"PhysicianId": 3339,
|
||||
"PhysicianName": "HATZENBUHLER SCOTTY",
|
||||
"MedianVDC": 208.1365,
|
||||
"MedianLOS": 5,
|
||||
"MedianCharges": 4045.0814,
|
||||
"Id": "3339",
|
||||
"Name": "HATZENBUHLER SCOTTY"
|
||||
}
|
||||
]
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
[
|
||||
{
|
||||
"EntityId": 93,
|
||||
"EntityName": "10 - Northern Valley Medical Center",
|
||||
"MedianVDC": 59.24215,
|
||||
"MedianLOS": 6,
|
||||
"MedianCharges": 991.3681,
|
||||
"Id": "93",
|
||||
"Name": "10 - Northern Valley Medical Center"
|
||||
}
|
||||
]
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"CaseTypeFamilyId": 206,
|
||||
"CostDriver": "Cardiovascular",
|
||||
"CodeType": null,
|
||||
"ExcludedEncounters": [],
|
||||
"IncludedEncounters": [],
|
||||
"ConfigurationGuid": "aa4cba4f-2506-462c-8e34-c45b21653988",
|
||||
"ExclusionCriteria": {
|
||||
"LosExclusionType": 0,
|
||||
"LosExclusionValue": 0,
|
||||
"CostExclusionType": 0,
|
||||
"CostExclusionValue": 0
|
||||
},
|
||||
"Filters": {
|
||||
"DischargeDateStart": "2023-01-01T00:00:00",
|
||||
"DischargeDateEnd": "2023-12-31T00:00:00",
|
||||
"FilterChipItems": []
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"ConfigurationGuid": "aa4cba4f-2506-462c-8e34-c45b21653988",
|
||||
"ExclusionCriteria": {
|
||||
"LosExclusionType": 0,
|
||||
"LosExclusionValue": 0,
|
||||
"CostExclusionType": 0,
|
||||
"CostExclusionValue": 0
|
||||
},
|
||||
"Filters": {
|
||||
"DischargeDateStart": "2023-01-01T00:00:00",
|
||||
"DischargeDateEnd": "2023-12-31T00:00:00",
|
||||
"FilterChipItems": []
|
||||
}
|
||||
}
|
||||
+134
@@ -0,0 +1,134 @@
|
||||
[
|
||||
{
|
||||
"PhysicianID": 3153,
|
||||
"PhysicianName": "TOZIER BOBBY",
|
||||
"PhysicianGUID": "d3d281ce-c255-45f0-8334-88e15ffe48cd",
|
||||
"PhysicianGroupAffiliationID": 0,
|
||||
"PhysicianGroupAffiliation": "Not Specified",
|
||||
"PhysicianGroupAffiliationGUID": "1c3af86f-a7b7-4484-935c-bad5b93627e7",
|
||||
"PhysicianSpecialtyID": 208,
|
||||
"PhysicianSpecialty": "123 - Hospitalist",
|
||||
"PhysicianSpecialtyGUID": "3a3e27d9-3454-4fc3-83a9-e86b6fe3bd61"
|
||||
},
|
||||
{
|
||||
"PhysicianID": 3845,
|
||||
"PhysicianName": "KEITHLEY CHRISTOPHER",
|
||||
"PhysicianGUID": "9dc822af-5b79-4063-b75a-72cc4cca6040",
|
||||
"PhysicianGroupAffiliationID": 0,
|
||||
"PhysicianGroupAffiliation": "Not Specified",
|
||||
"PhysicianGroupAffiliationGUID": "1c3af86f-a7b7-4484-935c-bad5b93627e7",
|
||||
"PhysicianSpecialtyID": 208,
|
||||
"PhysicianSpecialty": "123 - Hospitalist",
|
||||
"PhysicianSpecialtyGUID": "3a3e27d9-3454-4fc3-83a9-e86b6fe3bd61"
|
||||
},
|
||||
{
|
||||
"PhysicianID": 1370,
|
||||
"PhysicianName": "BONELLO HUONG",
|
||||
"PhysicianGUID": "1fbc3e74-e32e-4a31-a55a-2ba2a581bf68",
|
||||
"PhysicianGroupAffiliationID": 0,
|
||||
"PhysicianGroupAffiliation": "Not Specified",
|
||||
"PhysicianGroupAffiliationGUID": "1c3af86f-a7b7-4484-935c-bad5b93627e7",
|
||||
"PhysicianSpecialtyID": 221,
|
||||
"PhysicianSpecialty": "17 - Internal Medicine",
|
||||
"PhysicianSpecialtyGUID": "02db369d-885a-474a-acaf-81363e490534"
|
||||
},
|
||||
{
|
||||
"PhysicianID": 24764,
|
||||
"PhysicianName": "FLUETSCH CARY",
|
||||
"PhysicianGUID": "723d834b-d4da-4885-9efb-4c9de59cb982",
|
||||
"PhysicianGroupAffiliationID": 0,
|
||||
"PhysicianGroupAffiliation": "Not Specified",
|
||||
"PhysicianGroupAffiliationGUID": "1c3af86f-a7b7-4484-935c-bad5b93627e7",
|
||||
"PhysicianSpecialtyID": 221,
|
||||
"PhysicianSpecialty": "17 - Internal Medicine",
|
||||
"PhysicianSpecialtyGUID": "02db369d-885a-474a-acaf-81363e490534"
|
||||
},
|
||||
{
|
||||
"PhysicianID": 4446,
|
||||
"PhysicianName": "DEMAS CHARLEY",
|
||||
"PhysicianGUID": "acefb0de-25b1-4cda-9eae-2b5799155816",
|
||||
"PhysicianGroupAffiliationID": 0,
|
||||
"PhysicianGroupAffiliation": "Not Specified",
|
||||
"PhysicianGroupAffiliationGUID": "1c3af86f-a7b7-4484-935c-bad5b93627e7",
|
||||
"PhysicianSpecialtyID": 271,
|
||||
"PhysicianSpecialty": "62 - Critical Care Medicine",
|
||||
"PhysicianSpecialtyGUID": "32c0a064-a015-472a-b1a1-3ee9ada450f2"
|
||||
},
|
||||
{
|
||||
"PhysicianID": 3343,
|
||||
"PhysicianName": "BLINKA GRAIG",
|
||||
"PhysicianGUID": "a96d6d2c-029f-4689-8f31-51870150ac1c",
|
||||
"PhysicianGroupAffiliationID": 0,
|
||||
"PhysicianGroupAffiliation": "Not Specified",
|
||||
"PhysicianGroupAffiliationGUID": "1c3af86f-a7b7-4484-935c-bad5b93627e7",
|
||||
"PhysicianSpecialtyID": 208,
|
||||
"PhysicianSpecialty": "123 - Hospitalist",
|
||||
"PhysicianSpecialtyGUID": "3a3e27d9-3454-4fc3-83a9-e86b6fe3bd61"
|
||||
},
|
||||
{
|
||||
"PhysicianID": 720,
|
||||
"PhysicianName": "TOMASSI RUSS",
|
||||
"PhysicianGUID": "3802cc8a-5ad5-48e0-864e-9acfe0e4d324",
|
||||
"PhysicianGroupAffiliationID": 0,
|
||||
"PhysicianGroupAffiliation": "Not Specified",
|
||||
"PhysicianGroupAffiliationGUID": "1c3af86f-a7b7-4484-935c-bad5b93627e7",
|
||||
"PhysicianSpecialtyID": 221,
|
||||
"PhysicianSpecialty": "17 - Internal Medicine",
|
||||
"PhysicianSpecialtyGUID": "02db369d-885a-474a-acaf-81363e490534"
|
||||
},
|
||||
{
|
||||
"PhysicianID": 3481,
|
||||
"PhysicianName": "TREVIZO DIRK",
|
||||
"PhysicianGUID": "55639862-736c-4e9b-afcc-16673445c181",
|
||||
"PhysicianGroupAffiliationID": 0,
|
||||
"PhysicianGroupAffiliation": "Not Specified",
|
||||
"PhysicianGroupAffiliationGUID": "1c3af86f-a7b7-4484-935c-bad5b93627e7",
|
||||
"PhysicianSpecialtyID": 221,
|
||||
"PhysicianSpecialty": "17 - Internal Medicine",
|
||||
"PhysicianSpecialtyGUID": "02db369d-885a-474a-acaf-81363e490534"
|
||||
},
|
||||
{
|
||||
"PhysicianID": 2986,
|
||||
"PhysicianName": "COAXUM RUDY",
|
||||
"PhysicianGUID": "3cd87422-3164-4c2c-9f42-dafa6c927353",
|
||||
"PhysicianGroupAffiliationID": 0,
|
||||
"PhysicianGroupAffiliation": "Not Specified",
|
||||
"PhysicianGroupAffiliationGUID": "1c3af86f-a7b7-4484-935c-bad5b93627e7",
|
||||
"PhysicianSpecialtyID": 221,
|
||||
"PhysicianSpecialty": "17 - Internal Medicine",
|
||||
"PhysicianSpecialtyGUID": "02db369d-885a-474a-acaf-81363e490534"
|
||||
},
|
||||
{
|
||||
"PhysicianID": 842,
|
||||
"PhysicianName": "CLENDENON RENDA",
|
||||
"PhysicianGUID": "edb778e5-c677-4800-a1bc-153331e52f48",
|
||||
"PhysicianGroupAffiliationID": 0,
|
||||
"PhysicianGroupAffiliation": "Not Specified",
|
||||
"PhysicianGroupAffiliationGUID": "1c3af86f-a7b7-4484-935c-bad5b93627e7",
|
||||
"PhysicianSpecialtyID": 221,
|
||||
"PhysicianSpecialty": "17 - Internal Medicine",
|
||||
"PhysicianSpecialtyGUID": "02db369d-885a-474a-acaf-81363e490534"
|
||||
},
|
||||
{
|
||||
"PhysicianID": 4269,
|
||||
"PhysicianName": "CROUTHAMEL SUNNY",
|
||||
"PhysicianGUID": "5c889c75-adab-4c08-9ccb-347ce13b9e70",
|
||||
"PhysicianGroupAffiliationID": 0,
|
||||
"PhysicianGroupAffiliation": "Not Specified",
|
||||
"PhysicianGroupAffiliationGUID": "1c3af86f-a7b7-4484-935c-bad5b93627e7",
|
||||
"PhysicianSpecialtyID": 221,
|
||||
"PhysicianSpecialty": "17 - Internal Medicine",
|
||||
"PhysicianSpecialtyGUID": "02db369d-885a-474a-acaf-81363e490534"
|
||||
},
|
||||
{
|
||||
"PhysicianID": 3939,
|
||||
"PhysicianName": "LANMAN JOVAN",
|
||||
"PhysicianGUID": "5b68c9cf-beaa-4267-9bc7-05cddba3de4c",
|
||||
"PhysicianGroupAffiliationID": 0,
|
||||
"PhysicianGroupAffiliation": "Not Specified",
|
||||
"PhysicianGroupAffiliationGUID": "1c3af86f-a7b7-4484-935c-bad5b93627e7",
|
||||
"PhysicianSpecialtyID": 221,
|
||||
"PhysicianSpecialty": "17 - Internal Medicine",
|
||||
"PhysicianSpecialtyGUID": "02db369d-885a-474a-acaf-81363e490534"
|
||||
}
|
||||
]
|
||||
+612
@@ -0,0 +1,612 @@
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.Authorization;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.FiscalMonths;
|
||||
using Strata.ContinuousImprovement.Biz.FreeForm.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.FreeForm.Opportunities.Filters;
|
||||
using Strata.ContinuousImprovement.Biz.Generics;
|
||||
using Strata.ContinuousImprovement.Biz.Initiatives;
|
||||
using Strata.ContinuousImprovement.Biz.Pagination;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.Hangfire.Jazz.Client;
|
||||
using Strata.Hangfire.Jazz.Client.Models;
|
||||
using Strata.SqlTools.Configuration.Common.AsyncFactory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
using VerifyTests;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.FreeForm.Opportunities
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture, Category("Unit")]
|
||||
public class FFOpportunityServiceTests
|
||||
{
|
||||
|
||||
private Mock<IFFOpportunityService> _freeformOpportunityServiceMock;
|
||||
private Mock<IAsyncDbContextFactory<JazzDbContext>> _dbContextFactoryMock;
|
||||
private Mock<IJazzDbContext> _jazzDbContextMock;
|
||||
private Mock<IJazzHangfireServiceClient> _hangfireServiceMock;
|
||||
private Mock<IAuthorizationServiceClient> _authorizationServiceMock;
|
||||
private Mock<IFiscalMonthResolver> _fiscalMonthResolverMock;
|
||||
private IInitiativeService _initiativeService;
|
||||
private IUpdateFactOpportunitySavingsService _updateFactOpportunitySavingsService;
|
||||
private VerifySettings _verifySettings;
|
||||
|
||||
private static readonly ResourceFileExtractor _extractor = new ResourceFileExtractor(".Resource.");
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
_freeformOpportunityServiceMock = new Mock<IFFOpportunityService>();
|
||||
_dbContextFactoryMock = new Mock<IAsyncDbContextFactory<JazzDbContext>>();
|
||||
_jazzDbContextMock = new Mock<IJazzDbContext>();
|
||||
_hangfireServiceMock = new Mock<IJazzHangfireServiceClient>();
|
||||
_fiscalMonthResolverMock = new Mock<IFiscalMonthResolver>();
|
||||
_updateFactOpportunitySavingsService = Mock.Of<IUpdateFactOpportunitySavingsService>();
|
||||
_initiativeService = Mock.Of<IInitiativeService>();
|
||||
Mock.Get(_updateFactOpportunitySavingsService)
|
||||
.Setup(s => s.UpdateFactOpportunitySavings(It.IsAny<CancellationToken>()));
|
||||
Mock.Get(_initiativeService)
|
||||
.Setup(s => s.DeleteAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(true));
|
||||
_authorizationServiceMock = new Mock<IAuthorizationServiceClient>();
|
||||
_authorizationServiceMock
|
||||
.Setup(o => o.AddPermissionsFromDefaultsAsync(It.IsAny<Guid>(), It.IsAny<SecurableEntityType>(), It.IsAny<CancellationToken>()));
|
||||
_verifySettings = new VerifySettings();
|
||||
_verifySettings.UseDirectory("snapshots");
|
||||
_verifySettings.AddNamedGuid(JazzEntityFrameworkFactory.CurrentConfigurationGuid, "ConfigurationGuid");
|
||||
_verifySettings.ScrubInlineGuids();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Asc()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var freeformOpportunityService = new FFOpportunityService(framework, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
var filters = new FFFilters()
|
||||
{
|
||||
FinancialImprovementTypes = new List<string>(),
|
||||
MetricTypes = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
|
||||
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions("IdentifiedSavings", SortOrder.Asc);
|
||||
|
||||
// act
|
||||
var taskResult = await freeformOpportunityService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
await Verifier.Verify(taskResult, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Desc()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var freeformOpportunityService = new FFOpportunityService(framework, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
var filters = new FFFilters()
|
||||
{
|
||||
FinancialImprovementTypes = new List<string>(),
|
||||
MetricTypes = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
|
||||
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions("IdentifiedSavings", SortOrder.Desc);
|
||||
|
||||
// act
|
||||
var taskResult = await freeformOpportunityService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
await Verifier.Verify(taskResult, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFilterData))]
|
||||
public async Task TestValidateFilters(FFFilters filters)
|
||||
{
|
||||
if (filters == null) return;
|
||||
await Verifier.Verify(filters, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(TestGetExcelWorkbookNullFilterCases))]
|
||||
public async Task TestGetExcelWorkbook(FFFilters filters)
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
//var opp = framework.FFOpportunities.First();
|
||||
var service = new FFOpportunityService(framework, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
|
||||
// act
|
||||
var wb = await service.ExportAsync(new SortOptions(), filters, CancellationToken.None);
|
||||
#pragma warning disable S125 // Sections of code should not be commented out
|
||||
//wb.SaveAs(System.IO.Path.Combine(@"C:\Git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "ExcelFilter.xlsx"));
|
||||
#pragma warning restore S125 // Sections of code should not be commented out
|
||||
|
||||
// assert
|
||||
try
|
||||
{
|
||||
await Verifier.Verify(wb.GetDataTables(), _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.Write("Verifier.VerifyFile failed. Using back up verification method");
|
||||
wb.Worksheets.Should().HaveCount(1);
|
||||
var ws = wb.Worksheet(1);
|
||||
ws.Should().NotBeNull();
|
||||
|
||||
var expected = filters == null
|
||||
? @"Examples.FreeFormOpportunity.ExcelNullFilter.xlsx"
|
||||
: @"Examples.FreeFormOpportunity.ExcelFilter.xlsx";
|
||||
using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected))
|
||||
using (var actualStream = new MemoryStream())
|
||||
{
|
||||
wb.SaveAs(actualStream);
|
||||
actualStream.Compare(expectedStream, out var message).Should().BeTrue(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> TestGetExcelWorkbookNullFilterCases()
|
||||
{
|
||||
yield return new TestCaseData(new FFFilters()
|
||||
{
|
||||
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid,
|
||||
FinancialImprovementTypes = new[] { ((int)FinancialImprovementType.Revenue).ToString() },
|
||||
MetricTypes = new[] { ((int)MetricType.FinancialPerUnit).ToString() },
|
||||
}).SetName("{m} Filtered");
|
||||
yield return new TestCaseData(null).SetName("{m} Null Filters");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSetHidden()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunities = framework.FFOpportunities;
|
||||
var opportunity = opportunities.First(vo => !vo.IsHidden);
|
||||
var isHidden = opportunity.IsHidden;
|
||||
var service = new FFOpportunityService(framework, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
|
||||
// act
|
||||
await service.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
await Verifier.Verify(result, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
result.IsHidden.Should().Be(!isHidden);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetFilterOptionsAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunityService = new FFOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
var configurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid;
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var task = await opportunityService
|
||||
.GetFilterOptionsAsync(configurationGuid, cancellationToken);
|
||||
|
||||
// assert
|
||||
await Verifier.Verify(task, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
catch (OperationCanceledException e)
|
||||
{
|
||||
await Verifier.Verify(e, _verifySettings)
|
||||
.ScrubMember("StackTrace")
|
||||
.UseFileName($"{TestContext.CurrentContext.TestName()} {e.GetType().Name}");
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var freeformOpportunityService = new FFOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
try
|
||||
{
|
||||
var opportunities = freeformOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;
|
||||
|
||||
//act
|
||||
await freeformOpportunityService.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden,
|
||||
|
||||
cancellationToken);
|
||||
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return;
|
||||
|
||||
var result = freeformOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result;
|
||||
await Verifier.Verify(result.IsHidden, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
catch (AggregateException e)
|
||||
{
|
||||
await Verifier.Verify(e.InnerException, _verifySettings)
|
||||
.ScrubMember("StackTrace")
|
||||
.UseFileName($"{TestContext.CurrentContext.TestName()} {e.InnerException.GetType().Name}");
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.FFOpportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;
|
||||
var freeformOpportunityService = new FFOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await freeformOpportunityService.SetHiddenAsync(Guid.Empty, !isHidden,
|
||||
cancellationToken);
|
||||
}
|
||||
catch (OperationCanceledException e)
|
||||
{
|
||||
await Verifier.Verify(e, _verifySettings)
|
||||
.ScrubMember("StackTrace")
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var freeformOpportunityService = new FFOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
try
|
||||
{
|
||||
var opportunities = freeformOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
|
||||
if (opportunity == null) return;
|
||||
|
||||
var note = "new test note";
|
||||
// act
|
||||
await freeformOpportunityService.SetNoteAsync(opportunity.OpportunityGuid, note, CancellationToken.None);
|
||||
if (cancellationToken.IsCancellationRequested || jazzEntityFrameworkFactory.JazzDbContext == null)
|
||||
{
|
||||
var result = async () => await freeformOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken);
|
||||
|
||||
// assert
|
||||
await Verifier.ThrowsTask(result, _verifySettings)
|
||||
.ScrubMember("StackTrace")
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await freeformOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken);
|
||||
|
||||
// assert
|
||||
await Verifier.Verify(result.Note, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
}
|
||||
catch (AggregateException e)
|
||||
{
|
||||
await Verifier.Verify(e.InnerException, _verifySettings)
|
||||
.ScrubMember("StackTrace")
|
||||
.UseFileName($"{TestContext.CurrentContext.TestName()} {e.InnerException.GetType().Name}");
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSetNote()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunities = framework.UVOpportunities;
|
||||
var opportunity = opportunities.First(vo => string.IsNullOrEmpty(vo.Note));
|
||||
var note = opportunity.Note;
|
||||
var expected = "Now is the time for all good engineers to write great code!";
|
||||
var service = new FFOpportunityService(framework, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
|
||||
// act
|
||||
await service.SetNoteAsync(opportunity.OpportunityGuid, expected, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
await Verifier.Verify(result.Note, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
result.Note.Should().NotBeNullOrEmpty()
|
||||
.And.NotBe(note)
|
||||
.And.Be(expected);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.FFOpportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
if (opportunity == null) return;
|
||||
var note = "new test note";
|
||||
var freeformOpportunityService = new FFOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await freeformOpportunityService.SetNoteAsync(Guid.Empty, note, cancellationToken);
|
||||
|
||||
// assert
|
||||
}
|
||||
catch (OperationCanceledException e)
|
||||
{
|
||||
await Verifier.Verify(e, _verifySettings)
|
||||
.ScrubMember("StackTrace")
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetAllAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var freeformOpportunityService = new FFOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
|
||||
// act
|
||||
var taskResult = await freeformOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
await Verifier.Verify(taskResult, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetById(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var freeformOpportunityService = new FFOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
|
||||
// act
|
||||
var tempResult = await freeformOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var taskResult =
|
||||
await freeformOpportunityService.GetById(tempResult.FirstOrDefault()?.OpportunityGuid ?? Guid.Empty, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
await Verifier.Verify(taskResult, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<FFOpportunity>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetByIds(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var freeformOpportunityService = new FFOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
|
||||
// act
|
||||
var tempResult = await freeformOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var ids = tempResult.Select(o => o.OpportunityGuid);
|
||||
var taskResult = await freeformOpportunityService.GetByIds(ids, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
await Verifier.Verify(taskResult, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<FFOpportunity>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestCreateFreeFormOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var freeformOpportunityService = new FFOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
|
||||
var authorGuid = Guid.NewGuid();
|
||||
var configurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345");
|
||||
var newOpportunity = new FFOpportunityDataModel()
|
||||
{
|
||||
AuthorName = "TestAuthor",
|
||||
AuthorGuid = authorGuid,
|
||||
ConfigurationGuid = configurationGuid,
|
||||
Denominator = "Patient Days",
|
||||
Numerator = "Imaging Procedure",
|
||||
FinancialImprovementType = FinancialImprovementType.Cost,
|
||||
MetricType = MetricType.Financial,
|
||||
Name = "Test"
|
||||
};
|
||||
|
||||
_hangfireServiceMock.Setup(x => x.EnqueueJobAsync(It.IsAny<EnqueueJobDto>(), It.IsAny<CancellationToken>())).ReturnsAsync(new JobEnqueuedResponse() { JobId = Guid.Parse("d47bea06-37bb-440e-82d9-cec74e523e01") });
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var result = await freeformOpportunityService.CreateAsync(newOpportunity, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
await Verifier.Verify(result, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
catch (NullReferenceException e)
|
||||
{
|
||||
await Verifier.Verify(e, _verifySettings)
|
||||
.ScrubMember("StackTrace")
|
||||
.UseFileName($"{TestContext.CurrentContext.TestName()} {e.GetType().Name}");
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestCreateFreeFormOpportunityPreventsDuplicateNames(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var freeformOpportunityService = new FFOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object,
|
||||
_fiscalMonthResolverMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_authorizationServiceMock.Object);
|
||||
|
||||
var newOpportunity = new FFOpportunityDataModel()
|
||||
{
|
||||
Name = "Free Form Opportunity 1",
|
||||
AuthorName = "TestAuthor",
|
||||
AuthorGuid = Guid.NewGuid(),
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"),
|
||||
FinancialImprovementType = FinancialImprovementType.Cost,
|
||||
MetricType = MetricType.Financial,
|
||||
};
|
||||
|
||||
_hangfireServiceMock.Setup(x => x.EnqueueJobAsync(It.IsAny<EnqueueJobDto>(), It.IsAny<CancellationToken>())).ReturnsAsync(new JobEnqueuedResponse() { JobId = Guid.Parse("d47bea06-37bb-440e-82d9-cec74e523e01") });
|
||||
|
||||
if (!TestContext.CurrentContext.Test.Name.Contains("With Framework"))
|
||||
{
|
||||
// act
|
||||
var result = async () => await freeformOpportunityService.CreateAsync(newOpportunity, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
await Verifier.ThrowsTask(result, _verifySettings)
|
||||
.ScrubMember("StackTrace")
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// act
|
||||
var result = await freeformOpportunityService.CreateAsync(newOpportunity, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
await Verifier.Verify(result, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
|
||||
#region TestCaseData
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFilterData()
|
||||
{
|
||||
yield return new TestCaseData(new FFFilters { ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("{m} No Filters");
|
||||
yield return new TestCaseData(new FFFilters { ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("{m} View Visible");
|
||||
yield return new TestCaseData(new FFFilters { ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("{m} Not View Visible");
|
||||
yield return new TestCaseData(new FFFilters { IdentifiedSavings = 1999, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("{m} By Identified Savings");
|
||||
yield return new TestCaseData(new FFFilters { IdentifiedSavings = 999, ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("{m} By Identified Savings Not ViewVisible");
|
||||
yield return new TestCaseData(new FFFilters { FinancialImprovementTypes = new[] { "1" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("{m} By FinancialImprovementType");
|
||||
yield return new TestCaseData(new FFFilters { FinancialImprovementTypes = new[] { "2" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), ViewVisible = false })
|
||||
.SetName("{m} By FinancialImprovementType Not ViewVisible");
|
||||
yield return new TestCaseData(new FFFilters { MetricTypes = new[] { "1" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("{m} By MetricType");
|
||||
yield return new TestCaseData(new FFFilters { MetricTypes = new[] { "2" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), ViewVisible = false })
|
||||
.SetName("{m} By MetricType Not ViewVisible");
|
||||
yield return new TestCaseData(new FFFilters { OpportunitySearch = "QV - 123", ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("{m} Search By Id");
|
||||
yield return new TestCaseData(new FFFilters { ExcludeInitiatives = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("{m} Exclude Opportunities with Initiatives");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+506
@@ -0,0 +1,506 @@
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.Authorization;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.Filter;
|
||||
using Strata.ContinuousImprovement.Biz.GeneralLedger.Details;
|
||||
using Strata.ContinuousImprovement.Biz.GeneralLedger.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.GeneralLedger.Opportunities.Filters;
|
||||
using Strata.ContinuousImprovement.Biz.Generics;
|
||||
using Strata.ContinuousImprovement.Biz.Initiatives;
|
||||
using Strata.ContinuousImprovement.Biz.Pagination;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.Hangfire.Jazz.Client;
|
||||
using Strata.SqlTools.Configuration.Common.AsyncFactory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.GeneralLedger.Opportunities
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class GLOpportunityServiceTests
|
||||
{
|
||||
|
||||
private Mock<IGLDetailService> _glOpportunityServiceMock;
|
||||
private Mock<IAsyncDbContextFactory<JazzDbContext>> _dbContextFactoryMock;
|
||||
private Mock<IJazzDbContext> _jazzDbContextMock;
|
||||
private Mock<IJazzHangfireServiceClient> _hangfireServiceMock;
|
||||
private Mock<IAuthorizationServiceClient> _authorizationServiceMock;
|
||||
private IUpdateFactOpportunitySavingsService _updateFactOpportunitySavingsService;
|
||||
private IInitiativeService _initiativeService;
|
||||
|
||||
private static readonly ResourceFileExtractor _extractor = new ResourceFileExtractor(".Resource.");
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
_glOpportunityServiceMock = new Mock<IGLDetailService>();
|
||||
_dbContextFactoryMock = new Mock<IAsyncDbContextFactory<JazzDbContext>>();
|
||||
_jazzDbContextMock = new Mock<IJazzDbContext>();
|
||||
_hangfireServiceMock = new Mock<IJazzHangfireServiceClient>();
|
||||
_updateFactOpportunitySavingsService = Mock.Of<IUpdateFactOpportunitySavingsService>();
|
||||
_initiativeService = Mock.Of<IInitiativeService>();
|
||||
Mock.Get(_updateFactOpportunitySavingsService)
|
||||
.Setup(s => s.UpdateFactOpportunitySavings(It.IsAny<CancellationToken>()));
|
||||
Mock.Get(_initiativeService)
|
||||
.Setup(s => s.DeleteAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(true));
|
||||
_authorizationServiceMock = new Mock<IAuthorizationServiceClient>();
|
||||
_authorizationServiceMock
|
||||
.Setup(o => o.AddPermissionsFromDefaultsAsync(It.IsAny<Guid>(), It.IsAny<SecurableEntityType>(), It.IsAny<CancellationToken>()));
|
||||
}
|
||||
|
||||
[Test, Ignore("new filtering broke these tests")]
|
||||
public async Task TestFirstPage_Sorted_Asc()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var glOpportunityService = new GLOpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
var filters = new GLFilters()
|
||||
{
|
||||
Types = new List<string>(),
|
||||
Levels = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
Seasonality = SeasonalityType.WithAndWithout,
|
||||
|
||||
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions("IdentifiedSavings", SortOrder.Asc);
|
||||
|
||||
// act
|
||||
var taskResult = await glOpportunityService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<GLOpportunity>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().IdentifiedSavings
|
||||
.Should().BeLessThan(taskResult.Data.Last().IdentifiedSavings);
|
||||
}
|
||||
|
||||
[Test, Ignore("new filtering broke these tests")]
|
||||
public async Task TestFirstPage_Sorted_Desc()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var glOpportunityService = new GLOpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
var filters = new GLFilters()
|
||||
{
|
||||
Types = new List<string>(),
|
||||
Levels = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
|
||||
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions("IdentifiedSavings", SortOrder.Desc);
|
||||
|
||||
// act
|
||||
var taskResult = await glOpportunityService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<GLOpportunity>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().IdentifiedSavings
|
||||
.Should().BeGreaterThan(taskResult.Data.Last().IdentifiedSavings);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFilterData))]
|
||||
public void TestValidateFilters(GLFilters filters)
|
||||
{
|
||||
if (filters == null) return;
|
||||
if (filters.Types.Any())
|
||||
filters.Types.Should()
|
||||
.AllBeOfType<string>()
|
||||
.And.NotBeNullOrEmpty();
|
||||
if (filters.Levels.Any())
|
||||
filters.Levels.Should()
|
||||
.AllBeOfType<string>()
|
||||
.And.NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[Test, Ignore("new filtering broke these tests")]
|
||||
public async Task TestGetExcelWorkbook()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opp = framework.GLOpportunities.First();
|
||||
var filters = new GLFilters()
|
||||
{
|
||||
ConfigurationGuid = framework.Configurations.First().ConfigurationGuid,
|
||||
Types = new[] { opp.Type },
|
||||
Levels = new[] { opp.Level }
|
||||
};
|
||||
var service = new GLOpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var wb = await service.ExportAsync(new SortOptions(), filters, CancellationToken.None);
|
||||
#pragma warning disable S125 // Sections of code should not be commented out
|
||||
//wb.SaveAs(System.IO.Path.Combine(@"C:\git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "ExcelFilter.xlsx"));
|
||||
#pragma warning restore S125 // Sections of code should not be commented out
|
||||
|
||||
// assert
|
||||
wb.Worksheets.Should().HaveCount(1);
|
||||
var ws = wb.Worksheet(1);
|
||||
ws.Should().NotBeNull();
|
||||
|
||||
var expected = @"Examples.GeneralLedgerOpportunity.ExcelFilter.xlsx";
|
||||
using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected))
|
||||
using (var actualStream = new MemoryStream())
|
||||
{
|
||||
wb.SaveAs(actualStream);
|
||||
actualStream.Compare(expectedStream, out var message).Should().BeTrue(message);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetExcelWorkbookNullFilter()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var service = new GLOpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var wb = await service.ExportAsync(null, null, CancellationToken.None);
|
||||
#pragma warning disable S125 // Sections of code should not be commented out
|
||||
//wb.SaveAs(System.IO.Path.Combine(@"C:\git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "ExcelNullFilter.xlsx"));
|
||||
#pragma warning restore S125 // Sections of code should not be commented out
|
||||
|
||||
// assert
|
||||
wb.Worksheets.Should().HaveCount(1);
|
||||
var ws = wb.Worksheet(1);
|
||||
ws.Should().NotBeNull();
|
||||
|
||||
var expected = @"Examples.GeneralLedgerOpportunity.ExcelNullFilter.xlsx";
|
||||
using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected))
|
||||
using (var actualStream = new MemoryStream())
|
||||
{
|
||||
wb.SaveAs(actualStream);
|
||||
actualStream.Compare(expectedStream, out var message).Should().BeTrue(message);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSetHidden()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunities = framework.GLOpportunities;
|
||||
var opportunity = opportunities.First(vo => !vo.IsHidden);
|
||||
var isHidden = opportunity.IsHidden;
|
||||
var service = new GLOpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
await service.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
result.IsHidden.Should().Be(!isHidden);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetFilterOptionsAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await opportunityService
|
||||
.GetFilterOptionsAsync(new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
return;
|
||||
}
|
||||
taskResult.Should()
|
||||
.BeOfType<GLFilterOptions>()
|
||||
.And.NotBeNull();
|
||||
taskResult.Types.Should().AllBeOfType<FilterMember>().And.NotBeNullOrEmpty()
|
||||
.And.NotContain(t => string.IsNullOrEmpty(t.Id))
|
||||
.And.NotContain(t => string.IsNullOrEmpty(t.Text));
|
||||
taskResult.Levels.Should().AllBeOfType<FilterMember>().And.NotBeNullOrEmpty()
|
||||
.And.NotContain(l => string.IsNullOrEmpty(l.Id))
|
||||
.And.NotContain(l => string.IsNullOrEmpty(l.Text));
|
||||
}
|
||||
catch (NotImplementedException nie)
|
||||
{
|
||||
nie.Should().BeOfType<NotImplementedException>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
try
|
||||
{
|
||||
var opportunities = glOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;
|
||||
|
||||
//act
|
||||
await glOpportunityService.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden,
|
||||
|
||||
cancellationToken);
|
||||
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return;
|
||||
|
||||
var result = glOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result;
|
||||
|
||||
result.IsHidden.Should().Be(!isHidden);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
switch (e.GetType().Name)
|
||||
{
|
||||
case "AggregateException":
|
||||
case "OperationCanceledException":
|
||||
return;
|
||||
}
|
||||
e.Should().NotBeOfType<Exception>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.GLOpportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;
|
||||
var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await glOpportunityService.SetHiddenAsync(Guid.Empty, !isHidden,
|
||||
cancellationToken);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
try
|
||||
{
|
||||
var opportunities = glOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
|
||||
if (opportunity == null) return;
|
||||
|
||||
var note = "new test note";
|
||||
// act
|
||||
await glOpportunityService.SetNoteAsync(opportunity.OpportunityGuid, note,
|
||||
CancellationToken.None);
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return;
|
||||
var result = glOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result;
|
||||
result.Note.Should().Be(note);
|
||||
|
||||
// assert
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
switch (e.GetType().Name)
|
||||
{
|
||||
case "AggregateException":
|
||||
case "OperationCanceledException":
|
||||
return;
|
||||
}
|
||||
e.Should().NotBeOfType<Exception>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSetNote()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunities = framework.GLOpportunities;
|
||||
var opportunity = opportunities.First(vo => string.IsNullOrEmpty(vo.Note));
|
||||
var note = opportunity.Note;
|
||||
var expected = "Now is the time for all good engineers to write great code!";
|
||||
var service = new GLOpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
await service.SetNoteAsync(opportunity.OpportunityGuid, expected, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
result.Note.Should().NotBeNullOrEmpty()
|
||||
.And.NotBe(note)
|
||||
.And.Be(expected);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.GLOpportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
if (opportunity == null) return;
|
||||
var note = "new test note";
|
||||
var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await glOpportunityService.SetNoteAsync(Guid.Empty, note, cancellationToken);
|
||||
|
||||
// assert
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetAllAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var taskResult = await glOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetById(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var tempResult = await glOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var taskResult =
|
||||
await glOpportunityService.GetById(tempResult.FirstOrDefault()?.OpportunityGuid ?? Guid.Empty, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<GLOpportunity>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetByIds(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var tempResult = await glOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var ids = tempResult.Select(o => o.OpportunityGuid);
|
||||
var taskResult = await glOpportunityService.GetByIds(ids, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<GLOpportunity>();
|
||||
}
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
|
||||
#region TestCaseData
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFilterData()
|
||||
{
|
||||
yield return new TestCaseData(new GLFilters { ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("No Filters");
|
||||
yield return new TestCaseData(new GLFilters { ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("View Visible");
|
||||
yield return new TestCaseData(new GLFilters { ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Not View Visible");
|
||||
yield return new TestCaseData(new GLFilters { IdentifiedSavings = 1999, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings");
|
||||
yield return new TestCaseData(new GLFilters { IdentifiedSavings = 999, ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings Not ViewVisible");
|
||||
yield return new TestCaseData(new GLFilters { Levels = new[] { "Overall" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By Level");
|
||||
yield return new TestCaseData(new GLFilters { Levels = new[] { "Department" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), ViewVisible = false })
|
||||
.SetName("By Level Not ViewVisible");
|
||||
yield return new TestCaseData(new GLFilters { Types = new[] { "Revenue" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By Type");
|
||||
yield return new TestCaseData(new GLFilters { Types = new[] { "Expense" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), ViewVisible = false })
|
||||
.SetName("By Type Not ViewVisible");
|
||||
yield return new TestCaseData(new GLFilters { OpportunitySearch = "GL - 101", ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Search By Id");
|
||||
yield return new TestCaseData(new GLFilters { ExcludeInitiatives = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Exclude Opportunities with Initiatives");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.UserSetting;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Generics
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class UserSettingServieTest
|
||||
{
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetUserSetting(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var userSettingService = new UserSettingService(jazzEntityFrameworkFactory, null, null, null);
|
||||
var userGuid = jazzEntityFrameworkFactory.UserSettings?.First().UserGuid ?? Guid.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await userSettingService.GetById(userGuid, cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<UserSetting.CciUserSetting>();
|
||||
}
|
||||
}
|
||||
catch (AssertionException ae)
|
||||
{
|
||||
ae.Should().BeOfType<AssertionException>();
|
||||
}
|
||||
catch (NullReferenceException nre)
|
||||
{
|
||||
nre.Should().BeOfType<NullReferenceException>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetUserSetting(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var userSettingService = new UserSettingService(jazzEntityFrameworkFactory, null, null, null);
|
||||
var userSetting = jazzEntityFrameworkFactory.UserSettings?.First();
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await userSettingService.SetUserSetting(userSetting, cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<UserSetting.CciUserSetting>();
|
||||
}
|
||||
}
|
||||
catch (NullReferenceException nre)
|
||||
{
|
||||
nre.Should().BeOfType<NullReferenceException>();
|
||||
}
|
||||
catch (TaskCanceledException tce)
|
||||
{
|
||||
tce.Should().BeOfType<TaskCanceledException>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using Hangfire;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.Authorization;
|
||||
using Strata.ContinuousImprovement.Biz.Configuration;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts.Snowflake;
|
||||
using Strata.ContinuousImprovement.Biz.FiscalMonths;
|
||||
using Strata.ContinuousImprovement.Biz.Generics;
|
||||
using Strata.ContinuousImprovement.Biz.Initiatives;
|
||||
using Strata.ContinuousImprovement.Biz.Notification;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.CoreLib.Claims;
|
||||
using Strata.Hangfire.Jazz.Client;
|
||||
using Strata.Id.Client;
|
||||
using Strata.Schema.Client;
|
||||
using Strata.SqlTools.Configuration.Common.AsyncFactory;
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyTests;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture]
|
||||
public class OpportunityServiceTests
|
||||
{
|
||||
public VerifySettings VerifySettings { get; set; }
|
||||
public CentralDbContext CentralDbContext { get; set; }
|
||||
public IClaimsPrincipalAccessor ClaimsPrincipalAccessor { get; set; }
|
||||
public IAsyncDbContextFactory<JazzDbContext> DbContextFactory { get; set; }
|
||||
public IJazzDbContext JazzDbContext { get; set; }
|
||||
public IJazzHangfireServiceClient JazzHangfireServiceClient { get; set; }
|
||||
public IAuthorizationServiceClient AuthorizationServiceClient { get; set; }
|
||||
public IIdServiceClient IdServiceClient { get; set; }
|
||||
public IConfigurationService ConfigurationService { get; set; }
|
||||
|
||||
public IFiscalMonthResolver FiscalMonthResolver { get; set; }
|
||||
public ISchemaServiceClient SchemaServiceClient { get; set; }
|
||||
public IBackgroundJobClient BackgroundJobClient { get; set; }
|
||||
public INotificationHub NotificationHub { get; set; }
|
||||
public IHubClients<INotificationHub> HubClients { get; set; }
|
||||
public IHubContext<NotificationHub, INotificationHub> NotificationHubContext { get; set; }
|
||||
public IInitiativeService InitiativeService { get; set; }
|
||||
public ISnowflakeDatabaseContext SnowflakeDatabaseContext { get; set; }
|
||||
public IUpdateFactOpportunitySavingsService UpdateFactOpportunitySavingsService { get; set; }
|
||||
|
||||
public JazzEntityFrameworkFactory JAZZ_Framework { get; set; }
|
||||
|
||||
[OneTimeSetUp]
|
||||
public async Task TestFixtureSetup()
|
||||
{
|
||||
VerifySettings = TestExtensions.TestSettings();
|
||||
var dbContextOptions = new DbContextOptions<CentralDbContext>();
|
||||
CentralDbContext = new CentralDbContext(dbContextOptions);
|
||||
ClaimsPrincipalAccessor = Mock.Of<IClaimsPrincipalAccessor>();
|
||||
DbContextFactory = Mock.Of<IAsyncDbContextFactory<JazzDbContext>>();
|
||||
JazzHangfireServiceClient = Mock.Of<IJazzHangfireServiceClient>();
|
||||
AuthorizationServiceClient = Mock.Of<IAuthorizationServiceClient>();
|
||||
IdServiceClient = Mock.Of<IIdServiceClient>();
|
||||
ConfigurationService = Mock.Of<IConfigurationService>();
|
||||
FiscalMonthResolver = Mock.Of<IFiscalMonthResolver>();
|
||||
SchemaServiceClient = Mock.Of<ISchemaServiceClient>();
|
||||
BackgroundJobClient = Mock.Of<IBackgroundJobClient>();
|
||||
NotificationHub = Mock.Of<INotificationHub>();
|
||||
HubClients = Mock.Of<IHubClients<INotificationHub>>();
|
||||
NotificationHubContext = Mock.Of<IHubContext<NotificationHub, INotificationHub>>();
|
||||
InitiativeService = Mock.Of<IInitiativeService>();
|
||||
SnowflakeDatabaseContext = Mock.Of<ISnowflakeDatabaseContext>();
|
||||
UpdateFactOpportunitySavingsService = Mock.Of<IUpdateFactOpportunitySavingsService>();
|
||||
|
||||
JAZZ_Framework = new JazzEntityFrameworkFactory();
|
||||
JazzDbContext = await JAZZ_Framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var configurations = JazzDbContext.Configurations;
|
||||
|
||||
Mock.Get(AuthorizationServiceClient)
|
||||
.Setup(o => o.AddPermissionsFromDefaultsAsync(It.IsAny<Guid>(), It.IsAny<SecurableEntityType>(), It.IsAny<CancellationToken>()));
|
||||
Mock.Get(ConfigurationService)
|
||||
.Setup(s => s.GetConfigurationAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
.Returns<Guid, CancellationToken>((configurationGuid, token) =>
|
||||
Task.FromResult(configurations.SingleOrDefault(c => c.ConfigurationGuid == configurationGuid)));
|
||||
|
||||
Mock.Get(IdServiceClient)
|
||||
.Setup(s => s.GetStrataId(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(9));
|
||||
|
||||
Mock.Get(NotificationHub)
|
||||
.Setup(s => s.SendOpportunityUpdate(It.IsAny<string>()));
|
||||
Mock.Get(NotificationHub)
|
||||
.Setup(s => s.SendOpportunityUpdateError(It.IsAny<string>(), It.IsAny<string>()));
|
||||
Mock.Get(HubClients)
|
||||
.Setup(s => s.Group(It.IsAny<string>()))
|
||||
.Returns(NotificationHub);
|
||||
Mock.Get(NotificationHubContext)
|
||||
.Setup(s => s.Clients)
|
||||
.Returns(HubClients);
|
||||
|
||||
Mock.Get(InitiativeService)
|
||||
.Setup(s => s.DeleteAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(true));
|
||||
Mock.Get(UpdateFactOpportunitySavingsService)
|
||||
.Setup(s => s.UpdateFactOpportunitySavings(It.IsAny<CancellationToken>()));
|
||||
|
||||
Mock.Get(DbContextFactory)
|
||||
.Setup(s => s.CreateDbContextAsync(It.IsAny<CancellationToken>()))
|
||||
.Returns(() => Task.FromResult((JazzDbContext)JazzDbContext));
|
||||
}
|
||||
}
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.Pagination;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using System.Linq;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Pagination
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class IQueryableExtensionsTest
|
||||
{
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestIQueryableOrderBy()
|
||||
{
|
||||
// arrange
|
||||
var jeff = new JazzEntityFrameworkFactory();
|
||||
var _opportunities = jeff.UVOpportunities.OrderByDescending(o => o.OpportunityKey);
|
||||
var list = _opportunities.AsQueryable()
|
||||
.OrderBy("OpportunityKey");
|
||||
// act
|
||||
|
||||
// assert
|
||||
list.First().OpportunityKey.Should().Be(_opportunities.Last().OpportunityKey);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestIQueryableOrderByDescending()
|
||||
{
|
||||
// arrange
|
||||
var jeff = new JazzEntityFrameworkFactory();
|
||||
var _opportunities = jeff.UVOpportunities.OrderBy(o => o.OpportunityKey);
|
||||
var list = _opportunities.AsQueryable()
|
||||
.OrderByDescending("OpportunityKey");
|
||||
// act
|
||||
|
||||
// assert
|
||||
list.First().OpportunityKey.Should().Be(_opportunities.Last().OpportunityKey);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using Strata.ApiLib.Standard.Models;
|
||||
using Strata.ContinuousImprovement.Biz.UtilizationVariation.Opportunities;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Pagination
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class PaginatedListTest
|
||||
{
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPaginatedList()
|
||||
{
|
||||
// arrange
|
||||
var jeff = new JazzEntityFrameworkFactory();
|
||||
var _opportunities = jeff.UVOpportunities;
|
||||
var pagingInfo = new PagingInfo() { ResultsPerPage = 25, PageNumber = 1, TotalNumberOfResults = 2 };
|
||||
var paginatedList = new PagedApiResponse<UVOpportunity>() { Data = _opportunities, PagingInfo = pagingInfo };
|
||||
|
||||
// act
|
||||
|
||||
// assert
|
||||
paginatedList.PagingInfo.PageNumber.Should().Be(1);
|
||||
paginatedList.PagingInfo.TotalPages.Should().Be(1);
|
||||
paginatedList.PagingInfo.TotalNumberOfResults.Should().Be(2);
|
||||
paginatedList.PagingInfo.ResultsPerPage.Should().Be(25);
|
||||
paginatedList.Data.Should()
|
||||
.AllBeOfType<UVOpportunity>()
|
||||
.And.HaveCount(_opportunities.Count);
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
}
|
||||
}
|
||||
+498
@@ -0,0 +1,498 @@
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.Authorization;
|
||||
using Strata.ContinuousImprovement.Biz.Configuration;
|
||||
using Strata.ContinuousImprovement.Biz.Filter;
|
||||
using Strata.ContinuousImprovement.Biz.Generics;
|
||||
using Strata.ContinuousImprovement.Biz.Initiatives;
|
||||
using Strata.ContinuousImprovement.Biz.Pagination;
|
||||
using Strata.ContinuousImprovement.Biz.Payroll.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.Payroll.Opportunities.Filters;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.Hangfire.Jazz.Client;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Payroll.Opportunities
|
||||
{
|
||||
class PROpportunityServiceTest
|
||||
{
|
||||
private Mock<IJazzHangfireServiceClient> _hangfireServiceMock;
|
||||
private static readonly ResourceFileExtractor _extractor = new ResourceFileExtractor(".Resource.");
|
||||
private Mock<IAuthorizationServiceClient> _authorizationServiceMock;
|
||||
private IUpdateFactOpportunitySavingsService _updateFactOpportunitySavingsService;
|
||||
private IInitiativeService _initiativeService;
|
||||
private Mock<IConfigurationService> _configurationServiceMock;
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
_hangfireServiceMock = new Mock<IJazzHangfireServiceClient>();
|
||||
_authorizationServiceMock = new Mock<IAuthorizationServiceClient>();
|
||||
_updateFactOpportunitySavingsService = Mock.Of<IUpdateFactOpportunitySavingsService>();
|
||||
_initiativeService = Mock.Of<IInitiativeService>();
|
||||
Mock.Get(_updateFactOpportunitySavingsService)
|
||||
.Setup(s => s.UpdateFactOpportunitySavings(It.IsAny<CancellationToken>()));
|
||||
Mock.Get(_initiativeService)
|
||||
.Setup(s => s.DeleteAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(true));
|
||||
_configurationServiceMock = new Mock<IConfigurationService>();
|
||||
_authorizationServiceMock
|
||||
.Setup(o => o.AddPermissionsFromDefaultsAsync(It.IsAny<Guid>(), It.IsAny<SecurableEntityType>(), It.IsAny<CancellationToken>()));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Asc()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var prOpportunityService = new PROpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
var filters = new PRFilters()
|
||||
{
|
||||
PayrollGoalTypes = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
|
||||
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions("IdentifiedSavings", SortOrder.Asc);
|
||||
|
||||
// act
|
||||
var taskResult = await prOpportunityService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<PROpportunity>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().IdentifiedSavings
|
||||
.Should().BeLessThan(taskResult.Data.Last().IdentifiedSavings);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Desc()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var prOpportunityService = new PROpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
var filters = new PRFilters()
|
||||
{
|
||||
PayrollGoalTypes = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
|
||||
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions("IdentifiedSavings", SortOrder.Desc);
|
||||
|
||||
// act
|
||||
var taskResult = await prOpportunityService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<PROpportunity>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().IdentifiedSavings
|
||||
.Should().BeGreaterThan(taskResult.Data.Last().IdentifiedSavings);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFilterData))]
|
||||
public void TestValidateFilters(PRFilters filters)
|
||||
{
|
||||
if (filters == null) return;
|
||||
if (filters.PayrollGoalTypes.Any())
|
||||
filters.PayrollGoalTypes.Should()
|
||||
.AllBeOfType<string>()
|
||||
.And.NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetExcelWorkbook()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opp = framework.PROpportunities.First();
|
||||
var filters = new PRFilters()
|
||||
{
|
||||
ConfigurationGuid = framework.Configurations.First().ConfigurationGuid,
|
||||
PayrollGoalTypes = new[] { opp.PayrollGoal },
|
||||
};
|
||||
var service = new PROpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
|
||||
// act
|
||||
var wb = await service.ExportAsync(new SortOptions(), filters, CancellationToken.None);
|
||||
#pragma warning disable S125 // Sections of code should not be commented out
|
||||
//wb.SaveAs(System.IO.Path.Combine(@"C:\git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "ExcelFilter.xlsx"));
|
||||
#pragma warning restore S125 // Sections of code should not be commented out
|
||||
|
||||
// assert
|
||||
wb.Worksheets.Should().HaveCount(1);
|
||||
var ws = wb.Worksheet(1);
|
||||
ws.Should().NotBeNull();
|
||||
|
||||
var expected = @"Examples.PayrollOpportunity.ExcelFilter.xlsx";
|
||||
using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected))
|
||||
using (var actualStream = new MemoryStream())
|
||||
{
|
||||
wb.SaveAs(actualStream);
|
||||
actualStream.Compare(expectedStream, out var message).Should().BeTrue(message);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetExcelWorkbookNullFilter()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var service = new PROpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
|
||||
// act
|
||||
var wb = await service.ExportAsync(null, null, CancellationToken.None);
|
||||
#pragma warning disable S125 // Sections of code should not be commented out
|
||||
//wb.SaveAs(System.IO.Path.Combine(@"C:\git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "ExcelNullFilter.xlsx"));
|
||||
#pragma warning restore S125 // Sections of code should not be commented out
|
||||
|
||||
// assert
|
||||
wb.Worksheets.Should().HaveCount(1);
|
||||
var ws = wb.Worksheet(1);
|
||||
ws.Should().NotBeNull();
|
||||
|
||||
var expected = @"Examples.PayrollOpportunity.ExcelNullFilter.xlsx";
|
||||
using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected))
|
||||
using (var actualStream = new MemoryStream())
|
||||
{
|
||||
wb.SaveAs(actualStream);
|
||||
actualStream.Compare(expectedStream, out var message).Should().BeTrue(message);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSetHidden()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunities = framework.PROpportunities;
|
||||
var opportunity = opportunities.First(vo => !vo.IsHidden);
|
||||
var isHidden = opportunity.IsHidden;
|
||||
var service = new PROpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
|
||||
// act
|
||||
await service.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
result.IsHidden.Should().Be(!isHidden);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetFilterOptionsAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunityService = new PROpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await opportunityService
|
||||
.GetFilterOptionsAsync(new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
return;
|
||||
}
|
||||
taskResult.Should()
|
||||
.BeOfType<PRFilterOptions>()
|
||||
.And.NotBeNull();
|
||||
taskResult.PayrollGoalTypes.Should().AllBeOfType<FilterMember>().And.NotBeNullOrEmpty()
|
||||
.And.NotContain(t => string.IsNullOrEmpty(t.Id))
|
||||
.And.NotContain(t => string.IsNullOrEmpty(t.Text));
|
||||
}
|
||||
catch (NotImplementedException nie)
|
||||
{
|
||||
nie.Should().BeOfType<NotImplementedException>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var prOpportunityService = new PROpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
try
|
||||
{
|
||||
var opportunities = prOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;
|
||||
|
||||
//act
|
||||
await prOpportunityService.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden,
|
||||
|
||||
cancellationToken);
|
||||
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return;
|
||||
|
||||
var result = prOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result;
|
||||
|
||||
result.IsHidden.Should().Be(!isHidden);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
switch (e.GetType().Name)
|
||||
{
|
||||
case "AggregateException":
|
||||
case "OperationCanceledException":
|
||||
return;
|
||||
}
|
||||
e.Should().NotBeOfType<Exception>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.PROpportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;
|
||||
var prOpportunityService = new PROpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await prOpportunityService.SetHiddenAsync(Guid.Empty, !isHidden,
|
||||
cancellationToken);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var prOpportunityService = new PROpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
try
|
||||
{
|
||||
var opportunities = prOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
|
||||
if (opportunity == null) return;
|
||||
|
||||
var note = "new test note";
|
||||
// act
|
||||
await prOpportunityService.SetNoteAsync(opportunity.OpportunityGuid, note,
|
||||
CancellationToken.None);
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return;
|
||||
var result = prOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result;
|
||||
result.Note.Should().Be(note);
|
||||
|
||||
// assert
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
switch (e.GetType().Name)
|
||||
{
|
||||
case "AggregateException":
|
||||
case "OperationCanceledException":
|
||||
return;
|
||||
}
|
||||
e.Should().NotBeOfType<Exception>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSetNote()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunities = framework.PROpportunities;
|
||||
var opportunity = opportunities.First(vo => string.IsNullOrEmpty(vo.Note));
|
||||
var note = opportunity.Note;
|
||||
var expected = "Now is the time for all good engineers to write great code!";
|
||||
var service = new PROpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
|
||||
// act
|
||||
await service.SetNoteAsync(opportunity.OpportunityGuid, expected, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
result.Note.Should().NotBeNullOrEmpty()
|
||||
.And.NotBe(note)
|
||||
.And.Be(expected);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.PROpportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
if (opportunity == null) return;
|
||||
var note = "new test note";
|
||||
var prOpportunityService = new PROpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await prOpportunityService.SetNoteAsync(Guid.Empty, note, cancellationToken);
|
||||
|
||||
// assert
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetAllAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var prOpportunityService = new PROpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
|
||||
// act
|
||||
var taskResult = await prOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetById(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var prOpportunityService = new PROpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
|
||||
// act
|
||||
var tempResult = await prOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var taskResult =
|
||||
await prOpportunityService.GetById(tempResult.FirstOrDefault()?.OpportunityGuid ?? Guid.Empty, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<PROpportunity>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetByIds(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var prOpportunityService = new PROpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object,
|
||||
_initiativeService, _updateFactOpportunitySavingsService,
|
||||
_configurationServiceMock.Object);
|
||||
|
||||
// act
|
||||
var tempResult = await prOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var ids = tempResult.Select(o => o.OpportunityGuid);
|
||||
var taskResult = await prOpportunityService.GetByIds(ids, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<PROpportunity>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
|
||||
#region TestCaseData
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFilterData()
|
||||
{
|
||||
yield return new TestCaseData(new PRFilters { ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("No Filters");
|
||||
yield return new TestCaseData(new PRFilters { ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("View Visible");
|
||||
yield return new TestCaseData(new PRFilters { ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Not View Visible");
|
||||
yield return new TestCaseData(new PRFilters { IdentifiedSavings = 1999, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings");
|
||||
yield return new TestCaseData(new PRFilters { IdentifiedSavings = 999, ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings Not ViewVisible");
|
||||
yield return new TestCaseData(new PRFilters { PayrollGoalTypes = new[] { "Both" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By Variability");
|
||||
yield return new TestCaseData(new PRFilters { PayrollGoalTypes = new[] { "Fixed" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), ViewVisible = false })
|
||||
.SetName("By Variability Not ViewVisible");
|
||||
yield return new TestCaseData(new PRFilters { OpportunitySearch = "GL - 101", ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Search By Id");
|
||||
yield return new TestCaseData(new PRFilters { ExcludeInitiatives = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Exclude Opportunities with Initiatives");
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.PeerGroups;
|
||||
using Strata.ContinuousImprovement.Biz.PeerGroups.Enums;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.StrataSphereCompare.Client.Models.Enums;
|
||||
using Superpower.Model;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
using VerifyTests;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.PeerGroup
|
||||
{
|
||||
public class PeerGroupServiceTest
|
||||
{
|
||||
private readonly string _duplicateName = "Test Name";
|
||||
private readonly int _existingGroupId = 1;
|
||||
private ILogger<PeerGroupService> _logger { get; set; }
|
||||
private VerifySettings _verifySettings { get; set; }
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
_verifySettings = TestExtensions.TestSettings();
|
||||
_logger = Mock.Of<ILogger<PeerGroupService>>();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestValidDropdownItems()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var peerGroupService = new PeerGroupService(framework, _logger);
|
||||
|
||||
// act
|
||||
var dropdownItems = peerGroupService.GetDropdownItems();
|
||||
|
||||
// assert
|
||||
await Verifier.Verify(dropdownItems, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestTooLongNameThrowsAnError()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var peerGroupService = new PeerGroupService(framework, _logger);
|
||||
|
||||
// act
|
||||
var exception = Assert.ThrowsAsync<Exception>(() => peerGroupService.CreateAsync(new PeerGroupDto() { Name = new string('a', 101) }, default));
|
||||
|
||||
// assert
|
||||
Assert.That(exception, Is.Not.Null);
|
||||
Assert.That("Rollup column exceeds maximum number of characters", Is.EqualTo(exception.Message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestDuplicateNameThrowsAnError()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var peerGroupService = new PeerGroupService(framework, _logger);
|
||||
|
||||
// act
|
||||
var exception = Assert.ThrowsAsync<Exception>(() => peerGroupService.CreateAsync(new PeerGroupDto() { Name = _duplicateName }, default));
|
||||
|
||||
// assert
|
||||
Assert.That(exception, Is.Not.Null);
|
||||
Assert.That("Rollup column name already exists.", Is.EqualTo(exception.Message));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetGroupByIdReturnsCorrectGroup()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var peerGroupService = new PeerGroupService(framework, _logger);
|
||||
|
||||
// act
|
||||
var group = await peerGroupService.GetByIdAsync(_existingGroupId, default);
|
||||
|
||||
// assert
|
||||
Assert.That(group, Is.Not.Null);
|
||||
Assert.That(_duplicateName, Is.EqualTo(group.Name));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestCreateSavesAnItem()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var peerGroupService = new PeerGroupService(framework, _logger);
|
||||
var dto = new PeerGroupDto()
|
||||
{
|
||||
Name = "New Item",
|
||||
AmcTypes = new List<byte>() { (byte)IsAmc.NonAcademicMedicalCenters, (byte)IsAmc.AcademicMedicalCenters },
|
||||
EntityTypes = new List<byte>() { (byte)HospitalType.ShortTermAcuteCareHospital, (byte)HospitalType.CancerCenter },
|
||||
CensusRegions = new List<byte>() { (byte)CensusRegion.Midwest, (byte)CensusRegion.Northeast },
|
||||
OperatingExpenses = new List<byte>() { (byte)OperatingExpense._250MTo500M, (byte)OperatingExpense._100MTo250M },
|
||||
BedSize = new List<byte>() { (byte)BedSize._0_250, (byte)BedSize._251_500 },
|
||||
UrbanRural = new List<byte>() { (byte)UrbanRural.Urban, (byte)UrbanRural.Rural }
|
||||
};
|
||||
|
||||
// act
|
||||
var result = await peerGroupService.CreateAsync(dto, default);
|
||||
|
||||
// assert
|
||||
Assert.That(result, Is.EqualTo(true));
|
||||
var itemsFromDB = await peerGroupService.GetAllAsync(default);
|
||||
var savedItem = itemsFromDB.FirstOrDefault(i => i.Name == dto.Name);
|
||||
AssertPeerGroups(dto, savedItem);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestUpdateRewritesMappings()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var peerGroupService = new PeerGroupService(framework, _logger);
|
||||
var dto = new PeerGroupDto()
|
||||
{
|
||||
PeerGroupId = 1,
|
||||
Name = "Changed Item",
|
||||
AmcTypes = new List<byte>() { (byte)IsAmc.AcademicMedicalCenters },
|
||||
EntityTypes = new List<byte>() { (byte)HospitalType.CancerCenter, (byte)HospitalType.RehabLTACOther },
|
||||
CensusRegions = new List<byte>() { (byte)CensusRegion.West, (byte)CensusRegion.Midwest },
|
||||
OperatingExpenses = new List<byte>() { (byte)OperatingExpense.GreaterThan1B, (byte)OperatingExpense._100MTo250M },
|
||||
BedSize = new List<byte>() { (byte)BedSize._251_500, (byte)BedSize._501_750 },
|
||||
UrbanRural = new List<byte>() { (byte)UrbanRural.Rural }
|
||||
};
|
||||
|
||||
// act
|
||||
var result = await peerGroupService.UpdateAsync(dto.PeerGroupId, dto, default);
|
||||
|
||||
// assert
|
||||
Assert.That(result, Is.EqualTo(true));
|
||||
var itemsFromDB = await peerGroupService.GetAllAsync(default);
|
||||
var savedItem = itemsFromDB.FirstOrDefault(i => i.Name == dto.Name);
|
||||
AssertPeerGroups(dto, savedItem);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestDeleteWorksCorrectly()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var peerGroupService = new PeerGroupService(framework, _logger);
|
||||
// act
|
||||
await peerGroupService.DeleteAsync(_existingGroupId, default);
|
||||
|
||||
// assert
|
||||
var itemsFromDB = await peerGroupService.GetAllAsync(default);
|
||||
var savedItem = itemsFromDB.FirstOrDefault(i => i.Name == _duplicateName || i.PeerGroupId == _existingGroupId);
|
||||
Assert.That(savedItem, Is.Null);
|
||||
}
|
||||
|
||||
private void AssertPeerGroups(PeerGroupDto expected, PeerGroupDto actual)
|
||||
{
|
||||
Assert.That(actual, Is.Not.Null);
|
||||
Assert.That(actual.AmcTypes, Is.EqualTo(expected.AmcTypes));
|
||||
Assert.That(actual.EntityTypes, Is.EqualTo(expected.EntityTypes));
|
||||
Assert.That(actual.CensusRegions, Is.EqualTo(expected.CensusRegions));
|
||||
Assert.That(actual.OperatingExpenses, Is.EqualTo(expected.OperatingExpenses));
|
||||
Assert.That(actual.BedSize, Is.EqualTo(expected.BedSize));
|
||||
Assert.That(actual.UrbanRural, Is.EqualTo(expected.UrbanRural));
|
||||
}
|
||||
}
|
||||
}
|
||||
+302
@@ -0,0 +1,302 @@
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.FiscalMonths;
|
||||
using Strata.ContinuousImprovement.Biz.PerformanceEngine;
|
||||
using Strata.ContinuousImprovement.Biz.Shared;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
using VerifyTests;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.PerformanceEngine
|
||||
{
|
||||
[TestFixture, Category("Unit"), Category("CCI")]
|
||||
public class PerformanceEngineTests
|
||||
{
|
||||
private VerifySettings _verifySettings;
|
||||
[OneTimeSetUp]
|
||||
public void FixtureSetup()
|
||||
{
|
||||
_verifySettings = TestExtensions.TestSettings();
|
||||
#pragma warning disable S3878 // Arrays should not be created for params parameters
|
||||
_verifySettings
|
||||
.ScrubMembers(["FiscalYear", "FiscalYearID", "CalendarYear"]);
|
||||
#pragma warning restore S3878 // Arrays should not be created for params parameters
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestCalculateUVSavings()
|
||||
{
|
||||
//ORG 0222 | Demo 1 | ADLT Total Knee Replacement W/O - Supplies - 10 - Northern Valley Medical Center - FY2017 | Hetzer Adriane (no seasonality)
|
||||
var currentYear = DateTime.Now.Year;
|
||||
MonthlyRampUp[] rampUps =
|
||||
{
|
||||
new MonthlyRampUp(1, currentYear, 100), new MonthlyRampUp(2, currentYear, 100), new MonthlyRampUp(3, currentYear, 100), new MonthlyRampUp(4, currentYear, 100),
|
||||
new MonthlyRampUp(5, currentYear, 100),new MonthlyRampUp(6, currentYear, 100),new MonthlyRampUp(7, currentYear, 100),new MonthlyRampUp(8, currentYear, 100),
|
||||
new MonthlyRampUp(9, currentYear, 100),new MonthlyRampUp(10, currentYear, 100),new MonthlyRampUp(11, currentYear, 100),new MonthlyRampUp(12, currentYear, 100)
|
||||
};
|
||||
const bool isInverse = true;
|
||||
const bool isSeasonal = false;
|
||||
double[] goalUnits = { 13221, 17628, 22035, 22035, 8814, 26442, 8814, 13221, 22035, 17628, 30849, 44070 };
|
||||
double[] baselineUnits = { 12231, 16788, 21605, 21305, 8430, 24648, 8172, 11847, 24535, 16704, 26159, 45000 };
|
||||
double[] baselineStats = { 3, 4, 5, 5, 2, 6, 2, 3, 5, 4, 7, 10 };
|
||||
double[] trackingUnits = { 54314, 8798, 31680, 21415, 25895, 0, 0, 0, 0, 0, 0, 0 };
|
||||
double[] trackingStats = { 13, 2, 8, 5, 5, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
var trackingYearMonths = GetTrackingYearMonths(currentYear).ToList();
|
||||
|
||||
var performanceBaselineData = PerformanceComparisonData.SetupBaselineDataList(baselineUnits, baselineStats, currentYear - 1);
|
||||
var performanceTrackingData = PerformanceComparisonData.SetupTrackingDataList(goalUnits, trackingUnits, trackingStats, currentYear);
|
||||
|
||||
var group = new PerformanceGroup(1, "testItem");
|
||||
var options = new PerformanceOptions(isSeasonal, isInverse, true);
|
||||
|
||||
var testGroup = new PerformanceTrackingItem(group, rampUps, options, performanceBaselineData, performanceTrackingData, trackingYearMonths);
|
||||
|
||||
await Verifier.Verify(testGroup.MonthlyTrackingData, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test(Description = "Dev Major PerformanceAGain - FY2019 (test for seasonality)")]
|
||||
public async Task TestSavingsFreeForm()
|
||||
{
|
||||
var currentYear = DateTime.Now.Year;
|
||||
MonthlyRampUp[] rampUps =
|
||||
{
|
||||
new MonthlyRampUp(1, currentYear, 100), new MonthlyRampUp(2, currentYear, 100), new MonthlyRampUp(3, currentYear, 100), new MonthlyRampUp(4, currentYear, 100),
|
||||
new MonthlyRampUp(5, currentYear, 100),new MonthlyRampUp(6, currentYear, 100),new MonthlyRampUp(7, currentYear, 100),new MonthlyRampUp(8, currentYear, 100),
|
||||
new MonthlyRampUp(9, currentYear, 100),new MonthlyRampUp(10, currentYear, 100),new MonthlyRampUp(11, currentYear, 100),new MonthlyRampUp(12, currentYear, 100)
|
||||
};
|
||||
const bool isInverse = true;
|
||||
const bool isSeasonal = true;
|
||||
double[] goalUnits = { 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 };
|
||||
double[] baselineUnits = { 200, 150, 100, 150, 200, 100, 100, 100, 150, 200, 500, 320 };
|
||||
double[] baselineStats = { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 };
|
||||
double[] trackingUnits = { 100, 100, 100, 100, 200, 0, 0, 0, 0, 0, 0, 0 };
|
||||
double[] trackingStats = { 10, 10, 10, 10, 5, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
var trackingYearMonths = GetTrackingYearMonths(currentYear).ToList();
|
||||
|
||||
var performanceBaselineData = PerformanceComparisonData.SetupBaselineDataList(baselineUnits, baselineStats, currentYear - 1);
|
||||
var performanceTrackingData = PerformanceComparisonData.SetupTrackingDataList(goalUnits, trackingUnits, trackingStats, currentYear);
|
||||
|
||||
var group = new PerformanceGroup(1, "testItem");
|
||||
var options = new PerformanceOptions(isSeasonal, isInverse, true);
|
||||
|
||||
var testGroup = new PerformanceTrackingItem(group, rampUps, options, performanceBaselineData, performanceTrackingData, trackingYearMonths);
|
||||
|
||||
await Verifier.Verify(testGroup.MonthlyTrackingData, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test(Description = "Dev Major TestNotInverse - FY2019 (test for seasonality, NotInverse)")]
|
||||
public async Task TestSavingsFreeFormRevenue()
|
||||
{
|
||||
var currentYear = DateTime.Now.Year;
|
||||
MonthlyRampUp[] rampUps =
|
||||
{
|
||||
new MonthlyRampUp(1, currentYear, 100), new MonthlyRampUp(2, currentYear, 100), new MonthlyRampUp(3, currentYear, 100), new MonthlyRampUp(4, currentYear, 100),
|
||||
new MonthlyRampUp(5, currentYear, 100),new MonthlyRampUp(6, currentYear, 100),new MonthlyRampUp(7, currentYear, 100),new MonthlyRampUp(8, currentYear, 100),
|
||||
new MonthlyRampUp(9, currentYear, 100),new MonthlyRampUp(10, currentYear, 100),new MonthlyRampUp(11, currentYear, 100),new MonthlyRampUp(12, currentYear, 100)
|
||||
};
|
||||
const bool isInverse = false;
|
||||
const bool isSeasonal = true;
|
||||
double[] goalUnits = { 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000 };
|
||||
double[] baselineUnits = { 200, 150, 100, 150, 200, 100, 100, 100, 150, 200, 500, 320 };
|
||||
double[] baselineStats = { 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 };
|
||||
double[] trackingUnits = { 100, 100, 100, 100, 200, 0, 0, 0, 0, 0, 0, 0 };
|
||||
double[] trackingStats = { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 };
|
||||
|
||||
var trackingYearMonths = GetTrackingYearMonths(currentYear).ToList();
|
||||
|
||||
var performanceBaselineData = PerformanceComparisonData.SetupBaselineDataList(baselineUnits, baselineStats, currentYear - 1);
|
||||
var performanceTrackingData = PerformanceComparisonData.SetupTrackingDataList(goalUnits, trackingUnits, trackingStats, currentYear);
|
||||
|
||||
var group = new PerformanceGroup(1, "testItem");
|
||||
var options = new PerformanceOptions(isSeasonal, isInverse, true);
|
||||
|
||||
var testGroup = new PerformanceTrackingItem(group, rampUps, options, performanceBaselineData, performanceTrackingData, trackingYearMonths);
|
||||
|
||||
await Verifier.Verify(testGroup.MonthlyTrackingData, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test(Description = "ORG 0222 | Demo 1 | Respiratory Failure - Respiratory Failure - Cardiac Surgery - FY2017 | Entity 20")]
|
||||
[Ignore("Test database needs to be rolled over to the new year")]
|
||||
public async Task TestSavingsQV()
|
||||
{
|
||||
var currentYear = DateTime.Now.Year;
|
||||
MonthlyRampUp[] rampUps =
|
||||
{
|
||||
new MonthlyRampUp(1, currentYear, 100), new MonthlyRampUp(2, currentYear, 100), new MonthlyRampUp(3, currentYear, 100), new MonthlyRampUp(4, currentYear, 100),
|
||||
new MonthlyRampUp(5, currentYear, 100),new MonthlyRampUp(6, currentYear, 100),new MonthlyRampUp(7, currentYear, 100),new MonthlyRampUp(8, currentYear, 100),
|
||||
new MonthlyRampUp(9, currentYear, 100),new MonthlyRampUp(10, currentYear, 100),new MonthlyRampUp(11, currentYear, 100),new MonthlyRampUp(12, currentYear, 100)
|
||||
};
|
||||
const bool isInverse = true;
|
||||
const bool isSeasonal = false;
|
||||
double[] goalUnits = { 1.249525, 1.249525, 1.249525, 1.249525, 1.249525, 1.249525, 1.249525, 1.249525, 1.249525, 1.249525, 1.249525, 1.249525 };
|
||||
double[] baselineUnits = { 5, 3, 3, 2, 2, 0, 2, 3, 2, 3, 2, 3 };
|
||||
double[] baselineStats = { 9, 14, 12, 11, 8, 13, 12, 17, 13, 10, 14, 18 };
|
||||
double[] trackingUnits = { 2, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0 };
|
||||
double[] trackingStats = { 13, 13, 15, 16, 11, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
var trackingYearMonths = GetTrackingYearMonths(currentYear).ToList();
|
||||
|
||||
var performanceBaselineData = PerformanceComparisonData.SetupBaselineDataList(baselineUnits, baselineStats, currentYear - 1);
|
||||
var performanceTrackingData = PerformanceComparisonData.SetupTrackingDataList(goalUnits, trackingUnits, trackingStats, currentYear);
|
||||
|
||||
var group = new PerformanceGroup(1, "testItem");
|
||||
var options = new PerformanceOptions(isSeasonal, isInverse, true);
|
||||
|
||||
var testGroup = new PerformanceTrackingItem(group, rampUps, options, performanceBaselineData, performanceTrackingData, trackingYearMonths);
|
||||
|
||||
await Verifier.Verify(testGroup.MonthlyTrackingData, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test(Description = "ORG 0222 | Demo 1 | Purchased Services Reduction - FY2017")]
|
||||
[Ignore("Test database needs to be rolled over to the new year")]
|
||||
public async Task TestSavingsGL()
|
||||
{
|
||||
var currentYear = DateTime.Now.Year;
|
||||
MonthlyRampUp[] rampUps =
|
||||
{
|
||||
new MonthlyRampUp(1, currentYear, 100), new MonthlyRampUp(2, currentYear, 100), new MonthlyRampUp(3, currentYear, 100), new MonthlyRampUp(4, currentYear, 100),
|
||||
new MonthlyRampUp(5, currentYear, 100),new MonthlyRampUp(6, currentYear, 100),new MonthlyRampUp(7, currentYear, 100),new MonthlyRampUp(8, currentYear, 100),
|
||||
new MonthlyRampUp(9, currentYear, 100),new MonthlyRampUp(10, currentYear, 100),new MonthlyRampUp(11, currentYear, 100),new MonthlyRampUp(12, currentYear, 100)
|
||||
};
|
||||
const bool isInverse = true;
|
||||
const bool isSeasonal = true;
|
||||
double[] goalUnits = { 244588.94, 308260.21, 522852.42, 242258.14, 429804.75, 298079.59, 291399.34, 303184.35, 423257, 296446.05, 267084.76, 338172.85 };
|
||||
double[] baselineUnits = { 305736.17, 385325.27, 653565.52, 302822.67, 537255.94, 372599.49, 364249.17, 378980.44, 529071.25, 370557.56, 333855.95, 422716.06 };
|
||||
double[] baselineStats = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
|
||||
double[] trackingUnits = { 308148.44, 263286.57, 300898.51, 283803.3, 496369.18, 0, 0, 0, 0, 0, 0, 0 };
|
||||
double[] trackingStats = { 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
var trackingYearMonths = GetTrackingYearMonths(currentYear).ToList();
|
||||
|
||||
var performanceBaselineData = PerformanceComparisonData.SetupBaselineDataList(baselineUnits, baselineStats, currentYear - 1);
|
||||
var performanceTrackingData = PerformanceComparisonData.SetupTrackingDataList(goalUnits, trackingUnits, trackingStats, currentYear);
|
||||
|
||||
var group = new PerformanceGroup(1, "testItem");
|
||||
var options = new PerformanceOptions(isSeasonal, isInverse, true);
|
||||
|
||||
var testGroup = new PerformanceTrackingItem(group, rampUps, options, performanceBaselineData, performanceTrackingData, trackingYearMonths);
|
||||
|
||||
await Verifier.Verify(testGroup.MonthlyTrackingData, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test(Description = "Dev Major | TestStartDate - FY2019")]
|
||||
[Ignore("Test database needs to be rolled over to the new year")]
|
||||
public async Task TestSavingsLateStartDate()
|
||||
{
|
||||
var currentYear = DateTime.Now.Year;
|
||||
MonthlyRampUp[] rampUps =
|
||||
{
|
||||
new MonthlyRampUp(1, currentYear, 0), new MonthlyRampUp(2, currentYear, 0), new MonthlyRampUp(3, currentYear, 0), new MonthlyRampUp(4, currentYear, 100),
|
||||
new MonthlyRampUp(5, currentYear, 100),new MonthlyRampUp(6, currentYear, 100),new MonthlyRampUp(7, currentYear, 100),new MonthlyRampUp(8, currentYear, 100),
|
||||
new MonthlyRampUp(9, currentYear, 100),new MonthlyRampUp(10, currentYear, 100),new MonthlyRampUp(11, currentYear, 100),new MonthlyRampUp(12, currentYear, 100)
|
||||
};
|
||||
const bool isInverse = true;
|
||||
const bool isSeasonal = true;
|
||||
double[] goalUnits = { 460.165, 368.132, 607.4178, 312.9122, 276.099, 239.2858, 294.5056, 257.6924, 184.066, 18.4066, 1601.3742, 404.9452 };
|
||||
double[] baselineUnits = { 500, 500, 500, 500, 400, 500, 500, 600, 500, 500, 700, 1000 };
|
||||
double[] baselineStats = { 25, 20, 33, 17, 15, 13, 16, 14, 10, 1, 87, 22 };
|
||||
double[] trackingUnits = { 0, 0, 0, 200, 350, 400, 800, 700, 650, 9000, 130, 500 };
|
||||
double[] trackingStats = { 0, 0, 0, 20, 20, 20, 20, 20, 20, 20, 20, 20 };
|
||||
|
||||
var trackingYearMonths = GetTrackingYearMonths(currentYear).ToList();
|
||||
|
||||
var performanceBaselineData = PerformanceComparisonData.SetupBaselineDataList(baselineUnits, baselineStats, currentYear - 1);
|
||||
var performanceTrackingData = PerformanceComparisonData.SetupTrackingDataList(goalUnits, trackingUnits, trackingStats, currentYear);
|
||||
|
||||
var group = new PerformanceGroup(1, "testItem");
|
||||
var options = new PerformanceOptions(isSeasonal, isInverse, true);
|
||||
|
||||
var testGroup = new PerformanceTrackingItem(group, rampUps, options, performanceBaselineData, performanceTrackingData, trackingYearMonths);
|
||||
|
||||
await Verifier.Verify(testGroup.MonthlyTrackingData, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test(Description = "Dave Mulka 10% reduction non-seasonal")]
|
||||
public async Task TestMisalignedTrackingPeriodsReduction()
|
||||
{
|
||||
var currentYear = DateTime.Now.Year;
|
||||
MonthlyRampUp[] rampUps =
|
||||
{
|
||||
new MonthlyRampUp(1, currentYear, 50), new MonthlyRampUp(2, currentYear, 75), new MonthlyRampUp(3, currentYear, 100),
|
||||
new MonthlyRampUp(4, currentYear, 100), new MonthlyRampUp(5, currentYear, 100),new MonthlyRampUp(6, currentYear, 100)
|
||||
};
|
||||
const bool isInverse = true;
|
||||
const bool isSeasonal = false;
|
||||
double[] baselineUnits = { 16, 21, 15, 22, 18, 29, 16, 26, 9 };
|
||||
double[] baselineStats = { 9, 14, 10, 12, 11, 17, 10, 14, 7 };
|
||||
double[] trackingUnits = { 7, 6, 8, 12, 7, 11 };
|
||||
//seasonality = false, so we spread the goal across the tracking months
|
||||
var baselineUnitAverageGoal = baselineUnits.Average() * 0.9;
|
||||
double[] goalUnits = { baselineUnitAverageGoal, baselineUnitAverageGoal, baselineUnitAverageGoal, baselineUnitAverageGoal, baselineUnitAverageGoal, baselineUnitAverageGoal };
|
||||
double[] trackingStats = { 4, 3, 5, 6, 4, 7 };
|
||||
|
||||
var trackingYearMonths = GetTrackingYearMonths(currentYear, 6).ToList();
|
||||
|
||||
var performanceBaselineData = PerformanceComparisonData.SetupBaselineDataList(baselineUnits, baselineStats, currentYear - 1, 4);
|
||||
var performanceTrackingData = PerformanceComparisonData.SetupTrackingDataList(goalUnits, trackingUnits, trackingStats, currentYear);
|
||||
|
||||
var group = new PerformanceGroup(1, "testItem");
|
||||
var options = new PerformanceOptions(isSeasonal, isInverse, true);
|
||||
|
||||
var testGroup = new PerformanceTrackingItem(group, rampUps, options, performanceBaselineData, performanceTrackingData, trackingYearMonths);
|
||||
|
||||
await Verifier.Verify(testGroup.MonthlyTrackingData, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test(Description = "Dave Mulka 10% reduction seasonal")]
|
||||
public async Task TestMisalignedTrackingPeriodsReductionSeasonal()
|
||||
{
|
||||
var currentYear = DateTime.Now.Year;
|
||||
MonthlyRampUp[] rampUps =
|
||||
{
|
||||
new MonthlyRampUp(1, currentYear, 50), new MonthlyRampUp(2, currentYear, 75), new MonthlyRampUp(3, currentYear, 100),
|
||||
new MonthlyRampUp(4, currentYear, 100), new MonthlyRampUp(5, currentYear, 100),new MonthlyRampUp(6, currentYear, 100)
|
||||
};
|
||||
const bool isInverse = true;
|
||||
const bool isSeasonal = true;
|
||||
double[] baselineUnits = { 16, 21, 15, 22, 18, 29, 16, 26, 9 };
|
||||
double[] baselineStats = { 9, 14, 10, 12, 11, 17, 10, 14, 7 };
|
||||
double[] trackingUnits = { 7, 6, 8, 12, 7, 11 };
|
||||
//no month match for the first three months, so we use the baseline average to calculate our monthly goal
|
||||
var baselineUnitAverageGoal = baselineUnits.Average() * 0.9;
|
||||
double[] goalUnits = { baselineUnitAverageGoal, baselineUnitAverageGoal, baselineUnitAverageGoal, 14.4, 18.9, 13.5 };
|
||||
double[] trackingStats = { 4, 3, 5, 6, 4, 7 };
|
||||
|
||||
var trackingYearMonths = GetTrackingYearMonths(currentYear, 6).ToList();
|
||||
|
||||
var performanceBaselineData = PerformanceComparisonData.SetupBaselineDataList(baselineUnits, baselineStats, currentYear - 1, 4);
|
||||
var performanceTrackingData = PerformanceComparisonData.SetupTrackingDataList(goalUnits, trackingUnits, trackingStats, currentYear);
|
||||
|
||||
var group = new PerformanceGroup(1, "testItem");
|
||||
var options = new PerformanceOptions(isSeasonal, isInverse, true);
|
||||
|
||||
var testGroup = new PerformanceTrackingItem(group, rampUps, options, performanceBaselineData, performanceTrackingData, trackingYearMonths);
|
||||
|
||||
await Verifier.Verify(testGroup.MonthlyTrackingData, _verifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
internal static IEnumerable<TrackingYearMonth> GetTrackingYearMonths(int year, int count = 12)
|
||||
{
|
||||
return Enumerable.Range(1, count).ToList()
|
||||
.ConvertAll(i =>
|
||||
{
|
||||
var ym = new TrackingYearMonth(year, year,
|
||||
new FiscalMonth(Guid.NewGuid(), (byte)i, (byte)i, $"{i}", "", "", 0, 0, $"Month{i:00}", 0, 0), true, true, true);
|
||||
return ym;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
+295
@@ -0,0 +1,295 @@
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.Filter;
|
||||
using Strata.ContinuousImprovement.Biz.Pagination;
|
||||
using Strata.ContinuousImprovement.Biz.QualityVariation.Breakdowns;
|
||||
using Strata.ContinuousImprovement.Biz.QualityVariation.Breakdowns.Filters;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.QualityVariation.Breakdowns
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class QVIBreakdownServiceTest
|
||||
{
|
||||
private Mock<IQVIBreakdownService> _qviBreakdownServiceMock;
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
_qviBreakdownServiceMock = new Mock<IQVIBreakdownService>();
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFrameworkWithFilterData))]
|
||||
public async Task TestGetPagedAsyncWithFramework(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, QVIBreakdownFilters filters, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var qviBreakdownService = new QVIBreakdownService(jazzEntityFrameworkFactory, null, null);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await qviBreakdownService
|
||||
.GetPagedAsync(new PagingOptions(), filters, cancellationToken);
|
||||
|
||||
// assert
|
||||
var result = taskResult.Data;
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
result.Should().BeNullOrEmpty();
|
||||
return;
|
||||
}
|
||||
|
||||
result.Should()
|
||||
.NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIBreakdown>();
|
||||
|
||||
if (filters.BreakdownIds.Any())
|
||||
result.Should()
|
||||
.Contain(vo => filters.BreakdownIds.Contains(vo.BreakdownId.ToString()));
|
||||
}
|
||||
catch (AssertionException)
|
||||
{
|
||||
// Intentionally left empty
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Asc()
|
||||
{
|
||||
// arrange
|
||||
var qviBreakdownService = new QVIBreakdownService(new JazzEntityFrameworkFactory(), null, null);
|
||||
var filters = new QVIBreakdownFilters()
|
||||
{
|
||||
IdentifiedSavings = 0,
|
||||
BreakdownIds = new List<string>(),
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions() { SortField = "QVICasesTotal", SortOrder = SortOrder.Asc };
|
||||
|
||||
// act
|
||||
var taskResult = await qviBreakdownService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIBreakdown>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().QVICasesTotal
|
||||
.Should().BeLessThan(taskResult.Data.Last().QVICasesTotal);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Desc()
|
||||
{
|
||||
// arrange
|
||||
var qviBreakdownService = new QVIBreakdownService(new JazzEntityFrameworkFactory(), null, null);
|
||||
var filters = new QVIBreakdownFilters()
|
||||
{
|
||||
IdentifiedSavings = 0,
|
||||
BreakdownIds = new List<string>(),
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions() { SortField = "QVICasesTotal", SortOrder = SortOrder.Desc };
|
||||
|
||||
// act
|
||||
var taskResult = await qviBreakdownService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIBreakdown>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().QVICasesTotal
|
||||
.Should().BeGreaterThan(taskResult.Data.Last().QVICasesTotal);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFilterData))]
|
||||
public void TestValidateFilters(QVIBreakdownFilters filters)
|
||||
{
|
||||
if (filters == null) return;
|
||||
if (filters.BreakdownIds.Any())
|
||||
filters.BreakdownIds.Should()
|
||||
.AllBeOfType<string>()
|
||||
.And.NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetFilterOptionsAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var qviBreakdownService = new QVIBreakdownService(jazzEntityFrameworkFactory, null, null);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await qviBreakdownService
|
||||
.GetFilterOptionsAsync(new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
return;
|
||||
}
|
||||
taskResult.Should()
|
||||
.BeOfType<QVIBreakdownFilterOptions>()
|
||||
.And.NotBeNull();
|
||||
taskResult.Breakdowns.Should().AllBeOfType<FilterMember>().And.NotBeNullOrEmpty()
|
||||
.And.NotContain(cd => string.IsNullOrEmpty(cd.Id))
|
||||
.And.NotContain(cd => string.IsNullOrEmpty(cd.Text));
|
||||
}
|
||||
catch (NotImplementedException nie)
|
||||
{
|
||||
nie.Should().BeOfType<NotImplementedException>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
#region JazzDbService Tests
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetAllAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var qviBreakdownService = new QVIBreakdownService(jazzEntityFrameworkFactory, null, null);
|
||||
|
||||
// act
|
||||
var taskResult = await qviBreakdownService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
[Test, Ignore("Broken due to removal of Key from VariationCaseType")]
|
||||
public async Task TestGetAllAsync_Filtered()
|
||||
{
|
||||
// arrange
|
||||
var factory = new JazzEntityFrameworkFactory();
|
||||
var filters = factory.QVIOpportunities;
|
||||
var qviBreakdownService = new QVIBreakdownService(factory, null, null);
|
||||
|
||||
// act
|
||||
var taskResult = await qviBreakdownService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIBreakdown>()
|
||||
.And.HaveCountGreaterThan(0)
|
||||
.And.NotContain(o => string.IsNullOrEmpty(o.ToString()))
|
||||
.And.Contain(o => filters.Select(f => f.BreakdownName).Contains(o.BreakdownName))
|
||||
.And.Contain(o => filters.Select(f => f.ConfigurationGuid).Contains(o.ConfigurationGuid));
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks)), Ignore("Complex key issue")]
|
||||
public async Task TestGetById(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var qviBreakdownService = new QVIBreakdownService(jazzEntityFrameworkFactory, null, null);
|
||||
var tempResult = await qviBreakdownService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// act
|
||||
var taskResult =
|
||||
await qviBreakdownService.GetById(tempResult.FirstOrDefault()?.BreakdownId ?? 1, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<QVIBreakdown>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks)), Ignore("Complex key issue")]
|
||||
public async Task TestGetByIds(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var qviBreakdownService = new QVIBreakdownService(jazzEntityFrameworkFactory, null, null);
|
||||
var tempResult = await qviBreakdownService.GetAllAsync(CancellationToken.None);
|
||||
var ids = tempResult.Select(o => o.BreakdownId);
|
||||
|
||||
// act
|
||||
var taskResult = await qviBreakdownService.GetByIds(ids, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIBreakdown>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
|
||||
// Method intentionally left empty.
|
||||
|
||||
}
|
||||
|
||||
#region TestCaseData
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFilterData()
|
||||
{
|
||||
yield return new TestCaseData(new QVIBreakdownFilters { ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("No Filters");
|
||||
yield return new TestCaseData(new QVIBreakdownFilters { IdentifiedSavings = 1999, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings");
|
||||
yield return new TestCaseData(new QVIBreakdownFilters { BreakdownIds = new[] { "1" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By Breakdown");
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFrameworkWithFilterData()
|
||||
{
|
||||
var testCases = GetFilterData().ToList();
|
||||
var jeffs = JazzEntityFrameworkFactory.GetFrameworksWithCancellation()
|
||||
.Select(tcd => tcd.Arguments);
|
||||
foreach (var tcd in jeffs)
|
||||
{
|
||||
var jeff = (JazzEntityFrameworkFactory)tcd[0];
|
||||
var ct = (CancellationToken)tcd[1];
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
yield return new TestCaseData(jeff, testCase.Arguments.GetValue(0), ct)
|
||||
.SetName($"{testCase.TestName} {(string.IsNullOrEmpty(jeff.TestName) ? "w/o Jeff" : "w/Jeff")}")
|
||||
.SetCategory(jeff.TestName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+291
@@ -0,0 +1,291 @@
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.Filter;
|
||||
using Strata.ContinuousImprovement.Biz.Pagination;
|
||||
using Strata.ContinuousImprovement.Biz.QualityVariation.Events;
|
||||
using Strata.ContinuousImprovement.Biz.QualityVariation.Events.Filters;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.QualityVariation.Events
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Minor Code Smell", "S101:Types should be named in PascalCase", Justification = "Standard abbreviation")]
|
||||
public class QVIEventServiceTest
|
||||
{
|
||||
private Mock<IQVIEventService> _qviEventSeriveMock;
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
_qviEventSeriveMock = new Mock<IQVIEventService>();
|
||||
}
|
||||
|
||||
|
||||
[TestCaseSource(nameof(GetFrameworkWithFilterData))]
|
||||
public async Task TestGetPagedAsyncWithFramework(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, QVIEventFilters filters, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var qviEventService = new QVIEventService(jazzEntityFrameworkFactory, null, null);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await qviEventService.GetPagedAsync(new PagingOptions(), filters, cancellationToken);
|
||||
|
||||
// assert
|
||||
var result = taskResult.Data;
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
result.Should().BeNullOrEmpty();
|
||||
return;
|
||||
}
|
||||
|
||||
result.Should().NotBeNullOrEmpty().And.AllBeOfType<QVIEvent>();
|
||||
|
||||
if (filters.QualityVariationEventIds.Any())
|
||||
result.Should()
|
||||
.Contain(vo => filters.QualityVariationEventIds.Contains(vo.QualityVariationEventName.ToString()));
|
||||
}
|
||||
catch (AssertionException)
|
||||
{
|
||||
// Intentionally left empty
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Asc()
|
||||
{
|
||||
// arrange
|
||||
var qviEventService = new QVIEventService(new JazzEntityFrameworkFactory(), null, null);
|
||||
var filters = new QVIEventFilters()
|
||||
{
|
||||
QualityVariationEventIds = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
QVICases = 0,
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions() { SortField = "QVICasesTotal", SortOrder = SortOrder.Asc };
|
||||
|
||||
// act
|
||||
var taskResult = await qviEventService.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIEvent>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().QVICasesTotal.Should().BeLessThan(taskResult.Data.Last().QVICasesTotal);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Desc()
|
||||
{
|
||||
// arrange
|
||||
var qviEventService = new QVIEventService(new JazzEntityFrameworkFactory(), null, null);
|
||||
var filters = new QVIEventFilters()
|
||||
{
|
||||
QualityVariationEventIds = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
QVICases = 0,
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions() { SortField = "QVICasesTotal", SortOrder = SortOrder.Desc };
|
||||
|
||||
// act
|
||||
var taskResult = await qviEventService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIEvent>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().QVICasesTotal.Should().BeGreaterThan(taskResult.Data.Last().QVICasesTotal);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFilterData))]
|
||||
public void TestValidateFilters(QVIEventFilters filters)
|
||||
{
|
||||
if (filters == null) return;
|
||||
if (filters.QualityVariationEventIds.Any())
|
||||
filters.QualityVariationEventIds.Should()
|
||||
.AllBeOfType<string>()
|
||||
.And.NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetFilterOptionsAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var qviEventService = new QVIEventService(jazzEntityFrameworkFactory, null, null);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await qviEventService
|
||||
.GetFilterOptionsAsync(new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
return;
|
||||
}
|
||||
taskResult.Should().BeOfType<QVIEventFilterOptions>().And.NotBeNull();
|
||||
taskResult.QualityVariationEvents.Should().AllBeOfType<FilterMember>()
|
||||
.And.NotBeNullOrEmpty()
|
||||
.And.NotContain(cd => string.IsNullOrEmpty(cd.Id))
|
||||
.And.NotContain(cd => string.IsNullOrEmpty(cd.Text));
|
||||
}
|
||||
catch (NotImplementedException nie)
|
||||
{
|
||||
nie.Should().BeOfType<NotImplementedException>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
#region JazzDbService Tests
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetAllAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var qviEventService = new QVIEventService(jazzEntityFrameworkFactory, null, null);
|
||||
|
||||
// act
|
||||
var taskResult = await qviEventService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
[Test, Ignore("Broken due to removal of Key from VariationCaseType")]
|
||||
public async Task TestGetAllAsync_Filtered()
|
||||
{
|
||||
// arrange
|
||||
var factory = new JazzEntityFrameworkFactory();
|
||||
var filters = factory.QVIOpportunities;
|
||||
var qviEventService = new QVIEventService(factory, null, null);
|
||||
|
||||
// act
|
||||
var taskResult = await qviEventService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIEvent>()
|
||||
.And.HaveCountGreaterThan(0)
|
||||
.And.NotContain(o => string.IsNullOrEmpty(o.ToString()))
|
||||
.And.Contain(o => filters.Select(f => f.QualityVariationEventName).Contains(o.QualityVariationEventName))
|
||||
.And.Contain(o => filters.Select(f => f.ConfigurationGuid).Contains(o.ConfigurationGuid));
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks)), Ignore("Complex key issue")]
|
||||
public async Task TestGetById(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var qviEventService = new QVIEventService(jazzEntityFrameworkFactory, null, null);
|
||||
var tempResult = await qviEventService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// act
|
||||
var taskResult =
|
||||
await qviEventService.GetById(tempResult.FirstOrDefault()?.QualityVariationEventId ?? 1, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<QVIEvent>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks)), Ignore("Complex key issue")]
|
||||
public async Task TestGetByIds(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var qviEventService = new QVIEventService(jazzEntityFrameworkFactory, null, null);
|
||||
var tempResult = await qviEventService.GetAllAsync(CancellationToken.None);
|
||||
var ids = tempResult.Select(o => o.QualityVariationEventId);
|
||||
|
||||
// act
|
||||
var taskResult = await qviEventService.GetByIds(ids, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIEvent>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
|
||||
}
|
||||
|
||||
#region TestCaseData
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFilterData()
|
||||
{
|
||||
yield return new TestCaseData(new QVIEventFilters { ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("No Filters");
|
||||
yield return new TestCaseData(new QVIEventFilters { IdentifiedSavings = 1999, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings");
|
||||
yield return new TestCaseData(new QVIEventFilters { QualityVariationEventIds = new[] { "1" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By Event ID");
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFrameworkWithFilterData()
|
||||
{
|
||||
var testCases = GetFilterData().ToList();
|
||||
var jeffs = JazzEntityFrameworkFactory.GetFrameworksWithCancellation()
|
||||
.Select(tcd => tcd.Arguments);
|
||||
foreach (var tcd in jeffs)
|
||||
{
|
||||
var jeff = (JazzEntityFrameworkFactory)tcd[0];
|
||||
var ct = (CancellationToken)tcd[1];
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
yield return new TestCaseData(jeff, testCase.Arguments.GetValue(0), ct)
|
||||
.SetName($"{testCase.TestName} {(string.IsNullOrEmpty(jeff.TestName) ? "w/o Jeff" : "w/Jeff")}")
|
||||
.SetCategory(jeff.TestName);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+642
@@ -0,0 +1,642 @@
|
||||
using ClosedXML.Excel;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.Configuration;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.Filter;
|
||||
using Strata.ContinuousImprovement.Biz.Generics;
|
||||
using Strata.ContinuousImprovement.Biz.Initiatives;
|
||||
using Strata.ContinuousImprovement.Biz.Pagination;
|
||||
using Strata.ContinuousImprovement.Biz.QualityVariation.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.QualityVariation.Opportunities.Filters;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.SqlTools.Configuration.Common.AsyncFactory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.QualityVariation.Opportunities
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class QVIOpportunityServiceTest
|
||||
{
|
||||
|
||||
private Mock<IQVIOpportunityService> _qualityVariationItemOpportunityServiceMock;
|
||||
private Mock<IAsyncDbContextFactory<JazzDbContext>> _dbContextFactoryMock;
|
||||
private Mock<IJazzDbContext> _jazzDbContextMock;
|
||||
private IInitiativeService _initiativeService;
|
||||
private IUpdateFactOpportunitySavingsService _updateFactOpportunitySavingsService;
|
||||
private IConfigurationService _configurationService;
|
||||
private ILogger<QVIOpportunityService> _logger;
|
||||
private static readonly ResourceFileExtractor _extractor = new ResourceFileExtractor(".Resource.");
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
_qualityVariationItemOpportunityServiceMock = new Mock<IQVIOpportunityService>();
|
||||
_dbContextFactoryMock = new Mock<IAsyncDbContextFactory<JazzDbContext>>();
|
||||
_jazzDbContextMock = new Mock<IJazzDbContext>();
|
||||
_initiativeService = Mock.Of<IInitiativeService>();
|
||||
_updateFactOpportunitySavingsService = Mock.Of<IUpdateFactOpportunitySavingsService>();
|
||||
_configurationService = Mock.Of<IConfigurationService>();
|
||||
_logger = Mock.Of<ILogger<QVIOpportunityService>>();
|
||||
Mock.Get(_initiativeService)
|
||||
.Setup(s => s.DeleteAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(true));
|
||||
Mock.Get(_updateFactOpportunitySavingsService)
|
||||
.Setup(s => s.UpdateFactOpportunitySavings(It.IsAny<CancellationToken>()));
|
||||
Mock.Get(_configurationService)
|
||||
.Setup(s => s.GetConfigurationAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync((Guid guid, CancellationToken ct) => new Biz.Configuration.Configuration { ConfigurationGuid = guid });
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFrameworkWithFilterData))]
|
||||
public async Task TestGetPagedAsyncWithFramework(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, QVIFilters filters, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var qualityVariationItemOpportunityService = new QVIOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await qualityVariationItemOpportunityService
|
||||
.GetPagedAsync(new PagingOptions(), filters, cancellationToken);
|
||||
|
||||
// assert
|
||||
var result = taskResult.Data;
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
result.Should().BeNullOrEmpty();
|
||||
return;
|
||||
}
|
||||
|
||||
result.Should()
|
||||
.NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIOpportunity>();
|
||||
|
||||
if (filters.BreakdownIds.Any())
|
||||
result.Should()
|
||||
.Contain(vo => filters.BreakdownIds.Contains(vo.BreakdownId.ToString()));
|
||||
if (filters.ExcludeInitiatives)
|
||||
{
|
||||
result.ToList().ForEach(opportunity => opportunity.HasInitiative.Should().Be(false));
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filters.OpportunitySearch))
|
||||
result.Should()
|
||||
.Contain(vo => vo.OpportunityKey.Contains(filters.OpportunitySearch));
|
||||
}
|
||||
catch (AssertionException)
|
||||
{
|
||||
// Intentionally left empty
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Asc()
|
||||
{
|
||||
// arrange
|
||||
var qualityVariationItemOpportunityService = new QVIOpportunityService(new JazzEntityFrameworkFactory(), null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
var filters = new QVIFilters()
|
||||
{
|
||||
QualityVariationEventIds = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
BreakdownIds = new List<string>(),
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions() { SortField = "QVICases", SortOrder = SortOrder.Asc };
|
||||
|
||||
// act
|
||||
var taskResult = await qualityVariationItemOpportunityService
|
||||
.GetPagedAsync(new PagingOptions(), filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIOpportunity>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().QVICases
|
||||
.Should().BeLessThan(taskResult.Data.Last().QVICases);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Desc()
|
||||
{
|
||||
// arrange
|
||||
var qualityVariationItemOpportunityService = new QVIOpportunityService(new JazzEntityFrameworkFactory(), null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
var filters = new QVIFilters()
|
||||
{
|
||||
QualityVariationEventIds = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
BreakdownIds = new List<string>(),
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions() { SortField = "QVICases", SortOrder = SortOrder.Desc };
|
||||
|
||||
// act
|
||||
var taskResult = await qualityVariationItemOpportunityService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIOpportunity>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().QVICases
|
||||
.Should().BeGreaterThan(taskResult.Data.Last().QVICases);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFilterData))]
|
||||
public void TestValidateFilters(QVIFilters filters)
|
||||
{
|
||||
if (filters == null) return;
|
||||
if (filters.QualityVariationEventIds.Any())
|
||||
filters.QualityVariationEventIds.Should()
|
||||
.AllBeOfType<string>()
|
||||
.And.NotBeNullOrEmpty();
|
||||
if (filters.BreakdownIds.Any())
|
||||
filters.BreakdownIds.Should()
|
||||
.AllBeOfType<string>()
|
||||
.And.NotBeNullOrEmpty();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetExcelWorkbook()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var filters = new QVIFilters()
|
||||
{
|
||||
ConfigurationGuid = framework.Configurations.First().ConfigurationGuid,
|
||||
BreakdownIds = new[] { framework.QVIOpportunities.First().BreakdownId.ToString() },
|
||||
QualityVariationEventIds = new[]
|
||||
{framework.QVIOpportunities.First().QualityVariationEventId.ToString()},
|
||||
};
|
||||
var service = new QVIOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
|
||||
// act
|
||||
var wb = await service.ExportAsync(new SortOptions(), filters, CancellationToken.None);
|
||||
#pragma warning disable S125 // Sections of code should not be commented out
|
||||
//wb.SaveAs(System.IO.Path.Combine(@"C:\Git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "ExcelFilter.xlsx"));
|
||||
#pragma warning restore S125 // Sections of code should not be commented out
|
||||
|
||||
// assert
|
||||
wb.Worksheets.Should().HaveCount(1);
|
||||
var ws = wb.Worksheet(1);
|
||||
ws.Should().NotBeNull();
|
||||
|
||||
var expected = @"Examples.QualityVariationItemOpportunity.ExcelFilter.xlsx";
|
||||
using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected))
|
||||
using (var actualStream = new MemoryStream())
|
||||
{
|
||||
wb.SaveAs(actualStream);
|
||||
actualStream.Compare(expectedStream, out var message).Should().BeTrue(message);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetExcelWorkbookNullFilter()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
|
||||
var service = new QVIOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
|
||||
// act
|
||||
var wb = await service.ExportAsync(null, null, CancellationToken.None);
|
||||
#pragma warning disable S125 // Sections of code should not be commented out
|
||||
//wb.SaveAs(System.IO.Path.Combine(@"C:\Git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "ExcelNullFilter.xlsx"));
|
||||
#pragma warning restore S125 // Sections of code should not be commented out
|
||||
|
||||
// assert
|
||||
wb.Worksheets.Should().HaveCount(1);
|
||||
var ws = wb.Worksheet(1);
|
||||
ws.Should().NotBeNull();
|
||||
|
||||
var expected = @"Examples.QualityVariationItemOpportunity.ExcelNullFilter.xlsx";
|
||||
using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected))
|
||||
using (var actualStream = new MemoryStream())
|
||||
{
|
||||
wb.SaveAs(actualStream);
|
||||
actualStream.Compare(expectedStream, out var message).Should().BeTrue(message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetExcelWorkbookWithFramework(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var variationOpportunityService = new QVIOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
var filters = new QVIFilters
|
||||
{
|
||||
IdentifiedSavings = 0,
|
||||
QVICases = 0,
|
||||
BreakdownIds = new List<string>(),
|
||||
QualityVariationEventIds = new List<string>(),
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult =
|
||||
await variationOpportunityService.ExportAsync(new SortOptions(), filters, cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<XLWorkbook>();
|
||||
var wb = taskResult;
|
||||
wb.Worksheets.Should().HaveCountGreaterThan(0);
|
||||
var ws = wb.Worksheet("Sheet1");
|
||||
ws.ColumnCount().Should().BeGreaterThan(0);
|
||||
ws.RowCount().Should().BeGreaterThan(0);
|
||||
}
|
||||
}
|
||||
catch (TypeInitializationException tie)
|
||||
{
|
||||
tie.Should().BeOfType<TypeInitializationException>();
|
||||
}
|
||||
catch (AssertionException ae)
|
||||
{
|
||||
ae.Should().BeOfType<AssertionException>();
|
||||
}
|
||||
catch (ArgumentNullException arg)
|
||||
{
|
||||
arg.Should().BeOfType<ArgumentNullException>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSetHidden()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunities = framework.QVIOpportunities;
|
||||
var opportunity = opportunities.First(vo => !vo.IsHidden);
|
||||
var isHidden = opportunity.IsHidden;
|
||||
var service = new QVIOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
|
||||
// act
|
||||
await service.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
result.IsHidden.Should().Be(!isHidden);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetFilterOptionsAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var qualityVariationItemOpportunityService = new QVIOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await qualityVariationItemOpportunityService
|
||||
.GetFilterOptionsAsync(new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
return;
|
||||
}
|
||||
taskResult.Should()
|
||||
.BeOfType<QVIFilterOptions>()
|
||||
.And.NotBeNull();
|
||||
taskResult.Breakdowns.Should().AllBeOfType<FilterMember>().And.NotBeNullOrEmpty()
|
||||
.And.NotContain(cd => string.IsNullOrEmpty(cd.Id))
|
||||
.And.NotContain(cd => string.IsNullOrEmpty(cd.Text));
|
||||
}
|
||||
catch (NotImplementedException nie)
|
||||
{
|
||||
nie.Should().BeOfType<NotImplementedException>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var qualityVariationItemOpportunityService = new QVIOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
try
|
||||
{
|
||||
var opportunities = qualityVariationItemOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;
|
||||
|
||||
//act
|
||||
await qualityVariationItemOpportunityService.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden,
|
||||
cancellationToken);
|
||||
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return;
|
||||
var result = qualityVariationItemOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result;
|
||||
result.IsHidden.Should().Be(!isHidden);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
switch (e.GetType().Name)
|
||||
{
|
||||
case "AggregateException":
|
||||
case "OperationCanceledException":
|
||||
return;
|
||||
}
|
||||
e.Should().NotBeOfType<Exception>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.QVIOpportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;
|
||||
var qualityVariationItemOpportunityService = new QVIOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await qualityVariationItemOpportunityService.SetHiddenAsync(Guid.Empty, !isHidden,
|
||||
cancellationToken);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSetNote()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var opportunities = framework.QVIOpportunities;
|
||||
var opportunity = opportunities.First(vo => string.IsNullOrEmpty(vo.Note));
|
||||
var note = opportunity.Note;
|
||||
var expected = "Now is the time for all good engineers to write great code!";
|
||||
var service = new QVIOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
|
||||
// act
|
||||
await service.SetNoteAsync(opportunity.OpportunityGuid, expected, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None);
|
||||
result.Note.Should().NotBeNullOrEmpty()
|
||||
.And.NotBe(note)
|
||||
.And.Be(expected);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var qualityVariationItemOpportunityService = new QVIOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
try
|
||||
{
|
||||
var opportunities = qualityVariationItemOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
if (opportunity == null) return;
|
||||
var note = "new test note";
|
||||
// act
|
||||
await qualityVariationItemOpportunityService.SetNoteAsync(opportunity.OpportunityGuid, note,
|
||||
CancellationToken.None);
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return;
|
||||
var result = qualityVariationItemOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result;
|
||||
result.Note.Should().Be(note);
|
||||
|
||||
// assert
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
switch (e.GetType().Name)
|
||||
{
|
||||
case "AggregateException":
|
||||
case "OperationCanceledException":
|
||||
return;
|
||||
}
|
||||
e.Should().NotBeOfType<Exception>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.QVIOpportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
if (opportunity == null) return;
|
||||
var note = "new test note";
|
||||
var qualityVariationItemOpportunityService = new QVIOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await qualityVariationItemOpportunityService.SetNoteAsync(Guid.Empty, note, cancellationToken);
|
||||
|
||||
// assert
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region JazzDbService Tests
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetAllAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var qualityVariationItemOpportunityService = new QVIOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
|
||||
// act
|
||||
var taskResult = await qualityVariationItemOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
[Test, Ignore("Broken due to removal of Key from VariationCaseType")]
|
||||
public async Task TestGetAllAsync_Filtered()
|
||||
{
|
||||
// arrange
|
||||
var factory = new JazzEntityFrameworkFactory();
|
||||
var filters = factory.QVIOpportunities;
|
||||
var qualityVariationItemOpportunityService = new QVIOpportunityService(factory, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
|
||||
// act
|
||||
var taskResult = await qualityVariationItemOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIOpportunity>()
|
||||
.And.HaveCountGreaterThan(0)
|
||||
.And.NotContain(o => string.IsNullOrEmpty(o.ToString()))
|
||||
.And.Contain(o => filters.Select(f => f.OpportunityGuid).Contains(o.OpportunityGuid))
|
||||
.And.Contain(o => filters.Select(f => f.BreakdownName).Contains(o.BreakdownName))
|
||||
.And.Contain(o => filters.Select(f => f.ConfigurationGuid).Contains(o.ConfigurationGuid));
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetById(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var qualityVariationItemOpportunityService = new QVIOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
|
||||
// act
|
||||
var tempResult = await qualityVariationItemOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var taskResult =
|
||||
await qualityVariationItemOpportunityService.GetById(tempResult.FirstOrDefault()?.OpportunityGuid ?? Guid.Empty, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<QVIOpportunity>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetByIds(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var qualityVariationItemOpportunityService = new QVIOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService, _configurationService, _logger);
|
||||
|
||||
// act
|
||||
var tempResult = await qualityVariationItemOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var ids = tempResult.Select(o => o.OpportunityGuid);
|
||||
var taskResult = await qualityVariationItemOpportunityService.GetByIds(ids, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<QVIOpportunity>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
|
||||
#region TestCaseData
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFilterData()
|
||||
{
|
||||
yield return new TestCaseData(new QVIFilters { ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("No Filters");
|
||||
yield return new TestCaseData(new QVIFilters { ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("View Visible");
|
||||
yield return new TestCaseData(new QVIFilters { ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Not View Visible");
|
||||
yield return new TestCaseData(new QVIFilters { IdentifiedSavings = 1999, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings");
|
||||
yield return new TestCaseData(new QVIFilters { IdentifiedSavings = 999, ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings Not ViewVisible");
|
||||
yield return new TestCaseData(new QVIFilters { BreakdownIds = new[] { "1" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By Breakdown");
|
||||
yield return new TestCaseData(new QVIFilters { BreakdownIds = new[] { "2" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), ViewVisible = false })
|
||||
.SetName("By Breakdown Not ViewVisible");
|
||||
yield return new TestCaseData(new QVIFilters { QualityVariationEventIds = new[] { "1" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By QualityVariationEvent");
|
||||
yield return new TestCaseData(new QVIFilters { QualityVariationEventIds = new[] { "2" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), ViewVisible = false })
|
||||
.SetName("By QualityVariationEvent Not ViewVisible");
|
||||
yield return new TestCaseData(new QVIFilters { OpportunitySearch = "QV - 123", ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Search By Id");
|
||||
yield return new TestCaseData(new QVIFilters { ExcludeInitiatives = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Exclude Opportunities with Initiatives");
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFrameworkWithFilterData()
|
||||
{
|
||||
var testCases = GetFilterData().ToList();
|
||||
var jeffs = JazzEntityFrameworkFactory.GetFrameworksWithCancellation()
|
||||
.Select(tcd => tcd.Arguments);
|
||||
foreach (var tcd in jeffs)
|
||||
{
|
||||
var jeff = (JazzEntityFrameworkFactory)tcd[0];
|
||||
var ct = (CancellationToken)tcd[1];
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
yield return new TestCaseData(jeff, testCase.Arguments.GetValue(0), ct)
|
||||
.SetName($"{testCase.TestName} {(string.IsNullOrEmpty(jeff.TestName) ? "w/o Jeff" : "w/Jeff")}")
|
||||
.SetCategory(jeff.TestName);
|
||||
}
|
||||
|
||||
var serviceLineId = jeff.QVIOpportunities.FirstOrDefault(o => !o.IsHidden)?.BreakdownId ?? 0;
|
||||
if (string.IsNullOrEmpty(jeff.TestName))
|
||||
{
|
||||
yield return new TestCaseData(jeff,
|
||||
new QVIFilters { BreakdownIds = new[] { serviceLineId.ToString() }, ViewVisible = false }, ct)
|
||||
.SetName("By Service Line Not ViewVisible w/o Jeff");
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new TestCaseData(jeff, ct, new QVIFilters { BreakdownIds = new[] { serviceLineId.ToString() }, ViewVisible = false })
|
||||
.SetName("By Service Line Not ViewVisible w/Jeff")
|
||||
.Ignore("This test is broken");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
+201
@@ -0,0 +1,201 @@
|
||||
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 NonQviSavingsServiceTest
|
||||
{
|
||||
private Mock<ISnowflakeDatabaseContext> _snowflakeDatabaseContextMock;
|
||||
private Mock<IConfigurationService> _configurationServiceMock;
|
||||
private Mock<ILogger<NonQviSavingsService>> _loggerMock;
|
||||
private NonQviSavingsService _service;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_snowflakeDatabaseContextMock = new Mock<ISnowflakeDatabaseContext>();
|
||||
_configurationServiceMock = new Mock<IConfigurationService>();
|
||||
_loggerMock = new Mock<ILogger<NonQviSavingsService>>();
|
||||
|
||||
_service = new NonQviSavingsService(
|
||||
_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<CancellationToken>()))
|
||||
.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<NonQviCaseTypeFamilyInfo>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetCaseTypeFamilyInfoAsync_WhenNoSourceSystemIds_ReturnsEmpty()
|
||||
{
|
||||
var configurationGuid = Guid.NewGuid();
|
||||
_configurationServiceMock
|
||||
.Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny<CancellationToken>()))
|
||||
.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<NonQviCaseTypeFamilyInfo>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetCaseTypeFamilyInfoAsync_WhenEntitiesExist_QueriesSnowflake()
|
||||
{
|
||||
var configurationGuid = Guid.NewGuid();
|
||||
var expected = new[] { new NonQviCaseTypeFamilyInfo { CaseTypeFamilyId = 10, CaseCount = 3 } };
|
||||
|
||||
_configurationServiceMock
|
||||
.Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new CIConfiguration
|
||||
{
|
||||
EntityIdsCSV = "1",
|
||||
SourceSystemIdsCSV = "1",
|
||||
DepartmentRollupGlobalId = string.Empty,
|
||||
QualityVariationEndDate = new DateTime(2024, 12, 31)
|
||||
});
|
||||
|
||||
_snowflakeDatabaseContextMock
|
||||
.Setup(s => s.QueryAsync<NonQviCaseTypeFamilyInfo>(
|
||||
It.IsAny<string>(),
|
||||
nameof(NonQviSavingsService.GetCaseTypeFamilyInfoAsync),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()))
|
||||
.ReturnsAsync(expected);
|
||||
|
||||
var result = await _service.GetCaseTypeFamilyInfoAsync(configurationGuid, true, CancellationToken.None);
|
||||
|
||||
result.Should().BeEquivalentTo(expected);
|
||||
_snowflakeDatabaseContextMock.Verify(
|
||||
s => s.QueryAsync<NonQviCaseTypeFamilyInfo>(
|
||||
It.IsAny<string>(),
|
||||
nameof(NonQviSavingsService.GetCaseTypeFamilyInfoAsync),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetDrgTypeInfoAsync_WhenNoEntityIds_ReturnsEmpty()
|
||||
{
|
||||
var configurationGuid = Guid.NewGuid();
|
||||
_configurationServiceMock
|
||||
.Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny<CancellationToken>()))
|
||||
.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<NonQviDrgTypeInfo>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetDrgTypeInfoAsync_WhenNoSourceSystemIds_ReturnsEmpty()
|
||||
{
|
||||
var configurationGuid = Guid.NewGuid();
|
||||
_configurationServiceMock
|
||||
.Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny<CancellationToken>()))
|
||||
.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<NonQviDrgTypeInfo>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetDrgTypeInfoAsync_WhenEntitiesExist_QueriesSnowflake()
|
||||
{
|
||||
var configurationGuid = Guid.NewGuid();
|
||||
var expected = new[] { new NonQviDrgTypeInfo { DrgType = "MS" } };
|
||||
|
||||
_configurationServiceMock
|
||||
.Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new CIConfiguration
|
||||
{
|
||||
EntityIdsCSV = "1",
|
||||
SourceSystemIdsCSV = "1",
|
||||
DepartmentRollupGlobalId = string.Empty,
|
||||
QualityVariationEndDate = new DateTime(2024, 12, 31)
|
||||
});
|
||||
|
||||
_snowflakeDatabaseContextMock
|
||||
.Setup(s => s.QueryAsync<NonQviDrgTypeInfo>(
|
||||
It.IsAny<string>(),
|
||||
nameof(NonQviSavingsService.GetDrgTypeInfoAsync),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()))
|
||||
.ReturnsAsync(expected);
|
||||
|
||||
var result = await _service.GetDrgTypeInfoAsync(configurationGuid, true, CancellationToken.None);
|
||||
|
||||
result.Should().BeEquivalentTo(expected);
|
||||
_snowflakeDatabaseContextMock.Verify(
|
||||
s => s.QueryAsync<NonQviDrgTypeInfo>(
|
||||
It.IsAny<string>(),
|
||||
nameof(NonQviSavingsService.GetDrgTypeInfoAsync),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetDrgTypeInfoAsync_WhenConfigurationThrows_Rethrows()
|
||||
{
|
||||
var configurationGuid = Guid.NewGuid();
|
||||
_configurationServiceMock
|
||||
.Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny<CancellationToken>()))
|
||||
.ThrowsAsync(new InvalidOperationException("boom"));
|
||||
|
||||
var action = async () => await _service.GetDrgTypeInfoAsync(configurationGuid, true, CancellationToken.None);
|
||||
|
||||
await action.Should().ThrowAsync<InvalidOperationException>();
|
||||
}
|
||||
}
|
||||
}
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.Configuration;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts.Snowflake;
|
||||
using Strata.ContinuousImprovement.Biz.QualityVariation.QVI;
|
||||
using Strata.SqlTools.Configuration.Common.AsyncFactory;
|
||||
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 QviEncounterServiceTest
|
||||
{
|
||||
private Mock<ISnowflakeDatabaseContext> _snowflakeDatabaseContextMock;
|
||||
private Mock<IConfigurationService> _configurationServiceMock;
|
||||
private Mock<IAsyncDbContextFactory<JazzDbContext>> _dbContextFactoryMock;
|
||||
private Mock<ILogger<QviEncounterService>> _loggerMock;
|
||||
private QviEncounterService _service;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_snowflakeDatabaseContextMock = new Mock<ISnowflakeDatabaseContext>();
|
||||
_configurationServiceMock = new Mock<IConfigurationService>();
|
||||
_dbContextFactoryMock = new Mock<IAsyncDbContextFactory<JazzDbContext>>();
|
||||
_loggerMock = new Mock<ILogger<QviEncounterService>>();
|
||||
|
||||
_service = new QviEncounterService(
|
||||
_snowflakeDatabaseContextMock.Object,
|
||||
_configurationServiceMock.Object,
|
||||
_dbContextFactoryMock.Object,
|
||||
_loggerMock.Object);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetEncounterInfoAsync_WhenNoEntityIds_ReturnsEmptyAndSkipsDatabase()
|
||||
{
|
||||
var configurationGuid = Guid.NewGuid();
|
||||
_configurationServiceMock
|
||||
.Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new CIConfiguration { EntityIdsCSV = string.Empty, SourceSystemIdsCSV = "1" });
|
||||
|
||||
var result = await _service.GetEncounterInfoAsync(configurationGuid, DateTime.UtcNow, DateTime.UtcNow, CancellationToken.None);
|
||||
|
||||
result.Should().BeEmpty();
|
||||
_dbContextFactoryMock.Verify(f => f.CreateDbContextAsync(It.IsAny<CancellationToken>()), Times.Never);
|
||||
_snowflakeDatabaseContextMock.Verify(
|
||||
s => s.QueryAsync<EncounterInfo>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetEncounterInfoAsync_WhenNoSourceSystemIds_ReturnsEmptyAndSkipsDatabase()
|
||||
{
|
||||
var configurationGuid = Guid.NewGuid();
|
||||
_configurationServiceMock
|
||||
.Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new CIConfiguration { EntityIdsCSV = "1", SourceSystemIdsCSV = string.Empty });
|
||||
|
||||
var result = await _service.GetEncounterInfoAsync(configurationGuid, DateTime.UtcNow, DateTime.UtcNow, CancellationToken.None);
|
||||
|
||||
result.Should().BeEmpty();
|
||||
_dbContextFactoryMock.Verify(f => f.CreateDbContextAsync(It.IsAny<CancellationToken>()), Times.Never);
|
||||
_snowflakeDatabaseContextMock.Verify(
|
||||
s => s.QueryAsync<EncounterInfo>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetEncounterInfoAsync_WhenConfigurationThrows_Rethrows()
|
||||
{
|
||||
var configurationGuid = Guid.NewGuid();
|
||||
_configurationServiceMock
|
||||
.Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny<CancellationToken>()))
|
||||
.ThrowsAsync(new InvalidOperationException("boom"));
|
||||
|
||||
var action = async () => await _service.GetEncounterInfoAsync(configurationGuid, DateTime.UtcNow, DateTime.UtcNow, CancellationToken.None);
|
||||
|
||||
await action.Should().ThrowAsync<InvalidOperationException>();
|
||||
}
|
||||
}
|
||||
}
|
||||
+265
@@ -0,0 +1,265 @@
|
||||
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<ISnowflakeDatabaseContext> _snowflakeDatabaseContextMock;
|
||||
private Mock<IConfigurationService> _configurationServiceMock;
|
||||
private Mock<ILogger<QviLineItemSavingsService>> _loggerMock;
|
||||
private QviLineItemSavingsService _service;
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_snowflakeDatabaseContextMock = new Mock<ISnowflakeDatabaseContext>();
|
||||
_configurationServiceMock = new Mock<IConfigurationService>();
|
||||
_loggerMock = new Mock<ILogger<QviLineItemSavingsService>>();
|
||||
|
||||
_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<CancellationToken>()))
|
||||
.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<QviLineItemCaseTypeFamilyInfo>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetCaseTypeFamilyInfoAsync_WhenNoSourceSystemIds_ReturnsEmpty()
|
||||
{
|
||||
var configurationGuid = Guid.NewGuid();
|
||||
_configurationServiceMock
|
||||
.Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny<CancellationToken>()))
|
||||
.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<QviLineItemCaseTypeFamilyInfo>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
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<CancellationToken>()))
|
||||
.ReturnsAsync(new CIConfiguration
|
||||
{
|
||||
EntityIdsCSV = "1",
|
||||
SourceSystemIdsCSV = "1",
|
||||
DepartmentRollupGlobalId = string.Empty,
|
||||
QualityVariationEndDate = new DateTime(2024, 12, 31)
|
||||
});
|
||||
|
||||
_snowflakeDatabaseContextMock
|
||||
.Setup(s => s.QueryAsync<QviLineItemCaseTypeFamilyInfo>(
|
||||
It.IsAny<string>(),
|
||||
nameof(QviLineItemSavingsService.GetCaseTypeFamilyInfoAsync),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()))
|
||||
.ReturnsAsync(expected);
|
||||
|
||||
var result = await _service.GetCaseTypeFamilyInfoAsync(configurationGuid, true, CancellationToken.None);
|
||||
|
||||
result.Should().BeEquivalentTo(expected);
|
||||
_snowflakeDatabaseContextMock.Verify(
|
||||
s => s.QueryAsync<QviLineItemCaseTypeFamilyInfo>(
|
||||
It.IsAny<string>(),
|
||||
nameof(QviLineItemSavingsService.GetCaseTypeFamilyInfoAsync),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetDrgTypeInfoAsync_WhenNoEntityIds_ReturnsEmpty()
|
||||
{
|
||||
var configurationGuid = Guid.NewGuid();
|
||||
_configurationServiceMock
|
||||
.Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny<CancellationToken>()))
|
||||
.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<QviLineItemDrgTypeInfo>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
Times.Never);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetDrgTypeInfoAsync_WhenNoSourceSystemIds_ReturnsEmpty()
|
||||
{
|
||||
var configurationGuid = Guid.NewGuid();
|
||||
_configurationServiceMock
|
||||
.Setup(s => s.GetConfigurationAsync(configurationGuid, It.IsAny<CancellationToken>()))
|
||||
.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<QviLineItemDrgTypeInfo>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
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<CancellationToken>()))
|
||||
.ReturnsAsync(new CIConfiguration
|
||||
{
|
||||
EntityIdsCSV = "1",
|
||||
SourceSystemIdsCSV = "1",
|
||||
DepartmentRollupGlobalId = string.Empty,
|
||||
QualityVariationEndDate = new DateTime(2024, 12, 31)
|
||||
});
|
||||
|
||||
_snowflakeDatabaseContextMock
|
||||
.Setup(s => s.QueryAsync<QviLineItemDrgTypeInfo>(
|
||||
It.IsAny<string>(),
|
||||
nameof(QviLineItemSavingsService.GetDrgTypeInfoAsync),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()))
|
||||
.ReturnsAsync(expected);
|
||||
|
||||
var result = await _service.GetDrgTypeInfoAsync(configurationGuid, true, CancellationToken.None);
|
||||
|
||||
result.Should().BeEquivalentTo(expected);
|
||||
_snowflakeDatabaseContextMock.Verify(
|
||||
s => s.QueryAsync<QviLineItemDrgTypeInfo>(
|
||||
It.IsAny<string>(),
|
||||
nameof(QviLineItemSavingsService.GetDrgTypeInfoAsync),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()),
|
||||
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<CancellationToken>()))
|
||||
.ReturnsAsync(new CIConfiguration());
|
||||
|
||||
_snowflakeDatabaseContextMock
|
||||
.Setup(s => s.QueryAsync<QviLineItemEncounterSavingInfo>(
|
||||
It.IsAny<string>(),
|
||||
nameof(QviLineItemSavingsService.GetEncounterSavingInfoAsync),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()))
|
||||
.ReturnsAsync(expected);
|
||||
|
||||
var result = await _service.GetEncounterSavingInfoAsync(configurationGuid, null, null, CancellationToken.None);
|
||||
|
||||
result.Should().BeEquivalentTo(expected);
|
||||
_snowflakeDatabaseContextMock.Verify(
|
||||
s => s.QueryAsync<QviLineItemEncounterSavingInfo>(
|
||||
It.IsAny<string>(),
|
||||
nameof(QviLineItemSavingsService.GetEncounterSavingInfoAsync),
|
||||
It.Is<object>(o =>
|
||||
o.GetType().GetProperty("ConfigurationGUID") != null &&
|
||||
(Guid)o.GetType().GetProperty("ConfigurationGUID").GetValue(o)! == configurationGuid),
|
||||
It.IsAny<TimeSpan>()),
|
||||
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<CancellationToken>()))
|
||||
.ReturnsAsync(new CIConfiguration());
|
||||
|
||||
_snowflakeDatabaseContextMock
|
||||
.Setup(s => s.QueryAsync<QviLineItemEncounterSavingInfo>(
|
||||
It.Is<string>(q => q.Contains(":OpportunityGUID") && q.Contains(":IsBaseline")),
|
||||
nameof(QviLineItemSavingsService.GetEncounterSavingInfoAsync),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()))
|
||||
.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<CancellationToken>()))
|
||||
.ReturnsAsync(new CIConfiguration());
|
||||
|
||||
_snowflakeDatabaseContextMock
|
||||
.Setup(s => s.QueryAsync<QviLineItemEncounterSavingInfo>(
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<string>(),
|
||||
It.IsAny<object>(),
|
||||
It.IsAny<TimeSpan>()))
|
||||
.ThrowsAsync(new InvalidOperationException("boom"));
|
||||
|
||||
var action = async () => await _service.GetEncounterSavingInfoAsync(configurationGuid, null, null, CancellationToken.None);
|
||||
|
||||
await action.Should().ThrowAsync<InvalidOperationException>();
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
+118
@@ -0,0 +1,118 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="Resource\Examples\AllOpportunity\**" />
|
||||
<Compile Remove="StaffingToDemand\**" />
|
||||
<Compile Remove="Stubs\**" />
|
||||
<EmbeddedResource Remove="Resource\Examples\AllOpportunity\**" />
|
||||
<EmbeddedResource Remove="StaffingToDemand\**" />
|
||||
<None Remove="Api\**" />
|
||||
<EmbeddedResource Remove="Stubs\**" />
|
||||
<None Remove="Resource\Examples\AllOpportunity\**" />
|
||||
<None Remove="StaffingToDemand\**" />
|
||||
<None Remove="Stubs\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="All\OpportunityType.cs" />
|
||||
<Compile Remove="All\OpportunityTypesExtensions.cs" />
|
||||
<Compile Remove="Generics\ConfigurationServiceTest.cs" />
|
||||
<Compile Remove="Generics\DbSetExtensions.cs" />
|
||||
<Compile Remove="Generics\VariationOpportunityServiceTest.cs" />
|
||||
<Compile Remove="UtilizationVariation\Opportunities\VariationOpportunityFilter.cs" />
|
||||
<Compile Remove="Utilities\StringUtilsTest.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Resource\Examples\AllOpportunity\ExcelNullFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\EncounterOpportunity\ExcelFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\EncounterOpportunity\ExcelNullFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\ExcelFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\FreeFormOpportunity\ExcelFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\FreeFormOpportunity\ExcelNullFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\GeneralLedgerOpportunity\ExcelFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\GeneralLedgerOpportunity\ExcelNullFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\PayrollOpportunity\ExcelFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\PayrollOpportunity\ExcelNullFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\QualityVariationItemOpportunity\ExcelFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\QualityVariationItemOpportunity\ExcelNullFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\StaffingToDemandOpportunity\ExcelFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\StaffingToDemandOpportunity\ExcelNullFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\VariationOpportunity\ExcelFilter.xlsx" />
|
||||
<None Remove="Resource\Examples\VariationOpportunity\ExcelNullFilter.xlsx" />
|
||||
<None Remove="Resource\PRExcelFilter.xlsx" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Resource\Examples\AllOpportunity\ExcelFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\AllOpportunity\ExcelNullFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\EncounterOpportunity\ExcelFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\EncounterOpportunity\ExcelNullFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\GeneralLedgerOpportunity\ExcelFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\GeneralLedgerOpportunity\ExcelNullFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\PayrollOpportunity\ExcelFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\PayrollOpportunity\ExcelNullFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\FreeFormOpportunity\ExcelFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\FreeFormOpportunity\ExcelNullFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\QualityVariationItemOpportunity\ExcelFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\QualityVariationItemOpportunity\ExcelNullFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\StaffingToDemandOpportunity\ExcelFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\StaffingToDemandOpportunity\ExcelNullFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\VariationOpportunity\ExcelFilter.xlsx" />
|
||||
<EmbeddedResource Include="Resource\Examples\VariationOpportunity\ExcelNullFilter.xlsx" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="Strata - Backup.ContinuousImprovement.Test.Unit.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ClosedXML.Signed" Version="0.95.4" />
|
||||
<PackageReference Include="coverlet.msbuild" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.1" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.10" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
|
||||
<PackageReference Include="Moq" Version="4.20.72" />
|
||||
<PackageReference Include="NUnit" Version="4.3.2" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="5.0.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Remotion.Linq.Development" Version="2.2.0" />
|
||||
<PackageReference Include="Talentsoft.Moq.SetupAsync" Version="1.0.0" />
|
||||
<PackageReference Include="Verify.NUnit" Version="29.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Strata.ContinuousImprovement.Biz\Strata.ContinuousImprovement.Biz.csproj" />
|
||||
<ProjectReference Include="..\..\src\Strata.ContinuousImprovement.Api\Strata.ContinuousImprovement.Api.csproj" />
|
||||
<ProjectReference Include="..\Strata.ContinuousImprovement.JazzEntityFrameworkStub\Strata.ContinuousImprovement.JazzEntityFrameworkStub.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
|
||||
<_Parameter1>Strata.ContinuousImprovement.Api.Test.Unit</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
|
||||
<_Parameter1>Strata.ContinuousImprovement.JazzEntityFrameworkStub</_Parameter1>
|
||||
</AssemblyAttribute>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="ChargeCode\Opportunities\snapshots\" />
|
||||
<Folder Include="Exploration\snapshots\" />
|
||||
<Folder Include="Exploration\source\" />
|
||||
<Folder Include="PeerGroup\snapshots\" />
|
||||
<Folder Include="StrategicOpportunities\DistributionProcess\snapshots\" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.Shared;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.DistributionProcess.ChargeCode;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Enums;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
using VerifyTests;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities.DistributionProcess
|
||||
{
|
||||
public class DistributionProcessChargeCodeSqlBuilderTests : StrategicOpportunityTestsBase
|
||||
{
|
||||
private readonly long _testOpportunityId = 0;
|
||||
private readonly Period<DateOnly> _baselinePeriod;
|
||||
private readonly Period<DateOnly> _goalPeriod;
|
||||
private readonly Period<DateOnly> _trackingPeriod;
|
||||
private readonly double[] _rampUps;
|
||||
|
||||
public DistributionProcessChargeCodeSqlBuilderTests()
|
||||
{
|
||||
_baselinePeriod = new Period<DateOnly>(new DateOnly(2024, 1, 1), new DateOnly(2024, 12, 31));
|
||||
_goalPeriod = new Period<DateOnly>(new DateOnly(2025, 1, 1), new DateOnly(2025, 12, 31));
|
||||
_trackingPeriod = new Period<DateOnly>(new DateOnly(2026, 1, 1), new DateOnly(2026, 12, 31));
|
||||
_rampUps = [0.1, 0.2, 0.3, 0.4];
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(BuildInsertDistributedSqlTestCases))]
|
||||
public async Task BuildInsertDistributedSqlTest(DistributionMethod methodType, DistributionStage stage)
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DistributionProcessChargeCodeSqlBuilder(
|
||||
_testOpportunityId,
|
||||
_baselinePeriod,
|
||||
_goalPeriod,
|
||||
_trackingPeriod,
|
||||
_rampUps);
|
||||
|
||||
// Act
|
||||
var result = builder.BuildInsertDistributedSql(methodType, stage);
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result.Sql, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public async Task BuildDistributionSummarySqlTest(bool isInitiative)
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DistributionProcessChargeCodeSqlBuilder(
|
||||
_testOpportunityId,
|
||||
_baselinePeriod,
|
||||
_goalPeriod,
|
||||
_trackingPeriod,
|
||||
_rampUps);
|
||||
|
||||
// Act
|
||||
var result = builder.BuildDistributionSummarySql(isInitiative);
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result.Sql, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task BuildUpdateDetailCommittedByRampUpSqlTest()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DistributionProcessChargeCodeSqlBuilder(
|
||||
_testOpportunityId,
|
||||
_baselinePeriod,
|
||||
_goalPeriod,
|
||||
_trackingPeriod,
|
||||
_rampUps);
|
||||
|
||||
// Act
|
||||
var result = builder.BuildUpdateDetailCommittedByRampUpSql(_rampUps.Reverse().ToArray());
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result.Sql, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> BuildInsertDistributedSqlTestCases()
|
||||
{
|
||||
var distributionMethods = new[]
|
||||
{
|
||||
DistributionMethod.Average,
|
||||
DistributionMethod.Monthly
|
||||
};
|
||||
var distributionStages = new[]
|
||||
{
|
||||
DistributionStage.FromSourceToOpportunity,
|
||||
DistributionStage.OpportunityChangeGoalPeriod,
|
||||
DistributionStage.FromInitiativeToOpportunity,
|
||||
DistributionStage.FromOpportunityToInitiative,
|
||||
DistributionStage.InitiativeChangeTrackingPeriod
|
||||
};
|
||||
foreach (var method in distributionMethods)
|
||||
{
|
||||
foreach (var stage in distributionStages)
|
||||
{
|
||||
yield return new TestCaseData(method, stage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.Shared;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.DistributionProcess.GL;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Enums;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities.DistributionProcess
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture, Category("Unit"), Category("CCI")]
|
||||
public class DistributionProcessGLSqlBuilderTests : StrategicOpportunityTestsBase
|
||||
{
|
||||
private readonly long _testOpportunityId = 0;
|
||||
private readonly Period<DateOnly> _baselinePeriod;
|
||||
private readonly Period<DateOnly> _goalPeriod;
|
||||
private readonly Period<DateOnly> _trackingPeriod;
|
||||
private readonly double[] _rampUps;
|
||||
|
||||
public DistributionProcessGLSqlBuilderTests()
|
||||
{
|
||||
_baselinePeriod = new Period<DateOnly>(new DateOnly(2024, 1, 1), new DateOnly(2024, 12, 31));
|
||||
_goalPeriod = new Period<DateOnly>(new DateOnly(2025, 1, 1), new DateOnly(2025, 12, 31));
|
||||
_trackingPeriod = new Period<DateOnly>(new DateOnly(2026, 1, 1), new DateOnly(2026, 12, 31));
|
||||
_rampUps = [0.1, 0.2, 0.3, 0.4];
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(BuildInsertDistributedSqlTestCases))]
|
||||
public async Task BuildInsertDistributedSqlTest(DistributionMethod methodType, DistributionStage stage)
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DistributionProcessGLSqlBuilder(
|
||||
_testOpportunityId,
|
||||
_baselinePeriod,
|
||||
_goalPeriod,
|
||||
_trackingPeriod,
|
||||
_rampUps);
|
||||
|
||||
// Act
|
||||
var result = builder.BuildInsertDistributedSql(methodType, stage);
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result.Sql, VerifySettings)
|
||||
.UseFileName("GL " + TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[TestCase(true)]
|
||||
[TestCase(false)]
|
||||
public async Task BuildDistributionSummarySqlTest(bool isInitiative)
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DistributionProcessGLSqlBuilder(
|
||||
_testOpportunityId,
|
||||
_baselinePeriod,
|
||||
_goalPeriod,
|
||||
_trackingPeriod,
|
||||
_rampUps);
|
||||
|
||||
// Act
|
||||
var result = builder.BuildDistributionSummarySql(isInitiative);
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result.Sql, VerifySettings)
|
||||
.UseFileName("GL " + TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task BuildUpdateDetailCommittedByRampUpSqlTest()
|
||||
{
|
||||
// Arrange
|
||||
var builder = new DistributionProcessGLSqlBuilder(
|
||||
_testOpportunityId,
|
||||
_baselinePeriod,
|
||||
_goalPeriod,
|
||||
_trackingPeriod,
|
||||
_rampUps);
|
||||
|
||||
// Act
|
||||
var result = builder.BuildUpdateDetailCommittedByRampUpSql(_rampUps.Reverse().ToArray());
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result.Sql, VerifySettings)
|
||||
.UseFileName("GL " + TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> BuildInsertDistributedSqlTestCases()
|
||||
{
|
||||
var distributionMethods = new[]
|
||||
{
|
||||
DistributionMethod.Average,
|
||||
DistributionMethod.Monthly
|
||||
};
|
||||
var distributionStages = new[]
|
||||
{
|
||||
DistributionStage.FromSourceToOpportunity,
|
||||
DistributionStage.OpportunityChangeGoalPeriod,
|
||||
DistributionStage.FromInitiativeToOpportunity,
|
||||
DistributionStage.FromOpportunityToInitiative,
|
||||
DistributionStage.InitiativeChangeTrackingPeriod
|
||||
};
|
||||
foreach (var method in distributionMethods)
|
||||
{
|
||||
foreach (var stage in distributionStages)
|
||||
{
|
||||
yield return new TestCaseData(method, stage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+295
@@ -0,0 +1,295 @@
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Dtos;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Enums;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Queries;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.DataSchema.Models.Query;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities.Queries
|
||||
{
|
||||
[TestFixture]
|
||||
public class StrategicOpportunityDetailQueryBuilderTests : StrategicOpportunityTestsBase
|
||||
{
|
||||
private IStrategicOpportunityDetailQueryBuilder _builder;
|
||||
private const long TestOpportunityId = 123;
|
||||
private const long TestMeasureId = 456;
|
||||
private const string TestStartDate = "2024-01-01";
|
||||
private const int TestTrackingMonths = 12;
|
||||
private const string SelectQuery = "SELECT * FROM TestTable";
|
||||
private const string InvalidSelectQuery = "UPDATE TestTable SET Column1 = 'Value'";
|
||||
private const string ComplexSelectQuery = @"
|
||||
SELECT
|
||||
*
|
||||
FROM dss.FactPatientCostDetail AS COSTDETAIL
|
||||
RIGHT JOIN dss.FactPatientBillingLineItemDetail AS PBLID ON PBLID.rowid = COSTDETAIL.pblidrowid
|
||||
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
|
||||
LEFT JOIN CCI.FACTEXPLORATIONPOPULATIONENCOUNTER AS EXPLORATIONPOPULATIONENCOUNTER ON EXPLORATIONPOPULATIONENCOUNTER.encounterid = PBLID.encounterid
|
||||
LEFT JOIN CCI.VIEWENCOUNTERPATIENTTYPEROLLUP AS ENCOUNTERPATIENTTYPEROLLUP ON ENCOUNTERPATIENTTYPEROLLUP.encounterid = PBLID.encounterid
|
||||
INNER JOIN FW.DIMCHARGECODE AS CC ON CC.chargecodeid = PBLID.chargecodeid
|
||||
INNER JOIN DSS.DIMPHYSICIAN AS PHYSPRIMARY ON PHYSPRIMARY.physicianid = DSSPES.primaryphysicianid
|
||||
";
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_builder = new StrategicOpportunityDetailQueryBuilder();
|
||||
}
|
||||
|
||||
#region BuildInsertQuery Tests
|
||||
|
||||
[TestCase(true, TestName = "BuildInsertQuery with APRDRG")]
|
||||
[TestCase(false, TestName = "BuildInsertQuery without APRDRG")]
|
||||
public async Task BuildInsertQuery_ShouldGenerateValidSql(bool isUsingAprdrg)
|
||||
{
|
||||
// Arrange
|
||||
var opportunity = new StrategicOpportunityChargeCode { OpportunityId = TestOpportunityId };
|
||||
|
||||
// Act
|
||||
var result = _builder.BuildInsertQuery(opportunity, SelectQuery, isUsingAprdrg);
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildInsertQuery_WithInvalidSelectQuery_ShouldThrowException()
|
||||
{
|
||||
// Arrange
|
||||
var opportunity = new StrategicOpportunityChargeCode { OpportunityId = TestOpportunityId };
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() =>
|
||||
_builder.BuildInsertQuery(opportunity, InvalidSelectQuery, true));
|
||||
Assert.That(ex.Message, Does.Contain("Unexpected SQL syntax. SELECT should be first word."));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BuildDeleteQuery Tests
|
||||
|
||||
[Test]
|
||||
public async Task BuildDeleteQuery_WithOpportunityId_ShouldGenerateValidSql()
|
||||
{
|
||||
// Act
|
||||
var result = _builder.BuildDeleteQuery(TestOpportunityId);
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task BuildDeleteQuery_WithoutOpportunityId_ShouldGenerateParameterizedSql()
|
||||
{
|
||||
// Act
|
||||
var result = _builder.BuildDeleteQuery();
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BuildMergeQuery Tests
|
||||
|
||||
[TestCase(true, TestName = "BuildMergeQuery with APRDRG")]
|
||||
[TestCase(false, TestName = "BuildMergeQuery without APRDRG")]
|
||||
public async Task BuildMergeQuery_ShouldGenerateValidSql(bool isUsingAprdrg)
|
||||
{
|
||||
// Act
|
||||
var result = _builder.BuildMergeQuery(TestOpportunityId, SelectQuery, isUsingAprdrg);
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildMergeQuery_WithInvalidSelectQuery_ShouldThrowException()
|
||||
{
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() =>
|
||||
_builder.BuildMergeQuery(TestOpportunityId, InvalidSelectQuery, true));
|
||||
Assert.That(ex.Message, Does.Contain("Unexpected SQL syntax. SELECT should be first word."));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BuildGetDistinctEncounterCountQuery Tests
|
||||
|
||||
[TestCase(true, TestName = "BuildGetDistinctEncounterCountQuery with APRDRG")]
|
||||
[TestCase(false, TestName = "BuildGetDistinctEncounterCountQuery without APRDRG")]
|
||||
public async Task BuildGetDistinctEncounterCountQuery_ShouldGenerateValidSql(bool isUsingAprdrg)
|
||||
{
|
||||
// Arrange
|
||||
var getData = new StrategicOpportunityGetDetailData
|
||||
{
|
||||
Dimensions = new[] { "entity", "chargeCode", "costDriver" }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _builder.BuildGetDistinctEncounterCountQuery(TestOpportunityId, SelectQuery, isUsingAprdrg, getData);
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildGetDistinctEncounterCountQuery_ShouldThrowException()
|
||||
{
|
||||
// Arrange
|
||||
var getData = new StrategicOpportunityGetDetailData
|
||||
{
|
||||
Dimensions = new[] { "entity", "chargeCode", "costDriver" }
|
||||
};
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.Throws<InvalidOperationException>(() =>
|
||||
_builder.BuildGetDistinctEncounterCountQuery(TestOpportunityId, InvalidSelectQuery, true, getData));
|
||||
Assert.That(ex.Message, Does.Contain("Unexpected SQL syntax. SELECT should be first word."));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region BuildMergeSystemMeasureMergeQuery Tests
|
||||
|
||||
[TestCaseSource(nameof(GetMeasureTypeTestCases))]
|
||||
public async Task BuildMergeSystemMeasureMergeQuery_WithDifferentMeasureTypes_ShouldGenerateValidSql(MeasureType measureType)
|
||||
{
|
||||
// Act
|
||||
var result = _builder.BuildMergeSystemMeasureMergeQuery(TestOpportunityId, TestMeasureId, measureType, TestStartDate, TestTrackingMonths);
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.UseFileName($"{TestContext.CurrentContext.Test.Name}_{measureType}");
|
||||
}
|
||||
|
||||
private static IEnumerable<TestCaseData> GetMeasureTypeTestCases()
|
||||
{
|
||||
yield return new TestCaseData(MeasureType.CommittedCost).SetName("BuildMergeSystemMeasureMergeQuery with CommittedCost");
|
||||
yield return new TestCaseData(MeasureType.ActualCost).SetName("BuildMergeSystemMeasureMergeQuery with ActualCost");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetSelectMeasureSql Tests
|
||||
|
||||
[TestCaseSource(nameof(GetSelectMeasureSql_TestCases))]
|
||||
public async Task GetSelectMeasureSql_ShouldGenerateValidSql(MeasureType measureType)
|
||||
{
|
||||
// Arrange
|
||||
var marginFilters = new Dictionary<string, FilterCondition>
|
||||
{
|
||||
{ "DepartmentId", new FilterCondition { Operator = FilterOperator.In, Values = new List<string> { "1", "2", "3", "4", "5" } } },
|
||||
{ "ChargeCodeId", new FilterCondition { Operator = FilterOperator.NotIn, Values = new List<string> { "100", "200", "300" } } },
|
||||
{ "EntityId", new FilterCondition { Operator = FilterOperator.In, Values = new List<string> { "999" } } }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _builder.GetSelectMeasureSql(TestOpportunityId, measureType, ComplexSelectQuery, marginFilters);
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetSelectMeasureSql_EncountersCases()
|
||||
{
|
||||
// Arrange
|
||||
var marginFilters = new Dictionary<string, FilterCondition>();
|
||||
var complexSelectQuery = ComplexSelectQuery.Replace(
|
||||
"RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid",
|
||||
"INNER JOIN (SELECT * FROM clientdss.FactPatientEncounterSummary AS DSSPES) AS DSSPES ON DSSPES.encounterid = PBLID.encounterid"
|
||||
);
|
||||
|
||||
// Act
|
||||
var result = _builder.GetSelectMeasureSql(TestOpportunityId, MeasureType.EncountersCases, complexSelectQuery, marginFilters);
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
private static IEnumerable<TestCaseData> GetSelectMeasureSql_TestCases()
|
||||
{
|
||||
foreach (var x in Enum.GetValues<MeasureType>().Where(x => x < MeasureType.CommittedCost))
|
||||
{
|
||||
yield return new TestCaseData(x)
|
||||
.SetName($"GetSelectMeasureSql with {x}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region WrapIntoMeasureMergeQuery Tests
|
||||
|
||||
[Test]
|
||||
public async Task WrapIntoMeasureMergeQuery_ShouldWrapSelectQueryCorrectly()
|
||||
{
|
||||
// Act
|
||||
var result = _builder.WrapIntoMeasureMergeQuery(SelectQuery);
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region WrapIntoMeasureAverageQuery Tests
|
||||
|
||||
[Test]
|
||||
public async Task WrapIntoMeasureAverageQuery_ShouldWrapSelectQueryCorrectly()
|
||||
{
|
||||
// Act
|
||||
var result = _builder.WrapIntoMeasureAverageQuery(SelectQuery);
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region GetDeleteAllMeasuresSql Tests
|
||||
|
||||
[TestCaseSource(nameof(GetDeleteAllMeasuresSql_TestCases))]
|
||||
public async Task GetDeleteAllMeasuresSql_ShouldGenerateValidSql(long[] measureIds)
|
||||
{
|
||||
// Act
|
||||
var result = _builder.GetDeleteAllMeasuresSql(measureIds);
|
||||
|
||||
// Assert
|
||||
if (measureIds == null || measureIds.Length == 0)
|
||||
{
|
||||
Assert.That(result, Is.Empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
await Verifier.Verify(result, VerifySettings)
|
||||
.UseFileName(TestContext.CurrentContext.TestName());
|
||||
}
|
||||
|
||||
}
|
||||
private static IEnumerable<TestCaseData> GetDeleteAllMeasuresSql_TestCases()
|
||||
{
|
||||
yield return new TestCaseData(new long[] { 1, 2, 3, 4, 5 })
|
||||
.SetName("GetDeleteAllMeasuresSql with MeasureIds");
|
||||
yield return new TestCaseData(new long[] { })
|
||||
.SetName("GetDeleteAllMeasuresSql with empty MeasureIds");
|
||||
yield return new TestCaseData(null)
|
||||
.SetName("GetDeleteAllMeasuresSql with null MeasureIds");
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+703
@@ -0,0 +1,703 @@
|
||||
using Hangfire;
|
||||
using Microsoft.AspNetCore.SignalR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts.Snowflake;
|
||||
using Strata.ContinuousImprovement.Biz.Exploration;
|
||||
using Strata.ContinuousImprovement.Biz.Exploration.Filters;
|
||||
using Strata.ContinuousImprovement.Biz.Notification;
|
||||
using Strata.ContinuousImprovement.Biz.Population;
|
||||
using Strata.ContinuousImprovement.Biz.Shared;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.DistributionProcess;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Enums;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Queries;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.DataSchema.Client;
|
||||
using Strata.DataSchema.Models.Query;
|
||||
using Strata.DataSchema.Models.Schema;
|
||||
using Strata.Schema.Client;
|
||||
using Strata.Schema.Client.Dtos;
|
||||
using Strata.Schema.Client.Dtos.Info;
|
||||
using Strata.SqlTools.Configuration.Common.AsyncFactory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
using static Strata.ContinuousImprovement.Biz.Exploration.ExplorationService;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture, Category("Unit"), Category("CCI")]
|
||||
public class StrategicChargeCodeOpportunityDetailServiceTests : StrategicOpportunityTestsBase
|
||||
{
|
||||
private IStrategicChargeCodeOpportunityDetailService _strategicOpportunityDetailService;
|
||||
private Mock<IDataSchemaService> _mockDataSchemaService;
|
||||
private Mock<ISchemaServiceClient> _mockSchemaServiceClient;
|
||||
private Mock<ISnowflakeDatabaseContext> _mockSnowflakeContext;
|
||||
private Mock<IAsyncDbContextFactory<JazzDbContext>> _mockJazzDbContext;
|
||||
private Mock<IExplorationFilterService> _mockExplorationService;
|
||||
private Mock<IDistributionProcessFactory> _mockDistributionProcessFactory;
|
||||
private Mock<IStrategicOpportunityDetailQueryBuilder> _mockStrategicOpportunityDetailQueryBuilder;
|
||||
private Mock<IHubContext<NotificationHub, INotificationHub>> _mockNotificationHubClient;
|
||||
private Mock<ILogger<StrategicChargeCodeOpportunityDetailService>> _mockLogger;
|
||||
private Mock<IStrategicItemDimensionSyncService> _mockDimensionSyncService;
|
||||
private CentralDbContext _centralDbContext;
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void Setup()
|
||||
{
|
||||
// Create in-memory database
|
||||
var options = new DbContextOptionsBuilder<CentralDbContext>()
|
||||
.UseInMemoryDatabase(databaseName: "TestCentralDb_" + Guid.NewGuid())
|
||||
.Options;
|
||||
|
||||
_centralDbContext = new CentralDbContext(options);
|
||||
|
||||
// Arrange mocks
|
||||
_mockSchemaServiceClient = new Mock<ISchemaServiceClient>();
|
||||
_mockJazzDbContext = new Mock<IAsyncDbContextFactory<JazzDbContext>>();
|
||||
_mockSnowflakeContext = new Mock<ISnowflakeDatabaseContext>();
|
||||
_mockDataSchemaService = new Mock<IDataSchemaService>();
|
||||
_mockExplorationService = new Mock<IExplorationFilterService>();
|
||||
_mockNotificationHubClient = new Mock<IHubContext<NotificationHub, INotificationHub>>();
|
||||
_mockLogger = new Mock<ILogger<StrategicChargeCodeOpportunityDetailService>>();
|
||||
_mockDistributionProcessFactory = new Mock<IDistributionProcessFactory>();
|
||||
_mockStrategicOpportunityDetailQueryBuilder = new Mock<IStrategicOpportunityDetailQueryBuilder>();
|
||||
_mockDimensionSyncService = new Mock<IStrategicItemDimensionSyncService>();
|
||||
_mockDimensionSyncService.Setup(x => x.UpsertAsync(It.IsAny<StrategicOpportunity>(), It.IsAny<CancellationToken>())).Returns(Task.CompletedTask);
|
||||
_mockDimensionSyncService.Setup(x => x.DeleteAsync(It.IsAny<long>())).Returns(Task.CompletedTask);
|
||||
|
||||
// Seed ExplorationPopulation data for exploration test cases
|
||||
_centralDbContext.ExplorationPopulations.Add(new ExplorationPopulation
|
||||
{
|
||||
ExplorationPopulationId = 100,
|
||||
Name = "Test Exploration Population",
|
||||
CaseTypeFamilyId = 123,
|
||||
StrataId = 1,
|
||||
FiltersJSON = @"[{""ChipType"":4,""Key"":1,""DateRange"":[""2024-01-01T00:00:00"",""2024-12-31T00:00:00""]}]"
|
||||
});
|
||||
_centralDbContext.SaveChanges();
|
||||
|
||||
// Create in-memory JazzDbContext options that will be reused
|
||||
var jazzOptions = new DbContextOptionsBuilder<JazzDbContext>()
|
||||
.UseInMemoryDatabase(databaseName: "TestJazzDb_" + Guid.NewGuid())
|
||||
.Options;
|
||||
|
||||
// Seed the JazzDb with initial data
|
||||
using (var jazzDbContext = new JazzDbContext(jazzOptions))
|
||||
{
|
||||
jazzDbContext.SystemSettings.Add(new SystemSetting
|
||||
{
|
||||
SystemSettingId = 1,
|
||||
Name = "Flexible Exploration Inpatient Case Type Family",
|
||||
Value = "0"
|
||||
});
|
||||
jazzDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
// Mock JazzDbContext factory to return a NEW context instance each time
|
||||
_mockJazzDbContext.Setup(x => x.CreateDbContextAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(() => new JazzDbContext(jazzOptions));
|
||||
|
||||
// Mock ExplorationFilterService
|
||||
_mockExplorationService.Setup(x =>
|
||||
x.GetFilterStringsAsync(It.IsAny<IEnumerable<FilterChipItem>>(), It.IsAny<IQueryParamBase>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(("WHERE DSSPES.dischargedatetime >= :DischargeDateStart AND DSSPES.dischargedatetime < :DischargeDateEnd\r\n",
|
||||
"AND fpes.EntityId = 1\r\n"));
|
||||
|
||||
// Mock DataSchemaService
|
||||
var dataTableId = 12345;
|
||||
var dataColumnId = 67890;
|
||||
var testDataSourceId = 999;
|
||||
|
||||
_mockDataSchemaService.Setup(x =>
|
||||
x.GetDataSourcesAsync(It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<Strata.DataSchema.Models.DataSourceManagement.DataSource>
|
||||
{
|
||||
new Strata.DataSchema.Models.DataSourceManagement.DataSource
|
||||
{
|
||||
DataSourceId = testDataSourceId,
|
||||
Name = "DS Strata Encounter Cost Detail"
|
||||
}
|
||||
});
|
||||
|
||||
_mockDataSchemaService.Setup(x =>
|
||||
x.GetDataTablesByDataSourceId(It.Is<int>(dataSourceId => dataSourceId == testDataSourceId), It.IsAny<bool>(), It.IsAny<DataTableType?>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync((int dsId, bool includeChildren, DataTableType? tableType, CancellationToken ct) =>
|
||||
{
|
||||
var tableAliases = new[] { "dsspes", "pblid", "costdetail", "cc", "PATIENTTYPE", "physPrimary", "dsspeci", "explorationPopulationEncounter", "msdrg" };
|
||||
return tableAliases.Select(alias => new DataTable
|
||||
{
|
||||
DataTableId = dataTableId,
|
||||
SqlAlias = alias
|
||||
}).ToList();
|
||||
});
|
||||
|
||||
_mockDataSchemaService.Setup(x =>
|
||||
x.GetDataColumnsBySqlColumnNameAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync((string columnName, CancellationToken ct) => new List<DataColumn>
|
||||
{
|
||||
new DataColumn
|
||||
{
|
||||
DataColumnId = dataColumnId,
|
||||
DataTableId = dataTableId
|
||||
}
|
||||
});
|
||||
|
||||
_mockDataSchemaService.Setup(x =>
|
||||
x.BuildSqlQuery(It.IsAny<QueryConfig>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new SqlResponse
|
||||
{
|
||||
SqlQuery = _unitsOfServicePatPopQuery,
|
||||
Parameters = new List<KeyValuePair<string, object>>
|
||||
{
|
||||
new(":dischargedatetime_Start_0", new DateTime(2024, 1, 1)),
|
||||
new(":dischargedatetime_End_1", new DateTime(2024, 12, 31)),
|
||||
new(":chargecodeid_2", 3541)
|
||||
}
|
||||
});
|
||||
|
||||
// Mock SchemaServiceClient
|
||||
_mockSchemaServiceClient.Setup(x =>
|
||||
x.GetDimensionByGlobalIdAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new ScoreDimensionInfoDto { DimensionGuid = Guid.NewGuid() });
|
||||
|
||||
_mockSchemaServiceClient.Setup(x =>
|
||||
x.GetDimensionMembersFromHierarchyPathsAsync(It.IsAny<Guid>(), It.IsAny<IEnumerable<string>>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<MemberDto>
|
||||
{
|
||||
new MemberDto
|
||||
{
|
||||
Id = "777",
|
||||
Name = "Charge Code Stub"
|
||||
}
|
||||
});
|
||||
|
||||
_mockSchemaServiceClient.Setup(x =>
|
||||
x.GetHierarchyNodesFromHierarchyPathsAsync(It.IsAny<Guid>(), It.IsAny<IEnumerable<string>>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(new List<HierarchyNodeDto>());
|
||||
|
||||
// Mock Snowflake context
|
||||
_mockSnowflakeContext.Setup(x =>
|
||||
x.QueryAsync<StrategicOpportunityDetail>(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<object>(), It.IsAny<TimeSpan>()))
|
||||
.ReturnsAsync(new List<StrategicOpportunityDetail>());
|
||||
|
||||
_mockSnowflakeContext.Setup(x =>
|
||||
x.ExecuteScalarAsync<double>(It.IsAny<string>(), It.IsAny<object>()))
|
||||
.ReturnsAsync(123.45);
|
||||
|
||||
_mockSnowflakeContext.Setup(x =>
|
||||
x.ExecuteCommandAsync(It.IsAny<string>(), It.IsAny<object>(), It.IsAny<TimeSpan>()))
|
||||
.ReturnsAsync(1);
|
||||
|
||||
var claimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor();
|
||||
|
||||
_strategicOpportunityDetailService = new StrategicChargeCodeOpportunityDetailService(
|
||||
_mockJazzDbContext.Object,
|
||||
_centralDbContext,
|
||||
claimsPrincipalAccessor,
|
||||
_mockDataSchemaService.Object,
|
||||
_mockSchemaServiceClient.Object,
|
||||
_mockSnowflakeContext.Object,
|
||||
_mockExplorationService.Object,
|
||||
_mockDistributionProcessFactory.Object,
|
||||
_mockStrategicOpportunityDetailQueryBuilder.Object,
|
||||
_mockNotificationHubClient.Object,
|
||||
_mockDimensionSyncService.Object,
|
||||
_mockLogger.Object);
|
||||
}
|
||||
|
||||
[SetUp]
|
||||
public void TestSetup()
|
||||
{
|
||||
_centralDbContext.StrategicOpportunityMeasures.RemoveRange(_centralDbContext.StrategicOpportunityMeasures);
|
||||
_centralDbContext.StrategicOpportunityChargeCodes.RemoveRange(_centralDbContext.StrategicOpportunityChargeCodes);
|
||||
_centralDbContext.SaveChanges();
|
||||
}
|
||||
|
||||
private const string _unitsOfServicePatPopQuery = @"SELECT
|
||||
""DischargeDateTime"",
|
||||
ZEROIFNULL(""Value"") AS ""Value""
|
||||
|
||||
FROM (
|
||||
SELECT
|
||||
""DischargeDateTime"",
|
||||
SUM(""Value"") AS ""Value""
|
||||
|
||||
FROM (
|
||||
SELECT
|
||||
DSSPES.dischargedatetime AS ""DischargeDateTime"",
|
||||
SUM(PBLID.unitsofservice) AS ""Value""
|
||||
|
||||
FROM dss.FactPatientBillingLineItemDetail AS PBLID
|
||||
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
|
||||
|
||||
WHERE
|
||||
(((DSSPES.dischargedatetime >= :dischargedatetime_Start_0 AND DSSPES.dischargedatetime <= :dischargedatetime_End_1) AND PBLID.departmentid = :departmentid_2) AND DSSPES.primaryphysicianid = :primaryphysicianid_3)
|
||||
|
||||
GROUP BY
|
||||
""DischargeDateTime""
|
||||
|
||||
|
||||
)
|
||||
|
||||
GROUP BY
|
||||
""DischargeDateTime""
|
||||
|
||||
|
||||
)
|
||||
|
||||
ORDER BY
|
||||
""DischargeDateTime"" ASC NULLS FIRST";
|
||||
|
||||
private const string _unitsOfServiceFlexPopQuery = @"SELECT
|
||||
""DischargeDateTime"",
|
||||
ZEROIFNULL(""Value"") AS ""Value""
|
||||
|
||||
FROM (
|
||||
SELECT
|
||||
""DischargeDateTime"",
|
||||
SUM(""Value"") AS ""Value""
|
||||
|
||||
FROM (
|
||||
SELECT
|
||||
DSSPES.dischargedatetime AS ""DischargeDateTime"",
|
||||
SUM(PBLID.unitsofservice) AS ""Value""
|
||||
|
||||
FROM dss.FactPatientBillingLineItemDetail AS PBLID
|
||||
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
|
||||
LEFT JOIN CCI.FACTEXPLORATIONPOPULATIONENCOUNTER AS EXPLORATIONPOPULATIONENCOUNTER ON EXPLORATIONPOPULATIONENCOUNTER.encounterid = PBLID.encounterid
|
||||
|
||||
WHERE
|
||||
((DSSPES.dischargedatetime >= :dischargedatetime_Start_0 AND DSSPES.dischargedatetime <= :dischargedatetime_End_1) AND EXPLORATIONPOPULATIONENCOUNTER.explorationpopulationid = :explorationpopulationid_2)
|
||||
|
||||
GROUP BY
|
||||
""DischargeDateTime""
|
||||
|
||||
|
||||
)
|
||||
|
||||
GROUP BY
|
||||
""DischargeDateTime""
|
||||
|
||||
|
||||
)
|
||||
|
||||
ORDER BY
|
||||
""DischargeDateTime"" ASC NULLS FIRST";
|
||||
|
||||
private const string _contributionMarginPatPopQuery = @"SELECT
|
||||
""DischargeDateTime"",
|
||||
""dsspesNetRevenue"",
|
||||
ZEROIFNULL(""Value"") AS ""Value""
|
||||
|
||||
FROM (
|
||||
SELECT
|
||||
""DischargeDateTime"",
|
||||
""dsspesNetRevenue"",
|
||||
SUM(""Value"") AS ""Value""
|
||||
|
||||
FROM (
|
||||
SELECT
|
||||
DSSPES.dischargedatetime AS ""DischargeDateTime"",
|
||||
DSSPES.netrevenue AS ""dsspesNetRevenue"",
|
||||
SUM(COSTDETAIL.variabledirectcost) AS ""Value""
|
||||
|
||||
FROM dss.FactPatientCostDetail AS COSTDETAIL
|
||||
RIGHT JOIN dss.FactPatientBillingLineItemDetail AS PBLID ON PBLID.rowid = COSTDETAIL.pblidrowid
|
||||
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
|
||||
|
||||
WHERE
|
||||
((DSSPES.dischargedatetime >= :dischargedatetime_Start_0 AND DSSPES.dischargedatetime <= :dischargedatetime_End_1))
|
||||
|
||||
GROUP BY
|
||||
""DischargeDateTime"",
|
||||
""dsspesNetRevenue""
|
||||
|
||||
|
||||
)
|
||||
|
||||
GROUP BY
|
||||
""DischargeDateTime"",
|
||||
""dsspesNetRevenue""
|
||||
|
||||
|
||||
)
|
||||
|
||||
ORDER BY
|
||||
""DischargeDateTime"" ASC NULLS FIRST,
|
||||
""dsspesNetRevenue"" ASC NULLS FIRST";
|
||||
|
||||
private const string _contributionMarginFlexPopQuery = @"SELECT
|
||||
""DischargeDateTime"",
|
||||
""dsspesNetRevenue"",
|
||||
ZEROIFNULL(""Value"") AS ""Value""
|
||||
|
||||
FROM (
|
||||
SELECT
|
||||
""DischargeDateTime"",
|
||||
""dsspesNetRevenue"",
|
||||
SUM(""Value"") AS ""Value""
|
||||
|
||||
FROM (
|
||||
SELECT
|
||||
DSSPES.dischargedatetime AS ""DischargeDateTime"",
|
||||
DSSPES.netrevenue AS ""dsspesNetRevenue"",
|
||||
SUM(COSTDETAIL.variabledirectcost) AS ""Value""
|
||||
|
||||
FROM dss.FactPatientCostDetail AS COSTDETAIL
|
||||
RIGHT JOIN dss.FactPatientBillingLineItemDetail AS PBLID ON PBLID.rowid = COSTDETAIL.pblidrowid
|
||||
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
|
||||
LEFT JOIN CCI.FACTEXPLORATIONPOPULATIONENCOUNTER AS EXPLORATIONPOPULATIONENCOUNTER ON EXPLORATIONPOPULATIONENCOUNTER.encounterid = PBLID.encounterid
|
||||
|
||||
WHERE
|
||||
((DSSPES.dischargedatetime >= :dischargedatetime_Start_0 AND DSSPES.dischargedatetime <= :dischargedatetime_End_1) AND EXPLORATIONPOPULATIONENCOUNTER.explorationpopulationid = :explorationpopulationid_2)
|
||||
|
||||
GROUP BY
|
||||
""DischargeDateTime"",
|
||||
""dsspesNetRevenue""
|
||||
|
||||
|
||||
)
|
||||
|
||||
GROUP BY
|
||||
""DischargeDateTime"",
|
||||
""dsspesNetRevenue""
|
||||
|
||||
|
||||
)
|
||||
|
||||
ORDER BY
|
||||
""DischargeDateTime"" ASC NULLS FIRST,
|
||||
""dsspesNetRevenue"" ASC NULLS FIRST";
|
||||
|
||||
// SQL returned by BuildSqlQuery for the tracking merge path with clinical indicator population
|
||||
private const string _trackingPatPopQuery = @"SELECT
|
||||
""dsspesEncounterId"",
|
||||
""dsspesDischargeDateTime"",
|
||||
""dsspesEntityID"",
|
||||
""dsspesPhysicianId"",
|
||||
""dsspesPrimaryServiceLineId"",
|
||||
""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
""dsspesMSDRGCaseTypeFamilyId"",
|
||||
""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
""pblidDepartmentId"",
|
||||
""physPrimaryPhysicianSpecialtyId"",
|
||||
""ccChargeCodeID"",
|
||||
""ccCostDriver"",
|
||||
""encounterPatientTypeRollupPatientTypeRollup"",
|
||||
ZEROIFNULL(""Units"") AS ""Units"",
|
||||
ZEROIFNULL(""Cost"") AS ""Cost""
|
||||
|
||||
FROM (
|
||||
SELECT
|
||||
""dsspesEncounterId"",
|
||||
""dsspesDischargeDateTime"",
|
||||
""dsspesEntityID"",
|
||||
""dsspesPhysicianId"",
|
||||
""dsspesPrimaryServiceLineId"",
|
||||
""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
""dsspesMSDRGCaseTypeFamilyId"",
|
||||
""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
""pblidDepartmentId"",
|
||||
""physPrimaryPhysicianSpecialtyId"",
|
||||
""ccChargeCodeID"",
|
||||
""ccCostDriver"",
|
||||
""encounterPatientTypeRollupPatientTypeRollup"",
|
||||
SUM(""Units"") AS ""Units"",
|
||||
SUM(""Cost"") AS ""Cost""
|
||||
|
||||
FROM (
|
||||
SELECT
|
||||
DSSPES.encounterid AS ""dsspesEncounterId"",
|
||||
DSSPES.dischargedatetime AS ""dsspesDischargeDateTime"",
|
||||
DSSPES.entityid AS ""dsspesEntityID"",
|
||||
DSSPES.primaryphysicianid AS ""dsspesPhysicianId"",
|
||||
DSSPES.servicelineid AS ""dsspesPrimaryServiceLineId"",
|
||||
DSSPES.cptcodecasetypefamilyid AS ""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
DSSPES.msdrgcasetypefamilyid AS ""dsspesMSDRGCaseTypeFamilyId"",
|
||||
DSSPES.aprdrgcasetypefamilyid AS ""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
PBLID.departmentid AS ""pblidDepartmentId"",
|
||||
PHYSPRIMARY.physicianspecialtyid AS ""physPrimaryPhysicianSpecialtyId"",
|
||||
CC.chargecodeid AS ""ccChargeCodeID"",
|
||||
IFNULL(CC.costdriver::TEXT, '') AS ""ccCostDriver"",
|
||||
IFNULL(ENCOUNTERPATIENTTYPEROLLUP.patienttyperollup::TEXT, '') AS ""encounterPatientTypeRollupPatientTypeRollup"",
|
||||
NULL AS ""Cost"",
|
||||
SUM(PBLID.unitsofservice) AS ""Units""
|
||||
|
||||
FROM dss.FactPatientBillingLineItemDetail AS PBLID
|
||||
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
|
||||
LEFT JOIN dss.FactPatientEncounterClinicalIndicator AS DSSPECI ON DSSPECI.encounterid = PBLID.encounterid
|
||||
LEFT JOIN CCI.VIEWENCOUNTERPATIENTTYPEROLLUP AS ENCOUNTERPATIENTTYPEROLLUP ON ENCOUNTERPATIENTTYPEROLLUP.encounterid = PBLID.encounterid
|
||||
INNER JOIN FW.DIMCHARGECODE AS CC ON CC.chargecodeid = PBLID.chargecodeid
|
||||
INNER JOIN DSS.DIMPHYSICIAN AS PHYSPRIMARY ON PHYSPRIMARY.physicianid = DSSPES.primaryphysicianid
|
||||
|
||||
WHERE
|
||||
((DSSPES.dischargedatetime >= :dischargedatetime_Start_0 AND DSSPES.dischargedatetime <= :dischargedatetime_End_1) AND DSSPECI.clinicalindicatorid = :clinicalindicatorid_2)
|
||||
|
||||
GROUP BY
|
||||
""dsspesEncounterId"",
|
||||
""dsspesDischargeDateTime"",
|
||||
""dsspesEntityID"",
|
||||
""dsspesPhysicianId"",
|
||||
""dsspesPrimaryServiceLineId"",
|
||||
""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
""dsspesMSDRGCaseTypeFamilyId"",
|
||||
""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
""pblidDepartmentId"",
|
||||
""physPrimaryPhysicianSpecialtyId"",
|
||||
""ccChargeCodeID"",
|
||||
""ccCostDriver"",
|
||||
""encounterPatientTypeRollupPatientTypeRollup""
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
DSSPES.encounterid AS ""dsspesEncounterId"",
|
||||
DSSPES.dischargedatetime AS ""dsspesDischargeDateTime"",
|
||||
DSSPES.entityid AS ""dsspesEntityID"",
|
||||
DSSPES.primaryphysicianid AS ""dsspesPhysicianId"",
|
||||
DSSPES.servicelineid AS ""dsspesPrimaryServiceLineId"",
|
||||
DSSPES.cptcodecasetypefamilyid AS ""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
DSSPES.msdrgcasetypefamilyid AS ""dsspesMSDRGCaseTypeFamilyId"",
|
||||
DSSPES.aprdrgcasetypefamilyid AS ""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
PBLID.departmentid AS ""pblidDepartmentId"",
|
||||
PHYSPRIMARY.physicianspecialtyid AS ""physPrimaryPhysicianSpecialtyId"",
|
||||
CC.chargecodeid AS ""ccChargeCodeID"",
|
||||
IFNULL(CC.costdriver::TEXT, '') AS ""ccCostDriver"",
|
||||
IFNULL(ENCOUNTERPATIENTTYPEROLLUP.patienttyperollup::TEXT, '') AS ""encounterPatientTypeRollupPatientTypeRollup"",
|
||||
SUM(COSTDETAIL.variabledirectcost) AS ""Cost"",
|
||||
NULL AS ""Units""
|
||||
|
||||
FROM dss.FactPatientCostDetail AS COSTDETAIL
|
||||
RIGHT JOIN dss.FactPatientBillingLineItemDetail AS PBLID ON PBLID.rowid = COSTDETAIL.pblidrowid
|
||||
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
|
||||
LEFT JOIN dss.FactPatientEncounterClinicalIndicator AS DSSPECI ON DSSPECI.encounterid = PBLID.encounterid
|
||||
LEFT JOIN CCI.VIEWENCOUNTERPATIENTTYPEROLLUP AS ENCOUNTERPATIENTTYPEROLLUP ON ENCOUNTERPATIENTTYPEROLLUP.encounterid = PBLID.encounterid
|
||||
INNER JOIN FW.DIMCHARGECODE AS CC ON CC.chargecodeid = PBLID.chargecodeid
|
||||
INNER JOIN DSS.DIMPHYSICIAN AS PHYSPRIMARY ON PHYSPRIMARY.physicianid = DSSPES.primaryphysicianid
|
||||
|
||||
WHERE
|
||||
((DSSPES.dischargedatetime >= :dischargedatetime_Start_3 AND DSSPES.dischargedatetime <= :dischargedatetime_End_4) AND DSSPECI.clinicalindicatorid = :clinicalindicatorid_5)
|
||||
|
||||
GROUP BY
|
||||
""dsspesEncounterId"",
|
||||
""dsspesDischargeDateTime"",
|
||||
""dsspesEntityID"",
|
||||
""dsspesPhysicianId"",
|
||||
""dsspesPrimaryServiceLineId"",
|
||||
""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
""dsspesMSDRGCaseTypeFamilyId"",
|
||||
""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
""pblidDepartmentId"",
|
||||
""physPrimaryPhysicianSpecialtyId"",
|
||||
""ccChargeCodeID"",
|
||||
""ccCostDriver"",
|
||||
""encounterPatientTypeRollupPatientTypeRollup""
|
||||
|
||||
|
||||
)
|
||||
|
||||
GROUP BY
|
||||
""dsspesEncounterId"",
|
||||
""dsspesDischargeDateTime"",
|
||||
""dsspesEntityID"",
|
||||
""dsspesPhysicianId"",
|
||||
""dsspesPrimaryServiceLineId"",
|
||||
""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
""dsspesMSDRGCaseTypeFamilyId"",
|
||||
""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
""pblidDepartmentId"",
|
||||
""physPrimaryPhysicianSpecialtyId"",
|
||||
""ccChargeCodeID"",
|
||||
""ccCostDriver"",
|
||||
""encounterPatientTypeRollupPatientTypeRollup""
|
||||
|
||||
|
||||
)
|
||||
|
||||
ORDER BY
|
||||
""dsspesEncounterId"" ASC NULLS FIRST,
|
||||
""dsspesDischargeDateTime"" ASC NULLS FIRST,
|
||||
""dsspesEntityID"" ASC NULLS FIRST,
|
||||
""dsspesPhysicianId"" ASC NULLS FIRST,
|
||||
""dsspesPrimaryServiceLineId"" ASC NULLS FIRST,
|
||||
""dsspesCPTCodeCaseTypeFamilyId"" ASC NULLS FIRST,
|
||||
""dsspesMSDRGCaseTypeFamilyId"" ASC NULLS FIRST,
|
||||
""dsspesAPRDRGCaseTypeFamilyId"" ASC NULLS FIRST,
|
||||
""pblidDepartmentId"" ASC NULLS FIRST,
|
||||
""physPrimaryPhysicianSpecialtyId"" ASC NULLS FIRST,
|
||||
""ccChargeCodeID"" ASC NULLS FIRST,
|
||||
""ccCostDriver"" ASC NULLS FIRST,
|
||||
""encounterPatientTypeRollupPatientTypeRollup"" ASC NULLS FIRST";
|
||||
|
||||
// SQL returned by BuildSqlQuery for the tracking merge path with exploration population
|
||||
private const string _trackingFlexPopQuery = @"SELECT
|
||||
""dsspesEncounterId"",
|
||||
""dsspesDischargeDateTime"",
|
||||
""dsspesEntityID"",
|
||||
""dsspesPhysicianId"",
|
||||
""dsspesPrimaryServiceLineId"",
|
||||
""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
""dsspesMSDRGCaseTypeFamilyId"",
|
||||
""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
""pblidDepartmentId"",
|
||||
""physPrimaryPhysicianSpecialtyId"",
|
||||
""ccChargeCodeID"",
|
||||
""ccCostDriver"",
|
||||
""encounterPatientTypeRollupPatientTypeRollup"",
|
||||
ZEROIFNULL(""Units"") AS ""Units"",
|
||||
ZEROIFNULL(""Cost"") AS ""Cost""
|
||||
|
||||
FROM (
|
||||
SELECT
|
||||
""dsspesEncounterId"",
|
||||
""dsspesDischargeDateTime"",
|
||||
""dsspesEntityID"",
|
||||
""dsspesPhysicianId"",
|
||||
""dsspesPrimaryServiceLineId"",
|
||||
""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
""dsspesMSDRGCaseTypeFamilyId"",
|
||||
""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
""pblidDepartmentId"",
|
||||
""physPrimaryPhysicianSpecialtyId"",
|
||||
""ccChargeCodeID"",
|
||||
""ccCostDriver"",
|
||||
""encounterPatientTypeRollupPatientTypeRollup"",
|
||||
SUM(""Units"") AS ""Units"",
|
||||
SUM(""Cost"") AS ""Cost""
|
||||
|
||||
FROM (
|
||||
SELECT
|
||||
DSSPES.encounterid AS ""dsspesEncounterId"",
|
||||
DSSPES.dischargedatetime AS ""dsspesDischargeDateTime"",
|
||||
DSSPES.entityid AS ""dsspesEntityID"",
|
||||
DSSPES.primaryphysicianid AS ""dsspesPhysicianId"",
|
||||
DSSPES.servicelineid AS ""dsspesPrimaryServiceLineId"",
|
||||
DSSPES.cptcodecasetypefamilyid AS ""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
DSSPES.msdrgcasetypefamilyid AS ""dsspesMSDRGCaseTypeFamilyId"",
|
||||
DSSPES.aprdrgcasetypefamilyid AS ""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
PBLID.departmentid AS ""pblidDepartmentId"",
|
||||
PHYSPRIMARY.physicianspecialtyid AS ""physPrimaryPhysicianSpecialtyId"",
|
||||
CC.chargecodeid AS ""ccChargeCodeID"",
|
||||
IFNULL(CC.costdriver::TEXT, '') AS ""ccCostDriver"",
|
||||
IFNULL(ENCOUNTERPATIENTTYPEROLLUP.patienttyperollup::TEXT, '') AS ""encounterPatientTypeRollupPatientTypeRollup"",
|
||||
NULL AS ""Cost"",
|
||||
SUM(PBLID.unitsofservice) AS ""Units""
|
||||
|
||||
FROM dss.FactPatientBillingLineItemDetail AS PBLID
|
||||
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
|
||||
LEFT JOIN CCI.FACTEXPLORATIONPOPULATIONENCOUNTER AS EXPLORATIONPOPULATIONENCOUNTER ON EXPLORATIONPOPULATIONENCOUNTER.encounterid = PBLID.encounterid
|
||||
LEFT JOIN CCI.VIEWENCOUNTERPATIENTTYPEROLLUP AS ENCOUNTERPATIENTTYPEROLLUP ON ENCOUNTERPATIENTTYPEROLLUP.encounterid = PBLID.encounterid
|
||||
INNER JOIN FW.DIMCHARGECODE AS CC ON CC.chargecodeid = PBLID.chargecodeid
|
||||
INNER JOIN DSS.DIMPHYSICIAN AS PHYSPRIMARY ON PHYSPRIMARY.physicianid = DSSPES.primaryphysicianid
|
||||
|
||||
WHERE
|
||||
((DSSPES.dischargedatetime >= :dischargedatetime_Start_0 AND DSSPES.dischargedatetime <= :dischargedatetime_End_1) AND EXPLORATIONPOPULATIONENCOUNTER.explorationpopulationid = :explorationpopulationid_2)
|
||||
|
||||
GROUP BY
|
||||
""dsspesEncounterId"",
|
||||
""dsspesDischargeDateTime"",
|
||||
""dsspesEntityID"",
|
||||
""dsspesPhysicianId"",
|
||||
""dsspesPrimaryServiceLineId"",
|
||||
""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
""dsspesMSDRGCaseTypeFamilyId"",
|
||||
""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
""pblidDepartmentId"",
|
||||
""physPrimaryPhysicianSpecialtyId"",
|
||||
""ccChargeCodeID"",
|
||||
""ccCostDriver"",
|
||||
""encounterPatientTypeRollupPatientTypeRollup""
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
DSSPES.encounterid AS ""dsspesEncounterId"",
|
||||
DSSPES.dischargedatetime AS ""dsspesDischargeDateTime"",
|
||||
DSSPES.entityid AS ""dsspesEntityID"",
|
||||
DSSPES.primaryphysicianid AS ""dsspesPhysicianId"",
|
||||
DSSPES.servicelineid AS ""dsspesPrimaryServiceLineId"",
|
||||
DSSPES.cptcodecasetypefamilyid AS ""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
DSSPES.msdrgcasetypefamilyid AS ""dsspesMSDRGCaseTypeFamilyId"",
|
||||
DSSPES.aprdrgcasetypefamilyid AS ""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
PBLID.departmentid AS ""pblidDepartmentId"",
|
||||
PHYSPRIMARY.physicianspecialtyid AS ""physPrimaryPhysicianSpecialtyId"",
|
||||
CC.chargecodeid AS ""ccChargeCodeID"",
|
||||
IFNULL(CC.costdriver::TEXT, '') AS ""ccCostDriver"",
|
||||
IFNULL(ENCOUNTERPATIENTTYPEROLLUP.patienttyperollup::TEXT, '') AS ""encounterPatientTypeRollupPatientTypeRollup"",
|
||||
SUM(COSTDETAIL.variabledirectcost) AS ""Cost"",
|
||||
NULL AS ""Units""
|
||||
|
||||
FROM dss.FactPatientCostDetail AS COSTDETAIL
|
||||
RIGHT JOIN dss.FactPatientBillingLineItemDetail AS PBLID ON PBLID.rowid = COSTDETAIL.pblidrowid
|
||||
RIGHT JOIN clientdss.FactPatientEncounterSummary AS DSSPES ON DSSPES.encounterid = PBLID.encounterid
|
||||
LEFT JOIN CCI.FACTEXPLORATIONPOPULATIONENCOUNTER AS EXPLORATIONPOPULATIONENCOUNTER ON EXPLORATIONPOPULATIONENCOUNTER.encounterid = PBLID.encounterid
|
||||
LEFT JOIN CCI.VIEWENCOUNTERPATIENTTYPEROLLUP AS ENCOUNTERPATIENTTYPEROLLUP ON ENCOUNTERPATIENTTYPEROLLUP.encounterid = PBLID.encounterid
|
||||
INNER JOIN FW.DIMCHARGECODE AS CC ON CC.chargecodeid = PBLID.chargecodeid
|
||||
INNER JOIN DSS.DIMPHYSICIAN AS PHYSPRIMARY ON PHYSPRIMARY.physicianid = DSSPES.primaryphysicianid
|
||||
|
||||
WHERE
|
||||
((DSSPES.dischargedatetime >= :dischargedatetime_Start_3 AND DSSPES.dischargedatetime <= :dischargedatetime_End_4) AND EXPLORATIONPOPULATIONENCOUNTER.explorationpopulationid = :explorationpopulationid_5)
|
||||
|
||||
GROUP BY
|
||||
""dsspesEncounterId"",
|
||||
""dsspesDischargeDateTime"",
|
||||
""dsspesEntityID"",
|
||||
""dsspesPhysicianId"",
|
||||
""dsspesPrimaryServiceLineId"",
|
||||
""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
""dsspesMSDRGCaseTypeFamilyId"",
|
||||
""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
""pblidDepartmentId"",
|
||||
""physPrimaryPhysicianSpecialtyId"",
|
||||
""ccChargeCodeID"",
|
||||
""ccCostDriver"",
|
||||
""encounterPatientTypeRollupPatientTypeRollup""
|
||||
|
||||
|
||||
)
|
||||
|
||||
GROUP BY
|
||||
""dsspesEncounterId"",
|
||||
""dsspesDischargeDateTime"",
|
||||
""dsspesEntityID"",
|
||||
""dsspesPhysicianId"",
|
||||
""dsspesPrimaryServiceLineId"",
|
||||
""dsspesCPTCodeCaseTypeFamilyId"",
|
||||
""dsspesMSDRGCaseTypeFamilyId"",
|
||||
""dsspesAPRDRGCaseTypeFamilyId"",
|
||||
""pblidDepartmentId"",
|
||||
""physPrimaryPhysicianSpecialtyId"",
|
||||
""ccChargeCodeID"",
|
||||
""ccCostDriver"",
|
||||
""encounterPatientTypeRollupPatientTypeRollup""
|
||||
|
||||
|
||||
)
|
||||
|
||||
ORDER BY
|
||||
""dsspesEncounterId"" ASC NULLS FIRST,
|
||||
""dsspesDischargeDateTime"" ASC NULLS FIRST,
|
||||
""dsspesEntityID"" ASC NULLS FIRST,
|
||||
""dsspesPhysicianId"" ASC NULLS FIRST,
|
||||
""dsspesPrimaryServiceLineId"" ASC NULLS FIRST,
|
||||
""dsspesCPTCodeCaseTypeFamilyId"" ASC NULLS FIRST,
|
||||
""dsspesMSDRGCaseTypeFamilyId"" ASC NULLS FIRST,
|
||||
""dsspesAPRDRGCaseTypeFamilyId"" ASC NULLS FIRST,
|
||||
""pblidDepartmentId"" ASC NULLS FIRST,
|
||||
""physPrimaryPhysicianSpecialtyId"" ASC NULLS FIRST,
|
||||
""ccChargeCodeID"" ASC NULLS FIRST,
|
||||
""ccCostDriver"" ASC NULLS FIRST,
|
||||
""encounterPatientTypeRollupPatientTypeRollup"" ASC NULLS FIRST";
|
||||
}
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Queries;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture, Category("Unit"), Category("CCI")]
|
||||
internal class StrategicOpportunityGLDetailQueryBuilderTest
|
||||
{
|
||||
private StrategicOpportunityGLDetailQueryBuilder _queryBuilder;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_queryBuilder = new StrategicOpportunityGLDetailQueryBuilder();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildDeleteQuery_WithOpportunityId_EmbedsIdDirectly()
|
||||
{
|
||||
var result = _queryBuilder.BuildDeleteQuery(42);
|
||||
|
||||
result.Should().Contain("OpportunityId = 42");
|
||||
result.Should().NotContain(":opportunityId");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildDeleteQuery_WithoutOpportunityId_UsesParameterWithoutTrailingSemicolon()
|
||||
{
|
||||
var result = _queryBuilder.BuildDeleteQuery(null);
|
||||
|
||||
result.Should().Contain(":opportunityId");
|
||||
result.Should().NotContain(":opportunityId;");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildInsertQuery_WithTypedAccountIds_GeneratesAccountTypeMapCte()
|
||||
{
|
||||
var revenueIds = new List<int> { 100, 101 };
|
||||
var expenseIds = new List<int> { 200 };
|
||||
var statisticIds = new List<int> { 300 };
|
||||
|
||||
var result = _queryBuilder.BuildInsertQuery(
|
||||
opportunityId: 42,
|
||||
sourceTable: "fw.factglsampled",
|
||||
departmentIds: new List<int> { 1, 2 },
|
||||
revenueAccountIds: revenueIds,
|
||||
expenseAccountIds: expenseIds,
|
||||
statisticAccountIds: statisticIds,
|
||||
baselineStart: new DateOnly(2024, 1, 1),
|
||||
baselineEnd: new DateOnly(2024, 12, 31));
|
||||
|
||||
result.Should().Contain("(100, 0)");
|
||||
result.Should().Contain("(101, 0)");
|
||||
result.Should().Contain("(200, 1)");
|
||||
result.Should().Contain("(300, 2)");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildInsertQuery_WithTypedAccountIds_IncludesAccountTypeInInsertAndSelect()
|
||||
{
|
||||
var result = _queryBuilder.BuildInsertQuery(
|
||||
opportunityId: 42,
|
||||
sourceTable: "fw.factglsampled",
|
||||
departmentIds: new List<int> { 1 },
|
||||
revenueAccountIds: new List<int> { 100 },
|
||||
expenseAccountIds: new List<int> { 200 },
|
||||
statisticAccountIds: new List<int> { 300 },
|
||||
baselineStart: new DateOnly(2024, 1, 1),
|
||||
baselineEnd: new DateOnly(2024, 12, 31));
|
||||
|
||||
result.Should().Contain("AccountType,");
|
||||
result.Should().Contain("at.AccountType,");
|
||||
result.Should().Contain("at.AccountType;");
|
||||
result.Should().Contain("JOIN (SELECT AccountId, AccountType FROM (VALUES");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildMergeQuery_WithTypedAccountIds_IncludesAccountTypeInMergeConditionAndInsert()
|
||||
{
|
||||
var result = _queryBuilder.BuildMergeQuery(
|
||||
opportunityId: 42,
|
||||
sourceTable: "fw.factglsampled",
|
||||
departmentIds: new List<int> { 1 },
|
||||
revenueAccountIds: new List<int> { 100 },
|
||||
expenseAccountIds: new List<int> { 200 },
|
||||
statisticAccountIds: new List<int> { 300 },
|
||||
trackingStart: new DateOnly(2025, 1, 1),
|
||||
trackingEnd: new DateOnly(2025, 12, 31));
|
||||
|
||||
result.Should().Contain("AND t.AccountType = s.AccountType");
|
||||
result.Should().Contain("AccountId, AccountType, Amount");
|
||||
result.Should().Contain("s.AccountType, s.Amount");
|
||||
result.Should().Contain("at.AccountType,");
|
||||
result.Should().Contain("JOIN (SELECT AccountId, AccountType FROM (VALUES");
|
||||
}
|
||||
}
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Dtos;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Queries;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture, Category("Unit"), Category("CCI")]
|
||||
internal class StrategicOpportunityGLUpdateQueryBuilderTest : StrategicOpportunityTestsBase
|
||||
{
|
||||
private StrategicOpportunityGLUpdateQueryBuilder _queryBuilder;
|
||||
|
||||
private static readonly IEnumerable<string> Rows =
|
||||
[
|
||||
StrategicOpportunityDetailDimension.System.Value,
|
||||
StrategicOpportunityDetailDimension.Entity.Value,
|
||||
StrategicOpportunityDetailDimension.Department.Value,
|
||||
StrategicOpportunityDetailDimension.GLAccount.Value,
|
||||
];
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_queryBuilder = new StrategicOpportunityGLUpdateQueryBuilder();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task BuildUpdateQuery_WithFourAdjustments_GeneratesCorrectSql()
|
||||
{
|
||||
// Arrange
|
||||
const long opportunityId = 42;
|
||||
|
||||
var adjustments = new List<StrategicOpportunityGLAdjustment>
|
||||
{
|
||||
// Root-level adjustment
|
||||
new() { NodeKey = "root", GoalAmountValue = 50000 },
|
||||
// Entity-level adjustment
|
||||
new() { NodeKey = "101", GoalAmountValue = 20000 },
|
||||
// Entity + Department level: null (passthrough)
|
||||
new() { NodeKey = "101|201", GoalAmountValue = null },
|
||||
// Entity + Department + GLAccount (lowest level)
|
||||
new() { NodeKey = "101|201|3001", GoalAmountValue = 15000 },
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _queryBuilder.BuildUpdateQuery(adjustments, opportunityId, Rows).Query;
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result, VerifySettings);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildUpdateQuery_WithAccountTypeOnSecondAdjustment_IncludesAccountTypeFilterInSubquery()
|
||||
{
|
||||
// AccountType filters are embedded in the inner SELECT WHERE for non-first adjustments
|
||||
// (the first adjustment uses an outer WHERE clause that filters by hierarchy only)
|
||||
const long opportunityId = 42;
|
||||
|
||||
var adjustments = new List<StrategicOpportunityGLAdjustment>
|
||||
{
|
||||
new() { NodeKey = "root", GoalAmountValue = 50000 },
|
||||
new() { NodeKey = "101|201|3001", GoalAmountValue = 15000, AccountType = 0 },
|
||||
};
|
||||
|
||||
var (query, parameters) = _queryBuilder.BuildUpdateQuery(adjustments, opportunityId, Rows);
|
||||
|
||||
query.Should().Contain("AccountType = :AccountType_1");
|
||||
parameters.Should().ContainKey("AccountType_1");
|
||||
parameters["AccountType_1"].Should().Be((byte)0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildUpdateQuery_WithNullAccountType_OmitsAccountTypeFilter()
|
||||
{
|
||||
const long opportunityId = 42;
|
||||
|
||||
var adjustments = new List<StrategicOpportunityGLAdjustment>
|
||||
{
|
||||
new() { NodeKey = "root", GoalAmountValue = 50000 },
|
||||
new() { NodeKey = "101|201|3001", GoalAmountValue = 15000, AccountType = null },
|
||||
};
|
||||
|
||||
var (query, parameters) = _queryBuilder.BuildUpdateQuery(adjustments, opportunityId, Rows);
|
||||
|
||||
query.Should().NotContain("AccountType = :");
|
||||
parameters.Should().NotContainKey("AccountType_1");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildUpdateQuery_WithInvalidOpportunityId_ThrowsArgumentException()
|
||||
{
|
||||
var adjustments = new List<StrategicOpportunityGLAdjustment>
|
||||
{
|
||||
new() { NodeKey = "101", GoalAmountValue = 1000 },
|
||||
};
|
||||
|
||||
var act = () => _queryBuilder.BuildUpdateQuery(adjustments, opportunityId: 0, Rows);
|
||||
|
||||
act.Should().Throw<ArgumentException>().WithParameterName("opportunityId");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BuildUpdateQuery_WithEmptyNodeKey_ThrowsArgumentException()
|
||||
{
|
||||
var adjustments = new List<StrategicOpportunityGLAdjustment>
|
||||
{
|
||||
new() { NodeKey = "", GoalAmountValue = 1000 },
|
||||
};
|
||||
|
||||
var act = () => _queryBuilder.BuildUpdateQuery(adjustments, opportunityId: 42, Rows);
|
||||
|
||||
act.Should().Throw<ArgumentException>().WithParameterName("nodeKey");
|
||||
}
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
using NUnit.Framework;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyTests;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture]
|
||||
public class StrategicOpportunityTestsBase
|
||||
{
|
||||
protected VerifySettings VerifySettings { get; set; }
|
||||
|
||||
[OneTimeSetUp]
|
||||
public void TestFixtureSetup()
|
||||
{
|
||||
VerifySettings = TestExtensions.TestSettings();
|
||||
}
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Dtos;
|
||||
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Queries;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.StrategicOpportunities
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
[TestFixture, Category("Unit"), Category("CCI")]
|
||||
internal class StrategicOpportunityUpdateQueryBuilderTest : StrategicOpportunityTestsBase
|
||||
{
|
||||
private StrategicOpportunityUpdateQueryBuilder _queryBuilder;
|
||||
|
||||
private static readonly IEnumerable<string> Rows =
|
||||
[
|
||||
StrategicOpportunityDetailDimension.System.Value,
|
||||
StrategicOpportunityDetailDimension.Entity.Value,
|
||||
StrategicOpportunityDetailDimension.Department.Value,
|
||||
StrategicOpportunityDetailDimension.ChargeCode.Value,
|
||||
];
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
_queryBuilder = new StrategicOpportunityUpdateQueryBuilder();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task BuildUpdateQuery_WithFourAdjustments_GeneratesCorrectSql()
|
||||
{
|
||||
// Arrange
|
||||
const long opportunityId = 42;
|
||||
|
||||
var adjustments = new List<StrategicOpportunityChargeCodeAdjustment>
|
||||
{
|
||||
// Root-level adjustment: both units and costs
|
||||
new() { NodeKey = "root", UnitsValue = 1000m, CostsValue = 50000m },
|
||||
// Entity-level adjustment: costs only
|
||||
new() { NodeKey = "101", UnitsValue = null, CostsValue = 20000m },
|
||||
// Entity + Department level: units only
|
||||
new() { NodeKey = "101|201", UnitsValue = 300m, CostsValue = null },
|
||||
// Entity + Department + ChargeCode (lowest level): both units and costs
|
||||
new() { NodeKey = "101|201|3001", UnitsValue = 75m, CostsValue = 5000m },
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = _queryBuilder.BuildUpdateQuery(adjustments, opportunityId, Rows).Query;
|
||||
|
||||
// Assert
|
||||
await Verifier.Verify(result, VerifySettings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using Strata.ContinuousImprovement.Biz.Exploration.Opportunities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Stubs
|
||||
{
|
||||
public partial class JazzEntityFrameworkFactory
|
||||
{
|
||||
#region Opportunities
|
||||
|
||||
public List<EXOpportunity> EXOpportunities =
|
||||
new List<EXOpportunity>
|
||||
{
|
||||
new EXOpportunity
|
||||
{
|
||||
OpportunityGuid = Guid.NewGuid(),
|
||||
OpportunityKey = "EX - 101",
|
||||
Name = "Exploration Name 1",
|
||||
IdentifiedSavings = 1000d,
|
||||
InitiativeGuid = Guid.Empty,
|
||||
Note = string.Empty,
|
||||
IsHidden = false,
|
||||
ConfigurationGuid = ConfigurationGuid
|
||||
},
|
||||
new EXOpportunity
|
||||
{
|
||||
OpportunityGuid = Guid.NewGuid(),
|
||||
OpportunityKey = "EX - 102",
|
||||
Name = "Exploration Name 2",
|
||||
IdentifiedSavings = 2000d,
|
||||
InitiativeGuid = Guid.Empty,
|
||||
Note = string.Empty,
|
||||
IsHidden = false,
|
||||
ConfigurationGuid = ConfigurationGuid
|
||||
}
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
using ClosedXML.Excel;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.IO.Packaging;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Utilities
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
internal static class ExcelDocsComparer
|
||||
{
|
||||
public static bool Compare(string left, string right, out string message)
|
||||
{
|
||||
using (FileStream leftStream = File.OpenRead(left))
|
||||
using (FileStream rightStream = File.OpenRead(right))
|
||||
{
|
||||
return Compare(leftStream, rightStream, out message);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Compare(this Stream result, Stream expected, out string message)
|
||||
{
|
||||
using (Package leftPackage = Package.Open(result, FileMode.Open, FileAccess.Read))
|
||||
using (Package rightPackage = Package.Open(expected, FileMode.Open, FileAccess.Read))
|
||||
{
|
||||
return PackageHelper.Compare(leftPackage, rightPackage, false, ExcludeMethod, out message);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Compare(this IXLWorkbook result, IXLWorkbook expected, out string message)
|
||||
{
|
||||
using (var resultStream = new MemoryStream())
|
||||
using (var wbStream = new MemoryStream())
|
||||
{
|
||||
expected.SaveAs(wbStream);
|
||||
result.SaveAs(resultStream);
|
||||
return wbStream.Compare(resultStream, out message);
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ExcludeMethod(Uri uri)
|
||||
{
|
||||
//Exclude service data
|
||||
if (uri.OriginalString.EndsWith(".rels") ||
|
||||
uri.OriginalString.EndsWith(".psmdcp"))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Dictionary<string, DataTable> GetDataTables(this IXLWorkbook workbook)
|
||||
{
|
||||
var dataTables = new Dictionary<string, DataTable>();
|
||||
foreach (var ws in workbook.Worksheets)
|
||||
{
|
||||
var name = ws.Name;
|
||||
DataTable dt = new DataTable();
|
||||
foreach (var cell in ws.RowsUsed().First().CellsUsed())
|
||||
{
|
||||
var columnName = "_" + cell.Value.ToString().ToAlphaNumericOnly();
|
||||
dt.Columns.Add(columnName);
|
||||
}
|
||||
foreach (var row in ws.RowsUsed().Where(x => x.RowNumber() > 1))
|
||||
{
|
||||
DataRow temprow = dt.NewRow();
|
||||
|
||||
for (int i = 0; i < dt.Columns.Count; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cellValue = row.Cells().ElementAt(i).Value.ToString();
|
||||
temprow[i] = cellValue.TrimWhiteSpaces().RemoveLineBreaks();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
// Empty Cell
|
||||
}
|
||||
}
|
||||
|
||||
dt.Rows.Add(temprow);
|
||||
}
|
||||
dataTables.Add(name, dt);
|
||||
}
|
||||
return dataTables;
|
||||
}
|
||||
private static string ToAlphaNumericOnly(this string input)
|
||||
{
|
||||
Regex rgx = new Regex("[^a-zA-Z0-9]");
|
||||
return rgx.Replace(input, "");
|
||||
}
|
||||
|
||||
public static string TrimWhiteSpaces(this string text)
|
||||
{
|
||||
text = text.TrimStart(' ');
|
||||
text = text.TrimEnd(' ');
|
||||
text = text.Trim();
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
public static string RemoveLineBreaks(this string text)
|
||||
{
|
||||
string replaceWith = "";
|
||||
string removedBreaks = text.Replace("\r\n", replaceWith).Replace("\n", replaceWith).Replace("\r", replaceWith);
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+644
@@ -0,0 +1,644 @@
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.Utilities;
|
||||
using Strata.CoreLib.Claims;
|
||||
using Strata.FeatureFlags.Client;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Utilities
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class FeatureFlagWrapperTests
|
||||
{
|
||||
private IFeatureFlagServiceClient _mockFeatureFlagServiceClient;
|
||||
private IClaimsPrincipalAccessor _mockClaimsPrincipalAccessor;
|
||||
private FeatureFlagWrapper _featureFlagWrapper;
|
||||
private readonly Guid _testClientId = Guid.Parse(TestUtilities.DbGuid);
|
||||
private readonly Guid _alternateClientId = Guid.NewGuid();
|
||||
|
||||
[SetUp]
|
||||
public void SetUp()
|
||||
{
|
||||
_mockFeatureFlagServiceClient = Mock.Of<IFeatureFlagServiceClient>();
|
||||
_mockClaimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor();
|
||||
|
||||
_featureFlagWrapper = new FeatureFlagWrapper(
|
||||
_mockFeatureFlagServiceClient,
|
||||
_mockClaimsPrincipalAccessor);
|
||||
}
|
||||
|
||||
#region Test Case Sources
|
||||
|
||||
public static IEnumerable<TestCaseData> FeatureFlagTestCases()
|
||||
{
|
||||
foreach (FeatureFlag featureFlag in Enum.GetValues<FeatureFlag>())
|
||||
{
|
||||
var expectedKey = FeatureFlagLookup.Values[featureFlag];
|
||||
yield return new TestCaseData(featureFlag, expectedKey)
|
||||
.SetName("IsFeatureFlagOn_{0}_ReturnsTrue");
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> FeatureFlagDisabledTestCases()
|
||||
{
|
||||
foreach (FeatureFlag featureFlag in Enum.GetValues<FeatureFlag>().Take(3))
|
||||
{
|
||||
yield return new TestCaseData(featureFlag)
|
||||
.SetName("IsFeatureFlagOn_{0}_ReturnsFalse");
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> FeatureFlagConsistencyTestCases()
|
||||
{
|
||||
yield return new TestCaseData(true, false)
|
||||
.SetName("FeatureFlagConsistency_EnabledFlag_DefaultFalse");
|
||||
yield return new TestCaseData(true, true)
|
||||
.SetName("FeatureFlagConsistency_EnabledFlag_DefaultTrue");
|
||||
yield return new TestCaseData(false, false)
|
||||
.SetName("FeatureFlagConsistency_DisabledFlag_DefaultFalse");
|
||||
yield return new TestCaseData(false, true)
|
||||
.SetName("FeatureFlagConsistency_DisabledFlag_DefaultTrue");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IsFeatureFlagOn Tests
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(nameof(FeatureFlagTestCases))]
|
||||
public async Task IsFeatureFlagOn_WhenFeatureFlagEnabled_ReturnsTrue(FeatureFlag featureFlag, string expectedKey)
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync(expectedKey, _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsFeatureFlagOn(featureFlag, _testClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
Mock.Get(_mockFeatureFlagServiceClient).Verify(
|
||||
x => x.IsEnabledAsync(expectedKey, _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(nameof(FeatureFlagDisabledTestCases))]
|
||||
public async Task IsFeatureFlagOn_WhenFeatureFlagDisabled_ReturnsFalse(FeatureFlag featureFlag)
|
||||
{
|
||||
// Arrange
|
||||
var expectedKey = FeatureFlagLookup.Values[featureFlag];
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync(expectedKey, _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsFeatureFlagOn(featureFlag, _testClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsFeatureFlagOn_WithCustomDefaultValue_UsesProvidedDefault()
|
||||
{
|
||||
// Arrange
|
||||
const bool customDefaultValue = true;
|
||||
var featureFlag = FeatureFlag.ChargeCodeBeta;
|
||||
var expectedKey = FeatureFlagLookup.Values[featureFlag];
|
||||
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync(expectedKey, _testClientId, customDefaultValue, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(customDefaultValue);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsFeatureFlagOn(featureFlag, _testClientId, customDefaultValue);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(customDefaultValue));
|
||||
Mock.Get(_mockFeatureFlagServiceClient).Verify(
|
||||
x => x.IsEnabledAsync(expectedKey, _testClientId, customDefaultValue, It.IsAny<bool>(), It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsFeatureFlagOn_WithDifferentClientIds_CallsServiceWithCorrectClientId()
|
||||
{
|
||||
// Arrange
|
||||
var featureFlag = FeatureFlag.ChargeCodeBeta;
|
||||
var expectedKey = FeatureFlagLookup.Values[featureFlag];
|
||||
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync(expectedKey, _alternateClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsFeatureFlagOn(featureFlag, _alternateClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
Mock.Get(_mockFeatureFlagServiceClient).Verify(
|
||||
x => x.IsEnabledAsync(expectedKey, _alternateClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ChargeCodeBeta Tests
|
||||
|
||||
[Test]
|
||||
public async Task IsChargeCodeBetaEnabled_WithoutClientId_UsesCurrentUserDatabaseGuid()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("chargecodebeta", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsChargeCodeBetaEnabled();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
Mock.Get(_mockFeatureFlagServiceClient).Verify(
|
||||
x => x.IsEnabledAsync("chargecodebeta", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsChargeCodeBetaEnabled_WithClientId_UsesProvidedClientId()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("chargecodebeta", _alternateClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsChargeCodeBetaEnabled(_alternateClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsChargeCodeBetaEnabled_WithDefaultValue_UsesCustomDefault()
|
||||
{
|
||||
// Arrange
|
||||
const bool customDefault = true;
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("chargecodebeta", _testClientId, customDefault, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(customDefault);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsChargeCodeBetaEnabled(customDefault);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.EqualTo(customDefault));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CiBenchmarkingEnabled Tests
|
||||
|
||||
[Test]
|
||||
public async Task IsCiBenchmarkingEnabled_WithoutClientId_UsesCurrentUserDatabaseGuid()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("cibenchmarkingenabled", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsCiBenchmarkingEnabled();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsCiBenchmarkingEnabled_WithClientId_UsesProvidedClientId()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("cibenchmarkingenabled", _alternateClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsCiBenchmarkingEnabled(_alternateClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CiExplorationPopulationStrategicOpportunityWizard Tests
|
||||
|
||||
[Test]
|
||||
public async Task IsCiExplorationPopulationStrategicOpportunityWizardEnabled_WithoutClientId_UsesCurrentUserDatabaseGuid()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("ciexplorationpopulationstrategicopportunitywizard", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsCiExplorationPopulationStrategicOpportunityWizardEnabled();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsCiExplorationPopulationStrategicOpportunityWizardEnabled_WithClientId_UsesProvidedClientId()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("ciexplorationpopulationstrategicopportunitywizard", _alternateClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsCiExplorationPopulationStrategicOpportunityWizardEnabled(_alternateClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CiFlexibleExplorationEnabled Tests
|
||||
|
||||
[Test]
|
||||
public async Task IsCiFlexibleExplorationEnabled_WithoutClientId_UsesCurrentUserDatabaseGuid()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("ciflexibleexplorationenabled", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsCiFlexibleExplorationEnabled();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsCiFlexibleExplorationEnabled_WithClientId_UsesProvidedClientId()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("ciflexibleexplorationenabled", _alternateClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsCiFlexibleExplorationEnabled(_alternateClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CiFlexibleExplorationPage3Enabled Tests
|
||||
|
||||
[Test]
|
||||
public async Task IsCiFlexibleExplorationPage3Enabled_WithoutClientId_UsesCurrentUserDatabaseGuid()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("ciflexibleexplorationpage3enabled", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsCiFlexibleExplorationPage3Enabled();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsCiFlexibleExplorationPage3Enabled_WithClientId_UsesProvidedClientId()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("ciflexibleexplorationpage3enabled", _alternateClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsCiFlexibleExplorationPage3Enabled(_alternateClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region CiOpportunityWorkbooks Tests
|
||||
|
||||
[Test]
|
||||
public async Task IsCiOpportunityWorkbooksEnabled_WithoutClientId_UsesCurrentUserDatabaseGuid()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("ciopportunityworkbooks", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsCiOpportunityWorkbooksEnabled();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsCiOpportunityWorkbooksEnabled_WithClientId_UsesProvidedClientId()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("ciopportunityworkbooks", _alternateClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsCiOpportunityWorkbooksEnabled(_alternateClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DecisionSupportQueries Tests
|
||||
|
||||
[Test]
|
||||
public async Task IsDecisionSupportQueriesEnabled_WithoutClientId_UsesCurrentUserDatabaseGuid()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("is-decision-support-queries-enabled", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsDecisionSupportQueriesEnabled();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsDecisionSupportQueriesEnabled_WithClientId_UsesProvidedClientId()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("is-decision-support-queries-enabled", _alternateClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsDecisionSupportQueriesEnabled(_alternateClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region EnableEncounterOpportunityInTempo Tests
|
||||
|
||||
[Test]
|
||||
public async Task IsEnableEncounterOpportunityInTempoEnabled_WithoutClientId_UsesCurrentUserDatabaseGuid()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("enableencounteropportunityintempo", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsEnableEncounterOpportunityInTempoEnabled();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsEnableEncounterOpportunityInTempoEnabled_WithClientId_UsesProvidedClientId()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("enableencounteropportunityintempo", _alternateClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsEnableEncounterOpportunityInTempoEnabled(_alternateClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region EnablePayrollOpportunityInTempo Tests
|
||||
|
||||
[Test]
|
||||
public async Task IsEnablePayrollOpportunityInTempoEnabled_WithoutClientId_UsesCurrentUserDatabaseGuid()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("enablepayrollopportunityintempo", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsEnablePayrollOpportunityInTempoEnabled();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsEnablePayrollOpportunityInTempoEnabled_WithClientId_UsesProvidedClientId()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("enablepayrollopportunityintempo", _alternateClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsEnablePayrollOpportunityInTempoEnabled(_alternateClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region LoadExplorationPopulationDataFromPostgres Tests
|
||||
|
||||
[Test]
|
||||
public async Task IsLoadExplorationPopulationDataFromPostgresEnabled_WithoutClientId_UsesCurrentUserDatabaseGuid()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("loadexplorationpopulationdatafrompostgres", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsLoadExplorationPopulationDataFromPostgresEnabled();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsLoadExplorationPopulationDataFromPostgresEnabled_WithClientId_UsesProvidedClientId()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("loadexplorationpopulationdatafrompostgres", _alternateClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsLoadExplorationPopulationDataFromPostgresEnabled(_alternateClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region StrategicOpportunityEnabled Tests
|
||||
|
||||
[Test]
|
||||
public async Task IsStrategicOpportunityEnabled_WithoutClientId_UsesCurrentUserDatabaseGuid()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("strategic-opportunity-enabled", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsStrategicOpportunityEnabled();
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.True);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task IsStrategicOpportunityEnabled_WithClientId_UsesProvidedClientId()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("strategic-opportunity-enabled", _alternateClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsStrategicOpportunityEnabled(_alternateClientId);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Exception Handling Tests
|
||||
|
||||
[Test]
|
||||
public void IsFeatureFlagOn_WithInvalidFeatureFlag_ThrowsArgumentException()
|
||||
{
|
||||
// Arrange
|
||||
const FeatureFlag invalidFeatureFlag = (FeatureFlag)999;
|
||||
|
||||
// Act & Assert
|
||||
Assert.ThrowsAsync<KeyNotFoundException>(
|
||||
async () => await _featureFlagWrapper.IsFeatureFlagOn(invalidFeatureFlag, _testClientId));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Edge Case Tests
|
||||
|
||||
[Test]
|
||||
public async Task AllFeatureFlagMethods_WithServiceException_PropagatesException()
|
||||
{
|
||||
// Arrange
|
||||
var expectedException = new InvalidOperationException("Service unavailable");
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync(It.IsAny<string>(), It.IsAny<Guid>(), It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ThrowsAsync(expectedException);
|
||||
|
||||
// Act & Assert
|
||||
var ex = Assert.ThrowsAsync<InvalidOperationException>(
|
||||
async () => await _featureFlagWrapper.IsChargeCodeBetaEnabled());
|
||||
|
||||
Assert.That(ex.Message, Is.EqualTo("Service unavailable"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task AllFeatureFlagMethods_WithEmptyGuid_HandlesGracefully()
|
||||
{
|
||||
// Arrange
|
||||
var emptyGuid = Guid.Empty;
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("chargecodebeta", emptyGuid, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var result = await _featureFlagWrapper.IsChargeCodeBetaEnabled(emptyGuid);
|
||||
|
||||
// Assert
|
||||
Assert.That(result, Is.False);
|
||||
Mock.Get(_mockFeatureFlagServiceClient).Verify(
|
||||
x => x.IsEnabledAsync("chargecodebeta", emptyGuid, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()),
|
||||
Times.Once);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Integration Tests with Realistic Scenarios
|
||||
|
||||
[Test]
|
||||
public async Task MultipleConcurrentFeatureFlagCalls_HandlesCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("chargecodebeta", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(true);
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("cibenchmarkingenabled", _testClientId, false, It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(false);
|
||||
|
||||
// Act
|
||||
var task1 = _featureFlagWrapper.IsChargeCodeBetaEnabled();
|
||||
var task2 = _featureFlagWrapper.IsCiBenchmarkingEnabled();
|
||||
|
||||
await Task.WhenAll(task1, task2);
|
||||
|
||||
// Assert
|
||||
Assert.That(task1.Result, Is.True);
|
||||
Assert.That(task2.Result, Is.False);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCaseSource(nameof(FeatureFlagConsistencyTestCases))]
|
||||
public async Task FeatureFlagConsistency_BetweenOverloads_ReturnsExpectedResults(bool enabledFlag, bool customDefault)
|
||||
{
|
||||
// Arrange
|
||||
Mock.Get(_mockFeatureFlagServiceClient)
|
||||
.Setup(x => x.IsEnabledAsync("chargecodebeta", _testClientId, It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(enabledFlag);
|
||||
|
||||
// Act
|
||||
var resultWithoutClientId = await _featureFlagWrapper.IsChargeCodeBetaEnabled(customDefault);
|
||||
var resultWithClientId = await _featureFlagWrapper.IsChargeCodeBetaEnabled(_testClientId, customDefault);
|
||||
|
||||
// Assert
|
||||
Assert.That(resultWithoutClientId, Is.EqualTo(enabledFlag));
|
||||
Assert.That(resultWithClientId, Is.EqualTo(enabledFlag));
|
||||
Assert.That(resultWithoutClientId, Is.EqualTo(resultWithClientId));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Utilities
|
||||
{
|
||||
public interface IXLExample
|
||||
{
|
||||
void Create(string filePath);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,533 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.IO.Packaging;
|
||||
using System.Linq;
|
||||
using System.Net.Mime;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Utilities
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
public static class PackageHelper
|
||||
{
|
||||
public static void WriteXmlPart(Package package, Uri uri, object content, XmlSerializer serializer)
|
||||
{
|
||||
if (package.PartExists(uri))
|
||||
{
|
||||
package.DeletePart(uri);
|
||||
}
|
||||
PackagePart part = package.CreatePart(uri, MediaTypeNames.Text.Xml, CompressionOption.Fast);
|
||||
using (Stream stream = part.GetStream())
|
||||
{
|
||||
serializer.Serialize(stream, content);
|
||||
}
|
||||
}
|
||||
|
||||
public static object ReadXmlPart(Package package, Uri uri, XmlSerializer serializer)
|
||||
{
|
||||
if (!package.PartExists(uri))
|
||||
{
|
||||
throw new ApplicationException($"Package part '{uri.OriginalString}' doesn't exists!");
|
||||
}
|
||||
PackagePart part = package.GetPart(uri);
|
||||
using (Stream stream = part.GetStream())
|
||||
{
|
||||
return serializer.Deserialize(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteBinaryPart(Package package, Uri uri, Stream content)
|
||||
{
|
||||
if (package.PartExists(uri))
|
||||
{
|
||||
package.DeletePart(uri);
|
||||
}
|
||||
PackagePart part = package.CreatePart(uri, MediaTypeNames.Application.Octet, CompressionOption.Fast);
|
||||
using (Stream stream = part.GetStream())
|
||||
{
|
||||
StreamHelper.StreamToStreamAppend(content, stream);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns part's stream
|
||||
/// </summary>
|
||||
/// <param name="package"></param>
|
||||
/// <param name="uri"></param>
|
||||
/// <returns></returns>
|
||||
public static Stream ReadBinaryPart(Package package, Uri uri)
|
||||
{
|
||||
if (!package.PartExists(uri))
|
||||
{
|
||||
throw new ApplicationException("Package part doesn't exists!");
|
||||
}
|
||||
PackagePart part = package.GetPart(uri);
|
||||
return part.GetStream();
|
||||
}
|
||||
|
||||
public static void CopyPart(Uri uri, Package source, Package dest)
|
||||
{
|
||||
CopyPart(uri, source, dest, true);
|
||||
}
|
||||
|
||||
public static void CopyPart(Uri uri, Package source, Package dest, bool overwrite)
|
||||
{
|
||||
#region Check
|
||||
|
||||
if (ReferenceEquals(uri, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uri));
|
||||
}
|
||||
if (ReferenceEquals(source, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(source));
|
||||
}
|
||||
if (ReferenceEquals(dest, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dest));
|
||||
}
|
||||
|
||||
#endregion Check
|
||||
|
||||
if (dest.PartExists(uri))
|
||||
{
|
||||
if (!overwrite)
|
||||
{
|
||||
throw new ArgumentException("Specified part already exists", nameof(uri));
|
||||
}
|
||||
dest.DeletePart(uri);
|
||||
}
|
||||
|
||||
PackagePart sourcePart = source.GetPart(uri);
|
||||
PackagePart destPart = dest.CreatePart(uri, sourcePart.ContentType, sourcePart.CompressionOption);
|
||||
|
||||
using (Stream sourceStream = sourcePart.GetStream())
|
||||
{
|
||||
using (Stream destStream = destPart.GetStream())
|
||||
{
|
||||
StreamHelper.StreamToStreamAppend(sourceStream, destStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void WritePart<T>(Package package, PackagePartDescriptor descriptor, T content,
|
||||
Action<Stream, T> serializeAction)
|
||||
{
|
||||
#region Check
|
||||
|
||||
if (ReferenceEquals(package, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(package));
|
||||
}
|
||||
if (ReferenceEquals(descriptor, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(descriptor));
|
||||
}
|
||||
if (ReferenceEquals(serializeAction, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(serializeAction));
|
||||
}
|
||||
|
||||
#endregion Check
|
||||
|
||||
if (package.PartExists(descriptor.Uri))
|
||||
{
|
||||
package.DeletePart(descriptor.Uri);
|
||||
}
|
||||
PackagePart part = package.CreatePart(descriptor.Uri, descriptor.ContentType, descriptor.CompressOption);
|
||||
using (Stream stream = part.GetStream())
|
||||
{
|
||||
serializeAction(stream, content);
|
||||
}
|
||||
}
|
||||
|
||||
public static void WritePart(Package package, PackagePartDescriptor descriptor, Action<Stream> serializeAction)
|
||||
{
|
||||
#region Check
|
||||
|
||||
if (ReferenceEquals(package, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(package));
|
||||
}
|
||||
if (ReferenceEquals(descriptor, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(descriptor));
|
||||
}
|
||||
if (ReferenceEquals(serializeAction, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(serializeAction));
|
||||
}
|
||||
|
||||
#endregion Check
|
||||
|
||||
if (package.PartExists(descriptor.Uri))
|
||||
{
|
||||
package.DeletePart(descriptor.Uri);
|
||||
}
|
||||
PackagePart part = package.CreatePart(descriptor.Uri, descriptor.ContentType, descriptor.CompressOption);
|
||||
using (Stream stream = part.GetStream())
|
||||
{
|
||||
serializeAction(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static T ReadPart<T>(Package package, Uri uri, Func<Stream, T> deserializeFunc)
|
||||
{
|
||||
#region Check
|
||||
|
||||
if (ReferenceEquals(package, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(package));
|
||||
}
|
||||
if (ReferenceEquals(uri, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uri));
|
||||
}
|
||||
if (ReferenceEquals(deserializeFunc, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(deserializeFunc));
|
||||
}
|
||||
|
||||
#endregion Check
|
||||
|
||||
if (!package.PartExists(uri))
|
||||
{
|
||||
throw new ApplicationException($"Package part '{uri.OriginalString}' doesn't exists!");
|
||||
}
|
||||
PackagePart part = package.GetPart(uri);
|
||||
using (Stream stream = part.GetStream())
|
||||
{
|
||||
return deserializeFunc(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static void ReadPart(Package package, Uri uri, Action<Stream> deserializeAction)
|
||||
{
|
||||
#region Check
|
||||
|
||||
if (ReferenceEquals(package, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(package));
|
||||
}
|
||||
if (ReferenceEquals(uri, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uri));
|
||||
}
|
||||
if (ReferenceEquals(deserializeAction, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(deserializeAction));
|
||||
}
|
||||
|
||||
#endregion Check
|
||||
|
||||
if (!package.PartExists(uri))
|
||||
{
|
||||
throw new ApplicationException($"Package part '{uri.OriginalString}' doesn't exists!");
|
||||
}
|
||||
PackagePart part = package.GetPart(uri);
|
||||
using (Stream stream = part.GetStream())
|
||||
{
|
||||
deserializeAction(stream);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryReadPart(Package package, Uri uri, Action<Stream> deserializeAction)
|
||||
{
|
||||
#region Check
|
||||
|
||||
if (ReferenceEquals(package, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(package));
|
||||
}
|
||||
if (ReferenceEquals(uri, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uri));
|
||||
}
|
||||
if (ReferenceEquals(deserializeAction, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(deserializeAction));
|
||||
}
|
||||
|
||||
#endregion Check
|
||||
|
||||
if (!package.PartExists(uri))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
PackagePart part = package.GetPart(uri);
|
||||
using (Stream stream = part.GetStream())
|
||||
{
|
||||
deserializeAction(stream);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare to packages by parts like streams
|
||||
/// </summary>
|
||||
/// <param name="left"></param>
|
||||
/// <param name="right"></param>
|
||||
/// <param name="compareToFirstDifference"></param>
|
||||
/// <param name="excludeMethod"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Compare(Package left, Package right, bool compareToFirstDifference, out string message)
|
||||
{
|
||||
return Compare(left, right, compareToFirstDifference, null, out message);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare to packages by parts like streams
|
||||
/// </summary>
|
||||
/// <param name="left"></param>
|
||||
/// <param name="right"></param>
|
||||
/// <param name="compareToFirstDifference"></param>
|
||||
/// <param name="excludeMethod"></param>
|
||||
/// <param name="message"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Compare(Package left, Package right, bool compareToFirstDifference,
|
||||
Func<Uri, bool> excludeMethod, out string message)
|
||||
{
|
||||
#region Check
|
||||
|
||||
if (left == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(left));
|
||||
}
|
||||
if (right == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(right));
|
||||
}
|
||||
|
||||
#endregion Check
|
||||
|
||||
excludeMethod = excludeMethod ?? (uri => false);
|
||||
PackagePartCollection leftParts = left.GetParts();
|
||||
PackagePartCollection rightParts = right.GetParts();
|
||||
|
||||
var pairs = new Dictionary<Uri, PartPair>();
|
||||
foreach (PackagePart part in leftParts)
|
||||
{
|
||||
if (excludeMethod(part.Uri))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
pairs.Add(part.Uri, new PartPair(part.Uri, CompareStatus.OnlyOnLeft));
|
||||
}
|
||||
foreach (PackagePart part in rightParts)
|
||||
{
|
||||
if (excludeMethod(part.Uri))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (pairs.TryGetValue(part.Uri, out PartPair pair))
|
||||
{
|
||||
pair.Status = CompareStatus.Equal;
|
||||
}
|
||||
else
|
||||
{
|
||||
pairs.Add(part.Uri, new PartPair(part.Uri, CompareStatus.OnlyOnRight));
|
||||
}
|
||||
}
|
||||
|
||||
if (compareToFirstDifference && pairs.Any(pair => pair.Value.Status != CompareStatus.Equal))
|
||||
{
|
||||
goto EXIT;
|
||||
}
|
||||
|
||||
foreach (PartPair pair in pairs.Values)
|
||||
{
|
||||
if (pair.Status != CompareStatus.Equal)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var leftPart = left.GetPart(pair.Uri);
|
||||
var rightPart = right.GetPart(pair.Uri);
|
||||
using (Stream leftPackagePartStream = leftPart.GetStream(FileMode.Open, FileAccess.Read))
|
||||
using (Stream rightPackagePartStream = rightPart.GetStream(FileMode.Open, FileAccess.Read))
|
||||
using (var leftMemoryStream = new MemoryStream())
|
||||
using (var rightMemoryStream = new MemoryStream())
|
||||
{
|
||||
leftPackagePartStream.CopyTo(leftMemoryStream);
|
||||
rightPackagePartStream.CopyTo(rightMemoryStream);
|
||||
|
||||
leftMemoryStream.Seek(0, SeekOrigin.Begin);
|
||||
rightMemoryStream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
bool stripColumnWidthsFromSheet = TestHelper.StripColumnWidths &&
|
||||
leftPart.ContentType == @"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml" &&
|
||||
rightPart.ContentType == @"application/vnd.openxmlformats-officedocument.spreadsheetml.worksheet+xml";
|
||||
|
||||
var tuple1 = new Tuple<Uri, Stream>(pair.Uri, leftMemoryStream);
|
||||
var tuple2 = new Tuple<Uri, Stream>(pair.Uri, rightMemoryStream);
|
||||
|
||||
if (!StreamHelper.Compare(tuple1, tuple2, stripColumnWidthsFromSheet))
|
||||
{
|
||||
pair.Status = CompareStatus.NonEqual;
|
||||
if (compareToFirstDifference)
|
||||
{
|
||||
goto EXIT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EXIT:
|
||||
List<PartPair> sortedPairs = pairs.Values.ToList();
|
||||
sortedPairs.Sort((one, other) => one.Uri.OriginalString.CompareTo(other.Uri.OriginalString));
|
||||
var sbuilder = new StringBuilder();
|
||||
foreach (PartPair pair in sortedPairs)
|
||||
{
|
||||
if (pair.Status == CompareStatus.Equal)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
sbuilder.AppendFormat("{0} :{1}", pair.Uri, pair.Status);
|
||||
sbuilder.AppendLine();
|
||||
}
|
||||
message = sbuilder.ToString();
|
||||
return message.Length == 0;
|
||||
}
|
||||
|
||||
#region Nested type: PackagePartDescriptor
|
||||
|
||||
public sealed class PackagePartDescriptor
|
||||
{
|
||||
#region Private fields
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private readonly CompressionOption _compressOption;
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private readonly string _contentType;
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private readonly Uri _uri;
|
||||
|
||||
#endregion Private fields
|
||||
|
||||
#region Constructor
|
||||
|
||||
/// <summary>
|
||||
/// Instance constructor
|
||||
/// </summary>
|
||||
/// <param name=nameof(uri)>Part uri</param>
|
||||
/// <param name="contentType">Content type from <see cref="MediaTypeNames" /></param>
|
||||
/// <param name="compressOption"></param>
|
||||
public PackagePartDescriptor(Uri uri, string contentType, CompressionOption compressOption)
|
||||
{
|
||||
#region Check
|
||||
|
||||
if (ReferenceEquals(uri, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(uri));
|
||||
}
|
||||
if (string.IsNullOrEmpty(contentType))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(contentType));
|
||||
}
|
||||
|
||||
#endregion Check
|
||||
|
||||
_uri = uri;
|
||||
_contentType = contentType;
|
||||
_compressOption = compressOption;
|
||||
}
|
||||
|
||||
#endregion Constructor
|
||||
|
||||
#region Public properties
|
||||
|
||||
public Uri Uri
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get => _uri;
|
||||
}
|
||||
|
||||
public string ContentType
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get => _contentType;
|
||||
}
|
||||
|
||||
public CompressionOption CompressOption
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return _compressOption; }
|
||||
}
|
||||
|
||||
#endregion Public properties
|
||||
|
||||
#region Public methods
|
||||
|
||||
public override string ToString() => $"Uri:{_uri} ContentType: {_contentType}, Compression: {_compressOption}";
|
||||
|
||||
#endregion Public methods
|
||||
}
|
||||
|
||||
#endregion Nested type: PackagePartDescriptor
|
||||
|
||||
#region Nested type: CompareStatus
|
||||
|
||||
private enum CompareStatus
|
||||
{
|
||||
OnlyOnLeft,
|
||||
OnlyOnRight,
|
||||
Equal,
|
||||
NonEqual
|
||||
}
|
||||
|
||||
#endregion Nested type: CompareStatus
|
||||
|
||||
#region Nested type: PartPair
|
||||
|
||||
private sealed class PartPair
|
||||
{
|
||||
#region Private fields
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private readonly Uri _uri;
|
||||
|
||||
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
|
||||
private CompareStatus _status;
|
||||
|
||||
#endregion Private fields
|
||||
|
||||
#region Constructor
|
||||
|
||||
public PartPair(Uri uri, CompareStatus status)
|
||||
{
|
||||
_uri = uri;
|
||||
_status = status;
|
||||
}
|
||||
|
||||
#endregion Constructor
|
||||
|
||||
#region Public properties
|
||||
|
||||
public Uri Uri
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return _uri; }
|
||||
}
|
||||
|
||||
public CompareStatus Status
|
||||
{
|
||||
[DebuggerStepThrough]
|
||||
get { return _status; }
|
||||
[DebuggerStepThrough]
|
||||
set { _status = value; }
|
||||
}
|
||||
|
||||
#endregion Public properties
|
||||
}
|
||||
|
||||
#endregion Nested type: PartPair
|
||||
|
||||
//--
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,253 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Summary description for ResourceFileExtractor.
|
||||
/// </summary>
|
||||
[ExcludeFromCodeCoverage]
|
||||
public sealed class ResourceFileExtractor
|
||||
{
|
||||
#region Static
|
||||
|
||||
#region Private fields
|
||||
|
||||
private static readonly IDictionary<string, ResourceFileExtractor> extractors = new ConcurrentDictionary<string, ResourceFileExtractor>();
|
||||
|
||||
#endregion Private fields
|
||||
|
||||
#region Public properties
|
||||
|
||||
/// <summary>Instance of resource extractor for executing assembly </summary>
|
||||
public static ResourceFileExtractor Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
var _assembly = Assembly.GetCallingAssembly();
|
||||
var _key = _assembly.GetName().FullName;
|
||||
if (extractors.TryGetValue(_key, out var extractor) ||
|
||||
extractors.TryGetValue(_key, out extractor)) return extractor;
|
||||
|
||||
extractor = new ResourceFileExtractor(_assembly, true, null);
|
||||
extractors.Add(_key, extractor);
|
||||
|
||||
return extractor;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Public properties
|
||||
|
||||
#endregion Static
|
||||
|
||||
#region Private fields
|
||||
|
||||
//private readonly Assembly m_assembly;
|
||||
private readonly ResourceFileExtractor m_baseExtractor;
|
||||
|
||||
//private bool m_isStatic;
|
||||
//private string ResourceFilePath { get; }
|
||||
|
||||
#endregion Private fields
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Create instance
|
||||
/// </summary>
|
||||
/// <param name="resourceFilePath"><c>ResourceFilePath</c> in assembly. Example: .Properties.Scripts.</param>
|
||||
/// <param name="baseExtractor"></param>
|
||||
public ResourceFileExtractor(string resourceFilePath, ResourceFileExtractor baseExtractor)
|
||||
: this(Assembly.GetCallingAssembly(), baseExtractor)
|
||||
{
|
||||
ResourceFilePath = resourceFilePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create instance
|
||||
/// </summary>
|
||||
/// <param name="baseExtractor"></param>
|
||||
public ResourceFileExtractor(ResourceFileExtractor baseExtractor)
|
||||
: this(Assembly.GetCallingAssembly(), baseExtractor)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create instance
|
||||
/// </summary>
|
||||
/// <param name="resourcePath"><c>ResourceFilePath</c> in assembly. Example: .Properties.Scripts.</param>
|
||||
public ResourceFileExtractor(string resourcePath)
|
||||
: this(Assembly.GetCallingAssembly(), resourcePath)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instance constructor
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <param name="resourcePath"></param>
|
||||
public ResourceFileExtractor(Assembly assembly, string resourcePath)
|
||||
: this(assembly ?? Assembly.GetCallingAssembly())
|
||||
{
|
||||
ResourceFilePath = resourcePath;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instance constructor
|
||||
/// </summary>
|
||||
public ResourceFileExtractor()
|
||||
: this(Assembly.GetCallingAssembly())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instance constructor
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
public ResourceFileExtractor(Assembly assembly)
|
||||
: this(assembly ?? Assembly.GetCallingAssembly(), (ResourceFileExtractor)null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instance constructor
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <param name="baseExtractor"></param>
|
||||
public ResourceFileExtractor(Assembly assembly, ResourceFileExtractor baseExtractor)
|
||||
: this(assembly ?? Assembly.GetCallingAssembly(), false, baseExtractor)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instance constructor
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <param name="isStatic"></param>
|
||||
/// <param name="baseExtractor"></param>
|
||||
/// <exception cref="ArgumentNullException">Argument is null.</exception>
|
||||
private ResourceFileExtractor(Assembly assembly, bool isStatic, ResourceFileExtractor baseExtractor)
|
||||
{
|
||||
#region Check
|
||||
|
||||
if (assembly is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(assembly));
|
||||
}
|
||||
|
||||
#endregion Check
|
||||
|
||||
Assembly = assembly;
|
||||
m_baseExtractor = baseExtractor;
|
||||
AssemblyName = Assembly.GetName().Name;
|
||||
IsStatic = isStatic;
|
||||
ResourceFilePath = ".Resources.";
|
||||
}
|
||||
|
||||
#endregion Constructors
|
||||
|
||||
#region Public properties
|
||||
|
||||
/// <summary> Work assembly </summary>
|
||||
public Assembly Assembly { get; }
|
||||
|
||||
/// <summary> Work assembly name </summary>
|
||||
public string AssemblyName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Path to read resource files. Example: .Resources.Upgrades.
|
||||
/// </summary>
|
||||
public string ResourceFilePath { get; }
|
||||
|
||||
public bool IsStatic { get; set; }
|
||||
|
||||
public IEnumerable<string> GetFileNames(Func<String, Boolean> predicate = null)
|
||||
{
|
||||
predicate = predicate ?? (s => true);
|
||||
|
||||
var _path = AssemblyName + ResourceFilePath;
|
||||
foreach (string _resourceName in Assembly.GetManifestResourceNames())
|
||||
{
|
||||
if (_resourceName.StartsWith(_path) && predicate(_resourceName))
|
||||
{
|
||||
yield return _resourceName.Replace(_path, string.Empty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Public properties
|
||||
|
||||
#region Public methods
|
||||
|
||||
public string ReadFileFromResource(string fileName)
|
||||
{
|
||||
var _stream = ReadFileFromResourceToStream(fileName);
|
||||
string _result;
|
||||
var sr = new StreamReader(_stream);
|
||||
try
|
||||
{
|
||||
_result = sr.ReadToEnd();
|
||||
}
|
||||
finally
|
||||
{
|
||||
sr.Close();
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
|
||||
public string ReadFileFromResourceFormat(string fileName, params object[] formatArgs)
|
||||
{
|
||||
return string.Format(ReadFileFromResource(fileName), formatArgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read file in current assembly by specific path
|
||||
/// </summary>
|
||||
/// <param name="specificPath">Specific path</param>
|
||||
/// <param name="fileName">Read file name</param>
|
||||
/// <returns></returns>
|
||||
public string ReadSpecificFileFromResource(string specificPath, string fileName)
|
||||
{
|
||||
ResourceFileExtractor _ext = new ResourceFileExtractor(Assembly, specificPath);
|
||||
return _ext.ReadFileFromResource(fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Read file in current assembly by specific file name
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ApplicationException"><c>ApplicationException</c>.</exception>
|
||||
public Stream ReadFileFromResourceToStream(string fileName)
|
||||
{
|
||||
var _nameResFile = AssemblyName + ResourceFilePath + fileName;
|
||||
var _stream = Assembly.GetManifestResourceStream(_nameResFile);
|
||||
|
||||
#region Not found
|
||||
|
||||
if (_stream is null)
|
||||
{
|
||||
#region Get from base extractor
|
||||
|
||||
if (!(m_baseExtractor is null))
|
||||
{
|
||||
return m_baseExtractor.ReadFileFromResourceToStream(fileName);
|
||||
}
|
||||
|
||||
#endregion Get from base extractor
|
||||
|
||||
throw new ArgumentException("Can't find resource file " + _nameResFile, nameof(fileName));
|
||||
}
|
||||
|
||||
#endregion Not found
|
||||
|
||||
return _stream;
|
||||
}
|
||||
|
||||
#endregion Public methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,191 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Help methods for work with streams
|
||||
/// </summary>
|
||||
[ExcludeFromCodeCoverage]
|
||||
public static class StreamHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert stream to byte array
|
||||
/// </summary>
|
||||
/// <param name="pStream">Stream</param>
|
||||
/// <returns>Byte array</returns>
|
||||
public static byte[] StreamToArray(Stream pStream)
|
||||
{
|
||||
long iLength = pStream.Length;
|
||||
var bytes = new byte[iLength];
|
||||
for (int i = 0; i < iLength; i++)
|
||||
{
|
||||
bytes[i] = (byte)pStream.ReadByte();
|
||||
}
|
||||
pStream.Close();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert byte array to stream
|
||||
/// </summary>
|
||||
/// <param name="pBynaryArray">Byte array</param>
|
||||
/// <param name="pStream">Open stream</param>
|
||||
/// <returns></returns>
|
||||
public static Stream ArrayToStreamAppend(byte[] pBynaryArray, Stream pStream)
|
||||
{
|
||||
#region Check params
|
||||
|
||||
if (ReferenceEquals(pBynaryArray, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(pBynaryArray));
|
||||
}
|
||||
if (ReferenceEquals(pStream, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(pStream));
|
||||
}
|
||||
if (!pStream.CanWrite)
|
||||
{
|
||||
throw new ArgumentException("Can't write to stream", nameof(pStream));
|
||||
}
|
||||
|
||||
#endregion Check params
|
||||
|
||||
foreach (byte b in pBynaryArray)
|
||||
{
|
||||
pStream.WriteByte(b);
|
||||
}
|
||||
return pStream;
|
||||
}
|
||||
|
||||
public static void StreamToStreamAppend(Stream streamIn, Stream streamToWrite)
|
||||
{
|
||||
StreamToStreamAppend(streamIn, streamToWrite, 0);
|
||||
}
|
||||
|
||||
public static void StreamToStreamAppend(Stream streamIn, Stream streamToWrite, long dataLength)
|
||||
{
|
||||
#region Check params
|
||||
|
||||
if (ReferenceEquals(streamIn, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(streamIn));
|
||||
}
|
||||
if (ReferenceEquals(streamToWrite, null))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(streamToWrite));
|
||||
}
|
||||
if (!streamIn.CanRead)
|
||||
{
|
||||
throw new ArgumentException("Can't read from stream", nameof(streamIn));
|
||||
}
|
||||
if (!streamToWrite.CanWrite)
|
||||
{
|
||||
throw new ArgumentException("Can't write to stream", nameof(streamToWrite));
|
||||
}
|
||||
|
||||
#endregion Check params
|
||||
|
||||
var buf = new byte[512];
|
||||
long length;
|
||||
if (dataLength == 0)
|
||||
{
|
||||
length = streamIn.Length - streamIn.Position;
|
||||
}
|
||||
else
|
||||
{
|
||||
length = dataLength;
|
||||
}
|
||||
long rest = length;
|
||||
while (rest > 0)
|
||||
{
|
||||
int len1 = streamIn.Read(buf, 0, rest >= 512 ? 512 : (int)rest);
|
||||
streamToWrite.Write(buf, 0, len1);
|
||||
rest -= len1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two streams by converting them to strings and comparing the strings
|
||||
/// </summary>
|
||||
/// <param name="one"></param>
|
||||
/// <param name="other"></param>
|
||||
/// /// <param name="stripColumnWidths"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Compare(Tuple<Uri, Stream> tuple1, Tuple<Uri, Stream> tuple2, bool stripColumnWidths)
|
||||
{
|
||||
#region Check
|
||||
|
||||
if (tuple1 == null || tuple1.Item1 == null || tuple1.Item2 == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tuple1));
|
||||
}
|
||||
if (tuple2 == null || tuple2.Item1 == null || tuple2.Item2 == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(tuple2));
|
||||
}
|
||||
if (tuple1.Item2.Position != 0)
|
||||
{
|
||||
throw new ArgumentException("Must be in position 0", nameof(tuple1));
|
||||
}
|
||||
if (tuple2.Item2.Position != 0)
|
||||
{
|
||||
throw new ArgumentException("Must be in position 0", nameof(tuple2));
|
||||
}
|
||||
|
||||
#endregion Check
|
||||
|
||||
var stringOne = new StreamReader(tuple1.Item2).ReadToEnd().RemoveIgnoredParts(tuple1.Item1, stripColumnWidths, ignoreGuids: true);
|
||||
var stringOther = new StreamReader(tuple2.Item2).ReadToEnd().RemoveIgnoredParts(tuple2.Item1, stripColumnWidths, ignoreGuids: true);
|
||||
return stringOne == stringOther;
|
||||
}
|
||||
|
||||
private static string RemoveIgnoredParts(this string s, Uri uri, bool ignoreColumnWidths, bool ignoreGuids)
|
||||
{
|
||||
s = uriSpecificIgnores.Where(p => p.Key.Equals(uri.OriginalString)).Aggregate(s, (current, pair) => pair.Value.Replace(current, ""));
|
||||
|
||||
// Collapse empty xml elements
|
||||
s = emptyXmlElementRegex.Replace(s, "<$1 />");
|
||||
|
||||
if (ignoreColumnWidths)
|
||||
s = RemoveColumnWidths(s);
|
||||
|
||||
if (ignoreGuids)
|
||||
s = RemoveGuids(s);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
private static IEnumerable<KeyValuePair<string, Regex>> uriSpecificIgnores = new List<KeyValuePair<string, Regex>>()
|
||||
{
|
||||
// Remove dcterms elements
|
||||
new KeyValuePair<string, Regex>("/docProps/core.xml", new Regex(@"<dcterms:(\w+).*?<\/dcterms:\1>", RegexOptions.Compiled))
|
||||
};
|
||||
|
||||
private static Regex emptyXmlElementRegex = new Regex(@"<([\w:]+)><\/\1>", RegexOptions.Compiled);
|
||||
private static Regex columnRegex = new Regex("<x:col.*?width=\"\\d+(\\.\\d+)?\".*?\\/>", RegexOptions.Compiled);
|
||||
private static Regex widthRegex = new Regex("width=\"\\d+(\\.\\d+)?\"\\s+", RegexOptions.Compiled);
|
||||
|
||||
private static string RemoveColumnWidths(string s)
|
||||
{
|
||||
var replacements = new Dictionary<string, string>();
|
||||
|
||||
foreach (var m in columnRegex.Matches(s).OfType<Match>())
|
||||
{
|
||||
var original = m.Groups[0].Value;
|
||||
var replacement = widthRegex.Replace(original, "");
|
||||
replacements.Add(original, replacement);
|
||||
}
|
||||
|
||||
return replacements.Aggregate(s, (current, r) => current.Replace(r.Key, r.Value));
|
||||
}
|
||||
|
||||
private static Regex guidRegex = new Regex(@"{[0-9A-Fa-f]{8}-([0-9A-Fa-f]{4}-){3}[0-9A-Fa-f]{12}}", RegexOptions.Compiled | RegexOptions.Multiline);
|
||||
|
||||
private static string RemoveGuids(string s) => guidRegex.Replace(s, m => string.Empty);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
using NUnit.Framework;
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using VerifyTests;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Utilities
|
||||
{
|
||||
public static class TestExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// The test name
|
||||
/// </summary>
|
||||
/// <param name="context"></param>
|
||||
/// <returns>
|
||||
/// The name of the test split by camel case for a max length of 200 characters.
|
||||
/// </returns>
|
||||
public static string TestName(this TestContext context, string suffix = "")
|
||||
{
|
||||
var testName = suffix == string.Empty
|
||||
? $"{context.Test.Name}".SplitCamelCase()
|
||||
: $"{context.Test.Name} - {suffix}".SplitCamelCase();
|
||||
testName = testName[..Math.Min(200, testName.Length)];
|
||||
return testName;
|
||||
}
|
||||
|
||||
public static string SplitCamelCase(this string input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input)) { return input; }
|
||||
|
||||
const string pattern = "([a-z](?=[A-Z])|[A-Z](?=[A-Z][a-r + t-z])|[A-Z](?=[A-Z][s][a-z]))";
|
||||
|
||||
if (input.StartsWith("FY", StringComparison.Ordinal))
|
||||
{ // hack for FY2012, etc
|
||||
return "FY " + Regex.Replace(input.Remove(0, 2), pattern, "$1 ");
|
||||
}
|
||||
input = Regex.Replace(input, @"\{|\}|:|,|\)|\(", "", RegexOptions.Singleline | RegexOptions.IgnoreCase);
|
||||
return Regex.Replace(input, pattern, "$1 ");
|
||||
}
|
||||
|
||||
public static VerifySettings TestSettings()
|
||||
{
|
||||
var settings = new VerifySettings();
|
||||
settings.UseDirectory("snapshots");
|
||||
settings.ScrubInlineGuids();
|
||||
return settings;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
using ClosedXML.Excel;
|
||||
using FluentAssertions;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Utilities
|
||||
{
|
||||
[ExcludeFromCodeCoverage]
|
||||
internal static class TestHelper
|
||||
{
|
||||
public static string CurrencySymbol => Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencySymbol;
|
||||
|
||||
public static string TestsRunDirectory => System.Reflection.Assembly.GetExecutingAssembly().Location;
|
||||
public static string TestsRootDirectory => Path.GetFullPath(Path.Combine(TestsRunDirectory, @"../../../../"));
|
||||
//Note: Run example tests parameters
|
||||
public static string TestsOutputDirectory => Path.Combine(Path.GetDirectoryName(TestsRunDirectory), "Generated");
|
||||
|
||||
public const string ActualTestResultPostFix = "";
|
||||
public static readonly string ExampleTestsOutputDirectory = Path.Combine(TestsOutputDirectory, "Examples");
|
||||
|
||||
private const bool CompareWithResources = true;
|
||||
|
||||
private static readonly ResourceFileExtractor _extractor = new ResourceFileExtractor(".Resource.");
|
||||
|
||||
public static void SaveWorkbook(XLWorkbook workbook, params string[] fileNameParts)
|
||||
{
|
||||
workbook.SaveAs(Path.Combine(new string[] { TestsOutputDirectory }.Concat(fileNameParts).ToArray()), true);
|
||||
}
|
||||
|
||||
// Because different fonts are installed on Unix,
|
||||
// the columns widths after AdjustToContents() will
|
||||
// cause the tests to fail.
|
||||
// Therefore we ignore the width attribute when running on Unix
|
||||
public static bool StripColumnWidths => IsRunningOnUnix;
|
||||
|
||||
public static bool IsRunningOnUnix
|
||||
{
|
||||
get
|
||||
{
|
||||
var p = (int)Environment.OSVersion.Platform;
|
||||
return ((p == 4) || (p == 6) || (p == 128));
|
||||
}
|
||||
}
|
||||
|
||||
public static void RunTestExample<T>(string filePartName, bool evaluateFormulae = false)
|
||||
where T : IXLExample, new()
|
||||
{
|
||||
// Make sure tests run on a deterministic culture
|
||||
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
|
||||
|
||||
var example = new T();
|
||||
var pathParts = filePartName.Split(new char[] { '\\' });
|
||||
var filePath1 = Path.Combine(new List<string>() { ExampleTestsOutputDirectory }.Concat(pathParts).ToArray());
|
||||
|
||||
var extension = Path.GetExtension(filePath1);
|
||||
var directory = Path.GetDirectoryName(filePath1);
|
||||
|
||||
var fileName = Path.GetFileNameWithoutExtension(filePath1);
|
||||
fileName += ActualTestResultPostFix;
|
||||
fileName = Path.ChangeExtension(fileName, extension);
|
||||
|
||||
filePath1 = Path.Combine(directory, "z" + fileName);
|
||||
var filePath2 = Path.Combine(directory, fileName);
|
||||
|
||||
//Run test
|
||||
example.Create(filePath1);
|
||||
using (var wb = new XLWorkbook(filePath1))
|
||||
wb.SaveAs(filePath2, validate: true, evaluateFormulae);
|
||||
|
||||
// Also load from template and save it again - but not necessary to test against reference file
|
||||
// We're just testing that it can save.
|
||||
using (var ms = new MemoryStream())
|
||||
using (var wb = XLWorkbook.OpenFromTemplate(filePath1))
|
||||
wb.SaveAs(ms, validate: true, evaluateFormulae);
|
||||
|
||||
var resourcePath = "Examples." + filePartName.Replace('\\', '.').TrimStart('.');
|
||||
using (var streamExpected = _extractor.ReadFileFromResourceToStream(resourcePath))
|
||||
using (var streamActual = File.OpenRead(filePath2))
|
||||
{
|
||||
var success = ExcelDocsComparer.Compare(streamActual, streamExpected, out string message);
|
||||
var formattedMessage =
|
||||
$"Actual file '{filePath2}' is different than the expected file '{resourcePath}'. The difference is: '{message}'";
|
||||
success.Should().BeTrue(formattedMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static void CreateAndCompare(Func<IXLWorkbook> workbookGenerator, string referenceResource, bool evaluateFormulae = false)
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("en-US");
|
||||
|
||||
var pathParts = referenceResource.Split(new char[] { '\\' });
|
||||
var filePath1 = Path.Combine(new List<string>() { TestsOutputDirectory }.Concat(pathParts).ToArray());
|
||||
|
||||
var extension = Path.GetExtension(filePath1);
|
||||
var directory = Path.GetDirectoryName(filePath1);
|
||||
|
||||
var fileName = Path.GetFileNameWithoutExtension(filePath1);
|
||||
fileName += ActualTestResultPostFix;
|
||||
fileName = Path.ChangeExtension(fileName, extension);
|
||||
|
||||
var filePath2 = Path.Combine(directory, fileName);
|
||||
|
||||
using (var wb = workbookGenerator.Invoke())
|
||||
wb.SaveAs(filePath2, true, evaluateFormulae);
|
||||
|
||||
var resourcePath = referenceResource.Replace('\\', '.').TrimStart('.');
|
||||
using (var streamExpected = _extractor.ReadFileFromResourceToStream(resourcePath))
|
||||
using (var streamActual = File.OpenRead(filePath2))
|
||||
{
|
||||
var success = ExcelDocsComparer.Compare(streamActual, streamExpected, out string message);
|
||||
var formattedMessage =
|
||||
$"Actual file '{filePath2}' is different than the expected file '{resourcePath}'. The difference is: '{message}'";
|
||||
success.Should().BeTrue(formattedMessage);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetResourcePath(string filePartName)
|
||||
{
|
||||
return filePartName.Replace('\\', '.').TrimStart('.');
|
||||
}
|
||||
|
||||
public static Stream GetStreamFromResource(string resourcePath)
|
||||
{
|
||||
return _extractor.ReadFileFromResourceToStream(resourcePath);
|
||||
}
|
||||
|
||||
public static void LoadFile(string filePartName)
|
||||
{
|
||||
IXLWorkbook wb;
|
||||
using var stream = GetStreamFromResource(GetResourcePath(filePartName));
|
||||
Action action = () =>
|
||||
{
|
||||
wb = new XLWorkbook(stream);
|
||||
};
|
||||
action.Should().NotThrow($"Unable to load resource {filePartName}");
|
||||
}
|
||||
|
||||
public static IEnumerable<String> ListResourceFiles(Func<String, Boolean> predicate = null)
|
||||
{
|
||||
return _extractor.GetFileNames(predicate);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using Moq;
|
||||
using Strata.CoreLib.Claims;
|
||||
using Strata.FeatureFlags.Client;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Claims;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.Utilities
|
||||
{
|
||||
public static class TestUtilities
|
||||
{
|
||||
public const string UserGuid = "eb7e4993-c65a-493a-9614-986a55dd0744";
|
||||
public const string DbGuid = "54409f55-5ddf-4748-8222-9ccfb04fb4f5";
|
||||
public const string ClientDbGuid = "1742934B-C508-402B-B8B5-D18C506474CB";
|
||||
public const string Username = "a";
|
||||
public const string Key = UserGuid + Username;
|
||||
public const string DbVersion = "202133";
|
||||
|
||||
public static IClaimsPrincipalAccessor GetClaimsPrincipalAccessor(string userGuid = null, string userName = null,
|
||||
bool isSdtEmployee = true, bool isClientDatabase = false, bool isEmptyDatabase = false, int strataId = 0)
|
||||
{
|
||||
var dbGuid = DbGuid;
|
||||
if (isClientDatabase) { dbGuid = ClientDbGuid; }
|
||||
if (isEmptyDatabase) { dbGuid = Guid.Empty.ToString(); }
|
||||
|
||||
var claims = new List<Claim>
|
||||
{
|
||||
new Claim(ClaimTypes.Name, "Name"),
|
||||
new Claim(StrataClaims.UserGuid, userGuid ?? UserGuid),
|
||||
new Claim(StrataClaims.Username, userName ?? Username),
|
||||
new Claim("given_name", "Firstname"),
|
||||
new Claim("family_name", "Lastname"),
|
||||
new Claim(StrataClaims.FirstName, "Firstname"),
|
||||
new Claim(StrataClaims.LastName, "Lastname"),
|
||||
new Claim(StrataClaims.DatabaseVersion, DbVersion),
|
||||
new Claim("strata_id", strataId.ToString()),
|
||||
new Claim(StrataClaims.DatabaseGuid, dbGuid),
|
||||
new Claim(StrataClaims.IsSdtEmployee, isSdtEmployee.ToString())
|
||||
};
|
||||
var claimIdentity = new ClaimsIdentity(claims, "mock");
|
||||
var claimsPrincipal = new ClaimsPrincipal(new[] { claimIdentity });
|
||||
var claimsPrincipalAccessorMock = new Mock<IClaimsPrincipalAccessor>();
|
||||
claimsPrincipalAccessorMock.Setup(s => s.GetCurrentClaimsPrincipal()).Returns(claimsPrincipal);
|
||||
|
||||
return claimsPrincipalAccessorMock.Object;
|
||||
}
|
||||
|
||||
internal static IFeatureFlagServiceClient GetFeatureFlagServiceClient(string featureFlag, bool isOn = true)
|
||||
{
|
||||
var featureFlagServiceClient = Mock.Of<IFeatureFlagServiceClient>();
|
||||
Mock.Get(featureFlagServiceClient)
|
||||
.Setup(s => s.IsEnabledAsync(It.IsAny<string>(), It.IsAny<Guid>(), It.IsAny<bool>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
|
||||
.Returns<string, Guid, bool, bool, CancellationToken>((flag, dbGuid, defaultValue, returnDefaultValue, token) => Task.FromResult(flag == featureFlag && dbGuid.ToString() == DbGuid ? isOn : !isOn));
|
||||
return featureFlagServiceClient;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.Utilities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static Org.BouncyCastle.Math.EC.ECCurve;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.UtilitiesTests
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class DateExtensionsTest
|
||||
{
|
||||
[TestCaseSource(nameof(GetStartOrEndDateOfYearPeriodCases))]
|
||||
public void TestGetStartOrEndDateOfYearPeriod(DateTime dateSource, DateTime dateExpected, int yearDiff)
|
||||
{
|
||||
var dateActual = dateSource.GetStartOrEndDateOfYearPeriod(yearDiff);
|
||||
dateActual.Should().Be(dateExpected);
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> GetStartOrEndDateOfYearPeriodCases()
|
||||
{
|
||||
yield return new TestCaseData(new DateTime(2024, 2, 29), new DateTime(2023, 3, 1), -1);
|
||||
yield return new TestCaseData(new DateTime(2025, 2, 28), new DateTime(2024, 3, 1), -1);
|
||||
yield return new TestCaseData(new DateTime(2023, 3, 1), new DateTime(2024, 2, 29), 1);
|
||||
yield return new TestCaseData(new DateTime(2024, 3, 1), new DateTime(2025, 2, 28), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
+672
@@ -0,0 +1,672 @@
|
||||
using ClosedXML.Excel;
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.DbContexts;
|
||||
using Strata.ContinuousImprovement.Biz.Filter;
|
||||
using Strata.ContinuousImprovement.Biz.Generics;
|
||||
using Strata.ContinuousImprovement.Biz.Initiatives;
|
||||
using Strata.ContinuousImprovement.Biz.Pagination;
|
||||
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
|
||||
using Strata.ContinuousImprovement.Biz.UtilizationVariation.Opportunities;
|
||||
using Strata.ContinuousImprovement.Biz.UtilizationVariation.Opportunities.Filters;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using Strata.SqlTools.Configuration.Common.AsyncFactory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.UtilizationVariation.Opportunities
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class UVOpportunityServiceTest
|
||||
{
|
||||
|
||||
private Mock<IUVOpportunityService> _variationOpportunityServiceMock;
|
||||
private Mock<IAsyncDbContextFactory<JazzDbContext>> _dbContextFactoryMock;
|
||||
private Mock<IJazzDbContext> _jazzDbContextMock;
|
||||
private IInitiativeService _initiativeService;
|
||||
private IUpdateFactOpportunitySavingsService _updateFactOpportunitySavingsService;
|
||||
private static readonly ResourceFileExtractor _extractor = new ResourceFileExtractor(".Resource.");
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
_variationOpportunityServiceMock = new Mock<IUVOpportunityService>();
|
||||
_dbContextFactoryMock = new Mock<IAsyncDbContextFactory<JazzDbContext>>();
|
||||
_jazzDbContextMock = new Mock<IJazzDbContext>();
|
||||
_initiativeService = Mock.Of<IInitiativeService>();
|
||||
_updateFactOpportunitySavingsService = Mock.Of<IUpdateFactOpportunitySavingsService>();
|
||||
Mock.Get(_initiativeService)
|
||||
.Setup(s => s.DeleteAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.FromResult(true));
|
||||
Mock.Get(_updateFactOpportunitySavingsService)
|
||||
.Setup(s => s.UpdateFactOpportunitySavings(It.IsAny<CancellationToken>()));
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFrameworkWithFilterData))]
|
||||
public async Task TestGetPagedAsyncWithFramework(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, UVFilters filters, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var variationOpportunityService = new UVOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await variationOpportunityService
|
||||
.GetPagedAsync(new PagingOptions(), filters, cancellationToken);
|
||||
|
||||
// assert
|
||||
var result = taskResult.Data;
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
result.Should().BeNullOrEmpty();
|
||||
return;
|
||||
}
|
||||
result.Should()
|
||||
.NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<UVOpportunity>();
|
||||
|
||||
if (filters.CaseTypeGuids.Any())
|
||||
result.Should()
|
||||
.Contain(vo => filters.CaseTypeGuids.Contains(vo.CaseTypeGuid));
|
||||
if (filters.EntityIds.Any())
|
||||
result.Should()
|
||||
.Contain(vo => filters.EntityIds.Contains(vo.EntityId.ToString()));
|
||||
if (filters.ServiceLineIds.Any())
|
||||
result.Should()
|
||||
.Contain(vo => filters.ServiceLineIds.Contains(vo.ServiceLineId.ToString()));
|
||||
if (filters.CostDrivers.Any())
|
||||
result.Should()
|
||||
.Contain(vo => filters.CostDrivers.Contains(vo.CostDriver));
|
||||
if (filters.ExcludeInitiatives)␍
|
||||
{
|
||||
result.ToList().ForEach(opportunity => opportunity.HasInitiative.Should().Be(false));␍
|
||||
}
|
||||
if (!string.IsNullOrEmpty(filters.OpportunitySearch))
|
||||
result.Should()
|
||||
.Contain(vo => vo.OpportunityKey.Contains(filters.OpportunitySearch));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Asc()
|
||||
{
|
||||
// arrange
|
||||
var variationOpportunityService = new UVOpportunityService(new JazzEntityFrameworkFactory(), null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
var filters = new UVFilters()
|
||||
{
|
||||
CaseTypeGuids = new List<Guid>(),
|
||||
CostDrivers = new List<string>(),
|
||||
EntityIds = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
ServiceLineIds = new List<string>(),
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",␍
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions() { SortField = "Cases", SortOrder = SortOrder.Asc };
|
||||
|
||||
// act
|
||||
var taskResult = await variationOpportunityService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<UVOpportunity>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().Cases
|
||||
.Should().BeLessThan(taskResult.Data.Last().Cases);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Desc()
|
||||
{
|
||||
// arrange
|
||||
var variationOpportunityService = new UVOpportunityService(new JazzEntityFrameworkFactory(), null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
var filters = new UVFilters()
|
||||
{
|
||||
CaseTypeGuids = new List<Guid>(),
|
||||
CostDrivers = new List<string>(),
|
||||
EntityIds = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
ServiceLineIds = new List<string>(),
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",␍
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
};
|
||||
|
||||
var pagingOptions = new PagingOptions() { SortField = "Cases", SortOrder = SortOrder.Desc };
|
||||
|
||||
// act
|
||||
var taskResult = await variationOpportunityService
|
||||
.GetPagedAsync(pagingOptions, filters, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<UVOpportunity>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
taskResult.Data.First().Cases
|
||||
.Should().BeGreaterThan(taskResult.Data.Last().Cases);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFilterData))]
|
||||
public void TestValidateFilters(UVFilters filters)
|
||||
{
|
||||
if (filters == null) return;
|
||||
if (filters.CaseTypeGuids.Any())
|
||||
filters.CaseTypeGuids.Should()
|
||||
.AllBeOfType<Guid>()
|
||||
.And.NotBeEmpty();
|
||||
if (filters.EntityIds.Any())
|
||||
filters.EntityIds.Should()
|
||||
.AllBeOfType<string>();
|
||||
if (filters.ServiceLineIds.Any())
|
||||
filters.ServiceLineIds.Should()
|
||||
.AllBeOfType<string>();
|
||||
if (filters.CostDrivers.Any())
|
||||
filters.CostDrivers.Should()
|
||||
.AllBeOfType<string>();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetExcelWorkbook()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var caseTypeGuid = framework.UVOpportunities.First().CaseTypeGuid;
|
||||
var costDriver = framework.UVOpportunities.First().CostDriver;
|
||||
var entityId = framework.UVOpportunities[1].EntityId;
|
||||
var filters = new UVFilters()
|
||||
{
|
||||
ConfigurationGuid = framework.Configurations.First().ConfigurationGuid,
|
||||
CaseTypeGuids = new[] { caseTypeGuid },
|
||||
CostDrivers = new[] { costDriver },
|
||||
EntityIds = entityId.Split(',', StringSplitOptions.TrimEntries).ToList()
|
||||
};
|
||||
var service = new UVOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var wb = await service.ExportAsync(new SortOptions(), filters, CancellationToken.None);
|
||||
#pragma warning disable S125 // Sections of code should not be commented out
|
||||
//wb.SaveAs(System.IO.Path.Combine(@"C:\Git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "ExcelFilter.xlsx"));
|
||||
#pragma warning restore S125 // Sections of code should not be commented out
|
||||
|
||||
// assert
|
||||
wb.Worksheets.Should().HaveCount(1);
|
||||
var ws = wb.Worksheet(1);
|
||||
ws.Should().NotBeNull();
|
||||
|
||||
var expected = @"Examples.VariationOpportunity.ExcelFilter.xlsx";
|
||||
using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected))
|
||||
using (var actualStream = new MemoryStream())
|
||||
{
|
||||
wb.SaveAs(actualStream);
|
||||
actualStream.Compare(expectedStream, out var message).Should().BeTrue(message);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetExcelWorkbookNullFilter()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
|
||||
var service = new UVOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var wb = await service.ExportAsync(null, null, CancellationToken.None);
|
||||
#pragma warning disable S125 // Sections of code should not be commented out
|
||||
//wb.SaveAs(System.IO.Path.Combine(@"C:\Git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "ExcelNullFilter.xlsx"));
|
||||
#pragma warning restore S125 // Sections of code should not be commented out
|
||||
|
||||
// assert
|
||||
wb.Worksheets.Should().HaveCount(1);
|
||||
var ws = wb.Worksheet(1);
|
||||
ws.Should().NotBeNull();
|
||||
|
||||
var expected = @"Examples.VariationOpportunity.ExcelNullFilter.xlsx";
|
||||
using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected))
|
||||
using (var actualStream = new MemoryStream())
|
||||
{
|
||||
wb.SaveAs(actualStream);
|
||||
actualStream.Compare(expectedStream, out var message).Should().BeTrue(message);
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetExcelWorkbookWithFramework(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var variationOpportunityService = new UVOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
var filters = new UVFilters()
|
||||
{
|
||||
CaseTypeGuids = new List<Guid>(),
|
||||
CostDrivers = new List<string>(),
|
||||
EntityIds = new List<string>(),
|
||||
IdentifiedSavings = 0,
|
||||
ServiceLineIds = new List<string>(),
|
||||
ViewVisible = true,
|
||||
ExcludeInitiatives = false,
|
||||
OpportunitySearch = "",
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult =
|
||||
await variationOpportunityService.ExportAsync(new SortOptions(), filters, cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<XLWorkbook>();
|
||||
var wb = taskResult;
|
||||
wb.Worksheets.Should().HaveCountGreaterThan(0);
|
||||
var ws = wb.Worksheet("Sheet1");
|
||||
ws.ColumnCount().Should().BeGreaterThan(0);
|
||||
ws.RowCount().Should().BeGreaterThan(0);
|
||||
}
|
||||
}
|
||||
catch (TypeInitializationException tie)
|
||||
{
|
||||
tie.Should().BeOfType<TypeInitializationException>();
|
||||
}
|
||||
catch (AssertionException ae)
|
||||
{
|
||||
ae.Should().BeOfType<AssertionException>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetFilterOptionsAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var variationOpportunityService = new UVOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await variationOpportunityService
|
||||
.GetFilterOptionsAsync(new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
return;
|
||||
}
|
||||
taskResult.Should()
|
||||
.BeOfType<UVFilterOptions>()
|
||||
.And.NotBeNull();
|
||||
taskResult.CostDrivers.Should().AllBeOfType<FilterMember>().And.NotBeNullOrEmpty()
|
||||
.And.NotContain(cd => string.IsNullOrEmpty(cd.Id))
|
||||
.And.NotContain(cd => string.IsNullOrEmpty(cd.Text));
|
||||
taskResult.CaseTypes.Should().AllBeOfType<FilterMember>().And.NotBeNullOrEmpty();
|
||||
taskResult.Entities.Should().AllBeOfType<FilterMember>().And.NotBeNullOrEmpty();
|
||||
taskResult.ServiceLines.Should().AllBeOfType<FilterMember>().And.NotBeNullOrEmpty();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSetHidden()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var variationOpportunity = framework.UVOpportunities.First(vo => !vo.IsHidden);
|
||||
var explorationOpportunity = framework.UVOpportunities.Last();
|
||||
var isVariationHidden = variationOpportunity.IsHidden;
|
||||
var isExplorationHidden = explorationOpportunity.IsHidden;
|
||||
var service = new UVOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
await service.SetHiddenAsync(variationOpportunity.OpportunityGuid, !isVariationHidden, CancellationToken.None);
|
||||
await service.SetHiddenAsync(explorationOpportunity.OpportunityGuid, !isExplorationHidden, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var dbContextUpdated = await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var resultUV = dbContextUpdated.UtilizationVariationOpportunitiesData.SingleOrDefault(opp => opp.OpportunityGuid == variationOpportunity.OpportunityGuid);
|
||||
var resultFE = dbContextUpdated.ExplorationVariationOpportunitiesData.SingleOrDefault(opp => opp.OpportunityGuid == explorationOpportunity.OpportunityGuid);
|
||||
resultUV.IsHidden.Should().Be(!isVariationHidden);
|
||||
resultFE.IsHidden.Should().Be(!isExplorationHidden);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var variationOpportunityService = new UVOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
try
|
||||
{
|
||||
var opportunities = variationOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;␍
|
||||
␍
|
||||
//act␍
|
||||
await variationOpportunityService.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden,␍
|
||||
cancellationToken);␍
|
||||
␍
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return;␍
|
||||
var result = variationOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result;␍
|
||||
result.IsHidden.Should().Be(!isHidden);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
switch (e.GetType().Name)
|
||||
{
|
||||
case "AggregateException":
|
||||
case "OperationCanceledException":
|
||||
return;
|
||||
}
|
||||
e.Should().NotBeOfType<Exception>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetHiddenAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.UVOpportunities.FirstOrDefault(o => o.IsHidden);
|
||||
if (opportunity == null) return;
|
||||
var isHidden = opportunity.IsHidden;
|
||||
var variationOpportunityService = new UVOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await variationOpportunityService.SetHiddenAsync(Guid.Empty, !isHidden,
|
||||
cancellationToken);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var variationOpportunityService = new UVOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
try
|
||||
{
|
||||
var opportunities = variationOpportunityService.GetAllAsync(cancellationToken).Result;
|
||||
|
||||
var opportunity = opportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
|
||||
if (opportunity == null) return;
|
||||
|
||||
var note = "new test note";
|
||||
// act
|
||||
await variationOpportunityService.SetNoteAsync(opportunity.OpportunityGuid, note,
|
||||
CancellationToken.None);
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return;
|
||||
var result = variationOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result;
|
||||
result.Note.Should().Be(note);
|
||||
|
||||
// assert
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
switch (e.GetType().Name)
|
||||
{
|
||||
case "AggregateException":
|
||||
case "OperationCanceledException":
|
||||
return;
|
||||
}
|
||||
e.Should().NotBeOfType<Exception>();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestSetNote()
|
||||
{
|
||||
// arrange
|
||||
var framework = new JazzEntityFrameworkFactory();
|
||||
await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
var variationOpportunity = framework.UVOpportunities.First(vo => string.IsNullOrEmpty(vo.Note));
|
||||
var explorationOpportunity = framework.UVOpportunities[5];
|
||||
var variationNote = variationOpportunity.Note;
|
||||
var explorationNote = explorationOpportunity.Note;
|
||||
var expected = "Now is the time for all good engineers to write great code!";
|
||||
var service = new UVOpportunityService(framework, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
await service.SetNoteAsync(variationOpportunity.OpportunityGuid, expected, CancellationToken.None);
|
||||
await service.SetNoteAsync(explorationOpportunity.OpportunityGuid, expected, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
var dbContextUpdated = await framework.CreateDbContextAsync(CancellationToken.None);
|
||||
|
||||
var resultUV = dbContextUpdated.UtilizationVariationOpportunitiesData.SingleOrDefault(opp => opp.OpportunityGuid == variationOpportunity.OpportunityGuid);
|
||||
var resultFE = dbContextUpdated.ExplorationVariationOpportunitiesData.SingleOrDefault(opp => opp.OpportunityGuid == explorationOpportunity.OpportunityGuid);
|
||||
|
||||
|
||||
resultUV.Note.Should().NotBeNullOrEmpty()
|
||||
.And.NotBe(variationNote)
|
||||
.And.Be(expected);
|
||||
resultFE.Note.Should().NotBeNullOrEmpty()
|
||||
.And.NotBe(explorationNote)
|
||||
.And.Be(expected);
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestSetNoteAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var opportunity = jazzEntityFrameworkFactory.UVOpportunities.FirstOrDefault(o => o.Note == string.Empty);
|
||||
if (opportunity == null) return;
|
||||
var note = "new test note";
|
||||
var variationOpportunityService = new UVOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
await variationOpportunityService.SetNoteAsync(Guid.Empty, note, cancellationToken);
|
||||
|
||||
// assert
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
#region JazzDbService Tests
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetAllAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var variationOpportunityService = new UVOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var taskResult = await variationOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestGetAllAsync_Filtered()
|
||||
{
|
||||
// arrange
|
||||
var factory = new JazzEntityFrameworkFactory();
|
||||
var filters = factory.UVOpportunities;
|
||||
var variationOpportunityService = new UVOpportunityService(factory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var taskResult = await variationOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<UVOpportunity>()
|
||||
.And.HaveCountGreaterThan(0)
|
||||
.And.NotContain(o => string.IsNullOrEmpty(o.ToString()))
|
||||
.And.Contain(o => filters.Select(f => f.OpportunityGuid).Contains(o.OpportunityGuid))
|
||||
.And.Contain(o => filters.Select(f => f.CostDriver).Contains(o.CostDriver))
|
||||
.And.Contain(o => filters.Select(f => f.ServiceLineName).Contains(o.ServiceLineName))
|
||||
.And.Contain(o => filters.Select(f => f.ConfigurationGuid).Contains(o.ConfigurationGuid));
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetById(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var variationOpportunityService = new UVOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var tempResult = await variationOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var taskResult =
|
||||
await variationOpportunityService.GetById(tempResult.FirstOrDefault()?.OpportunityGuid ?? Guid.Empty, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<UVOpportunity>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))]
|
||||
public async Task TestGetByIds(JazzEntityFrameworkFactory jazzEntityFrameworkFactory)
|
||||
{
|
||||
// arrange
|
||||
var variationOpportunityService = new UVOpportunityService(jazzEntityFrameworkFactory, null, null, _initiativeService, _updateFactOpportunitySavingsService);
|
||||
|
||||
// act
|
||||
var tempResult = await variationOpportunityService.GetAllAsync(CancellationToken.None);
|
||||
var ids = tempResult.Select(o => o.OpportunityGuid);
|
||||
var taskResult = await variationOpportunityService.GetByIds(ids, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<UVOpportunity>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
|
||||
#region TestCaseData
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFilterData()
|
||||
{
|
||||
yield return new TestCaseData(new UVFilters { ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("No Filters");
|
||||
yield return new TestCaseData(new UVFilters { ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("View Visible");
|
||||
yield return new TestCaseData(new UVFilters { ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Not View Visible");
|
||||
yield return new TestCaseData(new UVFilters
|
||||
{ CaseTypeGuids = new[] { new Guid("c7838982-b2c6-4e93-a571-c1fd5cedc961") }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By Case Type GUID");
|
||||
yield return new TestCaseData(new UVFilters { CostDrivers = new[] { "Cost Driver" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By Cost Driver");
|
||||
yield return new TestCaseData(new UVFilters { EntityIds = new[] { "1" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Entity ID");
|
||||
yield return new TestCaseData(new UVFilters { IdentifiedSavings = 1999, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings");
|
||||
yield return new TestCaseData(new UVFilters { ServiceLineIds = new[] { "1" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By Service Line");
|
||||
yield return new TestCaseData(new UVFilters
|
||||
{ CaseTypeGuids = new[] { new Guid("c7838982-b2c6-4e93-a571-c1fd5cedc961") }, ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By Case Type GUID Not ViewVisible");
|
||||
yield return new TestCaseData(
|
||||
new UVFilters { CostDrivers = new[] { "Cost Driver" }, ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") })
|
||||
.SetName("By Cost Driver Not ViewVisible");
|
||||
yield return new TestCaseData(new UVFilters { EntityIds = new[] { "1" }, ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Entity ID Not ViewVisible");
|
||||
yield return new TestCaseData(new UVFilters { IdentifiedSavings = 999, ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName(
|
||||
"By Identified Savings Not ViewVisible");
|
||||
yield return new TestCaseData(new UVFilters { ServiceLineIds = new[] { "2" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), ViewVisible = false })
|
||||
.SetName("By Service Line Not ViewVisible");
|
||||
yield return new TestCaseData(new UVFilters { OpportunitySearch = "UV - 123", ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Search By Id");
|
||||
yield return new TestCaseData(new UVFilters { ExcludeInitiatives = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Exclude Opportunities with Initiatives");
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFrameworkWithFilterData()
|
||||
{
|
||||
var testCases = GetFilterData().ToList();
|
||||
var jeffs = JazzEntityFrameworkFactory.GetFrameworksWithCancellation()
|
||||
.Select(tcd => tcd.Arguments);
|
||||
foreach (var tcd in jeffs)
|
||||
{
|
||||
var jeff = (JazzEntityFrameworkFactory)tcd[0];
|
||||
var ct = (CancellationToken)tcd[1];
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
yield return new TestCaseData(jeff, testCase.Arguments.GetValue(0), ct)
|
||||
.SetName($"{testCase.TestName} {(string.IsNullOrEmpty(jeff.TestName) ? "w/o Jeff" : "w/Jeff")}")
|
||||
.SetCategory(jeff.TestName);
|
||||
}
|
||||
|
||||
var serviceLineId = jeff.UVOpportunities.FirstOrDefault(o => !o.IsHidden)?.ServiceLineId ?? 0;
|
||||
if (string.IsNullOrEmpty(jeff.TestName))
|
||||
{
|
||||
yield return new TestCaseData(jeff,
|
||||
new UVFilters { ServiceLineIds = new[] { serviceLineId.ToString() }, ViewVisible = false }, ct)
|
||||
.SetName("By Service Line Not ViewVisible w/o Jeff");
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new TestCaseData(jeff,
|
||||
new UVFilters { ServiceLineIds = new[] { serviceLineId.ToString() }, ViewVisible = false }, ct)
|
||||
.SetName("By Service Line Not ViewVisible w/Jeff")
|
||||
.Ignore("This test is broken");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
+364
@@ -0,0 +1,364 @@
|
||||
using FluentAssertions;
|
||||
using Moq;
|
||||
using NUnit.Framework;
|
||||
using Strata.ContinuousImprovement.Biz.Filter;
|
||||
using Strata.ContinuousImprovement.Biz.Pagination;
|
||||
using Strata.ContinuousImprovement.Biz.UtilizationVariation.Opportunities.Filters;
|
||||
using Strata.ContinuousImprovement.Biz.UtilizationVariation.VariationCaseTypes;
|
||||
using Strata.ContinuousImprovement.Biz.UtilizationVariation.VariationCaseTypes.Filters;
|
||||
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit.UtilizationVariation.UVCaseType
|
||||
{
|
||||
[TestFixture, Category("Unit")]
|
||||
public class UVCaseTypeServiceTest
|
||||
{
|
||||
|
||||
private Mock<IUVCaseTypeService> _variationCaseTypeServiceMock;
|
||||
|
||||
[SetUp]
|
||||
public void TestSetUp()
|
||||
{
|
||||
_variationCaseTypeServiceMock = new Mock<IUVCaseTypeService>();
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFrameworkWithFilterCaseTypeData))]
|
||||
public async Task TestGetPagedAsyncWithFramework(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, UVCaseTypeFilters filters, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var VariationCaseTypeService = new UVCaseTypeService(jazzEntityFrameworkFactory, null, null);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await VariationCaseTypeService
|
||||
.GetPagedAsync(new PagingOptions(), filters, cancellationToken);
|
||||
|
||||
// assert
|
||||
var result = taskResult.Data;
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
result.Should().BeNullOrEmpty();
|
||||
return;
|
||||
}
|
||||
result.Should()
|
||||
.NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<Biz.UtilizationVariation.VariationCaseTypes.UVCaseType>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Asc()
|
||||
{
|
||||
// arrange
|
||||
var VariationCaseTypeService = new UVCaseTypeService(new JazzEntityFrameworkFactory(), null, null);␍
|
||||
var filtersData = new UVCaseTypeFilters() { ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") };
|
||||
var pagingOptions = new PagingOptions() { SortField = "CaseTypeName", SortOrder = SortOrder.Asc };
|
||||
|
||||
// act
|
||||
var taskResult = await VariationCaseTypeService
|
||||
.GetPagedAsync(pagingOptions, filtersData, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<Biz.UtilizationVariation.VariationCaseTypes.UVCaseType>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
//taskResult.Data.First().Cases
|
||||
// .Should().BeLessThan(taskResult.Data.Last().Cases);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task TestFirstPage_Sorted_Desc()
|
||||
{
|
||||
// arrange
|
||||
var VariationCaseTypeService = new UVCaseTypeService(new JazzEntityFrameworkFactory(), null, null);
|
||||
|
||||
var filtersData = new UVCaseTypeFilters() { ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") };
|
||||
var pagingOptions = new PagingOptions() { SortField = "CaseTypeName", SortOrder = SortOrder.Desc };
|
||||
|
||||
// act
|
||||
var taskResult = await VariationCaseTypeService
|
||||
.GetPagedAsync(pagingOptions, filtersData, CancellationToken.None);
|
||||
|
||||
// assert
|
||||
taskResult.Data.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<Biz.UtilizationVariation.VariationCaseTypes.UVCaseType>()
|
||||
.And.HaveCountGreaterThan(1);
|
||||
//taskResult.Data.First().Cases
|
||||
// .Should().BeGreaterThan(taskResult.Data.Last().Cases);
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GetFilterData))]
|
||||
public void TestValidateFilters(UVFilters filters)
|
||||
{
|
||||
if (filters == null) return;
|
||||
if (filters.CaseTypeGuids.Any())
|
||||
filters.CaseTypeGuids.Should()
|
||||
.AllBeOfType<Guid>()
|
||||
.And.NotBeEmpty();
|
||||
if (filters.EntityIds.Any())
|
||||
filters.EntityIds.Should()
|
||||
.AllBeOfType<string>();
|
||||
if (filters.ServiceLineIds.Any())
|
||||
filters.ServiceLineIds.Should()
|
||||
.AllBeOfType<string>();
|
||||
if (filters.CostDrivers.Any())
|
||||
filters.CostDrivers.Should()
|
||||
.AllBeOfType<string>();
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetFilterOptionsAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var variationOpportunityService = new UVCaseTypeService(jazzEntityFrameworkFactory, null, null);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await variationOpportunityService
|
||||
.GetFilterOptionsAsync(jazzEntityFrameworkFactory.UVCaseTypes.First().ConfigurationGuid, cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
return;
|
||||
}
|
||||
taskResult.Should()
|
||||
.BeOfType<UVFilterOptions>()
|
||||
.And.NotBeNull();
|
||||
taskResult.CaseTypes.Should().AllBeOfType<FilterMember>().And.NotBeNullOrEmpty();
|
||||
taskResult.ServiceLines.Should().AllBeOfType<FilterMember>().And.NotBeNullOrEmpty();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
#region JazzDbService Tests
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetAllAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var VariationCaseTypeService = new UVCaseTypeService(jazzEntityFrameworkFactory, null, null);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await VariationCaseTypeService.GetAllAsync(cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<Biz.UtilizationVariation.VariationCaseTypes.UVCaseType>()
|
||||
.And.HaveCountGreaterThan(0)
|
||||
.And.NotContain(o => string.IsNullOrEmpty(o.ToString()));
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetById(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var VariationCaseTypeService = new UVCaseTypeService(jazzEntityFrameworkFactory, null, null);
|
||||
var tempResult = await VariationCaseTypeService.GetAllAsync(CancellationToken.None);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult =
|
||||
await VariationCaseTypeService.GetById(tempResult.FirstOrDefault()?.CaseTypeId ?? 0, cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNull()
|
||||
.And.BeOfType<Biz.UtilizationVariation.VariationCaseTypes.UVCaseType>();
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException ioe)
|
||||
{
|
||||
ioe.Should().BeOfType<InvalidOperationException>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
[TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))]
|
||||
public async Task TestGetByIds(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken)
|
||||
{
|
||||
// arrange
|
||||
var VariationCaseTypeService = new UVCaseTypeService(jazzEntityFrameworkFactory, null, null);
|
||||
var tempResult = await VariationCaseTypeService.GetAllAsync(CancellationToken.None);
|
||||
var ids = tempResult.Select(o => o.CaseTypeId);
|
||||
|
||||
try
|
||||
{
|
||||
// act
|
||||
var taskResult = await VariationCaseTypeService.GetByIds(ids, cancellationToken);
|
||||
|
||||
// assert
|
||||
if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName))
|
||||
{
|
||||
taskResult.Should().BeNullOrEmpty();
|
||||
}
|
||||
else
|
||||
{
|
||||
taskResult.Should().NotBeNullOrEmpty()
|
||||
.And.AllBeOfType<Biz.UtilizationVariation.VariationCaseTypes.UVCaseType>();
|
||||
}
|
||||
}
|
||||
catch (InvalidOperationException ioe)
|
||||
{
|
||||
ioe.Should().BeOfType<InvalidOperationException>();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
e.Should().BeOfType<OperationCanceledException>();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
[TearDown]
|
||||
public void TestTearDown()
|
||||
{
|
||||
// Method intentionally left empty.
|
||||
}
|
||||
|
||||
#region TestCaseData
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFilterData()
|
||||
{
|
||||
yield return new TestCaseData(new UVFilters
|
||||
{
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
}).SetName("No Filters");
|
||||
yield return new TestCaseData(new UVFilters
|
||||
{
|
||||
CaseTypeGuids = new[] { new Guid("c7838982-b2c6-4e93-a571-c1fd5cedc961") },
|
||||
ViewVisible = true,
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
}).SetName("By Case Type GUID");
|
||||
yield return new TestCaseData(new UVFilters
|
||||
{
|
||||
IdentifiedSavings = 1999,
|
||||
ViewVisible = true,
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
}).SetName("By Identified Savings");
|
||||
yield return new TestCaseData(new UVFilters
|
||||
{
|
||||
ServiceLineIds = new[] { "1" },
|
||||
ViewVisible = true,
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
}).SetName("By Service Line");
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFilterCaseTypeData()
|
||||
{
|
||||
yield return new TestCaseData(new UVCaseTypeFilters
|
||||
{
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
}).SetName("No Filters");
|
||||
yield return new TestCaseData(new UVCaseTypeFilters
|
||||
{
|
||||
CaseTypeGuids = new[] { new Guid("c7838982-b2c6-4e93-a571-c1fd5cedc961") },
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
}).SetName("By Case Type GUID");
|
||||
yield return new TestCaseData(new UVCaseTypeFilters
|
||||
{
|
||||
IdentifiedSavings = 1999,
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
}).SetName("By Identified Savings");
|
||||
yield return new TestCaseData(new UVCaseTypeFilters
|
||||
{
|
||||
ServiceLineIds = new[] { "1" },
|
||||
ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345")
|
||||
}).SetName("By Service Line");
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFrameworkWithFilterData()
|
||||
{
|
||||
var testCases = GetFilterData().ToList();
|
||||
var jeffs = JazzEntityFrameworkFactory.GetFrameworksWithCancellation()
|
||||
.Select(tcd => tcd.Arguments);
|
||||
foreach (var tcd in jeffs)
|
||||
{
|
||||
var jeff = (JazzEntityFrameworkFactory)tcd[0];
|
||||
var ct = (CancellationToken)tcd[1];
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
yield return new TestCaseData(jeff, testCase.Arguments.GetValue(0), ct)
|
||||
.SetName($"{testCase.TestName} {(string.IsNullOrEmpty(jeff.TestName) ? "w/o Jeff" : "w/Jeff")}")
|
||||
.SetCategory(jeff.TestName);
|
||||
}
|
||||
|
||||
var serviceLineId = jeff.UVOpportunities.FirstOrDefault(o => !o.IsHidden)?.ServiceLineId ?? 0;
|
||||
if (string.IsNullOrEmpty(jeff.TestName))
|
||||
{
|
||||
yield return new TestCaseData(jeff,
|
||||
new UVFilters { ServiceLineIds = new[] { serviceLineId.ToString() }, ViewVisible = false }, ct)
|
||||
.SetName("By Service Line Not ViewVisible w/o Jeff");
|
||||
}
|
||||
else
|
||||
{
|
||||
yield return new TestCaseData(jeff,
|
||||
new UVFilters { ServiceLineIds = new[] { serviceLineId.ToString() }, ViewVisible = false }, ct)
|
||||
.SetName("By Service Line Not ViewVisible w/Jeff")
|
||||
.Ignore("This test is broken");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static IEnumerable<TestCaseData> GetFrameworkWithFilterCaseTypeData()
|
||||
{
|
||||
var testCases = GetFilterCaseTypeData().ToList();
|
||||
var jeffs = JazzEntityFrameworkFactory.GetFrameworksWithCancellation()
|
||||
.Select(tcd => tcd.Arguments);
|
||||
foreach (var tcd in jeffs)
|
||||
{
|
||||
var jeff = (JazzEntityFrameworkFactory)tcd[0];
|
||||
var ct = (CancellationToken)tcd[1];
|
||||
foreach (var testCase in testCases)
|
||||
{
|
||||
yield return new TestCaseData(jeff, testCase.Arguments.GetValue(0), ct)
|
||||
.SetName($"{testCase.TestName} {(string.IsNullOrEmpty(jeff.TestName) ? "w/o Jeff" : "w/Jeff")}")
|
||||
.SetCategory(jeff.TestName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using NUnit.Framework;
|
||||
using System.Threading.Tasks;
|
||||
using VerifyNUnit;
|
||||
|
||||
namespace Strata.ContinuousImprovement.Biz.Test.Unit
|
||||
{
|
||||
[TestFixture]
|
||||
public class VerifyChecksTests
|
||||
{
|
||||
[Test]
|
||||
public Task Run() =>
|
||||
VerifyChecks.Run();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"configProperties": {
|
||||
"System.Drawing.EnableUnixSupport": true
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user