using FluentAssertions; using Moq; using NUnit.Framework; using Strata.Authorization; using Strata.ContinuousImprovement.Biz.DbContexts; using Strata.ContinuousImprovement.Biz.Filter; using Strata.ContinuousImprovement.Biz.GeneralLedger.Details; using Strata.ContinuousImprovement.Biz.GeneralLedger.Opportunities; using Strata.ContinuousImprovement.Biz.GeneralLedger.Opportunities.Filters; using Strata.ContinuousImprovement.Biz.Generics; using Strata.ContinuousImprovement.Biz.Initiatives; using Strata.ContinuousImprovement.Biz.Pagination; using Strata.ContinuousImprovement.Biz.Test.Unit.Utilities; using Strata.ContinuousImprovement.JazzEntityFrameworkStub; using Strata.Hangfire.Jazz.Client; using Strata.SqlTools.Configuration.Common.AsyncFactory; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace Strata.ContinuousImprovement.Biz.Test.Unit.GeneralLedger.Opportunities { [TestFixture, Category("Unit")] public class GLOpportunityServiceTests { private Mock _glOpportunityServiceMock; private Mock> _dbContextFactoryMock; private Mock _jazzDbContextMock; private Mock _hangfireServiceMock; private Mock _authorizationServiceMock; private IUpdateFactOpportunitySavingsService _updateFactOpportunitySavingsService; private IInitiativeService _initiativeService; private static readonly ResourceFileExtractor _extractor = new ResourceFileExtractor(".Resource."); [SetUp] public void TestSetUp() { _glOpportunityServiceMock = new Mock(); _dbContextFactoryMock = new Mock>(); _jazzDbContextMock = new Mock(); _hangfireServiceMock = new Mock(); _updateFactOpportunitySavingsService = Mock.Of(); _initiativeService = Mock.Of(); Mock.Get(_updateFactOpportunitySavingsService) .Setup(s => s.UpdateFactOpportunitySavings(It.IsAny())); Mock.Get(_initiativeService) .Setup(s => s.DeleteAsync(It.IsAny(), It.IsAny())) .Returns(Task.FromResult(true)); _authorizationServiceMock = new Mock(); _authorizationServiceMock .Setup(o => o.AddPermissionsFromDefaultsAsync(It.IsAny(), It.IsAny(), It.IsAny())); } [Test, Ignore("new filtering broke these tests")] public async Task TestFirstPage_Sorted_Asc() { // arrange var framework = new JazzEntityFrameworkFactory(); await framework.CreateDbContextAsync(CancellationToken.None); var glOpportunityService = new GLOpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); var filters = new GLFilters() { Types = new List(), Levels = new List(), IdentifiedSavings = 0, ViewVisible = true, ExcludeInitiatives = false, OpportunitySearch = "", Seasonality = SeasonalityType.WithAndWithout, ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid }; var pagingOptions = new PagingOptions("IdentifiedSavings", SortOrder.Asc); // act var taskResult = await glOpportunityService .GetPagedAsync(pagingOptions, filters, CancellationToken.None); // assert taskResult.Data.Should().NotBeNullOrEmpty() .And.AllBeOfType() .And.HaveCountGreaterThan(1); taskResult.Data.First().IdentifiedSavings .Should().BeLessThan(taskResult.Data.Last().IdentifiedSavings); } [Test, Ignore("new filtering broke these tests")] public async Task TestFirstPage_Sorted_Desc() { // arrange var framework = new JazzEntityFrameworkFactory(); await framework.CreateDbContextAsync(CancellationToken.None); var glOpportunityService = new GLOpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); var filters = new GLFilters() { Types = new List(), Levels = new List(), IdentifiedSavings = 0, ViewVisible = true, ExcludeInitiatives = false, OpportunitySearch = "", ConfigurationGuid = JazzEntityFrameworkFactory.CurrentConfigurationGuid }; var pagingOptions = new PagingOptions("IdentifiedSavings", SortOrder.Desc); // act var taskResult = await glOpportunityService .GetPagedAsync(pagingOptions, filters, CancellationToken.None); // assert taskResult.Data.Should().NotBeNullOrEmpty() .And.AllBeOfType() .And.HaveCountGreaterThan(1); taskResult.Data.First().IdentifiedSavings .Should().BeGreaterThan(taskResult.Data.Last().IdentifiedSavings); } [TestCaseSource(nameof(GetFilterData))] public void TestValidateFilters(GLFilters filters) { if (filters == null) return; if (filters.Types.Any()) filters.Types.Should() .AllBeOfType() .And.NotBeNullOrEmpty(); if (filters.Levels.Any()) filters.Levels.Should() .AllBeOfType() .And.NotBeNullOrEmpty(); } [Test, Ignore("new filtering broke these tests")] public async Task TestGetExcelWorkbook() { // arrange var framework = new JazzEntityFrameworkFactory(); await framework.CreateDbContextAsync(CancellationToken.None); var opp = framework.GLOpportunities.First(); var filters = new GLFilters() { ConfigurationGuid = framework.Configurations.First().ConfigurationGuid, Types = new[] { opp.Type }, Levels = new[] { opp.Level } }; var service = new GLOpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); // act var wb = await service.ExportAsync(new SortOptions(), filters, CancellationToken.None); #pragma warning disable S125 // Sections of code should not be commented out //wb.SaveAs(System.IO.Path.Combine(@"C:\git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "ExcelFilter.xlsx")); #pragma warning restore S125 // Sections of code should not be commented out // assert wb.Worksheets.Should().HaveCount(1); var ws = wb.Worksheet(1); ws.Should().NotBeNull(); var expected = @"Examples.GeneralLedgerOpportunity.ExcelFilter.xlsx"; using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected)) using (var actualStream = new MemoryStream()) { wb.SaveAs(actualStream); actualStream.Compare(expectedStream, out var message).Should().BeTrue(message); } } [Test] public async Task TestGetExcelWorkbookNullFilter() { // arrange var framework = new JazzEntityFrameworkFactory(); await framework.CreateDbContextAsync(CancellationToken.None); var service = new GLOpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); // act var wb = await service.ExportAsync(null, null, CancellationToken.None); #pragma warning disable S125 // Sections of code should not be commented out //wb.SaveAs(System.IO.Path.Combine(@"C:\git\continuousimprovement\tests\Strata.ContinuousImprovement.Biz.Test.Unit\Resource", "ExcelNullFilter.xlsx")); #pragma warning restore S125 // Sections of code should not be commented out // assert wb.Worksheets.Should().HaveCount(1); var ws = wb.Worksheet(1); ws.Should().NotBeNull(); var expected = @"Examples.GeneralLedgerOpportunity.ExcelNullFilter.xlsx"; using (var expectedStream = _extractor.ReadFileFromResourceToStream(expected)) using (var actualStream = new MemoryStream()) { wb.SaveAs(actualStream); actualStream.Compare(expectedStream, out var message).Should().BeTrue(message); } } [Test] public async Task TestSetHidden() { // arrange var framework = new JazzEntityFrameworkFactory(); await framework.CreateDbContextAsync(CancellationToken.None); var opportunities = framework.GLOpportunities; var opportunity = opportunities.First(vo => !vo.IsHidden); var isHidden = opportunity.IsHidden; var service = new GLOpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); // act await service.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden, CancellationToken.None); // assert var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None); result.IsHidden.Should().Be(!isHidden); } [TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))] public async Task TestGetFilterOptionsAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken) { // arrange var opportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); try { // act var taskResult = await opportunityService .GetFilterOptionsAsync(new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), cancellationToken); // assert if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) { taskResult.Should().BeNull(); return; } taskResult.Should() .BeOfType() .And.NotBeNull(); taskResult.Types.Should().AllBeOfType().And.NotBeNullOrEmpty() .And.NotContain(t => string.IsNullOrEmpty(t.Id)) .And.NotContain(t => string.IsNullOrEmpty(t.Text)); taskResult.Levels.Should().AllBeOfType().And.NotBeNullOrEmpty() .And.NotContain(l => string.IsNullOrEmpty(l.Id)) .And.NotContain(l => string.IsNullOrEmpty(l.Text)); } catch (NotImplementedException nie) { nie.Should().BeOfType(); } catch (Exception e) { e.Should().BeOfType(); } } [TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))] public async Task TestSetHiddenAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken) { // arrange var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); try { var opportunities = glOpportunityService.GetAllAsync(cancellationToken).Result; var opportunity = opportunities.FirstOrDefault(o => o.IsHidden); if (opportunity == null) return; var isHidden = opportunity.IsHidden; //act await glOpportunityService.SetHiddenAsync(opportunity.OpportunityGuid, !isHidden, cancellationToken); if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return; var result = glOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result; result.IsHidden.Should().Be(!isHidden); } catch (Exception e) { switch (e.GetType().Name) { case "AggregateException": case "OperationCanceledException": return; } e.Should().NotBeOfType(); } } [TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))] public async Task TestSetHiddenAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken) { // arrange var opportunity = jazzEntityFrameworkFactory.GLOpportunities.FirstOrDefault(o => o.IsHidden); if (opportunity == null) return; var isHidden = opportunity.IsHidden; var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); try { // act await glOpportunityService.SetHiddenAsync(Guid.Empty, !isHidden, cancellationToken); } catch (Exception e) { e.Should().BeOfType(); } } [TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))] public async Task TestSetNoteAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken) { // arrange var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); try { var opportunities = glOpportunityService.GetAllAsync(cancellationToken).Result; var opportunity = opportunities.FirstOrDefault(o => o.Note == string.Empty); if (opportunity == null) return; var note = "new test note"; // act await glOpportunityService.SetNoteAsync(opportunity.OpportunityGuid, note, CancellationToken.None); if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) return; var result = glOpportunityService.GetById(opportunity.OpportunityGuid, cancellationToken).Result; result.Note.Should().Be(note); // assert } catch (Exception e) { switch (e.GetType().Name) { case "AggregateException": case "OperationCanceledException": return; } e.Should().NotBeOfType(); } } [Test] public async Task TestSetNote() { // arrange var framework = new JazzEntityFrameworkFactory(); await framework.CreateDbContextAsync(CancellationToken.None); var opportunities = framework.GLOpportunities; var opportunity = opportunities.First(vo => string.IsNullOrEmpty(vo.Note)); var note = opportunity.Note; var expected = "Now is the time for all good engineers to write great code!"; var service = new GLOpportunityService(framework, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); // act await service.SetNoteAsync(opportunity.OpportunityGuid, expected, CancellationToken.None); // assert var result = await service.GetById(opportunity.OpportunityGuid, CancellationToken.None); result.Note.Should().NotBeNullOrEmpty() .And.NotBe(note) .And.Be(expected); } [TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworksWithCancellation))] public async Task TestSetNoteAsync_NoOpportunity(JazzEntityFrameworkFactory jazzEntityFrameworkFactory, CancellationToken cancellationToken) { // arrange var opportunity = jazzEntityFrameworkFactory.GLOpportunities.FirstOrDefault(o => o.Note == string.Empty); if (opportunity == null) return; var note = "new test note"; var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); try { // act await glOpportunityService.SetNoteAsync(Guid.Empty, note, cancellationToken); // assert } catch (Exception e) { e.Should().BeOfType(); } } [TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))] public async Task TestGetAllAsync(JazzEntityFrameworkFactory jazzEntityFrameworkFactory) { // arrange var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); // act var taskResult = await glOpportunityService.GetAllAsync(CancellationToken.None); // assert if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) { taskResult.Should().BeNullOrEmpty(); } else { taskResult.Should().NotBeNullOrEmpty(); } } [TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))] public async Task TestGetById(JazzEntityFrameworkFactory jazzEntityFrameworkFactory) { // arrange var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); // act var tempResult = await glOpportunityService.GetAllAsync(CancellationToken.None); var taskResult = await glOpportunityService.GetById(tempResult.FirstOrDefault()?.OpportunityGuid ?? Guid.Empty, CancellationToken.None); // assert if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) { taskResult.Should().BeNull(); } else { taskResult.Should().NotBeNull() .And.BeOfType(); } } [TestCaseSource(typeof(JazzEntityFrameworkFactory), nameof(JazzEntityFrameworkFactory.GetFrameworks))] public async Task TestGetByIds(JazzEntityFrameworkFactory jazzEntityFrameworkFactory) { // arrange var glOpportunityService = new GLOpportunityService(jazzEntityFrameworkFactory, null, null, _hangfireServiceMock.Object, _authorizationServiceMock.Object, _initiativeService, _updateFactOpportunitySavingsService); // act var tempResult = await glOpportunityService.GetAllAsync(CancellationToken.None); var ids = tempResult.Select(o => o.OpportunityGuid); var taskResult = await glOpportunityService.GetByIds(ids, CancellationToken.None); // assert if (string.IsNullOrEmpty(jazzEntityFrameworkFactory.TestName)) { taskResult.Should().BeNullOrEmpty(); } else { taskResult.Should().NotBeNullOrEmpty() .And.AllBeOfType(); } } [TearDown] public void TestTearDown() { // Method intentionally left empty. } #region TestCaseData public static IEnumerable GetFilterData() { yield return new TestCaseData(new GLFilters { ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("No Filters"); yield return new TestCaseData(new GLFilters { ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("View Visible"); yield return new TestCaseData(new GLFilters { ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Not View Visible"); yield return new TestCaseData(new GLFilters { IdentifiedSavings = 1999, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName( "By Identified Savings"); yield return new TestCaseData(new GLFilters { IdentifiedSavings = 999, ViewVisible = false, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName( "By Identified Savings Not ViewVisible"); yield return new TestCaseData(new GLFilters { Levels = new[] { "Overall" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }) .SetName("By Level"); yield return new TestCaseData(new GLFilters { Levels = new[] { "Department" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), ViewVisible = false }) .SetName("By Level Not ViewVisible"); yield return new TestCaseData(new GLFilters { Types = new[] { "Revenue" }, ViewVisible = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }) .SetName("By Type"); yield return new TestCaseData(new GLFilters { Types = new[] { "Expense" }, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345"), ViewVisible = false }) .SetName("By Type Not ViewVisible"); yield return new TestCaseData(new GLFilters { OpportunitySearch = "GL - 101", ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Search By Id"); yield return new TestCaseData(new GLFilters { ExcludeInitiatives = true, ConfigurationGuid = new Guid("e96abe3e-1526-43ca-815e-ee30c5b34345") }).SetName("Exclude Opportunities with Initiatives"); } #endregion } }