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(); var controller = new AllOpportunitiesController(service, claimsPrincipalAccessor, featureFlagServiceClient, Mock.Of>()); 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 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(), Mock.Of>()); 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(), Mock.Of>()); var filterOptions = new AllFilterOptions { OpportunityTypes = Enum.GetValues() .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(), Mock.Of>()); 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(), Mock.Of>()); var export = await controller.Export(new AllOpportunityExportOptions { SortOptions = new SortOptions(), Filters = new AllFilters() }, CancellationToken.None); Assert.That(export, Is.AssignableFrom()); 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> GetPagedApiResponse(bool withExplorationOpportunities = true) { var jeff = new JazzEntityFrameworkFactory(); var dbContext = await jeff.CreateDbContextAsync(nameof(AllOpportunityControllerTests), CancellationToken.None); var result = new PagedApiResponse { 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 GetAllOpportunityService(PagedApiResponse pagedApiResponse = null) { var jeff = new JazzEntityFrameworkFactory(); var dbContext = await jeff.CreateDbContextAsync(nameof(AllOpportunityControllerTests), CancellationToken.None); var service = Mock.Of(); Mock.Get(service) .Setup(s => s.GetPagedAsync(It.IsAny(), It.IsAny>(), It.IsAny())) .Returns(Task.FromResult(pagedApiResponse ?? await GetPagedApiResponse())); Mock.Get(service) .Setup(s => s.NameIsValid(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) .Returns((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() .Select(ot => new FilterMember { Id = $"{(int)ot}", Text = ot.OpportunityTypeName() }) }; Mock.Get(service) .Setup(s => s.GetFilterOptionsAsync(It.IsAny(), It.IsAny())) .Returns((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(), It.IsAny(), It.IsAny())) .Returns(Task.FromResult(xlWorkbook)); Mock.Get(service) .Setup(s => s.SetHiddenAsync(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(Task.CompletedTask); Mock.Get(service) .Setup(s => s.SetNoteAsync(It.IsAny(), It.IsAny(), It.IsAny())) .Returns(Task.CompletedTask); Mock.Get(service) .Setup(s => s.GetById(It.IsAny(), It.IsAny())) .Returns((oppGuid, token) => Task.FromResult(dbContext.AllOpportunities.FirstOrDefault(opp => opp.OpportunityGuid == oppGuid))); return service; } } }