chore: deploy initial code base

This commit is contained in:
Thom Lamb
2026-05-12 10:34:30 -05:00
parent cce2961782
commit a81300a571
1829 changed files with 248331 additions and 1 deletions
@@ -0,0 +1,52 @@
using ClosedXML.Excel;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using NUnit.Framework;
using System;
using System.Threading.Tasks;
using NUnitSetup = NUnit.Framework.SetUpAttribute;
namespace Strata.ContinuousImprovement.Api.Test.Unit.ActionResults
{
[TestFixture, Category("Unit"), Category("ContentResult")]
public class ExcelContentResultTests
{
public ExcelContentResult ExcelContentResult { get; set; }
public IXLWorkbook Workbook { get; set; }
[NUnitSetup]
public void Setup()
{
Workbook = new XLWorkbook();
Workbook.AddWorksheet();
ExcelContentResult = new ExcelContentResult(Workbook, "Export");
}
[Test()]
public void ExcelContentResultTest()
{
// Assert
ExcelContentResult.Should().NotBeNull();
ExcelContentResult.Workbook.Should().NotBeNull();
ExcelContentResult.FileName.Should().NotBeNullOrEmpty();
}
[Test()]
public void ExecuteResultTest()
{
// Arange
var actionConext = new ActionContext();
Action executeResult = () => ExcelContentResult.ExecuteResult(actionConext);
executeResult.Should().NotThrow();
}
[Test(), Ignore("We don't currently use this implementation method")]
public async Task ExecuteResultAsyncTest()
{
// Arange
var actionConext = new ActionContext();
Assert.DoesNotThrowAsync(async () => await ExcelContentResult.ExecuteResultAsync(actionConext));
}
}
}
@@ -0,0 +1,221 @@
using ClosedXML.Excel;
using Microsoft.Extensions.Logging;
using Moq;
using MoreLinq;
using NUnit.Framework;
using Strata.ApiLib.Standard.Models;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.All;
using Strata.ContinuousImprovement.Biz.All.Opportunities;
using Strata.ContinuousImprovement.Biz.All.Opportunities.Filters;
using Strata.ContinuousImprovement.Biz.Export;
using Strata.ContinuousImprovement.Biz.Filter;
using Strata.ContinuousImprovement.Biz.Generics;
using Strata.ContinuousImprovement.Biz.Pagination;
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
using Strata.FeatureFlags.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class AllOpportunityControllerTests
{
public const string ConfigurationGuid = "aa4cba4f-2506-462c-8e34-c45b21653988";
[TestCaseSource(nameof(GetOpportunityTestCases))]
public async Task GetOpportunityTest(bool featureFlagSet, bool featureFlagIsOn, bool isSdtEmployee = true)
{
var result = await GetPagedApiResponse(featureFlagSet);
var service = await GetAllOpportunityService(result);
var claimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor(isSdtEmployee: isSdtEmployee);
var featureFlagServiceClient = featureFlagSet
? TestUtilities.GetFeatureFlagServiceClient("ciflexibleexplorationenabled", featureFlagIsOn)
: Mock.Of<IFeatureFlagServiceClient>();
var controller = new AllOpportunitiesController(service, claimsPrincipalAccessor,
featureFlagServiceClient,
Mock.Of<ILogger<AllOpportunitiesController>>());
var pagedResponse = await controller.GetOpportunities(new AllOpportunityLoadOptions
{
PagingOptions = new PagingOptions { First = 0, Rows = 20, SortField = "IdentifiedSavings", SortOrder = SortOrder.Desc },
Filters = new AllFilters
{
ConfigurationGuid = new Guid(ConfigurationGuid)
}
}, CancellationToken.None);
Assert.That(result, Is.SameAs(pagedResponse));
}
public static IEnumerable<TestCaseData> GetOpportunityTestCases()
{
yield return new TestCaseData(true, false, true)
.SetName(nameof(GetOpportunityTest) + " FeatureFlag Off SdtEmployee");
yield return new TestCaseData(true, true, true)
.SetName(nameof(GetOpportunityTest) + " FeatureFlag On SdtEmployee");
yield return new TestCaseData(true, false, false)
.SetName(nameof(GetOpportunityTest) + " FeatureFlag Off Not SdtEmployee");
yield return new TestCaseData(true, true, false)
.SetName(nameof(GetOpportunityTest) + " FeatureFlag On Not SdtEmployee");
yield return new TestCaseData(false, false, true)
.SetName(nameof(GetOpportunityTest) + " No FeatureFlag Off SdtEmployee");
yield return new TestCaseData(false, true, true)
.SetName(nameof(GetOpportunityTest) + " No FeatureFlag On SdtEmployee");
yield return new TestCaseData(false, false, false)
.SetName(nameof(GetOpportunityTest) + " No FeatureFlag Off Not SdtEmployee");
yield return new TestCaseData(false, true, false)
.SetName(nameof(GetOpportunityTest) + " No FeatureFlag On Not SdtEmployee");
}
[TestCase(false)]
[TestCase(true)]
public async Task GetNameIsValidTest(bool isValid)
{
var result = await GetPagedApiResponse();
var service = await GetAllOpportunityService(result);
var claimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor();
var firstRow = result.Data.First();
var validateName = new ValidateName
{
ConfigurationGuid = firstRow.ConfigurationGuid,
OpportunityGuid = isValid ? Guid.NewGuid() : firstRow.OpportunityGuid,
Name = firstRow.Name,
OpportunityType = firstRow.OpportunityType
};
var controller = new AllOpportunitiesController(service, claimsPrincipalAccessor,
Mock.Of<IFeatureFlagServiceClient>(),
Mock.Of<ILogger<AllOpportunitiesController>>());
var isNameValid = await controller.IsNameValid(validateName, CancellationToken.None);
Assert.That(isValid, Is.EqualTo(isNameValid));
}
[TestCase(true)]
[TestCase(false)]
public async Task GetFilterOptionsTest(bool isSdtEmployee)
{
var result = await GetPagedApiResponse();
var service = await GetAllOpportunityService(result);
var claimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor(isSdtEmployee: isSdtEmployee);
var controller = new AllOpportunitiesController(service, claimsPrincipalAccessor,
Mock.Of<IFeatureFlagServiceClient>(),
Mock.Of<ILogger<AllOpportunitiesController>>());
var filterOptions = new AllFilterOptions
{
OpportunityTypes = Enum.GetValues<OpportunityTypes>()
.Where(ot => isSdtEmployee || ot != OpportunityTypes.Blank)
.Select(ot => new FilterMember { Id = $"{(int)ot}", Text = ot.OpportunityTypeName() })
};
var options = await controller.GetFilterOptionsAsync(result.Data.First().ConfigurationGuid, CancellationToken.None);
filterOptions.OpportunityTypes
.ForEach(ot => Assert.That(options.OpportunityTypes.Any(x => x.Id == ot.Id && x.Text == ot.Text), Is.True));
}
[Test, Ignore("Ignoring because we don't have generic GetById endpoint to use here.")]
public async Task SetHiddenAsyncTest()
{
var result = await GetPagedApiResponse();
var service = await GetAllOpportunityService(result);
var claimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor();
var controller = new AllOpportunitiesController(service, claimsPrincipalAccessor,
Mock.Of<IFeatureFlagServiceClient>(),
Mock.Of<ILogger<AllOpportunitiesController>>());
var firstRow = result.Data.First(row => row.OpportunityType == (int)OpportunityTypes.Variation);
await controller.SetHiddenAsync(firstRow.OpportunityGuid, !firstRow.IsHidden, CancellationToken.None);
}
public async Task ExcelExportText()
{
var result = await GetPagedApiResponse();
var service = await GetAllOpportunityService(result);
var claimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor();
var controller = new AllOpportunitiesController(service, claimsPrincipalAccessor,
Mock.Of<IFeatureFlagServiceClient>(),
Mock.Of<ILogger<AllOpportunitiesController>>());
var export = await controller.Export(new AllOpportunityExportOptions
{
SortOptions = new SortOptions(),
Filters = new AllFilters()
}, CancellationToken.None);
Assert.That(export, Is.AssignableFrom<ExcelContentResult>());
var workbook = ((ExcelContentResult)export).Workbook;
var filename = ((ExcelContentResult)export).FileName;
Assert.Multiple(() =>
{
Assert.That(workbook.Worksheets.First().Rows().Count(), Is.GreaterThan(result.Data.Count()));
Assert.That(filename, Is.Not.Null);
Assert.That(filename, Is.Not.Empty);
});
}
private async Task<PagedApiResponse<AllOpportunity>> GetPagedApiResponse(bool withExplorationOpportunities = true)
{
var jeff = new JazzEntityFrameworkFactory();
var dbContext = await jeff.CreateDbContextAsync(nameof(AllOpportunityControllerTests), CancellationToken.None);
var result = new PagedApiResponse<AllOpportunity>
{
Data = withExplorationOpportunities
? dbContext.AllOpportunities
: dbContext.AllOpportunities.Where(opp => opp.OpportunityType != (int)OpportunityTypes.Blank),
PagingInfo = new PagingInfo
{
ResultsPerPage = 20,
TotalNumberOfResults = dbContext.AllOpportunities.Count(),
TotalPages = dbContext.AllOpportunities.Count() / 20,
PageNumber = 1
}
};
return result;
}
private async Task<IAllOpportunityService> GetAllOpportunityService(PagedApiResponse<AllOpportunity> pagedApiResponse = null)
{
var jeff = new JazzEntityFrameworkFactory();
var dbContext = await jeff.CreateDbContextAsync(nameof(AllOpportunityControllerTests), CancellationToken.None);
var service = Mock.Of<IAllOpportunityService>();
Mock.Get(service)
.Setup(s => s.GetPagedAsync(It.IsAny<PagingOptions>(), It.IsAny<IFilters<AllOpportunity>>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(pagedApiResponse ?? await GetPagedApiResponse()));
Mock.Get(service)
.Setup(s => s.NameIsValid(It.IsAny<Guid>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<Guid?>(), It.IsAny<CancellationToken>()))
.Returns<Guid, int, string, Guid?, CancellationToken>((config, oppType, name, oppGuid, token)
=> Task.FromResult(!dbContext.AllOpportunities.Any(opp
=> opp.ConfigurationGuid == config
&& opp.OpportunityType == oppType
&& opp.OpportunityGuid == oppGuid
&& opp.Name.Equals(name, StringComparison.CurrentCultureIgnoreCase))));
var filterOptions = new AllFilterOptions
{
OpportunityTypes = Enum.GetValues<OpportunityTypes>()
.Select(ot => new FilterMember { Id = $"{(int)ot}", Text = ot.OpportunityTypeName() })
};
Mock.Get(service)
.Setup(s => s.GetFilterOptionsAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, CancellationToken>((config, token) => Task.FromResult(filterOptions));
var exportOptions = new ExportOptions() { EmptyMessage = "No Opportunities" };
// configure column formats
exportOptions.AddColumnOptions("Identified Savings", "Currency2Dec");
exportOptions.AddColumnOptions("Is Hidden", "\"Yes\";-;\"No\"");
var xlWorkbook = (IXLWorkbook)ExportUtils.CreateExcelWorkbook(dbContext.AllOpportunities, exportOptions);
Mock.Get(service)
.Setup(s => s.ExportAsync(It.IsAny<SortOptions>(), It.IsAny<AllFilters>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(xlWorkbook));
Mock.Get(service)
.Setup(s => s.SetHiddenAsync(It.IsAny<Guid>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask);
Mock.Get(service)
.Setup(s => s.SetNoteAsync(It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(Task.CompletedTask);
Mock.Get(service)
.Setup(s => s.GetById(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, CancellationToken>((oppGuid, token) => Task.FromResult(dbContext.AllOpportunities.FirstOrDefault(opp => opp.OpportunityGuid == oppGuid)));
return service;
}
}
}
@@ -0,0 +1,85 @@
using FluentAssertions;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.ChargeCode.Initiatives;
using Strata.ContinuousImprovement.Biz.Initiatives;
using Strata.ContinuousImprovement.Biz.Mappers;
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class ChargeCodeInitiativesControllerTests
{
[TestCaseSource(nameof(DevDbTestCases1))]
[TestCaseSource(nameof(TestCases))]
public async Task Test(ChargeCodeInitiativesController controller, Guid opportunityGuid, Guid expected)
{
var dto = new InitiativeDto
{
OpportunityGuid = opportunityGuid,
TrackingStart = DateTime.Now.ToString("yyyy/MM/dd")
};
var result = await controller.Create(dto, CancellationToken.None);
var actual = result.Value;
actual.Should().Be(expected);
}
public static IEnumerable<TestCaseData> DevDbTestCases1()
{
var foundOpportunityGuid = Guid.NewGuid();
var notFoundOpportunityGuid = Guid.NewGuid();
var newInitiative = Guid.NewGuid();
var stakeholderUsers = Mock.Of<IStakeholderUser>();
var clientClaimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor();
var service = Mock.Of<ICCInitiativeService>();
Mock.Get(service)
.Setup(s => s.CreateChargeCodeInitiative(It.IsAny<Guid>(), It.IsAny<Initiative>(),
It.IsIn(new[] { foundOpportunityGuid }.AsEnumerable()), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(newInitiative));
var controller = new ChargeCodeInitiativesController(clientClaimsPrincipalAccessor, service, stakeholderUsers);
var notFoundService = Mock.Of<ICCInitiativeService>();
Mock.Get(notFoundService)
.Setup(s => s.CreateChargeCodeInitiative(It.IsAny<Guid>(), It.IsAny<Initiative>(),
It.IsNotIn(new[] { foundOpportunityGuid }.AsEnumerable()), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(Guid.Empty));
var notFoundController = new ChargeCodeInitiativesController(clientClaimsPrincipalAccessor, notFoundService, stakeholderUsers);
yield return new TestCaseData(controller, foundOpportunityGuid, newInitiative)
.SetName("Dev Db Opportunity Found");
yield return new TestCaseData(controller, notFoundOpportunityGuid, Guid.Empty)
.SetName("Dev Db Opportunity Not Found");
yield return new TestCaseData(notFoundController, notFoundOpportunityGuid, Guid.Empty)
.SetName("Dev Db Opportunity Not Found 1");
}
public static IEnumerable<TestCaseData> TestCases()
{
var foundOpportunityGuid = Guid.NewGuid();
var notFoundOpportunityGuid = Guid.NewGuid();
var stakeholderUsers = Mock.Of<IStakeholderUser>();
var service = Mock.Of<ICCInitiativeService>();
Mock.Get(service)
.Setup(s => s.CreateChargeCodeInitiative(It.IsIn(new[] { new Guid(TestUtilities.ClientDbGuid) }.AsEnumerable()),
It.IsAny<Initiative>(), It.IsIn(new[] { foundOpportunityGuid }.AsEnumerable()), It.IsAny<CancellationToken>()))
.Throws<Exception>();
var clientClaimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor(isClientDatabase: true);
var controller = new ChargeCodeInitiativesController(clientClaimsPrincipalAccessor, service, stakeholderUsers);
yield return new TestCaseData(controller, foundOpportunityGuid, Guid.Empty)
.SetName("Client Db Opportunity Found");
yield return new TestCaseData(controller, notFoundOpportunityGuid, Guid.Empty)
.SetName("Client Db Opportunity Not Found");
}
}
}
@@ -0,0 +1,374 @@
using ClosedXML.Excel;
using DocumentFormat.OpenXml.Drawing.Diagrams;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.All.Opportunities;
using Strata.ContinuousImprovement.Biz.ChargeCode.Initiatives;
using Strata.ContinuousImprovement.Biz.ChargeCode.Opportunities;
using Strata.ContinuousImprovement.Biz.Configuration;
using Strata.ContinuousImprovement.Biz.DbContexts;
using Strata.ContinuousImprovement.Biz.Dtos;
using Strata.ContinuousImprovement.Biz.Initiatives;
using Strata.ContinuousImprovement.Biz.OrgDefined;
using Strata.ContinuousImprovement.Biz.Shared;
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
using Strata.ContinuousImprovement.JazzEntityFrameworkStub.Generics;
using Strata.CoreLib.Claims;
using Strata.FeatureFlags.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NUnitSetup = NUnit.Framework.SetUpAttribute;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class ChargeCodeOpportunitiesControllerTests
{
public JazzDbContext DbContext { get; set; }
public ChargeCodeOpportunitiesController Controller { get; set; }
public IEnumerable<Biz.Configuration.Configuration> Configurations { get; set; }
public IClaimsPrincipalAccessor ClaimsPrincipalAccessor { get; set; }
public IConfigurationService ConfigurationService { get; set; }
public ICCOpportunityService OpportunityService;
public ICCInitiativeService InitiativeService;
public IOpportunityMetricCohortService OpportunityMetricCohortService;
public IFeatureFlagServiceClient FeatureFlagServiceClient;
public IAllOpportunityService AllOpportunityService;
[OneTimeSetUp]
public async Task ConfigurationsControllerTestSetup()
{
// Arrange
var jeff = new JazzEntityFrameworkFactory();
DbContext = await jeff.CreateDbContextAsync(nameof(ConfigurationsControllerTests), CancellationToken.None);
Configurations = jeff.Configurations.ToList();
var configuration = jeff.Configurations.First(c => c.ConfigurationGuid == JazzEntityFrameworkFactory.CurrentConfigurationGuid);
var ccOpportunityDataModel = jeff.CCOpportunities[0].MapToDataModel(configuration);
var workbook = new XLWorkbook();
// Act
ClaimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor();
FeatureFlagServiceClient = TestUtilities.GetFeatureFlagServiceClient("chargecodebeta", true);
ConfigurationService = Mock.Of<IConfigurationService>();
Mock.Get(ConfigurationService)
.Setup(s => s.GetConfigurationsAsync(It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(Configurations.AsEnumerable()));
Mock.Get(ConfigurationService)
.Setup(s => s.GetConfigurationAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(configuration));
AllOpportunityService = Mock.Of<IAllOpportunityService>();
Mock.Get(AllOpportunityService)
.Setup(s => s.NameIsValid(It.IsAny<Guid>(), It.IsAny<int>(), It.IsAny<string>(), It.IsAny<Guid?>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(true));
OpportunityService = Mock.Of<ICCOpportunityService>();
Mock.Get(OpportunityService)
.Setup(s => s.UpdateAsync(It.IsAny<Guid>(), It.IsAny<CCOpportunityDataModel>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(Guid.NewGuid().ToString()));
Mock.Get(OpportunityService)
.Setup(s => s.ValidateChargeCodesAsync(It.IsAny<List<string>>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(true));
Mock.Get(OpportunityService)
.Setup(s => s.ValidateOpportunityLevelsAsync(It.IsAny<OpportunityLevel>(), It.IsAny<List<string>>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(true));
Mock.Get(OpportunityService)
.Setup(s => s.DeleteAsync<CCOpportunityDataModel>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(true));
Mock.Get(OpportunityService)
.Setup(s => s.GetById(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, CancellationToken>((oppGuid, token)
=> oppGuid == ccOpportunityDataModel.OpportunityGuid
? Task.FromResult(ccOpportunityDataModel)
: Task.FromResult((CCOpportunityDataModel)null));
Mock.Get(OpportunityService)
.Setup(s => s.ExportAsync(It.IsAny<Guid>(), It.IsAny<IEnumerable<string>>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns<Guid, IEnumerable<string>, string, CancellationToken>((oppGuid, chargeCodes, userName, token)
=> oppGuid == ccOpportunityDataModel.OpportunityGuid
? Task.FromResult(((IXLWorkbook)workbook))
: Task.FromResult(((IXLWorkbook)null)));
Mock.Get(OpportunityService)
.Setup(s => s.UpdateGoalTotalUnitsOfServiceAsync(It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<double>(), It.IsAny<CancellationToken>()))
.Returns<Guid, string, double, CancellationToken>((oppGuid, key, value, token)
=> oppGuid == ccOpportunityDataModel.OpportunityGuid
? Task.FromResult(true)
: Task.FromResult(false));
Mock.Get(OpportunityService)
.Setup(s => s.UpdateGoalCostPerUnitAsync(It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<double>(), It.IsAny<CancellationToken>()))
.Returns<Guid, string, double, CancellationToken>((oppGuid, key, goalValue, token)
=> oppGuid == ccOpportunityDataModel.OpportunityGuid
? Task.FromResult(true)
: Task.FromResult(false));
Mock.Get(OpportunityService)
.Setup(s => s.GetInitiativeInfoAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(new InitiativeInfo()));
Mock.Get(OpportunityService)
.Setup(s => s.RefreshOpportunityTrackingData(It.IsAny<Guid>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, Guid, CancellationToken>((dbGuid, oppGuid, token)
=> dbGuid.ToString() == TestUtilities.DbGuid && oppGuid == ccOpportunityDataModel.OpportunityGuid
? Task.FromResult("Good")
: Task.FromResult(""));
InitiativeService = Mock.Of<ICCInitiativeService>();
Mock.Get(InitiativeService)
.Setup(s => s.UpdateSavings(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(true));
OpportunityMetricCohortService = Mock.Of<IOpportunityMetricCohortService>();
}
[NUnitSetup]
public void TestSetup()
{
// Arrange
Controller = new ChargeCodeOpportunitiesController(ClaimsPrincipalAccessor, ConfigurationService, OpportunityService, InitiativeService, OpportunityMetricCohortService, FeatureFlagServiceClient, AllOpportunityService);
}
[Test()]
public void ChargeCodeOpportunitiesControllerTest()
{
// Act
var controller = new ChargeCodeOpportunitiesController(ClaimsPrincipalAccessor, ConfigurationService, OpportunityService, InitiativeService, OpportunityMetricCohortService, FeatureFlagServiceClient, AllOpportunityService);
// Assert
controller.Should().NotBeNull();
}
[Test()]
public async Task UpdateOpportunityTest()
{
// Arrange
var opp = await DbContext.ChargeCodeOpportunities.FirstOrDefaultAsync(CancellationToken.None);
var opportunity = opp.MapToSaveModel();
// Act
var result = await Controller.UpdateOpportunity(opportunity.OpportunityGuid, opportunity, CancellationToken.None);
// Assert
var actual = result.Result;
result.Result.Should().BeOfType<OkObjectResult>();
var okResult = (OkObjectResult)result.Result;
okResult.Value.Should().BeOfType<string>();
var value = new Guid(okResult.Value as string);
value.Should().NotBeEmpty();
}
[Test()]
public async Task ValidateChargeCodesAsyncTest()
{
// Arrange
var chargeCodes = new List<string>();
// Act
var result = await Controller.ValidateChargeCodesAsync(new ChargeCodeOpportunitiesController.ValidateChargeCodeDto() { ChargeCodes = chargeCodes }, CancellationToken.None);
// Assert
result.Result.Should().BeOfType<OkObjectResult>();
var okResult = (OkObjectResult)result.Result;
okResult.Value.Should().BeOfType<bool>();
var value = (bool)okResult.Value;
value.Should().BeTrue();
}
[Test()]
public async Task GetCustomPickerChargeCodesAsyncTest()
{
// Arrange
var chargeCodes = new List<string>();
// Act
var result = await Controller.GetChargeCodeMembers(chargeCodes, CancellationToken.None);
// Assert
result.Result.Should().BeOfType<OkObjectResult>();
var okResult = (OkObjectResult)result.Result;
okResult.Value.Should().BeOfType<ChargeCodePickerModel[]>();
var value = (ChargeCodePickerModel[])okResult.Value;
value.Should().NotBeNull();
}
[Test()]
public async Task ValidateOpportunityLevelsAsyncTest()
{
// Arrange
var info = new ChargeCodeOpportunitiesController.OpportunityLevelSelectionInfo
{
Configuration = Configurations.First().ConfigurationGuid,
OpportunityLevel = OpportunityLevel.Entity,
OpportunityLevels = new List<string>()
};
// Act
var result = await Controller.ValidateOpportunityLevelsAsync(info, CancellationToken.None);
// Assert
result.Result.Should().BeOfType<OkObjectResult>();
var okResult = (OkObjectResult)result.Result;
okResult.Value.Should().BeOfType<bool>();
var value = (bool)okResult.Value;
value.Should().BeTrue();
}
[Test()]
public async Task DeleteTest()
{
// Act
var result = await Controller.Delete(Guid.NewGuid(), CancellationToken.None);
// Assert
result.Should().BeTrue();
}
[TestCase(true, TestName = "GetByIdTest - true")]
[TestCase(false, TestName = "GetByIdTest - false")]
public async Task GetByIdTest(bool withOpp)
{
// Arrange
var opp = await DbContext.ChargeCodeOpportunities.FirstAsync(CancellationToken.None);
// Act
var result = await Controller.GetById(withOpp ? opp.OpportunityGuid : Guid.NewGuid(), CancellationToken.None);
// Assert
if (withOpp)
{
result.Result.Should().BeOfType<OkObjectResult>();
var okResult = (OkObjectResult)result.Result;
okResult.Value.Should().BeOfType<CCOpportunityDto>()
.And.NotBeOfType<CCOpportunityDataModel>();
}
else
{
result.Result.Should().BeOfType<NotFoundResult>();
}
}
[TestCase(true, TestName = "GetEditModelTest - true")]
[TestCase(false, TestName = "GetEditModelTest - false")]
public async Task GetEditModelTest(bool withOpp)
{
// Arrange
var opp = await DbContext.ChargeCodeOpportunities.FirstAsync(CancellationToken.None);
// Act
var result = await Controller.GetEditModel(withOpp ? opp.OpportunityGuid : Guid.NewGuid(), CancellationToken.None);
// Assert
if (withOpp)
{
result.Should().BeOfType<CCOpportunitySaveModel>();
}
else
{
result.Should().BeNull();
}
}
[TestCase(true, TestName = "UpdateGoalTotalUnitsOfServiceTest - true")]
[TestCase(false, TestName = "UpdateGoalTotalUnitsOfServiceTest - false")]
public async Task UpdateGoalTotalUnitsOfServiceTest(bool withOpp)
{
// Arrange
var opp = await DbContext.ChargeCodeOpportunities.FirstAsync(CancellationToken.None);
// Act
var result = await Controller.UpdateGoalTotalUnitsOfService(withOpp ? opp.OpportunityGuid : Guid.NewGuid(), new ChargeCodeOpportunitiesController.GoalSetDto(), CancellationToken.None);
// Assert
result.Should().Be(withOpp);
}
[TestCase(true, TestName = "UpdateGoalCostPerUnitTest - true")]
[TestCase(false, TestName = "UpdateGoalCostPerUnitTest - false")]
public async Task UpdateGoalCostPerUnitTest(bool withOpp)
{
// Arrange
var opp = await DbContext.ChargeCodeOpportunities.FirstAsync(CancellationToken.None);
// Act
var result = await Controller.UpdateGoalCostPerUnit(withOpp ? opp.OpportunityGuid : Guid.NewGuid(), new ChargeCodeOpportunitiesController.GoalSetDto(), CancellationToken.None);
// Assert
result.Should().Be(withOpp);
}
[TestCase(true, TestName = "ExportTest - true")]
[TestCase(false, TestName = "ExportTest - false")]
public async Task ExportTest(bool withOpp)
{
// Arrange
var opp = await DbContext.ChargeCodeOpportunities.FirstAsync(CancellationToken.None);
var chargeCodeItems = new ChargeCodeOpportunitiesController.ChargeCodeItems
{
ChargeCodes = new List<string>()
};
// Act
var result = await Controller.Export(withOpp ? opp.OpportunityGuid : Guid.NewGuid(), chargeCodeItems, CancellationToken.None);
// Assert
result.Should().BeOfType<ExcelContentResult>();
var excelContentResult = (ExcelContentResult)result;
if (withOpp)
{
excelContentResult.Workbook.Should().NotBeNull();
}
else
{
excelContentResult.Workbook.Should().BeNull();
}
}
[Test()]
public async Task OpportunityCreateEnabledTest()
{
// Act
var result = await Controller.OpportunityCreateEnabled(CancellationToken.None);
// Assert
result.Should().BeTrue();
}
[Test()]
public async Task GetInitiativeInfoTest()
{
// Act
var result = await Controller.GetInitiativeInfo(Guid.NewGuid(), CancellationToken.None);
// Assert
result.Should().BeOfType<InitiativeInfo>()
.And.NotBeNull();
}
[TestCase(true, TestName = "RefreshTest - true")]
[TestCase(false, TestName = "RefreshTest - false")]
public async Task RefreshTest(bool withOpp)
{
// Arrange
var opp = await DbContext.ChargeCodeOpportunities.FirstAsync(CancellationToken.None);
// Act
var result = await Controller.Refresh(new ChargeCodeOpportunitiesController.RefreshData
{
DatabaseGuid = new Guid(TestUtilities.DbGuid),
Guid = withOpp ? opp.OpportunityGuid : Guid.NewGuid()
}, CancellationToken.None);
// Assert
result.Should().BeOfType<string>();
if (withOpp)
{
result.Should().NotBeNullOrEmpty();
}
else
{
result.Should().BeNullOrEmpty();
}
}
}
}
@@ -0,0 +1,127 @@
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Api.Test.Unit.Generics;
using Strata.ContinuousImprovement.Biz.ChargeCode.Jobs;
using System;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class ChargeCodeOpportunityDetailsControllerTests
{
public ChargeCodeOpportunityDetailsController Controller { get; set; }
public FakeBackgroundJobClient BackgroundJobClient { get; set; }
private Mock<ICCOpportunityClientJob> _mockClientJob;
private ILogger<ChargeCodeOpportunityDetailsController> _logger;
[OneTimeSetUp]
public void TestSetup()
{
// Arrange
BackgroundJobClient ??= new FakeBackgroundJobClient();
_mockClientJob = new Mock<ICCOpportunityClientJob>();
_logger = Mock.Of<ILogger<ChargeCodeOpportunityDetailsController>>();
_mockClientJob
.Setup(j => j.RefreshClientOpportunityBaselineDetails(It.IsAny<int>(), It.Is<Guid>(g => g != Guid.Empty), It.IsAny<CancellationToken>()))
.ReturnsAsync("baseline-job-123");
_mockClientJob
.Setup(j => j.RefreshClientOpportunityTrackingDetails(It.IsAny<int>(), It.Is<Guid>(g => g != Guid.Empty), It.IsAny<CancellationToken>()))
.ReturnsAsync("tracking-job-456");
_mockClientJob
.Setup(j => j.RefreshClientOpportunityBaselineDetails(It.IsAny<int>(), Guid.Empty, It.IsAny<CancellationToken>()))
.ThrowsAsync(new InvalidOperationException("Opportunity missing"));
_mockClientJob
.Setup(j => j.RefreshClientOpportunityTrackingDetails(It.IsAny<int>(), Guid.Empty, It.IsAny<CancellationToken>()))
.ThrowsAsync(new InvalidOperationException("Initiative missing"));
Controller = new ChargeCodeOpportunityDetailsController(BackgroundJobClient, _mockClientJob.Object, _logger);
}
[Test]
public void ChargeCodeOpportunityDetailsControllerTest()
{
// Arrange
var controller = new ChargeCodeOpportunityDetailsController(BackgroundJobClient, _mockClientJob.Object, _logger);
// Assert
controller.Should().NotBeNull();
}
[Test]
public void CreateTest()
{
// Arrange
Action create = () => Controller.Create(new ChargeCodeOpportunityDetailsController.ChargeCodeDetailInfo
{
StrataId = 9,
OpportunityGuid = Guid.NewGuid(),
IsBaseline = true,
IsUpdate = true
}, CancellationToken.None);
// Assert
create.Should().NotThrow();
}
[Test]
public async Task RefreshBaselineDetails_ReturnsOk_OnSuccess()
{
var request = new ChargeCodeOpportunityDetailsController.ChargeCodeOpportunityJobRequestInfo
{
StrataId = 9,
OpportunityGuid = Guid.NewGuid()
};
var result = await Controller.RefreshBaselineDetails(request, CancellationToken.None);
var ok = result.Should().BeOfType<OkObjectResult>().Subject;
ok.Value.Should().Be("baseline-job-123");
}
[Test]
public async Task RefreshTrackingDetails_ReturnsOk_OnSuccess()
{
var request = new ChargeCodeOpportunityDetailsController.ChargeCodeOpportunityJobRequestInfo
{
StrataId = 9,
OpportunityGuid = Guid.NewGuid()
};
var result = await Controller.RefreshTrackingDetails(request, CancellationToken.None);
var ok = result.Should().BeOfType<OkObjectResult>().Subject;
ok.Value.Should().Be("tracking-job-456");
}
[Test]
public async Task RefreshBaselineDetails_ReturnsBadRequest_OnException()
{
var request = new ChargeCodeOpportunityDetailsController.ChargeCodeOpportunityJobRequestInfo
{
StrataId = 9,
OpportunityGuid = Guid.Empty
};
var result = await Controller.RefreshBaselineDetails(request, CancellationToken.None);
result.Should().BeOfType<BadRequestResult>();
}
[Test]
public async Task RefreshTrackingDetails_ReturnsBadRequest_OnException()
{
var request = new ChargeCodeOpportunityDetailsController.ChargeCodeOpportunityJobRequestInfo
{
StrataId = 9,
OpportunityGuid = Guid.Empty
};
var result = await Controller.RefreshTrackingDetails(request, CancellationToken.None);
result.Should().BeOfType<BadRequestResult>();
}
}
}
@@ -0,0 +1,218 @@
using ClosedXML.Excel;
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Moq;
using NUnit.Framework;
using Strata.ApiLib.Standard.Models;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.ChargeCode.Initiatives;
using Strata.ContinuousImprovement.Biz.ChargeCode.Opportunities;
using Strata.ContinuousImprovement.Biz.DbContexts;
using Strata.ContinuousImprovement.Biz.Encounter.Opportunities.Filters;
using Strata.ContinuousImprovement.Biz.Filter;
using Strata.ContinuousImprovement.Biz.OpportunityComments;
using Strata.ContinuousImprovement.Biz.Pagination;
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NUnitSetup = NUnit.Framework.SetUpAttribute;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class ChargeCodeOppsControllerTests
{
public JazzDbContext DbContext { get; set; }
public ChargeCodeOppsController Controller { get; set; }
public ICommentService CommentService { get; set; }
public ICCOpportunityViewService OpportunityService { get; set; }
public ICCInitiativeService InitiativeService { get; set; }
[OneTimeSetUp]
public async Task ConfigurationsControllerTestSetup()
{
// Arrange
var jeff = new JazzEntityFrameworkFactory();
DbContext = await jeff.CreateDbContextAsync(nameof(ChargeCodeOppsControllerTests), CancellationToken.None);
var expectedData = jeff.CCOpportunities;
var expected = expectedData[0];
var expectedage = new PagedApiResponse<CCOpportunity>
{
Data = expectedData,
PagingInfo = new PagingInfo
{
TotalNumberOfResults = expectedData.Count,
TotalPages = 1,
ResultsPerPage = expectedData.Count,
PageNumber = 1
}
};
var workbook = new XLWorkbook();
workbook.AddWorksheet("ChargeCodeOpps");
CommentService = Mock.Of<ICommentService>();
OpportunityService = Mock.Of<ICCOpportunityViewService>();
Mock.Get(OpportunityService)
.Setup(s => s.GetPagedAsync(It.IsAny<PagingOptions>(), It.IsAny<IFilters<CCOpportunity>>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(expectedage));
Mock.Get(OpportunityService)
.Setup(s => s.ExportAsync(It.IsAny<SortOptions>(), It.IsAny<CCFilters>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult((IXLWorkbook)workbook));
Mock.Get(OpportunityService)
.Setup(s => s.GetFilterOptionsAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(new CCFilterOptions()));
Mock.Get(OpportunityService)
.Setup(s => s.GetById(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, CancellationToken>((oppGuid, token)
=> oppGuid == expected.OpportunityGuid
? Task.FromResult(expected)
: Task.FromResult((CCOpportunity)null));
var hiddenExpected = expected.IsHidden = !expectedData[0].IsHidden;
Mock.Get(OpportunityService)
.Setup(s => s.SetHiddenAsync(It.IsAny<Guid>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()))
.Returns<Guid, bool, CancellationToken>((oppGuid, isHidden, token)
=> oppGuid == expected.OpportunityGuid
? Task.CompletedTask
: Task.FromResult((CCOpportunity)null));
Mock.Get(OpportunityService)
.Setup(s => s.SetNoteAsync(It.IsAny<Guid>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns<Guid, string, CancellationToken>((oppGuid, note, token)
=> oppGuid == expected.OpportunityGuid
? Task.CompletedTask
: Task.FromResult((CCOpportunity)null));
InitiativeService = Mock.Of<ICCInitiativeService>();
}
[NUnitSetup]
public void TestSetup()
{
// Arrange
Controller = new ChargeCodeOppsController(OpportunityService);
}
[Test()]
public void ChargeCodeOppsControllerTest()
{
Controller.Should().NotBeNull();
}
[Test()]
public async Task GetOpportunitiesTest()
{
// Arrange
var loadOptions = new ChargeCodeOppsController.CCOpportunityLoadOptions
{
PagingOptions = new PagingOptions
{
First = 1,
Rows = int.MaxValue,
SortField = "IdentifiedSavings",
SortOrder = SortOrder.Desc
},
Filters = new CCFilters
{
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid
}
};
// Act
var result = await Controller.GetOpportunities(loadOptions, CancellationToken.None);
// Assert
result.Should().BeOfType<PagedApiResponse<CCOpportunity>>();
result.PagingInfo.Should().NotBeNull();
result.Data.Should().NotBeNull();
result.Data.Count().Should().Be(result.PagingInfo.TotalNumberOfResults);
}
[Test()]
public async Task ExportTest()
{
// Arrange
var exportOptions = new ChargeCodeOppsController.CCOpportunityExportOptions
{
Filters = new CCFilters
{
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid
}
};
// Act
var result = await Controller.Export(exportOptions, CancellationToken.None);
// Assert
result.Should().NotBeNull();
result.Should().BeOfType<ExcelContentResult>();
var excelContentResult = result as ExcelContentResult;
excelContentResult.Should().NotBeNull();
excelContentResult.FileName.Should().NotBeNullOrEmpty();
excelContentResult.Workbook.Should().NotBeNull();
}
[Test()]
public async Task GetFilterOptionsAsyncTest()
{
// Act
var result = await Controller.GetFilterOptionsAsync(JazzEntityFrameworkFactory.CurrentConfigurationGuid, CancellationToken.None);
// Assert
result.Should().NotBeNull();
result.Should().BeOfType<CCFilterOptions>();
}
// commenting out because we don't have getById endpoint test should be redone
[TestCase(true, TestName = "GetByIdTest - true", Ignore = "When I debug it passes, otherwise it doesn't")]
[TestCase(false, TestName = "GetByIdTest - false")]
public async Task GetByIdTest(bool withOpp)
{
//// Arrange
//var opp = await DbContext.ChargeCodeOpps.FirstOrDefaultAsync(CancellationToken.None);
//// Act
////var result = await Controller.GetById(withOpp ? opp.OpportunityGuid : Guid.NewGuid(), CancellationToken.None);
//// Assert
//if (withOpp)
//{
// result.Should().NotBeNull();
//}
//else
//{
// result.Should().BeNull();
//}
}
[TestCase(true, true, TestName = "SetHiddenAsyncTest - true - isHidden")]
[TestCase(true, false, TestName = "SetHiddenAsyncTest - true - not isHidden")]
[TestCase(false, true, TestName = "SetHiddenAsyncTest - false - isHidden")]
[TestCase(false, false, TestName = "SetHiddenAsyncTest - false - not isHidden")]
public async Task SetHiddenAsyncTest(bool withOpp, bool isHidden)
{
// Arrange
var opp = await DbContext.ChargeCodeOpps.FirstOrDefaultAsync(CancellationToken.None);
var opportunityGuid = withOpp ? opp.OpportunityGuid : Guid.NewGuid();
// Assert
Assert.DoesNotThrowAsync(async () => // Act
await Controller.SetHiddenAsync(opportunityGuid, isHidden, CancellationToken.None));
}
[TestCase(true, "", TestName = "SetNoteAsyncTest - true - note")]
[TestCase(true, null, TestName = "SetNoteAsyncTest - true - null")]
[TestCase(false, "", TestName = "SetNoteAsyncTest - false - not")]
[TestCase(false, null, TestName = "SetNoteAsyncTest - false - null")]
public async Task SetNoteAsyncTest(bool withOpp, string note)
{
// Arrange
var opp = await DbContext.ChargeCodeOpps.FirstOrDefaultAsync(CancellationToken.None);
var opportunityGuid = withOpp ? opp.OpportunityGuid : Guid.NewGuid();
// Assert
Assert.DoesNotThrowAsync(async () => // Act
await Controller.SetNoteAsync(opportunityGuid, note, CancellationToken.None));
}
}
}
@@ -0,0 +1,377 @@
using DocumentFormat.OpenXml.Drawing.Diagrams;
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Moq;
using NUnit.Framework;
using Strata.ApiLib.Standard.Models;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Api.Test.Unit.Generics;
using Strata.ContinuousImprovement.Biz.DbContexts;
using Strata.ContinuousImprovement.Biz.Dtos;
using Strata.ContinuousImprovement.Biz.Encounter.Opportunities.Filters;
using Strata.ContinuousImprovement.Biz.Network;
using Strata.ContinuousImprovement.Biz.Pagination;
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
using Strata.CoreLib.Claims;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NUnitSetup = NUnit.Framework.SetUpAttribute;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class ClientNetworkOpportunitiesControllerTests
{
public CentralDbContext DbContext { get; set; }
public ClientNetworkOpportunitiesController Controller { get; set; }
public ClientNetworkOpportunitiesController EmptyDbController { get; set; }
public ClientNetworkOpportunitiesController ControllerExceptions { get; set; }
public IClaimsPrincipalAccessor ClaimsPrincipalAccessor { get; set; }
public IClaimsPrincipalAccessor EnptyDbClaimsPrincipalAccessor { get; set; }
public IClientNetworkOpportunityService ClientNetworkOpportunityService { get; set; }
public IClientNetworkOpportunityService ClientNetworkOpportunityServiceException { get; set; }
public ILogger<ClientNetworkOpportunitiesController> Logger { get; set; }
[OneTimeSetUp]
public async Task ClientNetworkOpportunitiesControllerTestsSetup()
{
// Arrange
var jeff = new JazzEntityFrameworkFactory();
DbContext = await jeff.CreateCentralDbContextAsync(nameof(ClientNetworkOpportunitiesControllerTests), CancellationToken.None);
var expectedData = jeff.ClientNetworkOpportunities;
var opportunity = expectedData[0];
var expected = new PagedApiResponse<NetworkOpportunitySummary>
{
Data = expectedData.Select(d => new NetworkOpportunitySummary
{
NetworkOpportunityId = d.NetworkOpportunityId,
Name = d.NetworkOpportunity.Name,
AnalyticsWorkbookId = d.AnalyticsWorkbookId,
CostDriver = d.NetworkOpportunity.CostDriver,
Description = d.NetworkOpportunity.Description,
IsPublished = d.IsPublished
}),
PagingInfo = new PagingInfo
{
PageNumber = 1,
TotalNumberOfResults = expectedData.Count,
TotalPages = 1,
ResultsPerPage = expectedData.Count
}
};
// Act
ClaimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor();
EnptyDbClaimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor(isEmptyDatabase: true);
ClientNetworkOpportunityService = Mock.Of<IClientNetworkOpportunityService>();
Mock.Get(ClientNetworkOpportunityService)
.Setup(s => s.GetOpportunitiesAsync(It.IsAny<Guid>(), It.IsAny<PagingOptions>(), It.IsAny<NetworkOpportunityFilters>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(expected));
Mock.Get(ClientNetworkOpportunityService)
.Setup(s => s.GetByIdAsync(It.IsAny<Guid>(), It.IsAny<int>(), It.IsAny<CancellationToken>()))
.Returns<Guid, int, CancellationToken>((dbGuid, networkOpportunityId, token) =>
networkOpportunityId == opportunity.NetworkOpportunityId
? Task.FromResult(opportunity)
: Task.FromResult((ClientNetworkOpportunity)null));
Mock.Get(ClientNetworkOpportunityService)
.Setup(s => s.ConfigureAsync(It.IsAny<Guid>(), It.IsAny<int>(), It.IsAny<ClientNetworkOpportunity>(), It.IsAny<NetworkOpportunitySaveModel>(), It.IsAny<CancellationToken>()));
ClientNetworkOpportunityServiceException = Mock.Of<IClientNetworkOpportunityService>();
Mock.Get(ClientNetworkOpportunityServiceException)
.Setup(s => s.GetByIdAsync(It.IsAny<Guid>(), It.IsAny<int>(), It.IsAny<CancellationToken>()))
.Throws(new CreateWorkbookFromTemplateException());
Logger = Mock.Of<ILogger<ClientNetworkOpportunitiesController>>();
}
[NUnitSetup]
public void TestSetup()
{
Controller = new ClientNetworkOpportunitiesController(ClaimsPrincipalAccessor, ClientNetworkOpportunityService, Logger);
EmptyDbController = new ClientNetworkOpportunitiesController(EnptyDbClaimsPrincipalAccessor, ClientNetworkOpportunityService, Logger);
ControllerExceptions = new ClientNetworkOpportunitiesController(ClaimsPrincipalAccessor, ClientNetworkOpportunityServiceException, Logger);
}
[Test()]
public async Task ClientNetworkOpportunitiesControllerTest()
{
// Assert
Controller.Should().NotBeNull();
}
[Test()]
public async Task GetOpportunitiesTest()
{
// Arrange
var loadOptions = new NetworkOpportunityLoadOptions
{
Filters = new NetworkOpportunityFilters
{
},
PagingOptions = new Biz.Pagination.PagingOptions
{
First = 0,
Rows = 24
}
};
// Act
var result = await Controller.GetOpportunities(loadOptions, CancellationToken.None);
result.Should().NotBeNull();
result.Value.Should().NotBeNull()
.And.BeOfType<PagedApiResponse<NetworkOpportunitySummary>>();
}
[TestCase(true, TestName = "GetByIdTest w/ Exception")]
[TestCase(false, TestName = "GetByIdTest w/o Exception")]
public async Task GetByIdTest(bool withException)
{
// Arrange
var opportunity = DbContext.NetworkOpportunities.FirstOrDefault();
var clientNetworkOpportunity = DbContext.ClientNetworkOpportunities.FirstOrDefault(cno => cno.NetworkOpportunityId == opportunity.NetworkOpportunityId);
var dto = clientNetworkOpportunity.MapToDto();
ActionResult<ClientNetworkOpportunityDto> result;
// Act
if (withException)
{
result = await ControllerExceptions.GetById(opportunity.NetworkOpportunityId, CancellationToken.None);
}
else
{
result = await Controller.GetById(opportunity.NetworkOpportunityId, CancellationToken.None);
}
// Assert
if (withException)
{
result.Value.Should().BeNull();
result.Result.Should().BeOfType<ObjectResult>();
var objectResult = (ObjectResult)result.Result;
objectResult.StatusCode.Should().Be(500);
}
else
{
result.Value.Should().NotBeNull()
.And.BeOfType<ClientNetworkOpportunityDto>()
.And.BeEquivalentTo(dto);
}
}
[TestCase(true, TestName = "SaveTest w/ Exception")]
[TestCase(false, TestName = "SaveTest w/o Exception")]
public async Task SaveTest(bool withException)
{
// Arrange
var opportunity = DbContext.NetworkOpportunities.FirstOrDefault();
var clientNetworkOpportunity = DbContext.ClientNetworkOpportunities.FirstOrDefault(cno => cno.NetworkOpportunityId == opportunity.NetworkOpportunityId);
var dto = clientNetworkOpportunity.MapToDto();
// Act
IActionResult result;
if (withException)
{
result = await ControllerExceptions.Save(-1, dto, CancellationToken.None);
}
else
{
result = await Controller.Save(opportunity.NetworkOpportunityId, dto, CancellationToken.None);
}
// Assert
if (withException)
{
result.Should().NotBeNull()
.And.BeOfType<BadRequestResult>();
}
else
{
result.Should().NotBeNull()
.And.BeOfType<NoContentResult>();
}
}
[Test()]
public async Task DeleteTest()
{
// Arrange
var opportunity = DbContext.NetworkOpportunities.FirstOrDefault();
// Act
IActionResult result;
result = await Controller.Delete(opportunity.NetworkOpportunityId, CancellationToken.None);
// Assert
result.Should().NotBeNull()
.And.BeOfType<NoContentResult>();
}
[TestCase(true, true, TestName = "PublishTest w/ Exception on EmptyDb")]
[TestCase(false, true, TestName = "PublishTest w/o Exception on EmptyDb")]
[TestCase(true, false, TestName = "PublishTest w/ Exception")]
[TestCase(false, false, TestName = "PublishTest w/o Exception")]
public async Task PublishTest(bool withException, bool withEmptyDb)
{
// Arrange
var opportunity = DbContext.NetworkOpportunities.FirstOrDefault();
var clientNetworkOpportunity = DbContext.ClientNetworkOpportunities.FirstOrDefault(cno => cno.NetworkOpportunityId == opportunity.NetworkOpportunityId);
var dto = clientNetworkOpportunity.MapToDto();
ActionResult<bool> result;
// Act
if (withEmptyDb)
{
if (withException)
{
result = await EmptyDbController.Publish(-1, true, CancellationToken.None);
}
else
{
result = await EmptyDbController.Publish(opportunity.NetworkOpportunityId, true, CancellationToken.None);
}
}
else
{
if (withException)
{
result = await Controller.Publish(-1, true, CancellationToken.None);
}
else
{
result = await Controller.Publish(opportunity.NetworkOpportunityId, true, CancellationToken.None);
}
}
// Assert
if (withEmptyDb)
{
if (withException)
{
result.Should().NotBeNull();
result.Should().BeOfType<ActionResult<bool>>();
result.Result.Should().BeOfType<BadRequestResult>();
result.Value.Should().BeFalse();
}
else
{
result.Should().NotBeNull();
result.Should().BeOfType<ActionResult<bool>>();
result.Result.Should().BeOfType<BadRequestResult>();
}
}
else
{
if (withException)
{
result.Should().NotBeNull();
result.Should().BeOfType<ActionResult<bool>>();
result.Result.Should().BeOfType<BadRequestResult>();
result.Value.Should().BeFalse();
}
else
{
result.Should().NotBeNull();
result.Should().BeOfType<ActionResult<bool>>();
result.Result.Should().BeOfType<OkObjectResult>();
}
}
}
[Test()]
public async Task UpdateInitiativeStatusTest()
{
// Arrange
var opportunity = DbContext.NetworkOpportunities.FirstOrDefault();
var clientNetworkOpportunity = DbContext.ClientNetworkOpportunities.FirstOrDefault(cno => cno.NetworkOpportunityId == opportunity.NetworkOpportunityId);
var dto = clientNetworkOpportunity.MapToDto();
// Act
var result = await Controller.UpdateInitiativeStatus(opportunity.NetworkOpportunityId, Biz.Shared.InitiativeStatuses.Completed, CancellationToken.None);
// Assert
result.Should().NotBeNull()
.And.BeOfType<NoContentResult>();
}
[TestCase(true, true, TestName = "RevertWorkbookToTemplateTest w/ Exception on EmptyDb")]
[TestCase(false, true, TestName = "RevertWorkbookToTemplateTest w/o Exception on EmptyDb")]
[TestCase(true, false, TestName = "RevertWorkbookToTemplateTest w/ Exception")]
[TestCase(false, false, TestName = "RevertWorkbookToTemplateTest w/o Exception")]
public async Task RevertWorkbookToTemplateTest(bool withException, bool withEmptyDb)
{
// Arrange
var opportunity = DbContext.NetworkOpportunities.FirstOrDefault();
var clientNetworkOpportunity = DbContext.ClientNetworkOpportunities.FirstOrDefault(cno => cno.NetworkOpportunityId == opportunity.NetworkOpportunityId);
var dto = clientNetworkOpportunity.MapToDto();
ActionResult<bool> result;
// Act
if (withEmptyDb)
{
if (withException)
{
result = await EmptyDbController.RevertWorkbookToTemplate(-1, CancellationToken.None);
}
else
{
result = await EmptyDbController.RevertWorkbookToTemplate(opportunity.NetworkOpportunityId, CancellationToken.None);
}
}
else
{
if (withException)
{
result = await Controller.RevertWorkbookToTemplate(-1, CancellationToken.None);
}
else
{
result = await Controller.RevertWorkbookToTemplate(opportunity.NetworkOpportunityId, CancellationToken.None);
}
}
// Assert
if (withEmptyDb)
{
if (withException)
{
result.Should().NotBeNull();
result.Should().BeOfType<ActionResult<bool>>();
result.Result.Should().BeOfType<BadRequestResult>();
result.Value.Should().BeFalse();
}
else
{
result.Should().NotBeNull();
result.Should().BeOfType<ActionResult<bool>>();
result.Result.Should().BeOfType<BadRequestResult>();
}
}
else
{
if (withException)
{
result.Should().NotBeNull();
result.Should().BeOfType<ActionResult<bool>>();
result.Result.Should().BeOfType<BadRequestResult>();
result.Value.Should().BeFalse();
}
else
{
result.Should().NotBeNull();
result.Should().BeOfType<ActionResult<bool>>();
result.Result.Should().BeOfType<OkObjectResult>();
}
}
}
}
}
@@ -0,0 +1,289 @@
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.All.Opportunities;
using Strata.ContinuousImprovement.Biz.Initiatives;
using Strata.ContinuousImprovement.Biz.Network;
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
using Strata.CoreLib.Claims;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using NUnitSetup = NUnit.Framework.SetUpAttribute;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class ClientNetworkOpportunityLinkControllerTests
{
public ClientNetworkOpportunityLinkController Controller { get; set; }
public ClientNetworkOpportunityLinkController EmptyDbController { get; set; }
public IClaimsPrincipalAccessor ClaimsPrincipalAccessor { get; set; }
public IClaimsPrincipalAccessor EmptyDbClaimsPrincipalAccessor { get; set; }
public IClientNetworkOpportunityService clientNetworkOpportunityService;
public IClientNetworkOpportunityLinkService clientNetworkOpportunityLinkService;
public IAllOpportunityService allOpportunityService;
public IInitiativeService initiativeService;
public ILogger<ClientNetworkOpportunityLinkController> logger;
[OneTimeSetUp]
public void ClientNetworkOpportunityLinkControllerTestsSetup()
{
// Arrange
clientNetworkOpportunityService = Mock.Of<IClientNetworkOpportunityService>();
clientNetworkOpportunityLinkService = Mock.Of<IClientNetworkOpportunityLinkService>();
allOpportunityService = Mock.Of<IAllOpportunityService>();
initiativeService = Mock.Of<IInitiativeService>();
logger = Mock.Of<ILogger<ClientNetworkOpportunityLinkController>>();
// Act
ClaimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor();
EmptyDbClaimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor(isEmptyDatabase: true);
var expected = new ClientNetworkOpportunityLink
{
OpportunityGuid = Guid.NewGuid(),
ConfigurationGuid = Guid.NewGuid(),
ClientNetworkOpportunityLinkId = 1,
InitiativeGuid = Guid.NewGuid(),
ClientNetworkOpportunity = new ClientNetworkOpportunity
{
NetworkOpportunityId = 1,
}
};
Mock.Get(clientNetworkOpportunityLinkService)
.Setup(s => s.RolloverOpportunityLinkAsync(It.IsAny<Guid>(), It.IsAny<Guid>(), It.IsAny<Guid>(),
It.IsAny<Guid>(), It.IsAny<Guid>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, Guid, Guid, Guid, Guid, Guid, CancellationToken>(
(dbGuid, SrcConfigGuid, SrcOppGuid, RollConfigGuid, RollOppGuid, RollInitGuid, token) =>
dbGuid == Guid.Empty || SrcOppGuid == Guid.Empty
? Task.FromResult(default(ClientNetworkOpportunityLink))
: Task.FromResult(expected));
Mock.Get(clientNetworkOpportunityLinkService)
.Setup(s => s.DeleteOpportunityLinkAsync(It.IsAny<Guid>(), It.IsAny<Guid>(), It.IsAny<Guid>(),
It.IsAny<CancellationToken>()));
}
[NUnitSetup]
public void TestSetup()
{
// Act
Controller = new ClientNetworkOpportunityLinkController(
ClaimsPrincipalAccessor,
clientNetworkOpportunityService,
clientNetworkOpportunityLinkService,
allOpportunityService,
initiativeService,
logger);
EmptyDbController = new ClientNetworkOpportunityLinkController(
EmptyDbClaimsPrincipalAccessor,
clientNetworkOpportunityService,
clientNetworkOpportunityLinkService,
allOpportunityService,
initiativeService,
logger);
}
[Test()]
public async Task ClientNetworkOpportunityLinkControllerTest()
{
// Assert
Controller.Should().NotBeNull();
EmptyDbController.Should().NotBeNull();
}
[TestCaseSource(nameof(AddOpportunityLinkTestCases))]
public async Task AddOpportunityLinkTest(Guid opportunityGuid)
{
var result = await Controller.AddOpportunityLink(new ClientNetworkOpportunityLinkController.CreateNetworkOpportunityLinkDto
{
OpportunityGuid = opportunityGuid
}, CancellationToken.None);
result.Should().NotBeNull();
result.Should().BeOfType<ActionResult<ClientNetworkOpportunityLinkController.ClientNetworkOpportunityResultDto>>();
result.Result.Should().NotBeNull();
if (opportunityGuid == Guid.Empty)
{
result.Result.Should().BeOfType<BadRequestResult>();
}
else
{
result.Should().NotBeOfType<BadRequestResult>();
}
}
public static IEnumerable<TestCaseData> AddOpportunityLinkTestCases()
{
yield return new TestCaseData(Guid.Empty)
.SetName(nameof(AddOpportunityLinkTestCases) + " w/Empty Opp Guid");
yield return new TestCaseData(Guid.NewGuid())
.SetName(nameof(AddOpportunityLinkTestCases) + " w/Opp Guid");
}
[TestCaseSource(nameof(RolloverOpportunityLinkTestCases))]
public async Task RolloverOpportunityLinkTest(Guid srcOppGuid, bool useEmptyController)
{
// Arrange
var rolloverOpportunityInfo = new ClientNetworkOpportunityLinkController.RolloverOpportunityDto
{
SourceOpportunityGuid = srcOppGuid,
SourceConfigurationGuid = Guid.Empty,
DatabaseGuid = useEmptyController ? Guid.Empty : new Guid(TestUtilities.DbGuid),
};
// Act
var result = await Controller.RolloverOpportunityLink(rolloverOpportunityInfo, CancellationToken.None);
// Assert
result.Should().NotBeNull();
if (useEmptyController)
{
result.Result.Should().BeOfType<BadRequestResult>();
}
else
{
result.Result.Should().BeOfType<OkObjectResult>();
}
}
public static IEnumerable<TestCaseData> RolloverOpportunityLinkTestCases()
{
yield return new TestCaseData(Guid.Empty, true)
.SetName(nameof(RolloverOpportunityLinkTest) + " w/Empty Opp Guid, Empty Db Guid");
yield return new TestCaseData(Guid.Empty, false)
.SetName(nameof(RolloverOpportunityLinkTest) + " w/Empty Opp Guid");
yield return new TestCaseData(Guid.NewGuid(), true)
.SetName(nameof(RolloverOpportunityLinkTest) + " w/Opp Guid, Empty Db Guid");
yield return new TestCaseData(Guid.NewGuid(), false)
.SetName(nameof(RolloverOpportunityLinkTest) + " w/Opp Guid");
}
[TestCaseSource(nameof(DeleteOpportunityLinkTestCases))]
public async Task DeleteOpportunityLinkTest(Guid srcOppGuid, Guid configurationGuid, Guid databaseGuid, bool useEmptyController)
{
// Arrange
Mock.Get(clientNetworkOpportunityLinkService)
.Setup(s => s.ContainsOpportunityLinkAsync(It.IsAny<Guid>(), It.IsAny<Guid>(), It.IsAny<Guid>(),
It.IsAny<CancellationToken>()))
.Returns<Guid, Guid, Guid, CancellationToken>(
(dbGuid, configurationGuid, oppGuid, token) =>
oppGuid == Guid.Empty || dbGuid == Guid.Empty
? Task.FromResult(false)
: Task.FromResult(true));
var opportunity = new ClientNetworkOpportunityLinkController.ClientNetworkOpportunityLinkDto
{
ConfigurationGuid = configurationGuid,
DatabaseGuid = databaseGuid,
Id = srcOppGuid
};
// Act
ActionResult<bool> result;
if (useEmptyController)
{
result = await EmptyDbController.DeleteOpportunityLink(opportunity, CancellationToken.None);
}
else
{
result = await Controller.DeleteOpportunityLink(opportunity, CancellationToken.None);
}
// Assert
result.Should().NotBeNull();
if (useEmptyController)
{
result.Result.Should().BeOfType<BadRequestResult>();
}
}
public static IEnumerable<TestCaseData> DeleteOpportunityLinkTestCases()
{
var configurationGuid = JazzEntityFrameworkStub.JazzEntityFrameworkFactory.CurrentConfigurationGuid;
var databaseGuid = JazzEntityFrameworkStub.JazzEntityFrameworkFactory.DatabaseGuid;
yield return new TestCaseData(Guid.Empty, configurationGuid, Guid.Empty, true)
.SetName(nameof(DeleteOpportunityLinkTest) + " w/Empty Opp Guid, Empty Db Guid");
yield return new TestCaseData(Guid.Empty, configurationGuid, null, true)
.SetName(nameof(DeleteOpportunityLinkTest) + " w/Empty Opp Guid, Null Db Guid");
yield return new TestCaseData(Guid.Empty, configurationGuid, databaseGuid, false)
.SetName(nameof(DeleteOpportunityLinkTest) + " w/Empty Opp Guid");
yield return new TestCaseData(Guid.NewGuid(), configurationGuid, Guid.Empty, true)
.SetName(nameof(DeleteOpportunityLinkTest) + " w/Opp Guid, Empty Db Guid");
yield return new TestCaseData(Guid.NewGuid(), configurationGuid, null, true)
.SetName(nameof(DeleteOpportunityLinkTest) + " w/Opp Guid, Null Db Guid");
yield return new TestCaseData(Guid.NewGuid(), configurationGuid, databaseGuid, false)
.SetName(nameof(DeleteOpportunityLinkTest) + " w/Opp Guid");
}
[TestCaseSource(nameof(DeleteOpportunityLinkIfExistsTestCases))]
public async Task DeleteOpportunityLinkIfExistsTest(Guid opportunityGuid, Guid configurationGuid, bool useEmptyController)
{
// Arrange
Mock.Get(clientNetworkOpportunityLinkService)
.Setup(s => s.ContainsOpportunityLinkAsync(It.IsAny<Guid>(), It.IsAny<Guid>(), It.IsAny<Guid>(),
It.IsAny<CancellationToken>()))
.Returns<Guid, Guid, Guid, CancellationToken>(
(dbGuid, configurationGuid, oppGuid, token) =>
oppGuid == Guid.Empty || dbGuid == Guid.Empty
? Task.FromResult(false)
: Task.FromResult(true));
// Act
ActionResult<bool> result;
if (useEmptyController)
{
result = await EmptyDbController.DeleteOpportunityLinkIfExists(opportunityGuid, configurationGuid, CancellationToken.None);
}
else
{
result = await Controller.DeleteOpportunityLinkIfExists(opportunityGuid, configurationGuid, CancellationToken.None);
}
// Assert
result.Should().NotBeNull();
if (useEmptyController)
{
result.Result.Should().BeOfType<BadRequestResult>();
}
}
public static IEnumerable<TestCaseData> DeleteOpportunityLinkIfExistsTestCases()
{
var configurationGuid = JazzEntityFrameworkStub.JazzEntityFrameworkFactory.CurrentConfigurationGuid;
var databaseGuid = JazzEntityFrameworkStub.JazzEntityFrameworkFactory.DatabaseGuid;
yield return new TestCaseData(Guid.Empty, configurationGuid, true)
.SetName(nameof(DeleteOpportunityLinkIfExistsTest) + " w/Empty Opp Guid, Empty Db Guid");
yield return new TestCaseData(Guid.Empty, configurationGuid, true)
.SetName(nameof(DeleteOpportunityLinkIfExistsTest) + " w/Empty Opp Guid, Null Db Guid");
yield return new TestCaseData(Guid.Empty, configurationGuid, false)
.SetName(nameof(DeleteOpportunityLinkIfExistsTest) + " w/Empty Opp Guid");
yield return new TestCaseData(Guid.NewGuid(), configurationGuid, true)
.SetName(nameof(DeleteOpportunityLinkIfExistsTest) + " w/Opp Guid, Empty Db Guid");
yield return new TestCaseData(Guid.NewGuid(), configurationGuid, true)
.SetName(nameof(DeleteOpportunityLinkIfExistsTest) + " w/Opp Guid, Null Db Guid");
yield return new TestCaseData(Guid.NewGuid(), configurationGuid, false)
.SetName(nameof(DeleteOpportunityLinkIfExistsTest) + " w/Opp Guid");
}
[Test()]
public async Task DeleteInitiativeLinkTest()
{
Assert.Inconclusive();
}
[Test()]
public async Task DeleteInitiativeLinkTest1()
{
Assert.Inconclusive();
}
}
}
@@ -0,0 +1,98 @@
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.ClientWarehouses;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class ClientWarehousesControllerTests
{
private readonly ClientWarehousesController _clientWarehouseController;
private readonly Mock<IClientWarehouseService> _mockClientWarehouseService;
public ClientWarehousesControllerTests()
{
_mockClientWarehouseService = new Mock<IClientWarehouseService>();
_clientWarehouseController = new ClientWarehousesController(_mockClientWarehouseService.Object);
}
[Test]
public async Task GetAll_ReturnsAllClientWarehouses()
{
// Arrange
var warehouses = new List<ClientWarehouse>
{
new ClientWarehouse { DatabaseGuid = Guid.NewGuid() },
new ClientWarehouse { DatabaseGuid = Guid.NewGuid() }
};
_mockClientWarehouseService
.Setup(x => x.GetAll(It.IsAny<CancellationToken>()))
.ReturnsAsync(warehouses);
// Act
var result = await _clientWarehouseController.GetClientWarehouses(CancellationToken.None);
// Assert
var okResult = result.Result.Should().BeOfType<OkObjectResult>().Subject;
okResult.Value.Should().BeEquivalentTo(warehouses);
}
[Test]
public async Task GetAll_ReturnsNoContent_IfNoneExists()
{
// Arrange
var warehouses = new List<ClientWarehouse>();
_mockClientWarehouseService
.Setup(x => x.GetAll(It.IsAny<CancellationToken>()))
.ReturnsAsync(warehouses);
// Act
var result = await _clientWarehouseController.GetClientWarehouses(CancellationToken.None);
// Assert
var okResult = result.Result.Should().BeOfType<NoContentResult>();
}
[Test]
public async Task Add_ShouldReturnNewId()
{
// Arrange
var clientWarehouse = new ClientWarehouse();
_mockClientWarehouseService
.Setup(s => s.Add(clientWarehouse, It.IsAny<CancellationToken>()))
.ReturnsAsync(123);
// Act
var result = await _clientWarehouseController.AddClientWarehouse(clientWarehouse, CancellationToken.None);
// Assert
var okResult = result.Result.Should().BeOfType<CreatedAtActionResult>().Subject;
okResult.Value.Should().Be(123);
}
[Test]
public async Task Delete_ShouldReturn_NoContent()
{
// Arrange
var clientId = Guid.NewGuid();
_mockClientWarehouseService
.Setup(s => s.Delete(clientId, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
// Act
var result = await _clientWarehouseController.DeleteClientWarehouse(clientId, CancellationToken.None);
// Assert
result.Should().BeOfType<NoContentResult>();
}
}
}
@@ -0,0 +1,87 @@
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Api.Test.Unit.Api.Generics;
using Strata.ContinuousImprovement.Biz.Generics;
using Strata.ContinuousImprovement.Biz.OpportunityComments;
using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities;
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
using Strata.CoreLib.Claims.Extensions;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using static Strata.ContinuousImprovement.Api.Controllers.CommentsController;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class CommentsControllerTests
{
[TestCase(true, TestName = "Get Comments Global")]
[TestCase(false, TestName = "Get Comments Not Global")]
public async Task TestGetComments(bool isGlobal)
{
var jeff = new JazzEntityFrameworkFactory();
var dbContext = await jeff.CreateCentralDbContextAsync(nameof(CommentsControllerTests), CancellationToken.None);
var comments = await dbContext.Comments.ToListAsync(CancellationToken.None);
var clientClaimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor();
var service = Mock.Of<ICommentService>();
Mock.Get(service)
.Setup(s => s.GetCommentsAsync(It.IsAny<Guid>(), It.IsAny<int>(), It.IsAny<long>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(comments.Where(c => c.OpportunityId == 1).AsEnumerable()));
var controller = new CommentsController(service, clientClaimsPrincipalAccessor);
var options = new CommentOptions
{
IsGlobal = isGlobal,
OpportunityId = 1L,
OpportunityType = $"{(int)OpportunityTypes.ChargeCode}"
};
var result = await controller.GetComments(options, CancellationToken.None);
result.Should().NotBeEmpty();
}
[TestCase(true, true, TestName = "Add Comment Global")]
[TestCase(false, true, TestName = "Add Comment Not Global")]
[TestCase(true, false, TestName = "Add No Comment Global")]
[TestCase(false, false, TestName = "Add No Comment Not Global")]
public async Task TestAddComments(bool isGlobal, bool hasComment)
{
var jeff = new JazzEntityFrameworkFactory();
var dbContext = await jeff.CreateCentralDbContextAsync(nameof(CommentsControllerTests), CancellationToken.None);
var comments = await dbContext.Comments.ToListAsync(CancellationToken.None);
var newComment = new NewComment
{
IsGlobal = isGlobal,
OpportunityId = 1L,
OpportunityType = $"{(int)OpportunityTypes.ChargeCode}",
CommentDate = DateTimeOffset.Now,
Comment = hasComment ? "This is a new comment" : ""
};
var expected = newComment.Map();
var clientClaimsPrincipalAccessor = TestUtilities.GetClaimsPrincipalAccessor();
var user = clientClaimsPrincipalAccessor.GetCurrentClaimsPrincipal();
var name = user.GetUserFirstName();
var service = Mock.Of<ICommentService>();
Mock.Get(service)
.Setup(s => s.AddCommentAsync(It.IsAny<Guid>(), It.IsAny<int>(), It.IsAny<long>(),
It.IsAny<string>(), It.IsAny<DateTimeOffset?>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(expected));
var controller = new CommentsController(service, clientClaimsPrincipalAccessor);
var result = await controller.Create(newComment, CancellationToken.None);
if (!hasComment)
{
result.Should().Be(default);
}
else
{
result.Should().BeEquivalentTo(expected);
}
}
}
}
@@ -0,0 +1,128 @@
using FluentAssertions;
using Microsoft.EntityFrameworkCore;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.Configuration;
using Strata.ContinuousImprovement.Biz.DbContexts;
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
using Strata.Schema.Client;
using Strata.Schema.Client.Dtos.Info;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture(), Category("Unit"), Category("Controller")]
public class ConfigurationsControllerTests
{
public JazzDbContext DbContext { get; set; }
public IEnumerable<Biz.Configuration.Configuration> Configurations { get; set; }
public ISchemaServiceClient SchemaService { get; set; }
public IConfigurationService ConfigurationService { get; set; }
[OneTimeSetUp]
public async Task ConfigurationsControllerTestSetup()
{
var jeff = new JazzEntityFrameworkFactory();
DbContext = await jeff.CreateDbContextAsync(nameof(ConfigurationsControllerTests), CancellationToken.None);
Configurations = await DbContext.Configurations.ToListAsync();
var configuration = Configurations.First();
var entities = new HashSet<int>(configuration.ConfiguredEntityIds);
var expected = entities.Select(e => new Member
{
Id = e,
Name = $"Entity {e}"
});
var dimensionInfo = new ScoreDimensionInfoDto
{
FriendlyName = "Entity",
DefaultHierarchyGuid = Guid.NewGuid(),
DimensionGuid = Guid.NewGuid(),
ParentDimensionGuid = Guid.NewGuid()
};
ConfigurationService = Mock.Of<IConfigurationService>();
Mock.Get(ConfigurationService)
.Setup(s => s.GetConfigurationsAsync(It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(Configurations.AsEnumerable()));
Mock.Get(ConfigurationService)
.Setup(s => s.GetConfigurationAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(configuration));
SchemaService = Mock.Of<ISchemaServiceClient>();
Mock.Get(SchemaService)
.Setup(s => s.GetDimensionMembersByGlobalIdAsync<Member>(It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(expected));
Mock.Get(SchemaService)
.Setup(s => s.GetDimensionByGlobalIdAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(dimensionInfo));
Mock.Get(SchemaService)
.Setup(s => s.GetDimensionByIdAsync(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns(Task.FromResult(dimensionInfo));
}
[Test()]
public void ConfigurationsControllerTest()
{
var controller = new ConfigurationsController(ConfigurationService, SchemaService);
controller.Should().NotBeNull();
}
[Test()]
public async Task GetAllConfigurationsTest()
{
var controller = new ConfigurationsController(ConfigurationService, SchemaService);
controller.Should().NotBeNull();
var result = await controller.GetAllConfigurations(CancellationToken.None);
result.Should().BeEquivalentTo(Configurations);
}
[Test()]
public async Task GetConfigurationEntitiesTest()
{
var configuration = Configurations.First();
var entities = new HashSet<int>(configuration.ConfiguredEntityIds);
var expected = entities.Select(e => new Member
{
Id = e,
Name = $"Entity {e}"
});
var controller = new ConfigurationsController(ConfigurationService, SchemaService);
var result = await controller.GetConfigurationEntities(configuration.ConfigurationGuid, CancellationToken.None);
result.Should().BeEquivalentTo(expected);
}
[Test()]
public async Task GetConfigurationEntityInfoTest()
{
var configuration = Configurations.First();
var entities = new HashSet<int>(configuration.ConfiguredEntityIds);
var controller = new ConfigurationsController(ConfigurationService, SchemaService);
var result = await controller.GetConfigurationEntityInfo(configuration.ConfigurationGuid, CancellationToken.None);
result.Should().NotBeNull()
.And.BeOfType<EntityInfo>();
result.EntityTitle.Should().NotBeNullOrEmpty();
result.EntityTitle.Should().Be("Entities");
result.EntityText.Should().Be("Entity");
result.DepartmentRollupGlobalId.Should().Be("Entity");
result.HierarchicalGuid.Should().NotBeEmpty();
}
[Test()]
public async Task GetConfigurationServiceLineInfoTest()
{
var configuration = Configurations.First();
var controller = new ConfigurationsController(ConfigurationService, SchemaService);
var result = await controller.GetConfigurationServiceLineInfo(configuration.ConfigurationGuid, CancellationToken.None);
result.Should().NotBeNull()
.And.BeOfType<ServiceLineInfo>();
result.ServiceLineName.Should().NotBeNullOrEmpty();
result.ServiceLineName.Should().Be("Entity");
result.ServiceLineTitle.Should().Be("Entities");
}
}
}
@@ -0,0 +1,66 @@
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.Databases;
using Strata.ContinuousImprovement.Biz.Replication;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class DatabaseControllerTests
{
private readonly DatabasesController _databaseController;
private readonly Mock<IDatabaseService> _mockDatabaseService;
public DatabaseControllerTests()
{
_mockDatabaseService = new Mock<IDatabaseService>();
_databaseController = new DatabasesController(_mockDatabaseService.Object);
}
[Test]
public async Task Get_ReturnsAllDatabases()
{
// Arrange
var databases = new List<Database>
{
new Database { DatabaseGuid = Guid.NewGuid() },
new Database { DatabaseGuid = Guid.NewGuid() }
};
_mockDatabaseService
.Setup(x => x.GetDatabasesAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(databases);
// Act
var result = await _databaseController.Get(CancellationToken.None);
// Assert
var okResult = result.Result.Should().BeOfType<OkObjectResult>().Subject;
okResult.Value.Should().BeEquivalentTo(databases);
}
[Test]
public async Task Get_ReturnsNoContent_IfNoneExists()
{
// Arrange
var databases = new List<Database>();
_mockDatabaseService
.Setup(x => x.GetDatabasesAsync(It.IsAny<CancellationToken>()))
.ReturnsAsync(databases);
// Act
var result = await _databaseController.Get(CancellationToken.None);
// Assert
var okResult = result.Result.Should().BeOfType<NoContentResult>();
}
}
}
@@ -0,0 +1,225 @@
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.Configuration;
using Strata.ContinuousImprovement.Biz.DbContexts;
using Strata.ContinuousImprovement.Biz.Exploration;
using Strata.ContinuousImprovement.Biz.Exploration.CaseTypeFamilies;
using Strata.ContinuousImprovement.Biz.Exploration.Filters;
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
using Strata.FeatureFlags.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class ExplorationControllerTests
{
public JazzEntityFrameworkFactory JazzEntityFrameworkFactory { get; set; }
public JazzDbContext JazzDbContext { get; set; }
public ExplorationController ExplorationController { get; set; }
public IConfigurationService ConfigurationService { get; set; }
public IExplorationService ExplorationService { get; set; }
public IFeatureFlagServiceClient FeatureFlagServiceClient { get; set; }
[OneTimeSetUp]
public async Task ClientNetworkOpportunityLinkControllerTestsSetup()
{
// Arrange
JazzEntityFrameworkFactory = new JazzEntityFrameworkFactory();
JazzDbContext = await JazzEntityFrameworkFactory.CreateDbContextAsync(nameof(ConfigurationsControllerTests), CancellationToken.None);
ConfigurationService = Mock.Of<IConfigurationService>();
ExplorationService = Mock.Of<IExplorationService>();
FeatureFlagServiceClient = Mock.Of<IFeatureFlagServiceClient>();
// Act
}
[SetUp]
public async Task Setup()
{
// Arrange
ExplorationController = new ExplorationController(ExplorationService, ConfigurationService, FeatureFlagServiceClient, Mock.Of<ILogger<ExplorationController>>());
// Act
}
[Test]
public async Task ExplorationControllerTest()
{
// Assert
ExplorationController.Should().NotBeNull();
}
[TestCaseSource(nameof(GetCaseTypeFamilySummariesTestCases))]
public async Task GetCaseTypeFamilySummariesTest(Guid configurationGuid)
{
// Arrange
var configuration = JazzDbContext.Configurations.First();
var explorationInfo = new ExplorationInfo
{
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid,
ExclusionCriteria = new Biz.Exploration.Filters.ExclusionCriteria(),
Filters = new Biz.Exploration.Filters.Filter
{
DischargeDateStart = new System.DateTime(2024, 1, 1),
DischargeDateEnd = new System.DateTime(2024, 12, 31),
FilterChipItems = new List<FilterChipItem>()
}
};
var result = new List<CaseTypeFamilySummaryData>();
if (configuration.ConfigurationGuid == configurationGuid)
{
Mock.Get(ConfigurationService)
.Setup(s => s.GetById(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, CancellationToken>(
(configurationGuid, token) => Task.FromResult(JazzDbContext.Configurations.First()));
Mock.Get(ConfigurationService)
.Setup(s => s.Contains(It.IsAny<Biz.Configuration.Configuration>(), It.IsAny<CancellationToken>()))
.Returns<Biz.Configuration.Configuration, CancellationToken>(
(configuration, token) => Task.FromResult(true));
Mock.Get(ConfigurationService)
.Setup(s => s.IsConfigurationValid(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, CancellationToken>(
(configurationGuid, token) => Task.FromResult(true));
}
else
{
Mock.Get(ConfigurationService)
.Setup(s => s.GetById(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, CancellationToken>(
(configurationGuid, token) => Task.FromResult(default(Strata.ContinuousImprovement.Biz.Configuration.Configuration)));
Mock.Get(ConfigurationService)
.Setup(s => s.Contains(It.IsAny<Biz.Configuration.Configuration>(), It.IsAny<CancellationToken>()))
.Returns<Biz.Configuration.Configuration, CancellationToken>(
(configuration, token) => Task.FromResult(false));
Mock.Get(ConfigurationService)
.Setup(s => s.IsConfigurationValid(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, CancellationToken>(
(configurationGuid, token) => Task.FromResult(false));
}
Mock.Get(ExplorationService)
.Setup(s => s.GetCaseTypeFamilySummariesAsync(It.IsAny<ExplorationInfo>(), It.IsAny<CancellationToken>()))
.Returns<ExplorationInfo, CancellationToken>(
(explorationInfo, token) => Task.FromResult(result.AsEnumerable()));
// Act
var controllerResponse = await ExplorationController.GetCaseTypeFamilySummaries(explorationInfo, CancellationToken.None);
// Assert
controllerResponse.Should().NotBeNull();
if (controllerResponse.Result is OkObjectResult okResult)
{
okResult.Should().NotBeNull();
var value = okResult.Value as IEnumerable<CaseTypeFamilySummaryData>;
value.Should().NotBeNull();
}
else
{
controllerResponse.Result.Should().BeOfType<BadRequestResult>();
}
}
[TestCaseSource(nameof(GetCaseTypeFamilyDetailsTestCases))]
public async Task GetCaseTypeFamilyDetailsTest(Guid configurationGuid)
{
// Arrange
var configuration = JazzDbContext.Configurations.First();
var explorationInfo = new ExplorationDetailInfo
{
ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid,
CaseTypeFamilyId = 0,
ExclusionCriteria = new Biz.Exploration.Filters.ExclusionCriteria(),
Filters = new Biz.Exploration.Filters.Filter
{
DischargeDateStart = new System.DateTime(2024, 1, 1),
DischargeDateEnd = new System.DateTime(2024, 12, 31),
FilterChipItems = new List<FilterChipItem>()
}
};
var result = new CaseTypeFamilyDetailInfo
{
Metrics = new CaseTypeFamilyMetric(),
CaseTypeFamilyDetails = Enumerable.Empty<CaseTypeFamilyDetailData>()
};
if (configuration.ConfigurationGuid == configurationGuid)
{
Mock.Get(ConfigurationService)
.Setup(s => s.GetById(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, CancellationToken>(
(configurationGuid, token) => Task.FromResult(JazzDbContext.Configurations.First()));
Mock.Get(ConfigurationService)
.Setup(s => s.Contains(It.IsAny<Biz.Configuration.Configuration>(), It.IsAny<CancellationToken>()))
.Returns<Biz.Configuration.Configuration, CancellationToken>(
(configuration, token) => Task.FromResult(true));
Mock.Get(ConfigurationService)
.Setup(s => s.IsConfigurationValid(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, CancellationToken>(
(configurationGuid, token) => Task.FromResult(true));
}
else
{
Mock.Get(ConfigurationService)
.Setup(s => s.GetById(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, CancellationToken>(
(configurationGuid, token) => Task.FromResult(default(Strata.ContinuousImprovement.Biz.Configuration.Configuration)));
Mock.Get(ConfigurationService)
.Setup(s => s.Contains(It.IsAny<Biz.Configuration.Configuration>(), It.IsAny<CancellationToken>()))
.Returns<Biz.Configuration.Configuration, CancellationToken>(
(configuration, token) => Task.FromResult(false));
Mock.Get(ConfigurationService)
.Setup(s => s.IsConfigurationValid(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, CancellationToken>(
(configurationGuid, token) => Task.FromResult(false));
}
Mock.Get(ExplorationService)
.Setup(s => s.GetCaseTypeFamilyDetailsAsync(It.IsAny<ExplorationDetailInfo>(), It.IsAny<CancellationToken>()))
.Returns<ExplorationDetailInfo, CancellationToken>(
(exploration, token) => Task.FromResult(result));
// Act
var controllerResponse = await ExplorationController.GetCaseTypeFamilyDetails(explorationInfo, CancellationToken.None);
// Assert
controllerResponse.Should().NotBeNull();
if (controllerResponse.Result is OkObjectResult okResult)
{
okResult.Should().NotBeNull();
okResult.Value.Should().BeOfType<CaseTypeFamilyDetailInfo>();
configuration.ConfigurationGuid.Should().Be(configurationGuid);
}
else if (controllerResponse.Result is BadRequestResult badRequestResult)
{
badRequestResult.Should().NotBeNull();
}
}
public static IEnumerable<TestCaseData> GetCaseTypeFamilySummariesTestCases()
{
var configurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid;
yield return new TestCaseData(configurationGuid)
.SetName("summaries valid configuration");
yield return new TestCaseData(Guid.NewGuid())
.SetName("summaries invalid configuration");
}
public static IEnumerable<TestCaseData> GetCaseTypeFamilyDetailsTestCases()
{
var configurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid;
yield return new TestCaseData(configurationGuid)
.SetName("details valid configuration");
yield return new TestCaseData(Guid.NewGuid())
.SetName("details invalid configuration");
}
}
}
@@ -0,0 +1,92 @@
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.Dtos;
using Strata.ContinuousImprovement.Biz.Exploration;
using Strata.ContinuousImprovement.Biz.Population;
using Strata.ContinuousImprovement.Biz.UserSetting;
using Strata.DecisionSupport.Models.Encounters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class ExplorationPopulationsControllerTests
{
public ExplorationPopulationsController Controller { get; set; }
public IUserSettingService UserSettingService { get; set; }
public IExplorationPopulationService PopulationService { get; set; }
public IExplorationService ExplorationService { get; set; }
[OneTimeSetUp]
public async Task ExplorationPopulationsControllerTests_OneTimeSetUp()
{
UserSettingService = Mock.Of<IUserSettingService>();
PopulationService = Mock.Of<IExplorationPopulationService>();
ExplorationService = Mock.Of<IExplorationService>();
}
[SetUp]
public void ExplorationPopulationsControllerTests_Setup()
{
Controller = new ExplorationPopulationsController(UserSettingService, PopulationService, ExplorationService, Mock.Of<ILogger<ExplorationPopulationsController>>());
}
[TestCaseSource(nameof(GetEncountersTestCases))]
public async Task GetEncountersTest(ExplorationPopulationDto population, IEnumerable<EncounterPhysicianInfo> encounterPhysicians)
{
// Arrange
long populationId = 0;
Guid configurationGuid = new Guid();
Mock.Get(PopulationService)
.Setup(s => s.GetPopulationDataAsync(It.IsAny<long>(), It.IsAny<CancellationToken>()))
.Returns<long, CancellationToken>((populationId, token) => Task.FromResult(population));
Mock.Get(ExplorationService)
.Setup(s => s.GetEncountersAsync(It.IsAny<ExplorationDetailInfo>(), It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<ExplorationDetailInfo, Guid, CancellationToken>((exploration, configurationGuid, token) => Task.FromResult(encounterPhysicians));
// Act
var response = await Controller.GetEncounters(populationId, configurationGuid, CancellationToken.None);
// Assert
response.Should().NotBeNull();
if (population == null || encounterPhysicians == null)
{
response.Result.Should().BeOfType<BadRequestResult>();
}
else
{
response.Result.Should().BeOfType<OkObjectResult>();
var okResult = (OkObjectResult)response.Result;
okResult.Value.Should().BeAssignableTo<IEnumerable<IJazzExplorationEncounterInfo>>();
okResult.Value.Should().NotBeNull();
}
}
public static IEnumerable<TestCaseData> GetEncountersTestCases()
{
var population = new ExplorationPopulationDto()
{
FiltersJSON = string.Empty
};
var encounterPhysicians = Enumerable.Empty<EncounterPhysicianInfo>();
yield return new TestCaseData(population, encounterPhysicians)
.SetName("Population and Encounters are not null");
yield return new TestCaseData(population, null)
.SetName("Encounters is null");
yield return new TestCaseData(null, encounterPhysicians)
.SetName("Population is null");
yield return new TestCaseData(null, null)
.SetName("Population and Encounters are null");
}
}
}
@@ -0,0 +1,180 @@
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Moq;
using NUnit.Framework;
using Strata.ApiLib.Standard.Models;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.DbContexts;
using Strata.ContinuousImprovement.Biz.FreeForm.Initiatives;
using Strata.ContinuousImprovement.Biz.FreeForm.Opportunities;
using Strata.ContinuousImprovement.Biz.FreeForm.Opportunities.Filters;
using Strata.ContinuousImprovement.Biz.Initiatives;
using Strata.ContinuousImprovement.Biz.Pagination;
using Strata.ContinuousImprovement.JazzEntityFrameworkStub;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class FreeFormOpportunitiesControllerTests
{
public JazzEntityFrameworkFactory jazzEntityFrameworkFactory { get; set; }
public JazzDbContext DbContext { get; set; }
public IFFOpportunityService FFOpportunityService { get; set; }
public IFFInitiativeService FFInitiativeService { get; set; }
public IInitiativeService InitiativeService { get; set; }
public FreeFormOpportunitiesController Controller { get; set; }
[OneTimeSetUp]
public async Task FreeFormOpportunitiesControllerTestSetup()
{
jazzEntityFrameworkFactory = new JazzEntityFrameworkFactory();
DbContext = await jazzEntityFrameworkFactory.CreateDbContextAsync(nameof(ConfigurationsControllerTests), CancellationToken.None);
FFOpportunityService = Mock.Of<IFFOpportunityService>();
InitiativeService = Mock.Of<IInitiativeService>();
}
[SetUp]
public async Task Setup()
{
// Arrange
Controller = new FreeFormOpportunitiesController(FFOpportunityService, InitiativeService);
}
[Test()]
public async Task FreeFormOpportunitiesControllerTest()
{
// Act
// Assert
Controller.Should().NotBeNull();
}
[Test()]
public async Task GetOpportunitiesTest()
{
// Arrange
var opportunities = DbContext.FFOpportunities.Take(25).ToList();
var pagingOptions = new PagingOptions
{
First = 1,
Rows = 25,
SortField = nameof(FFOpportunity.IdentifiedSavings),
SortOrder = SortOrder.Asc
};
var loadOptions = new FFOpportunityLoadOptions
{
Filters = new FFFilters { ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid },
PagingOptions = pagingOptions,
};
var response = new PagedApiResponse<FFOpportunity>
{
PagingInfo = new PagingInfo
{
PageNumber = 1,
TotalNumberOfResults = opportunities.Count,
TotalPages = opportunities.Count / pagingOptions.Rows,
ResultsPerPage = pagingOptions.Rows
},
Data = opportunities
};
Mock.Get(FFOpportunityService)
.Setup(x => x.GetPagedAsync(It.IsAny<PagingOptions>(), It.IsAny<FFFilters>(), It.IsAny<CancellationToken>()))
.Returns<PagingOptions, FFFilters, CancellationToken>(
(pagingOptions, filters, token) =>
Task.FromResult(response)
);
// Act
var controllerResponse = await Controller.GetOpportunities(loadOptions, CancellationToken.None);
// Assert
controllerResponse.Should().NotBeNull();
}
[Test()]
public async Task GetByIdTest()
{
// Arrange
var opportunities = DbContext.FreeFormOpportunities.ToList();
var firstOpportunity = opportunities.First();
if (firstOpportunity.Configuration == null)
{
var configuration = DbContext.Configurations.First();
if (configuration.FiscalMonthResolver == null)
{
var fmr = jazzEntityFrameworkFactory.FiscalMonthResolver;
configuration.FiscalMonthResolver = fmr;
}
firstOpportunity.Configuration = configuration;
}
var dfltOpportunity = default(FFOpportunityDataModel);
var fmResolver = jazzEntityFrameworkFactory.FiscalMonthResolver;
Mock.Get(FFOpportunityService)
.Setup(x => x.GetDataModelById(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
.Returns<Guid, CancellationToken>(
(opportunityGuid, token) =>
opportunityGuid != firstOpportunity.OpportunityGuid
? Task.FromResult(dfltOpportunity)
: Task.FromResult(firstOpportunity)
);
var detailModel = firstOpportunity.MapToDetailModel(fmResolver);
// Act
var controllerResponse = await Controller.GetById(firstOpportunity.OpportunityGuid, CancellationToken.None);
// Assert
controllerResponse.Should().NotBeNull();
controllerResponse.Result.Should().NotBeNull();
controllerResponse.Result.Should().BeOfType<OkObjectResult>();
var result = (OkObjectResult)controllerResponse.Result;
result.Should().NotBeNull();
result.Should().BeOfType<OkObjectResult>();
result.Value.Should().NotBeNull();
result.Value.Should().BeOfType<FFOpportunityDetailModel>();
var detail = (FFOpportunityDetailModel)result.Value;
detail.Should().BeEquivalentTo(detailModel);
}
[Test()]
public async Task CreateTest()
{
Assert.Inconclusive();
}
[Test()]
public async Task DeleteTest()
{
Assert.Inconclusive();
}
[Test()]
public async Task GetInitiativeTest()
{
Assert.Inconclusive();
}
[Test()]
public async Task SetGoalsAsyncTest()
{
Assert.Inconclusive();
}
[Test()]
public async Task ExportTest()
{
Assert.Inconclusive();
}
[Test()]
public async Task GetFilterOptionsAsyncTest()
{
Assert.Inconclusive();
}
}
}
@@ -0,0 +1,83 @@
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers.JazzQvi;
using Strata.ContinuousImprovement.Biz.QualityVariation.QVI;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class NonQviSavingsControllerTests
{
private Mock<INonQviSavingsService> _serviceMock;
private NonQviSavingsController _controller;
[SetUp]
public void SetUp()
{
_serviceMock = new Mock<INonQviSavingsService>();
_controller = new NonQviSavingsController(_serviceMock.Object);
}
[Test]
public async Task GetCaseTypeFamilies_WhenConfigurationGuidIsEmpty_ReturnsBadRequest()
{
var result = await _controller.GetCaseTypeFamilies(Guid.Empty, false, CancellationToken.None);
result.Result.Should().BeOfType<BadRequestObjectResult>();
_serviceMock.Verify(s => s.GetCaseTypeFamilyInfoAsync(It.IsAny<Guid>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task GetCaseTypeFamilies_WhenConfigurationGuidIsValid_ReturnsOk()
{
var configurationGuid = Guid.NewGuid();
var expected = new[] { new NonQviCaseTypeFamilyInfo { CaseTypeFamilyId = 1, CaseCount = 5 } };
_serviceMock
.Setup(s => s.GetCaseTypeFamilyInfoAsync(configurationGuid, true, It.IsAny<CancellationToken>()))
.ReturnsAsync(expected);
var result = await _controller.GetCaseTypeFamilies(configurationGuid, true, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>();
var okResult = result.Result as OkObjectResult;
var value = okResult?.Value as System.Collections.Generic.IEnumerable<NonQviCaseTypeFamilyInfo>;
value.Should().NotBeNull();
value!.Single().CaseTypeFamilyId.Should().Be(1);
_serviceMock.Verify(s => s.GetCaseTypeFamilyInfoAsync(configurationGuid, true, It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task GetDrgTypes_WhenConfigurationGuidIsEmpty_ReturnsBadRequest()
{
var result = await _controller.GetDrgTypes(Guid.Empty, false, CancellationToken.None);
result.Result.Should().BeOfType<BadRequestObjectResult>();
_serviceMock.Verify(s => s.GetDrgTypeInfoAsync(It.IsAny<Guid>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task GetDrgTypes_WhenConfigurationGuidIsValid_ReturnsOk()
{
var configurationGuid = Guid.NewGuid();
var expected = new[] { new NonQviDrgTypeInfo { DrgType = "MS" } };
_serviceMock
.Setup(s => s.GetDrgTypeInfoAsync(configurationGuid, true, It.IsAny<CancellationToken>()))
.ReturnsAsync(expected);
var result = await _controller.GetDrgTypes(configurationGuid, true, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>();
var okResult = result.Result as OkObjectResult;
var value = okResult?.Value as System.Collections.Generic.IEnumerable<NonQviDrgTypeInfo>;
value.Should().NotBeNull();
value!.Single().DrgType.Should().Be("MS");
_serviceMock.Verify(s => s.GetDrgTypeInfoAsync(configurationGuid, true, It.IsAny<CancellationToken>()), Times.Once);
}
}
}
@@ -0,0 +1,57 @@
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers.JazzQvi;
using Strata.ContinuousImprovement.Biz.QualityVariation.QVI;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class QviEncountersControllerTests
{
private Mock<IQviEncounterService> _serviceMock;
private QviEncountersController _controller;
[SetUp]
public void SetUp()
{
_serviceMock = new Mock<IQviEncounterService>();
_controller = new QviEncountersController(_serviceMock.Object);
}
[Test]
public async Task Get_WhenConfigurationGuidIsEmpty_ReturnsBadRequest()
{
var result = await _controller.Get(Guid.Empty, DateTime.UtcNow, DateTime.UtcNow, CancellationToken.None);
result.Result.Should().BeOfType<BadRequestObjectResult>();
_serviceMock.Verify(s => s.GetEncounterInfoAsync(It.IsAny<Guid>(), It.IsAny<DateTime>(), It.IsAny<DateTime>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task Get_WhenConfigurationGuidIsValid_ReturnsOk()
{
var configurationGuid = Guid.NewGuid();
var startDate = new DateTime(2024, 1, 1);
var endDate = new DateTime(2024, 12, 31);
var expected = new[] { new EncounterInfo { EncounterId = 11, EncounterRecordNumber = "enc-11" } };
_serviceMock
.Setup(s => s.GetEncounterInfoAsync(configurationGuid, startDate, endDate, It.IsAny<CancellationToken>()))
.ReturnsAsync(expected);
var result = await _controller.Get(configurationGuid, startDate, endDate, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>();
var okResult = result.Result as OkObjectResult;
var value = okResult?.Value as System.Collections.Generic.IEnumerable<EncounterInfo>;
value.Should().NotBeNull();
value!.Single().EncounterId.Should().Be(11);
_serviceMock.Verify(s => s.GetEncounterInfoAsync(configurationGuid, startDate, endDate, It.IsAny<CancellationToken>()), Times.Once);
}
}
}
@@ -0,0 +1,111 @@
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers.JazzQvi;
using Strata.ContinuousImprovement.Biz.QualityVariation.QVI;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[TestFixture, Category("Unit"), Category("Controller")]
public class QviLineItemSavingsControllerTests
{
private Mock<IQviLineItemSavingsService> _serviceMock;
private QviLineItemSavingsController _controller;
[SetUp]
public void SetUp()
{
_serviceMock = new Mock<IQviLineItemSavingsService>();
_controller = new QviLineItemSavingsController(_serviceMock.Object);
}
[Test]
public async Task GetCaseTypeFamilies_WhenConfigurationGuidIsEmpty_ReturnsBadRequest()
{
var result = await _controller.GetCaseTypeFamilies(Guid.Empty, false, CancellationToken.None);
result.Result.Should().BeOfType<BadRequestObjectResult>();
_serviceMock.Verify(s => s.GetCaseTypeFamilyInfoAsync(It.IsAny<Guid>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task GetCaseTypeFamilies_WhenConfigurationGuidIsValid_ReturnsOk()
{
var configurationGuid = Guid.NewGuid();
var expected = new[] { new QviLineItemCaseTypeFamilyInfo { QualityVariationEventId = 1, CaseTypeFamilyId = 2 } };
_serviceMock
.Setup(s => s.GetCaseTypeFamilyInfoAsync(configurationGuid, true, It.IsAny<CancellationToken>()))
.ReturnsAsync(expected);
var result = await _controller.GetCaseTypeFamilies(configurationGuid, true, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>();
var okResult = result.Result as OkObjectResult;
var value = okResult?.Value as System.Collections.Generic.IEnumerable<QviLineItemCaseTypeFamilyInfo>;
value.Should().NotBeNull();
value!.Single().CaseTypeFamilyId.Should().Be(2);
_serviceMock.Verify(s => s.GetCaseTypeFamilyInfoAsync(configurationGuid, true, It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task GetDrgTypes_WhenConfigurationGuidIsEmpty_ReturnsBadRequest()
{
var result = await _controller.GetDrgTypes(Guid.Empty, false, CancellationToken.None);
result.Result.Should().BeOfType<BadRequestObjectResult>();
_serviceMock.Verify(s => s.GetDrgTypeInfoAsync(It.IsAny<Guid>(), It.IsAny<bool>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task GetDrgTypes_WhenConfigurationGuidIsValid_ReturnsOk()
{
var configurationGuid = Guid.NewGuid();
var expected = new[] { new QviLineItemDrgTypeInfo { DrgType = "APR" } };
_serviceMock
.Setup(s => s.GetDrgTypeInfoAsync(configurationGuid, true, It.IsAny<CancellationToken>()))
.ReturnsAsync(expected);
var result = await _controller.GetDrgTypes(configurationGuid, true, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>();
var okResult = result.Result as OkObjectResult;
var value = okResult?.Value as System.Collections.Generic.IEnumerable<QviLineItemDrgTypeInfo>;
value.Should().NotBeNull();
value!.Single().DrgType.Should().Be("APR");
_serviceMock.Verify(s => s.GetDrgTypeInfoAsync(configurationGuid, true, It.IsAny<CancellationToken>()), Times.Once);
}
[Test]
public async Task GetEncounterSavings_WhenConfigurationGuidIsEmpty_ReturnsBadRequest()
{
var result = await _controller.GetEncounterSavings(Guid.Empty, cancellationToken: CancellationToken.None);
result.Result.Should().BeOfType<BadRequestObjectResult>();
_serviceMock.Verify(s => s.GetEncounterSavingInfoAsync(It.IsAny<Guid>(), It.IsAny<Guid?>(), It.IsAny<bool?>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task GetEncounterSavings_WhenConfigurationGuidIsValid_ReturnsOk()
{
var configurationGuid = Guid.NewGuid();
var expected = new[] { new QviLineItemEncounterSavingInfo { EncounterRecordNumber = "enc-1" } };
_serviceMock
.Setup(s => s.GetEncounterSavingInfoAsync(configurationGuid, It.IsAny<Guid?>(), It.IsAny<bool?>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(expected);
var result = await _controller.GetEncounterSavings(configurationGuid, cancellationToken: CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>();
var okResult = result.Result as OkObjectResult;
var value = okResult?.Value as System.Collections.Generic.IEnumerable<QviLineItemEncounterSavingInfo>;
value.Should().NotBeNull();
value!.Single().EncounterRecordNumber.Should().Be("enc-1");
_serviceMock.Verify(s => s.GetEncounterSavingInfoAsync(configurationGuid, null, null, It.IsAny<CancellationToken>()), Times.Once);
}
}
}
@@ -0,0 +1,337 @@
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Dtos;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[ExcludeFromCodeCoverage]
[TestFixture, Category("Unit"), Category("Controller")]
public class StrategicChargeCodeControllerTests
{
private StrategicChargeCodeController _controller;
private Mock<IStrategicOpportunityService> _mockOpportunityService;
private Mock<IStrategicChargeCodeOpportunityDetailService> _mockDetailService;
[SetUp]
public void SetUp()
{
_mockOpportunityService = new Mock<IStrategicOpportunityService>();
_mockDetailService = new Mock<IStrategicChargeCodeOpportunityDetailService>();
_controller = new StrategicChargeCodeController(_mockOpportunityService.Object, _mockDetailService.Object);
}
// --- GetOpportunityChargeCode ---
[Test]
public async Task GetOpportunityChargeCode_ReturnsOk_WhenFound()
{
const long opportunityId = 1;
var data = new StrategicOpportunityChargeCodeEditData();
_mockOpportunityService
.Setup(s => s.GetStrategicOpportunityChargeCode(opportunityId, It.IsAny<CancellationToken>()))
.ReturnsAsync(data);
var result = await _controller.GetOpportunityChargeCode(opportunityId, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>()
.Which.Value.Should().Be(data);
}
[Test]
public async Task GetOpportunityChargeCode_ReturnsNotFound_WhenMissing()
{
_mockOpportunityService
.Setup(s => s.GetStrategicOpportunityChargeCode(It.IsAny<long>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((StrategicOpportunityChargeCodeEditData)null);
var result = await _controller.GetOpportunityChargeCode(99, CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
// --- CreateOpportunityChargeCode ---
[Test]
public async Task CreateOpportunityChargeCode_ReturnsOk_WithNewId_WhenSuccessful()
{
const long newId = 42;
var dto = new StrategicOpportunityChargeCodeDto();
_mockOpportunityService
.Setup(s => s.CreateOpportunityChargeCodeAsync(dto, It.IsAny<CancellationToken>()))
.ReturnsAsync(newId);
var result = await _controller.CreateOpportunityChargeCode(dto, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>()
.Which.Value.Should().Be(newId);
}
[Test]
public async Task CreateOpportunityChargeCode_ReturnsBadRequest_WhenServiceReturnsZero()
{
_mockOpportunityService
.Setup(s => s.CreateOpportunityChargeCodeAsync(It.IsAny<StrategicOpportunityChargeCodeDto>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(0L);
var result = await _controller.CreateOpportunityChargeCode(new StrategicOpportunityChargeCodeDto(), CancellationToken.None);
result.Result.Should().BeOfType<BadRequestResult>();
}
// --- UpdateOpportunityChargeCode ---
[Test]
public async Task UpdateOpportunityChargeCode_ReturnsOk_WhenSuccessful()
{
const long opportunityId = 5;
_mockOpportunityService
.Setup(s => s.UpdateOpportunityChargeCode(opportunityId, It.IsAny<StrategicOpportunityChargeCodeUpdateDto>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(opportunityId);
var result = await _controller.UpdateOpportunityChargeCode(opportunityId, new StrategicOpportunityChargeCodeUpdateDto(), CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>();
}
[Test]
public async Task UpdateOpportunityChargeCode_ReturnsNotFound_WhenServiceReturnsZero()
{
_mockOpportunityService
.Setup(s => s.UpdateOpportunityChargeCode(It.IsAny<long>(), It.IsAny<StrategicOpportunityChargeCodeUpdateDto>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(0L);
var result = await _controller.UpdateOpportunityChargeCode(99, new StrategicOpportunityChargeCodeUpdateDto(), CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
// --- DeleteOpportunityChargeCode ---
[Test]
public async Task DeleteOpportunityChargeCode_ReturnsNotFound_WhenOpportunityDoesNotExist()
{
_mockOpportunityService
.Setup(s => s.ContainsAsync(It.IsAny<long>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
var result = await _controller.DeleteOpportunityChargeCode(99, CancellationToken.None);
result.Should().BeOfType<NotFoundResult>();
_mockOpportunityService.Verify(s => s.DeleteChargeCodeOpportunityAsync(It.IsAny<long>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task DeleteOpportunityChargeCode_ReturnsNoContent_WhenDeleted()
{
const long opportunityId = 7;
_mockOpportunityService.Setup(s => s.ContainsAsync(opportunityId, It.IsAny<CancellationToken>())).ReturnsAsync(true);
_mockOpportunityService.Setup(s => s.DeleteChargeCodeOpportunityAsync(opportunityId, It.IsAny<CancellationToken>())).ReturnsAsync(true);
var result = await _controller.DeleteOpportunityChargeCode(opportunityId, CancellationToken.None);
result.Should().BeOfType<NoContentResult>();
}
[Test]
public async Task DeleteOpportunityChargeCode_ReturnsBadRequest_WhenDeleteFails()
{
const long opportunityId = 7;
_mockOpportunityService.Setup(s => s.ContainsAsync(opportunityId, It.IsAny<CancellationToken>())).ReturnsAsync(true);
_mockOpportunityService.Setup(s => s.DeleteChargeCodeOpportunityAsync(opportunityId, It.IsAny<CancellationToken>())).ReturnsAsync(false);
var result = await _controller.DeleteOpportunityChargeCode(opportunityId, CancellationToken.None);
result.Should().BeOfType<BadRequestResult>();
}
// --- GetGoalDetail ---
[Test]
public async Task GetGoalDetail_ReturnsOk_WhenFound()
{
const long opportunityId = 3;
var getData = new StrategicOpportunityGetDetailData();
var data = new StrategicOpportunityDetailData();
_mockDetailService
.Setup(s => s.GetStrategicOpportunityDetailData(opportunityId, false, getData, It.IsAny<CancellationToken>()))
.ReturnsAsync(data);
var result = await _controller.GetGoalDetail(opportunityId, getData, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>()
.Which.Value.Should().Be(data);
}
[Test]
public async Task GetGoalDetail_ReturnsNotFound_WhenMissing()
{
_mockDetailService
.Setup(s => s.GetStrategicOpportunityDetailData(It.IsAny<long>(), false, It.IsAny<StrategicOpportunityGetDetailData>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((StrategicOpportunityDetailData)null);
var result = await _controller.GetGoalDetail(99, new StrategicOpportunityGetDetailData(), CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
[Test]
public async Task GetGoalDetail_PassesIsTrackingFalse_ToService()
{
const long opportunityId = 3;
var getData = new StrategicOpportunityGetDetailData();
_mockDetailService
.Setup(s => s.GetStrategicOpportunityDetailData(opportunityId, false, getData, It.IsAny<CancellationToken>()))
.ReturnsAsync(new StrategicOpportunityDetailData());
await _controller.GetGoalDetail(opportunityId, getData, CancellationToken.None);
_mockDetailService.Verify(s => s.GetStrategicOpportunityDetailData(opportunityId, false, getData, CancellationToken.None), Times.Once);
}
// --- GetTrackingDetail ---
[Test]
public async Task GetTrackingDetail_ReturnsOk_WhenFound()
{
const long opportunityId = 4;
var getData = new StrategicOpportunityGetDetailData();
var data = new StrategicOpportunityDetailData();
_mockDetailService
.Setup(s => s.GetStrategicOpportunityDetailData(opportunityId, true, getData, It.IsAny<CancellationToken>()))
.ReturnsAsync(data);
var result = await _controller.GetTrackingDetail(opportunityId, getData, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>()
.Which.Value.Should().Be(data);
}
[Test]
public async Task GetTrackingDetail_ReturnsNotFound_WhenMissing()
{
_mockDetailService
.Setup(s => s.GetStrategicOpportunityDetailData(It.IsAny<long>(), true, It.IsAny<StrategicOpportunityGetDetailData>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((StrategicOpportunityDetailData)null);
var result = await _controller.GetTrackingDetail(99, new StrategicOpportunityGetDetailData(), CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
[Test]
public async Task GetTrackingDetail_PassesIsTrackingTrue_ToService()
{
const long opportunityId = 4;
var getData = new StrategicOpportunityGetDetailData();
_mockDetailService
.Setup(s => s.GetStrategicOpportunityDetailData(opportunityId, true, getData, It.IsAny<CancellationToken>()))
.ReturnsAsync(new StrategicOpportunityDetailData());
await _controller.GetTrackingDetail(opportunityId, getData, CancellationToken.None);
_mockDetailService.Verify(s => s.GetStrategicOpportunityDetailData(opportunityId, true, getData, CancellationToken.None), Times.Once);
}
// --- UpdateDetails ---
[Test]
public async Task UpdateDetails_ReturnsBadRequest_WhenDtoIsNull()
{
var result = await _controller.UpdateDetails(1, null, CancellationToken.None);
result.Should().BeOfType<BadRequestResult>();
_mockDetailService.Verify(s => s.UpdateStrategicOpportunityDetailsData(
It.IsAny<long>(), It.IsAny<IEnumerable<StrategicOpportunityChargeCodeAdjustment>>(), It.IsAny<IEnumerable<string>>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task UpdateDetails_ReturnsBadRequest_WhenAdjustmentsIsEmpty()
{
var dto = new StrategicChargeCodeController.UpdateDetailsDto
{
Adjustments = new List<StrategicOpportunityChargeCodeAdjustment>(),
Rows = new List<string> { "system", "entity" }
};
var result = await _controller.UpdateDetails(1, dto, CancellationToken.None);
result.Should().BeOfType<BadRequestResult>();
_mockDetailService.Verify(s => s.UpdateStrategicOpportunityDetailsData(
It.IsAny<long>(), It.IsAny<IEnumerable<StrategicOpportunityChargeCodeAdjustment>>(), It.IsAny<IEnumerable<string>>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task UpdateDetails_ReturnsBadRequest_WhenRowsIsEmpty()
{
var dto = new StrategicChargeCodeController.UpdateDetailsDto
{
Adjustments = new List<StrategicOpportunityChargeCodeAdjustment> { new() { NodeKey = "101", CostsValue = 5000m } },
Rows = new List<string>()
};
var result = await _controller.UpdateDetails(1, dto, CancellationToken.None);
result.Should().BeOfType<BadRequestResult>();
_mockDetailService.Verify(s => s.UpdateStrategicOpportunityDetailsData(
It.IsAny<long>(), It.IsAny<IEnumerable<StrategicOpportunityChargeCodeAdjustment>>(), It.IsAny<IEnumerable<string>>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task UpdateDetails_ReturnsOk_AndCallsService_WhenDtoIsValid()
{
const long opportunityId = 42;
var dto = new StrategicChargeCodeController.UpdateDetailsDto
{
Adjustments = new List<StrategicOpportunityChargeCodeAdjustment> { new() { NodeKey = "101", CostsValue = 5000m } },
Rows = new List<string> { "system", "entity", "chargeCode" }
};
var result = await _controller.UpdateDetails(opportunityId, dto, CancellationToken.None);
result.Should().BeOfType<OkResult>();
_mockDetailService.Verify(s => s.UpdateStrategicOpportunityDetailsData(
opportunityId, dto.Adjustments, dto.Rows, CancellationToken.None), Times.Once);
}
// --- Route attribute assertions ---
[Test]
public void Controller_HasExpectedRouteTemplate()
{
var routeAttr = typeof(StrategicChargeCodeController).GetCustomAttribute<RouteAttribute>();
routeAttr.Should().NotBeNull();
routeAttr.Template.Should().Be("api/v{api-version:apiVersion}/[controller]");
}
[TestCase(nameof(StrategicChargeCodeController.GetOpportunityChargeCode), typeof(HttpGetAttribute), "{opportunityId}/[action]")]
[TestCase(nameof(StrategicChargeCodeController.CreateOpportunityChargeCode), typeof(HttpPostAttribute), null)]
[TestCase(nameof(StrategicChargeCodeController.UpdateOpportunityChargeCode), typeof(HttpPutAttribute), "{opportunityId}")]
[TestCase(nameof(StrategicChargeCodeController.DeleteOpportunityChargeCode), typeof(HttpDeleteAttribute), "{opportunityId}")]
[TestCase(nameof(StrategicChargeCodeController.GetGoalDetail), typeof(HttpPostAttribute), "{opportunityId}/goal-detail")]
[TestCase(nameof(StrategicChargeCodeController.ExportInitiative), typeof(HttpPostAttribute), "{opportunityId}/export")]
[TestCase(nameof(StrategicChargeCodeController.ExportOpportunity), typeof(HttpPostAttribute), "{opportunityId}/export-opportunity")]
[TestCase(nameof(StrategicChargeCodeController.GetTrackingDetail), typeof(HttpPostAttribute), "{opportunityId}/tracking-detail")]
[TestCase(nameof(StrategicChargeCodeController.UpdateDetails), typeof(HttpPutAttribute), "{opportunityId}/details")]
public void ActionRoute_HasExpectedHttpMethodAndTemplate(string methodName, Type httpAttrType, string expectedTemplate)
{
var method = typeof(StrategicChargeCodeController).GetMethod(methodName);
method.Should().NotBeNull($"method '{methodName}' should exist on {nameof(StrategicChargeCodeController)}");
var attr = method.GetCustomAttribute(httpAttrType);
attr.Should().NotBeNull($"{methodName} should be decorated with [{httpAttrType.Name}]");
var template = (string)attr.GetType().GetProperty("Template").GetValue(attr);
template.Should().Be(expectedTemplate);
}
}
}
@@ -0,0 +1,335 @@
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Dtos;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[ExcludeFromCodeCoverage]
[TestFixture, Category("Unit"), Category("Controller")]
public class StrategicGeneralLedgerControllerTests
{
private StrategicGeneralLedgerController _controller;
private Mock<IStrategicOpportunityService> _mockOpportunityService;
private Mock<IStrategicGLOpportunityDetailService> _mockDetailService;
[SetUp]
public void SetUp()
{
_mockOpportunityService = new Mock<IStrategicOpportunityService>();
_mockDetailService = new Mock<IStrategicGLOpportunityDetailService>();
_controller = new StrategicGeneralLedgerController(_mockOpportunityService.Object, _mockDetailService.Object);
}
// --- GetOpportunityGL ---
[Test]
public async Task GetOpportunityGL_ReturnsOk_WhenFound()
{
const long opportunityId = 1;
var data = new StrategicOpportunityGLEditData();
_mockOpportunityService
.Setup(s => s.GetStrategicOpportunityGL(opportunityId, It.IsAny<CancellationToken>()))
.ReturnsAsync(data);
var result = await _controller.GetOpportunityGL(opportunityId, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>()
.Which.Value.Should().Be(data);
}
[Test]
public async Task GetOpportunityGL_ReturnsNotFound_WhenMissing()
{
_mockOpportunityService
.Setup(s => s.GetStrategicOpportunityGL(It.IsAny<long>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((StrategicOpportunityGLEditData)null);
var result = await _controller.GetOpportunityGL(99, CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
// --- CreateOpportunityGeneralLedger ---
[Test]
public async Task CreateOpportunityGeneralLedger_ReturnsOk_WithNewId_WhenSuccessful()
{
const long newId = 42;
var dto = new StrategicOpportunityGLDto();
_mockOpportunityService
.Setup(s => s.CreateOpportunityGeneralLedgerAsync(dto, It.IsAny<CancellationToken>()))
.ReturnsAsync(newId);
var result = await _controller.CreateOpportunityGeneralLedger(dto, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>()
.Which.Value.Should().Be(newId);
}
[Test]
public async Task CreateOpportunityGeneralLedger_ReturnsBadRequest_WhenServiceReturnsZero()
{
_mockOpportunityService
.Setup(s => s.CreateOpportunityGeneralLedgerAsync(It.IsAny<StrategicOpportunityGLDto>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(0L);
var result = await _controller.CreateOpportunityGeneralLedger(new StrategicOpportunityGLDto(), CancellationToken.None);
result.Result.Should().BeOfType<BadRequestResult>();
}
// --- UpdateOpportunityGeneralLedger ---
[Test]
public async Task UpdateOpportunityGeneralLedger_ReturnsOk_WhenSuccessful()
{
const long opportunityId = 5;
_mockOpportunityService
.Setup(s => s.UpdateOpportunityGeneralLedger(opportunityId, It.IsAny<StrategicOpportunityGLUpdateDto>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(opportunityId);
var result = await _controller.UpdateOpportunityGeneralLedger(opportunityId, new StrategicOpportunityGLUpdateDto(), CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>();
}
[Test]
public async Task UpdateOpportunityGeneralLedger_ReturnsNotFound_WhenServiceReturnsZero()
{
_mockOpportunityService
.Setup(s => s.UpdateOpportunityGeneralLedger(It.IsAny<long>(), It.IsAny<StrategicOpportunityGLUpdateDto>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(0L);
var result = await _controller.UpdateOpportunityGeneralLedger(99, new StrategicOpportunityGLUpdateDto(), CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
// --- DeleteOpportunityGeneralLedger ---
[Test]
public async Task DeleteOpportunityGeneralLedger_ReturnsNotFound_WhenOpportunityDoesNotExist()
{
_mockOpportunityService
.Setup(s => s.ContainsGLAsync(It.IsAny<long>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
var result = await _controller.DeleteOpportunityGeneralLedger(99, CancellationToken.None);
result.Should().BeOfType<NotFoundResult>();
_mockOpportunityService.Verify(s => s.DeleteGeneralLedgerOpportunityAsync(It.IsAny<long>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task DeleteOpportunityGeneralLedger_ReturnsNoContent_WhenDeleted()
{
const long opportunityId = 7;
_mockOpportunityService.Setup(s => s.ContainsGLAsync(opportunityId, It.IsAny<CancellationToken>())).ReturnsAsync(true);
_mockOpportunityService.Setup(s => s.DeleteGeneralLedgerOpportunityAsync(opportunityId, It.IsAny<CancellationToken>())).ReturnsAsync(true);
var result = await _controller.DeleteOpportunityGeneralLedger(opportunityId, CancellationToken.None);
result.Should().BeOfType<NoContentResult>();
}
[Test]
public async Task DeleteOpportunityGeneralLedger_ReturnsBadRequest_WhenDeleteFails()
{
const long opportunityId = 7;
_mockOpportunityService.Setup(s => s.ContainsGLAsync(opportunityId, It.IsAny<CancellationToken>())).ReturnsAsync(true);
_mockOpportunityService.Setup(s => s.DeleteGeneralLedgerOpportunityAsync(opportunityId, It.IsAny<CancellationToken>())).ReturnsAsync(false);
var result = await _controller.DeleteOpportunityGeneralLedger(opportunityId, CancellationToken.None);
result.Should().BeOfType<BadRequestResult>();
}
// --- GetGLDetail ---
[Test]
public async Task GetGLDetail_ReturnsOk_WhenFound()
{
const long opportunityId = 3;
var dimensions = new[] { "system", "entity" };
var data = new StrategicOpportunityGLDetailData();
_mockDetailService
.Setup(s => s.GetStrategicOpportunityGLDetailData(opportunityId, false, dimensions, It.IsAny<CancellationToken>()))
.ReturnsAsync(data);
var result = await _controller.GetGLDetail(opportunityId, dimensions, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>()
.Which.Value.Should().Be(data);
}
[Test]
public async Task GetGLDetail_ReturnsNotFound_WhenMissing()
{
_mockDetailService
.Setup(s => s.GetStrategicOpportunityGLDetailData(It.IsAny<long>(), false, It.IsAny<string[]>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((StrategicOpportunityGLDetailData)null);
var result = await _controller.GetGLDetail(99, Array.Empty<string>(), CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
[Test]
public async Task GetGLDetail_PassesIsTrackingFalse_ToService()
{
const long opportunityId = 3;
var dimensions = new[] { "system" };
_mockDetailService
.Setup(s => s.GetStrategicOpportunityGLDetailData(opportunityId, false, dimensions, It.IsAny<CancellationToken>()))
.ReturnsAsync(new StrategicOpportunityGLDetailData());
await _controller.GetGLDetail(opportunityId, dimensions, CancellationToken.None);
_mockDetailService.Verify(s => s.GetStrategicOpportunityGLDetailData(opportunityId, false, dimensions, CancellationToken.None), Times.Once);
}
// --- GetGLTrackingDetail ---
[Test]
public async Task GetGLTrackingDetail_ReturnsOk_WhenFound()
{
const long opportunityId = 4;
var dimensions = new[] { "system", "glAccount" };
var data = new StrategicOpportunityGLDetailData();
_mockDetailService
.Setup(s => s.GetStrategicOpportunityGLDetailData(opportunityId, true, dimensions, It.IsAny<CancellationToken>()))
.ReturnsAsync(data);
var result = await _controller.GetGLTrackingDetail(opportunityId, dimensions, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>()
.Which.Value.Should().Be(data);
}
[Test]
public async Task GetGLTrackingDetail_ReturnsNotFound_WhenMissing()
{
_mockDetailService
.Setup(s => s.GetStrategicOpportunityGLDetailData(It.IsAny<long>(), true, It.IsAny<string[]>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((StrategicOpportunityGLDetailData)null);
var result = await _controller.GetGLTrackingDetail(99, Array.Empty<string>(), CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
[Test]
public async Task GetGLTrackingDetail_PassesIsTrackingTrue_ToService()
{
const long opportunityId = 4;
var dimensions = new[] { "system" };
_mockDetailService
.Setup(s => s.GetStrategicOpportunityGLDetailData(opportunityId, true, dimensions, It.IsAny<CancellationToken>()))
.ReturnsAsync(new StrategicOpportunityGLDetailData());
await _controller.GetGLTrackingDetail(opportunityId, dimensions, CancellationToken.None);
_mockDetailService.Verify(s => s.GetStrategicOpportunityGLDetailData(opportunityId, true, dimensions, CancellationToken.None), Times.Once);
}
// --- UpdateGLDetails ---
[Test]
public async Task UpdateGLDetails_ReturnsBadRequest_WhenDtoIsNull()
{
var result = await _controller.UpdateGLDetails(1, null, CancellationToken.None);
result.Should().BeOfType<BadRequestResult>();
_mockDetailService.Verify(s => s.UpdateStrategicOpportunityGLDetailsData(
It.IsAny<long>(), It.IsAny<IEnumerable<StrategicOpportunityGLAdjustment>>(), It.IsAny<IEnumerable<string>>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task UpdateGLDetails_ReturnsBadRequest_WhenAdjustmentsIsEmpty()
{
var dto = new UpdateGLDetailsDto
{
Adjustments = new List<StrategicOpportunityGLAdjustment>(),
Rows = new List<string> { "system", "entity" }
};
var result = await _controller.UpdateGLDetails(1, dto, CancellationToken.None);
result.Should().BeOfType<BadRequestResult>();
_mockDetailService.Verify(s => s.UpdateStrategicOpportunityGLDetailsData(
It.IsAny<long>(), It.IsAny<IEnumerable<StrategicOpportunityGLAdjustment>>(), It.IsAny<IEnumerable<string>>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task UpdateGLDetails_ReturnsBadRequest_WhenRowsIsEmpty()
{
var dto = new UpdateGLDetailsDto
{
Adjustments = new List<StrategicOpportunityGLAdjustment> { new() { NodeKey = "101", GoalAmountValue = 5000m } },
Rows = new List<string>()
};
var result = await _controller.UpdateGLDetails(1, dto, CancellationToken.None);
result.Should().BeOfType<BadRequestResult>();
_mockDetailService.Verify(s => s.UpdateStrategicOpportunityGLDetailsData(
It.IsAny<long>(), It.IsAny<IEnumerable<StrategicOpportunityGLAdjustment>>(), It.IsAny<IEnumerable<string>>(), It.IsAny<CancellationToken>()), Times.Never);
}
[Test]
public async Task UpdateGLDetails_ReturnsOk_AndCallsService_WhenDtoIsValid()
{
const long opportunityId = 42;
var dto = new UpdateGLDetailsDto
{
Adjustments = new List<StrategicOpportunityGLAdjustment> { new() { NodeKey = "101", GoalAmountValue = 5000m } },
Rows = new List<string> { "system", "entity", "glAccount" }
};
var result = await _controller.UpdateGLDetails(opportunityId, dto, CancellationToken.None);
result.Should().BeOfType<OkResult>();
_mockDetailService.Verify(s => s.UpdateStrategicOpportunityGLDetailsData(
opportunityId, dto.Adjustments, dto.Rows, CancellationToken.None), Times.Once);
}
// --- Route attribute assertions ---
[Test]
public void Controller_HasExpectedRouteTemplate()
{
var routeAttr = typeof(StrategicGeneralLedgerController).GetCustomAttribute<RouteAttribute>();
routeAttr.Should().NotBeNull();
routeAttr.Template.Should().Be("api/v{api-version:apiVersion}/[controller]");
}
[TestCase(nameof(StrategicGeneralLedgerController.GetOpportunityGL), typeof(HttpGetAttribute), "{opportunityId}/[action]")]
[TestCase(nameof(StrategicGeneralLedgerController.CreateOpportunityGeneralLedger), typeof(HttpPostAttribute), null)]
[TestCase(nameof(StrategicGeneralLedgerController.UpdateOpportunityGeneralLedger), typeof(HttpPutAttribute), "{opportunityId}")]
[TestCase(nameof(StrategicGeneralLedgerController.DeleteOpportunityGeneralLedger), typeof(HttpDeleteAttribute), "{opportunityId}")]
[TestCase(nameof(StrategicGeneralLedgerController.GetGLDetail), typeof(HttpPostAttribute), "{opportunityId}/detail")]
[TestCase(nameof(StrategicGeneralLedgerController.GetGLTrackingDetail), typeof(HttpPostAttribute), "{opportunityId}/tracking-detail")]
[TestCase(nameof(StrategicGeneralLedgerController.UpdateGLDetails), typeof(HttpPutAttribute), "{opportunityId}/details")]
public void ActionRoute_HasExpectedHttpMethodAndTemplate(string methodName, Type httpAttrType, string expectedTemplate)
{
var method = typeof(StrategicGeneralLedgerController).GetMethod(methodName);
method.Should().NotBeNull($"method '{methodName}' should exist on {nameof(StrategicGeneralLedgerController)}");
var attr = method.GetCustomAttribute(httpAttrType);
attr.Should().NotBeNull($"{methodName} should be decorated with [{httpAttrType.Name}]");
var template = (string)attr.GetType().GetProperty("Template").GetValue(attr);
template.Should().Be(expectedTemplate);
}
}
}
@@ -0,0 +1,326 @@
using FluentAssertions;
using Microsoft.AspNetCore.Mvc;
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.Controllers;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities;
using Strata.ContinuousImprovement.Biz.StrategicOpportunities.Dtos;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Controllers
{
[ExcludeFromCodeCoverage]
[TestFixture, Category("Unit"), Category("Controller")]
public class StrategicOpportunityControllerTests
{
private StrategicOpportunityController _controller;
private Mock<IStrategicOpportunityService> _mockOpportunityService;
[SetUp]
public void SetUp()
{
_mockOpportunityService = new Mock<IStrategicOpportunityService>();
_controller = new StrategicOpportunityController(_mockOpportunityService.Object);
}
// --- GetGeneralInfo ---
[Test]
public async Task GetGeneralInfo_ReturnsOk_WhenOpportunityExists()
{
const long opportunityId = 1;
var info = new StrategicOpportunityGeneralInfo();
_mockOpportunityService
.Setup(s => s.GetStrategicOpportunityGeneralInfo(opportunityId, It.IsAny<CancellationToken>()))
.ReturnsAsync(info);
var result = await _controller.GetGeneralInfo(opportunityId, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>()
.Which.Value.Should().Be(info);
}
[Test]
public async Task GetGeneralInfo_ReturnsNotFound_WhenOpportunityMissing()
{
_mockOpportunityService
.Setup(s => s.GetStrategicOpportunityGeneralInfo(It.IsAny<long>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((StrategicOpportunityGeneralInfo)null);
var result = await _controller.GetGeneralInfo(99, CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
// --- GetDrawerDetails ---
[Test]
public async Task GetDrawerDetails_ReturnsOk_WhenOpportunityExists()
{
const long opportunityId = 5;
var details = new StrategicOpportunityDrawerDetails();
_mockOpportunityService
.Setup(s => s.GetStrategicOpportunityDrawerDetails(opportunityId, It.IsAny<CancellationToken>()))
.ReturnsAsync(details);
var result = await _controller.GetDrawerDetails(opportunityId, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>()
.Which.Value.Should().Be(details);
}
[Test]
public async Task GetDrawerDetails_ReturnsNotFound_WhenOpportunityMissing()
{
_mockOpportunityService
.Setup(s => s.GetStrategicOpportunityDrawerDetails(It.IsAny<long>(), It.IsAny<CancellationToken>()))
.ReturnsAsync((StrategicOpportunityDrawerDetails)null);
var result = await _controller.GetDrawerDetails(99, CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
// --- Copy ---
[Test]
public async Task Copy_ReturnsOk_WithNewId_WhenSuccessful()
{
const long opportunityId = 10;
const long newId = 42;
_mockOpportunityService
.Setup(s => s.CopyStrategicOpportunity(opportunityId, It.IsAny<string>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(newId);
var result = await _controller.Copy(opportunityId, "Copy of Opp", CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>()
.Which.Value.Should().Be(newId);
}
[Test]
public async Task Copy_ReturnsBadRequest_WhenServiceReturnsZero()
{
_mockOpportunityService
.Setup(s => s.CopyStrategicOpportunity(It.IsAny<long>(), It.IsAny<string>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(0L);
var result = await _controller.Copy(10, "Copy of Opp", CancellationToken.None);
result.Result.Should().BeOfType<BadRequestResult>();
}
// --- SetStatus ---
[Test]
public async Task SetStatus_ReturnsOk_WhenUpdateSucceeds()
{
const long opportunityId = 3;
var dto = new StrategicOpportunityUpdateStatusDto();
_mockOpportunityService
.Setup(s => s.UpdateStrategicOpportunityStatus(opportunityId, dto, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
var result = await _controller.SetStatus(opportunityId, dto, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>();
}
[Test]
public async Task SetStatus_ReturnsNotFound_WhenUpdateFails()
{
_mockOpportunityService
.Setup(s => s.UpdateStrategicOpportunityStatus(It.IsAny<long>(), It.IsAny<StrategicOpportunityUpdateStatusDto>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
var result = await _controller.SetStatus(99, new StrategicOpportunityUpdateStatusDto(), CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
// --- UpdateLayout ---
[Test]
public async Task UpdateLayout_ReturnsOk_WhenUpdateSucceeds()
{
const long opportunityId = 7;
var layout = new StrategicOpportunityLayout();
_mockOpportunityService
.Setup(s => s.UpdateStrategicOpportunityLayout(opportunityId, layout, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
var result = await _controller.UpdateLayout(opportunityId, layout, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>();
}
[Test]
public async Task UpdateLayout_ReturnsNotFound_WhenUpdateFails()
{
_mockOpportunityService
.Setup(s => s.UpdateStrategicOpportunityLayout(It.IsAny<long>(), It.IsAny<StrategicOpportunityLayout>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
var result = await _controller.UpdateLayout(99, new StrategicOpportunityLayout(), CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
// --- UpdateRoles ---
[Test]
public async Task UpdateRoles_ReturnsOk_WhenUpdateSucceeds()
{
const long opportunityId = 4;
var dto = new StrategicRolesUpdate();
_mockOpportunityService
.Setup(s => s.UpdateRoles(opportunityId, dto, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
var result = await _controller.UpdateRoles(opportunityId, dto, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>();
}
[Test]
public async Task UpdateRoles_ReturnsNotFound_WhenUpdateFails()
{
_mockOpportunityService
.Setup(s => s.UpdateRoles(It.IsAny<long>(), It.IsAny<StrategicRolesUpdate>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
var result = await _controller.UpdateRoles(99, new StrategicRolesUpdate(), CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
// --- RunTrackingTask ---
[Test]
public async Task RunTrackingTask_ReturnsOk_WhenSuccessful()
{
const long opportunityId = 8;
_mockOpportunityService
.Setup(s => s.RunTrackingTask(opportunityId, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
var result = await _controller.RunTrackingTask(opportunityId, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>();
}
[Test]
public async Task RunTrackingTask_ReturnsNotFound_WhenOpportunityMissing()
{
_mockOpportunityService
.Setup(s => s.RunTrackingTask(It.IsAny<long>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
var result = await _controller.RunTrackingTask(99, CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
// --- GetMeasures ---
[Test]
public async Task GetMeasures_ReturnsOk_WhenMeasuresExist()
{
const long opportunityId = 2;
var measures = new List<StrategicOpportunityMeasureDto> { new() };
_mockOpportunityService
.Setup(s => s.GetStrategicOpportunityMeasures(opportunityId, It.IsAny<CancellationToken>()))
.ReturnsAsync(measures);
var result = await _controller.GetMeasures(opportunityId, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>()
.Which.Value.Should().Be(measures);
}
[Test]
public async Task GetMeasures_ReturnsNotFound_WhenNoMeasures()
{
_mockOpportunityService
.Setup(s => s.GetStrategicOpportunityMeasures(It.IsAny<long>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(new List<StrategicOpportunityMeasureDto>());
var result = await _controller.GetMeasures(99, CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
// --- CompleteInitiative ---
[Test]
public async Task CompleteInitiative_ReturnsOk_WhenSuccessful()
{
const long opportunityId = 6;
var data = new StrategicOpportunityCompleteInitiativeData();
_mockOpportunityService
.Setup(s => s.CompleteInitiative(opportunityId, data, It.IsAny<CancellationToken>()))
.ReturnsAsync(true);
var result = await _controller.CompleteInitiative(opportunityId, data, CancellationToken.None);
result.Result.Should().BeOfType<OkObjectResult>();
}
[Test]
public async Task CompleteInitiative_ReturnsNotFound_WhenOpportunityMissing()
{
_mockOpportunityService
.Setup(s => s.CompleteInitiative(It.IsAny<long>(), It.IsAny<StrategicOpportunityCompleteInitiativeData>(), It.IsAny<CancellationToken>()))
.ReturnsAsync(false);
var result = await _controller.CompleteInitiative(99, new StrategicOpportunityCompleteInitiativeData(), CancellationToken.None);
result.Result.Should().BeOfType<NotFoundResult>();
}
// --- Route attribute assertions ---
[Test]
public void Controller_HasExpectedRouteTemplate()
{
var routeAttr = typeof(StrategicOpportunityController).GetCustomAttribute<RouteAttribute>();
routeAttr.Should().NotBeNull();
routeAttr.Template.Should().Be("api/v{api-version:apiVersion}/[controller]");
}
[TestCase(nameof(StrategicOpportunityController.GetOpportunities), typeof(HttpGetAttribute), "")]
[TestCase(nameof(StrategicOpportunityController.GetGeneralInfo), typeof(HttpGetAttribute), "{opportunityId}/[action]")]
[TestCase(nameof(StrategicOpportunityController.IsNameValid), typeof(HttpPostAttribute), "[action]")]
[TestCase(nameof(StrategicOpportunityController.GetLayout), typeof(HttpGetAttribute), "{opportunityId}/[action]")]
[TestCase(nameof(StrategicOpportunityController.UpdateLayout), typeof(HttpPutAttribute), "{opportunityId}/[action]")]
[TestCase(nameof(StrategicOpportunityController.SetStatus), typeof(HttpPutAttribute), "{opportunityId}/[action]")]
[TestCase(nameof(StrategicOpportunityController.GetInitiatives), typeof(HttpGetAttribute), "[action]")]
[TestCase(nameof(StrategicOpportunityController.UpdateInitiative), typeof(HttpPutAttribute), "{opportunityId}/[action]")]
[TestCase(nameof(StrategicOpportunityController.UpdateRoles), typeof(HttpPutAttribute), "{opportunityId}/[action]")]
[TestCase(nameof(StrategicOpportunityController.UpdateRampUps), typeof(HttpPutAttribute), "{opportunityId}/ramp-ups")]
[TestCase(nameof(StrategicOpportunityController.GetRampUps), typeof(HttpGetAttribute), "{opportunityId}/[action]")]
[TestCase(nameof(StrategicOpportunityController.RunTrackingTask), typeof(HttpGetAttribute), "{opportunityId}/[action]")]
[TestCase(nameof(StrategicOpportunityController.CompleteInitiative), typeof(HttpPutAttribute), "{opportunityId}/[action]")]
[TestCase(nameof(StrategicOpportunityController.GetMeasures), typeof(HttpGetAttribute), "{opportunityId}/[action]")]
[TestCase(nameof(StrategicOpportunityController.GetPrimaryMeasure), typeof(HttpGetAttribute), "{opportunityId}/[action]")]
[TestCase(nameof(StrategicOpportunityController.GetMeasureDetails), typeof(HttpGetAttribute), "{measureId}/[action]")]
[TestCase(nameof(StrategicOpportunityController.GetDrawerDetails), typeof(HttpGetAttribute), "{opportunityId}")]
[TestCase(nameof(StrategicOpportunityController.Copy), typeof(HttpPostAttribute), "{opportunityId}/copy")]
public void ActionRoute_HasExpectedHttpMethodAndTemplate(string methodName, Type httpAttrType, string expectedTemplate)
{
var method = typeof(StrategicOpportunityController).GetMethod(methodName);
method.Should().NotBeNull($"method '{methodName}' should exist on {nameof(StrategicOpportunityController)}");
var attr = method.GetCustomAttribute(httpAttrType);
attr.Should().NotBeNull($"{methodName} should be decorated with [{httpAttrType.Name}]");
var template = (string)attr.GetType().GetProperty("Template").GetValue(attr);
template.Should().Be(expectedTemplate);
}
}
}
@@ -0,0 +1,20 @@
using Riok.Mapperly.Abstractions;
using Strata.ContinuousImprovement.Biz.Dtos;
using Strata.ContinuousImprovement.Biz.Network;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Generics
{
[Mapper(UseDeepCloning = true, EnumMappingStrategy = EnumMappingStrategy.ByName, EnumMappingIgnoreCase = true)]
public static partial class ClientNetworkOpportunityMapper
{
public static ClientNetworkOpportunityDto MapToDto(this ClientNetworkOpportunity src)
{
var mapped = src.Mapped();
return mapped;
}
private static partial ClientNetworkOpportunityDto Mapped(this ClientNetworkOpportunity src);
}
}
@@ -0,0 +1,13 @@
using Riok.Mapperly.Abstractions;
using Strata.ContinuousImprovement.Biz.OpportunityComments;
using static Strata.ContinuousImprovement.Api.Controllers.CommentsController;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Api.Generics
{
[Mapper(UseDeepCloning = true, EnumMappingStrategy = EnumMappingStrategy.ByName, EnumMappingIgnoreCase = true)]
public static partial class CommentMapper
{
public static partial Comment Map(this NewComment src);
}
}
@@ -0,0 +1,24 @@
using Hangfire;
using Hangfire.Common;
using Hangfire.States;
using System;
using System.Collections.Generic;
namespace Strata.ContinuousImprovement.Api.Test.Unit.Generics
{
public class FakeBackgroundJobClient : IBackgroundJobClient
{
public Queue<Job> Jobs { get; } = new Queue<Job>();
public string Create(Job job, IState state)
{
Jobs.Enqueue(job);
return Jobs.Count.ToString();
}
public bool ChangeState(string jobId, IState state, string expectedState)
{
throw new NotImplementedException();
}
}
}
@@ -0,0 +1,76 @@
using Moq;
using NUnit.Framework;
using Strata.ContinuousImprovement.Api.SnowflakeControllers;
using Strata.DecisionSupport.Biz.Mapperly;
using Strata.DecisionSupport.Biz.Services;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using VerifyNUnit;
using VerifyTests;
using Encounters = Strata.DecisionSupport.Biz.Encounters;
using Parameters = Strata.DecisionSupport.Biz.Parameters;
namespace Strata.ContinuousImprovement.Api.Test.Unit.SnowflakeControllers
{
[ExcludeFromCodeCoverage]
[TestFixture, Category("Unit"), Category("Controller")]
public class UtilizationVariationControllerTest
{
public VerifySettings verifySettings;
private UtilizationVariationController controller;
[SetUp]
public void SetUp()
{
var charges = new List<Encounters.ChargeInfo> {
new Encounters.ChargeInfo()
};
var jazzCharges = charges.Select(c => JazzEncounterInfoMapper.MapToJazz(c));
var service = Mock.Of<UtilizationVariationService>();
controller = new UtilizationVariationController(service);
verifySettings = TestExtensions.TestSettings();
}
[Test]
public async Task TestController()
{
var controllerExists = controller != null;
await Verifier.Verify(controllerExists, verifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
[TestCaseSource(nameof(GetChargeInfoTestCases))]
public async Task TestGetChargeInfo(Guid opportunityGuid, IEnumerable<int> chargeCodeIds)
{
var queryInfo = new Parameters.ChargeQueryInfo(Guid.NewGuid(), 10, chargeCodeIds.ToList(), opportunityGuid);
var response = await controller.GetChargeInfoAsync(queryInfo, CancellationToken.None);
await Verifier.Verify(response, verifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
[TestCaseSource(nameof(GetChargeInfoTestCases))]
public async Task TestGetAllChargeInfo(Guid opportunityGuid, IEnumerable<int> chargeCodeIds)
{
var queryInfo = new Parameters.AllChargeQueryInfo(opportunityGuid, chargeCodeIds.ToList());
var response = await controller.GetAllChargeInfoAsync(queryInfo, CancellationToken.None);
await Verifier.Verify(response, verifySettings)
.UseFileName(TestContext.CurrentContext.TestName());
}
public static IEnumerable<TestCaseData> GetChargeInfoTestCases()
{
yield return new TestCaseData(Guid.Empty, Enumerable.Empty<int>())
.SetName("{m} Empty OpportunityGuid");
yield return new TestCaseData(Guid.Empty, new[] { 1 })
.SetName("{m} with ChargeCodes");
yield return new TestCaseData(Guid.NewGuid(), new[] { 1 })
.SetName("{m} with Opportunity and ChargeCodes");
}
}
}
@@ -0,0 +1,78 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Configuration\**" />
<Compile Remove="Resource\Examples\AllOpportunity\**" />
<Compile Remove="Utilities\**" />
<EmbeddedResource Remove="Configuration\**" />
<EmbeddedResource Remove="Resource\Examples\AllOpportunity\**" />
<EmbeddedResource Remove="Utilities\**" />
<None Remove="Configuration\**" />
<None Remove="Resource\Examples\AllOpportunity\**" />
<None Remove="Utilities\**" />
</ItemGroup>
<ItemGroup>
<Compile Remove="Biz\All\OpportunityType.cs" />
<Compile Remove="Biz\Generics\ConfigurationServiceTest.cs" />
<Compile Remove="Biz\Generics\DbSetExtensions.cs" />
<Compile Remove="Biz\Generics\VariationOpportunityServiceTest.cs" />
<Compile Remove="Biz\SlugifyParameterTransformerTest.cs" />
<Compile Remove="Biz\StaffingToDemand\Opportunities\StaffingToDemandOpportunityServiceTest.cs" />
<Compile Remove="Biz\UtilizationVariation\Opportunities\VariationOpportunityFilter.cs" />
<Compile Remove="Generics\OpportunityTypeExtensions.cs" />
</ItemGroup>
<ItemGroup>
<None Remove="Resource\Examples\ExcelFilter.xlsx" />
<None Remove="Resource\PRExcelFilter.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" />
</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.Biz.Test.Unit\Strata.ContinuousImprovement.Biz.Test.Unit.csproj" />
<ProjectReference Include="..\Strata.ContinuousImprovement.Biz.Test.Unit\Strata.ContinuousImprovement.Biz.Test.Unit.csproj" />
</ItemGroup>
<ItemGroup>
<Folder Include="Resource\Examples\AllOpportunity\" />
<Folder Include="Resource\Examples\EncounterOpportunity\" />
<Folder Include="Resource\Examples\FreeFormOpportunity\" />
<Folder Include="Resource\Examples\GeneralLedgerOpportunity\" />
<Folder Include="Resource\Examples\PayrollOpportunity\" />
<Folder Include="Resource\Examples\QualityVariationItemOpportunity\" />
<Folder Include="Resource\Examples\StaffingToDemandOpportunity\" />
<Folder Include="Resource\Examples\VariationOpportunity\" />
<Folder Include="SnowflakeControllers\snapshots\" />
</ItemGroup>
</Project>
@@ -0,0 +1,47 @@
using NUnit.Framework;
using System;
using System.Text.RegularExpressions;
using VerifyTests;
namespace Strata.ContinuousImprovement.Api.Test.Unit
{
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)
{
var testName = context.Test.Name.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,5 @@
{
"configProperties": {
"System.Drawing.EnableUnixSupport": true
}
}