Index: Ringtoets/Integration/test/Ringtoets.Integration.Plugin.Test/TreeNodeInfos/DesignWaterLevelCalculationsGroupContextTreeNodeInfoTest.cs =================================================================== diff -u -ra6c8ce99232f4695f07c75d8bee5a7a101be46b3 -r5bb5f922652f2a8cc9a31c94ae2e891ffde02b6c --- Ringtoets/Integration/test/Ringtoets.Integration.Plugin.Test/TreeNodeInfos/DesignWaterLevelCalculationsGroupContextTreeNodeInfoTest.cs (.../DesignWaterLevelCalculationsGroupContextTreeNodeInfoTest.cs) (revision a6c8ce99232f4695f07c75d8bee5a7a101be46b3) +++ Ringtoets/Integration/test/Ringtoets.Integration.Plugin.Test/TreeNodeInfos/DesignWaterLevelCalculationsGroupContextTreeNodeInfoTest.cs (.../DesignWaterLevelCalculationsGroupContextTreeNodeInfoTest.cs) (revision 5bb5f922652f2a8cc9a31c94ae2e891ffde02b6c) @@ -19,28 +19,43 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. +using System; +using System.Collections.Generic; using System.Drawing; +using System.IO; using System.Linq; +using System.Threading; +using System.Windows.Forms; using Core.Common.Base; using Core.Common.Controls.TreeView; using Core.Common.Gui; using Core.Common.Gui.ContextMenu; +using Core.Common.Gui.Forms.MainWindow; +using Core.Common.Gui.Forms.ViewHost; +using Core.Common.Gui.TestUtil.ContextMenu; using Core.Common.TestUtil; +using Core.Common.Util; using NUnit.Extensions.Forms; using NUnit.Framework; using Rhino.Mocks; using Ringtoets.Common.Data.AssessmentSection; using Ringtoets.Common.Data.Hydraulics; using Ringtoets.Common.Data.TestUtil; using Ringtoets.Common.Forms.PresentationObjects; -using Ringtoets.Integration.Forms.PresentationObjects; +using Ringtoets.Common.Service.TestUtil; +using Ringtoets.HydraRing.Calculation.Calculator.Factory; +using Ringtoets.HydraRing.Calculation.Data.Input; +using Ringtoets.HydraRing.Calculation.TestUtil.Calculator; using RingtoetsCommonFormsResources = Ringtoets.Common.Forms.Properties.Resources; namespace Ringtoets.Integration.Plugin.Test.TreeNodeInfos { [TestFixture] public class DesignWaterLevelCalculationsGroupContextTreeNodeInfoTest : NUnitFormTest { + private const int contextMenuRunDesignWaterLevelCalculationsIndex = 0; + private readonly string testDataPath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Integration.Service, "HydraRingCalculation"); + [Test] public void Initialized_Always_ExpectedPropertiesSet() { @@ -108,11 +123,13 @@ { // Setup var mockRepository = new MockRepository(); - var assessmentSection = mockRepository.StrictMock(); + IAssessmentSection assessmentSection = AssessmentSectionHelper.CreateAssessmentSectionStub(mockRepository); var menuBuilder = mockRepository.StrictMock(); using (mockRepository.Ordered()) { + menuBuilder.Expect(mb => mb.AddCustomItem(null)).IgnoreArguments().Return(menuBuilder); + menuBuilder.Expect(mb => mb.AddSeparator()).Return(menuBuilder); menuBuilder.Expect(mb => mb.AddCollapseAllItem()).Return(menuBuilder); menuBuilder.Expect(mb => mb.AddExpandAllItem()).Return(menuBuilder); menuBuilder.Expect(mb => mb.Build()).Return(null); @@ -145,6 +162,310 @@ } [Test] + public void ContextMenuStrip_HydraulicBoundaryDatabaseNotLinked_ContextMenuItemCalculateAllDisabledAndTooltipSet() + { + // Setup + var mockRepository = new MockRepository(); + IAssessmentSection assessmentSection = AssessmentSectionHelper.CreateAssessmentSectionStub(mockRepository); + + var nodeData = new DesignWaterLevelCalculationsGroupContext(new ObservableList(), + assessmentSection); + + using (var treeViewControl = new TreeViewControl()) + { + var gui = mockRepository.Stub(); + gui.Stub(g => g.ProjectOpened += null).IgnoreArguments(); + gui.Stub(g => g.ProjectOpened -= null).IgnoreArguments(); + gui.Stub(cmp => cmp.Get(nodeData, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + mockRepository.ReplayAll(); + + using (var plugin = new RingtoetsPlugin()) + { + TreeNodeInfo info = GetInfo(plugin); + + plugin.Gui = gui; + + // Call + using (ContextMenuStrip contextMenu = info.ContextMenuStrip(nodeData, null, treeViewControl)) + { + // Assert + ToolStripItem contextMenuItem = contextMenu.Items[contextMenuRunDesignWaterLevelCalculationsIndex]; + + Assert.AreEqual("Alles be&rekenen", contextMenuItem.Text); + StringAssert.Contains("Er is geen hydraulische randvoorwaardendatabase geïmporteerd.", contextMenuItem.ToolTipText); + TestHelper.AssertImagesAreEqual(RingtoetsCommonFormsResources.CalculateAllIcon, contextMenuItem.Image); + Assert.IsFalse(contextMenuItem.Enabled); + } + } + } + + mockRepository.VerifyAll(); // Expect no calls on arguments + } + + [Test] + public void ContextMenuStrip_HydraulicBoundaryDatabaseLinkedToInvalidFile_ContextMenuItemCalculateAllDisabledAndTooltipSet() + { + // Setup + var mockRepository = new MockRepository(); + IAssessmentSection assessmentSection = AssessmentSectionHelper.CreateAssessmentSectionStub(null, mockRepository, "invalidFilePath"); + + var nodeData = new DesignWaterLevelCalculationsGroupContext(new ObservableList(), + assessmentSection); + + using (var treeViewControl = new TreeViewControl()) + { + var gui = mockRepository.Stub(); + gui.Stub(g => g.ProjectOpened += null).IgnoreArguments(); + gui.Stub(g => g.ProjectOpened -= null).IgnoreArguments(); + gui.Stub(cmp => cmp.Get(nodeData, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + mockRepository.ReplayAll(); + + using (var plugin = new RingtoetsPlugin()) + { + TreeNodeInfo info = GetInfo(plugin); + + plugin.Gui = gui; + + // Call + using (ContextMenuStrip contextMenu = info.ContextMenuStrip(nodeData, null, treeViewControl)) + { + // Assert + ToolStripItem contextMenuItem = contextMenu.Items[contextMenuRunDesignWaterLevelCalculationsIndex]; + + Assert.AreEqual("Alles be&rekenen", contextMenuItem.Text); + StringAssert.Contains("Herstellen van de verbinding met de hydraulische randvoorwaardendatabase is mislukt.", contextMenuItem.ToolTipText); + TestHelper.AssertImagesAreEqual(RingtoetsCommonFormsResources.CalculateAllIcon, contextMenuItem.Image); + Assert.IsFalse(contextMenuItem.Enabled); + } + } + } + + mockRepository.VerifyAll(); // Expect no calls on arguments + } + + [Test] + public void ContextMenuStrip_AllRequiredInputSet_ContextMenuItemCalculateAllEnabled() + { + // Setup + var mockRepository = new MockRepository(); + var assessmentSection = mockRepository.Stub(); + assessmentSection.Stub(a => a.HydraulicBoundaryDatabase).Return(new HydraulicBoundaryDatabase + { + FilePath = Path.Combine(TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, "HydraulicBoundaryDatabaseImporter"), "complete.sqlite") + }); + + var nodeData = new DesignWaterLevelCalculationsGroupContext(new ObservableList(), + assessmentSection); + + using (var treeViewControl = new TreeViewControl()) + { + var gui = mockRepository.Stub(); + gui.Stub(g => g.ProjectOpened += null).IgnoreArguments(); + gui.Stub(g => g.ProjectOpened -= null).IgnoreArguments(); + gui.Stub(cmp => cmp.Get(nodeData, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + mockRepository.ReplayAll(); + + using (var plugin = new RingtoetsPlugin()) + { + TreeNodeInfo info = GetInfo(plugin); + + plugin.Gui = gui; + + // Call + using (ContextMenuStrip contextMenu = info.ContextMenuStrip(nodeData, null, treeViewControl)) + { + // Assert + const string expectedItemText = @"Alles be&rekenen"; + const string expectedItemTooltip = @"Alle toetspeilen berekenen."; + + TestHelper.AssertContextMenuStripContainsItem(contextMenu, contextMenuRunDesignWaterLevelCalculationsIndex, + expectedItemText, expectedItemTooltip, RingtoetsCommonFormsResources.CalculateAllIcon); + } + } + } + + mockRepository.VerifyAll(); // Expect no calls on arguments + } + + [Test] + [Apartment(ApartmentState.STA)] + public void CalculateDesignWaterLevelsFromContextMenu_AllRequiredInputSet_SendsRightInputToCalculationService() + { + // Setup + var mockRepository = new MockRepository(); + var assessmentSection = new AssessmentSectionStub + { + HydraulicBoundaryDatabase = + { + FilePath = Path.Combine(testDataPath, "HRD ijsselmeer.sqlite") + } + }; + + var hydraulicBoundaryLocation1 = new TestHydraulicBoundaryLocation("locationName 1"); + var hydraulicBoundaryLocation2 = new TestHydraulicBoundaryLocation("locationName 2"); + assessmentSection.SetHydraulicBoundaryLocationCalculations(new[] + { + hydraulicBoundaryLocation1, + hydraulicBoundaryLocation2 + }); + + var context = new DesignWaterLevelCalculationsGroupContext(new ObservableList(), + assessmentSection); + + using (var treeViewControl = new TreeViewControl()) + { + var gui = mockRepository.Stub(); + gui.Stub(g => g.ProjectOpened += null).IgnoreArguments(); + gui.Stub(g => g.ProjectOpened -= null).IgnoreArguments(); + gui.Stub(cmp => cmp.Get(context, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + gui.Stub(g => g.MainWindow).Return(mockRepository.Stub()); + gui.Stub(g => g.DocumentViewController).Return(mockRepository.Stub()); + + var designWaterLevelCalculator = new TestDesignWaterLevelCalculator(); + var calculatorFactory = mockRepository.Stub(); + calculatorFactory.Expect(cf => cf.CreateDesignWaterLevelCalculator(testDataPath, string.Empty)).Return(designWaterLevelCalculator).Repeat.Times(8); + mockRepository.ReplayAll(); + + DialogBoxHandler = (name, wnd) => + { + // Expect an activity dialog which is automatically closed + }; + + using (var plugin = new RingtoetsPlugin()) + { + TreeNodeInfo info = GetInfo(plugin); + plugin.Gui = gui; + plugin.Activate(); + + using (ContextMenuStrip contextMenuAdapter = info.ContextMenuStrip(context, null, treeViewControl)) + using (new HydraRingCalculatorFactoryConfig(calculatorFactory)) + { + // Call + contextMenuAdapter.Items[contextMenuRunDesignWaterLevelCalculationsIndex].PerformClick(); + + // Assert + double signalingNorm = assessmentSection.FailureMechanismContribution.SignalingNorm; + double factorizedSignalingNorm = signalingNorm / 30; + AssertHydraRingCalculationInput(hydraulicBoundaryLocation1, + factorizedSignalingNorm, + designWaterLevelCalculator.ReceivedInputs.ElementAt(0)); + AssertHydraRingCalculationInput(hydraulicBoundaryLocation2, + factorizedSignalingNorm, + designWaterLevelCalculator.ReceivedInputs.ElementAt(1)); + + AssertHydraRingCalculationInput(hydraulicBoundaryLocation1, + signalingNorm, + designWaterLevelCalculator.ReceivedInputs.ElementAt(2)); + AssertHydraRingCalculationInput(hydraulicBoundaryLocation2, + signalingNorm, + designWaterLevelCalculator.ReceivedInputs.ElementAt(3)); + + double lowerLimitNorm = assessmentSection.FailureMechanismContribution.LowerLimitNorm; + AssertHydraRingCalculationInput(hydraulicBoundaryLocation1, + lowerLimitNorm, + designWaterLevelCalculator.ReceivedInputs.ElementAt(4)); + AssertHydraRingCalculationInput(hydraulicBoundaryLocation2, + lowerLimitNorm, + designWaterLevelCalculator.ReceivedInputs.ElementAt(5)); + + double factorizedLowerLimitNorm = lowerLimitNorm * 30; + AssertHydraRingCalculationInput(hydraulicBoundaryLocation1, + factorizedLowerLimitNorm, + designWaterLevelCalculator.ReceivedInputs.ElementAt(6)); + AssertHydraRingCalculationInput(hydraulicBoundaryLocation2, + factorizedLowerLimitNorm, + designWaterLevelCalculator.ReceivedInputs.ElementAt(7)); + } + } + } + + mockRepository.VerifyAll(); + } + + [Test] + [Apartment(ApartmentState.STA)] + public void GivenHydraulicBoundaryLocationThatSucceeds_CalculatingDesignWaterLevelFromContextMenu_ThenLogMessagesAddedOutputSet() + { + // Given + var mockRepository = new MockRepository(); + var assessmentSection = new AssessmentSectionStub + { + HydraulicBoundaryDatabase = + { + FilePath = Path.Combine(testDataPath, "HRD ijsselmeer.sqlite") + } + }; + + var hydraulicBoundaryLocation = new TestHydraulicBoundaryLocation("locationName"); + assessmentSection.SetHydraulicBoundaryLocationCalculations(new[] + { + hydraulicBoundaryLocation + }); + + var context = new DesignWaterLevelCalculationsGroupContext(new ObservableList(), + assessmentSection); + + using (var treeViewControl = new TreeViewControl()) + { + var gui = mockRepository.Stub(); + gui.Stub(g => g.ProjectOpened += null).IgnoreArguments(); + gui.Stub(g => g.ProjectOpened -= null).IgnoreArguments(); + gui.Stub(cmp => cmp.Get(context, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + gui.Stub(g => g.MainWindow).Return(mockRepository.Stub()); + gui.Stub(g => g.DocumentViewController).Return(mockRepository.Stub()); + + var designWaterLevelCalculator = new TestDesignWaterLevelCalculator + { + Converged = false + }; + var calculatorFactory = mockRepository.Stub(); + calculatorFactory.Expect(cf => cf.CreateDesignWaterLevelCalculator(testDataPath, string.Empty)).Return(designWaterLevelCalculator).Repeat.Times(4); + mockRepository.ReplayAll(); + + DialogBoxHandler = (name, wnd) => + { + // Expect an activity dialog which is automatically closed + }; + + using (var plugin = new RingtoetsPlugin()) + { + TreeNodeInfo info = GetInfo(plugin); + plugin.Gui = gui; + plugin.Activate(); + + using (ContextMenuStrip contextMenuAdapter = info.ContextMenuStrip(context, null, treeViewControl)) + using (new HydraRingCalculatorFactoryConfig(calculatorFactory)) + { + // When + Action call = () => contextMenuAdapter.Items[contextMenuRunDesignWaterLevelCalculationsIndex].PerformClick(); + + // Then + TestHelper.AssertLogMessages(call, messages => + { + string[] msgs = messages.ToArray(); + Assert.AreEqual(32, msgs.Length); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 0, "A+->A"); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 7, "A->B"); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 14, "B->C"); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 21, "C->D"); + + Assert.AreEqual($"Toetspeil berekenen voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie A+->A) is gelukt.", msgs.ElementAt(28)); + Assert.AreEqual($"Toetspeil berekenen voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie A->B) is gelukt.", msgs.ElementAt(29)); + Assert.AreEqual($"Toetspeil berekenen voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie B->C) is gelukt.", msgs.ElementAt(30)); + Assert.AreEqual($"Toetspeil berekenen voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie C->D) is gelukt.", msgs.ElementAt(31)); + }); + + HydraulicBoundaryLocationCalculationOutput output = assessmentSection.WaterLevelCalculationsForFactorizedSignalingNorm.Single().Output; + Assert.AreEqual(designWaterLevelCalculator.DesignWaterLevel, output.Result, output.Result.GetAccuracy()); + Assert.AreEqual(CalculationConvergence.CalculatedNotConverged, output.CalculationConvergence); + } + } + } + + mockRepository.VerifyAll(); + } + + [Test] public void ChildNodeObjects_Always_ReturnsChildrenOfData() { // Setup @@ -191,6 +512,28 @@ } } + private static void AssertHydraulicBoundaryLocationCalculationMessages(HydraulicBoundaryLocation hydraulicBoundaryLocation, + IEnumerable messages, + int startIndex, + string categoryName) + { + Assert.AreEqual($"Toetspeil berekenen voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie {categoryName}) is gestart.", messages.ElementAt(startIndex)); + CalculationServiceTestHelper.AssertValidationStartMessage(messages.ElementAt(startIndex + 1)); + CalculationServiceTestHelper.AssertValidationEndMessage(messages.ElementAt(startIndex + 2)); + CalculationServiceTestHelper.AssertCalculationStartMessage(messages.ElementAt(startIndex + 3)); + Assert.AreEqual($"Toetspeil berekening voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie {categoryName}) is niet geconvergeerd.", messages.ElementAt(startIndex + 4)); + StringAssert.StartsWith("Toetspeil berekening is uitgevoerd op de tijdelijke locatie", messages.ElementAt(startIndex + 5)); + CalculationServiceTestHelper.AssertCalculationEndMessage(messages.ElementAt(startIndex + 6)); + } + + private static void AssertHydraRingCalculationInput(HydraulicBoundaryLocation hydraulicBoundaryLocation, + double norm, + HydraRingCalculationInput actualCalculationInput) + { + Assert.AreEqual(hydraulicBoundaryLocation.Id, actualCalculationInput.HydraulicBoundaryLocationId); + Assert.AreEqual(StatisticsConverter.ProbabilityToReliability(norm), actualCalculationInput.Beta); + } + private static TreeNodeInfo GetInfo(RingtoetsPlugin plugin) { return plugin.GetTreeNodeInfos().First(tni => tni.TagType == typeof(DesignWaterLevelCalculationsGroupContext)); Index: Ringtoets/Integration/test/Ringtoets.Integration.Plugin.Test/TreeNodeInfos/WaveHeightCalculationsGroupContextTreeNodeInfoTest.cs =================================================================== diff -u -rd1f9d5bcdee552dd29c64194d455de245db0190d -r5bb5f922652f2a8cc9a31c94ae2e891ffde02b6c --- Ringtoets/Integration/test/Ringtoets.Integration.Plugin.Test/TreeNodeInfos/WaveHeightCalculationsGroupContextTreeNodeInfoTest.cs (.../WaveHeightCalculationsGroupContextTreeNodeInfoTest.cs) (revision d1f9d5bcdee552dd29c64194d455de245db0190d) +++ Ringtoets/Integration/test/Ringtoets.Integration.Plugin.Test/TreeNodeInfos/WaveHeightCalculationsGroupContextTreeNodeInfoTest.cs (.../WaveHeightCalculationsGroupContextTreeNodeInfoTest.cs) (revision 5bb5f922652f2a8cc9a31c94ae2e891ffde02b6c) @@ -19,28 +19,43 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. +using System; +using System.Collections.Generic; using System.Drawing; +using System.IO; using System.Linq; +using System.Threading; +using System.Windows.Forms; using Core.Common.Base; using Core.Common.Controls.TreeView; using Core.Common.Gui; using Core.Common.Gui.ContextMenu; +using Core.Common.Gui.Forms.MainWindow; +using Core.Common.Gui.Forms.ViewHost; +using Core.Common.Gui.TestUtil.ContextMenu; using Core.Common.TestUtil; +using Core.Common.Util; using NUnit.Extensions.Forms; using NUnit.Framework; using Rhino.Mocks; using Ringtoets.Common.Data.AssessmentSection; using Ringtoets.Common.Data.Hydraulics; using Ringtoets.Common.Data.TestUtil; using Ringtoets.Common.Forms.PresentationObjects; -using Ringtoets.Integration.Forms.PresentationObjects; +using Ringtoets.Common.Service.TestUtil; +using Ringtoets.HydraRing.Calculation.Calculator.Factory; +using Ringtoets.HydraRing.Calculation.Data.Input; +using Ringtoets.HydraRing.Calculation.TestUtil.Calculator; using RingtoetsCommonFormsResources = Ringtoets.Common.Forms.Properties.Resources; namespace Ringtoets.Integration.Plugin.Test.TreeNodeInfos { [TestFixture] public class WaveHeightCalculationsGroupContextTreeNodeInfoTest : NUnitFormTest { + private const int contextMenuRunWaveHeightCalculationsIndex = 0; + private readonly string testDataPath = TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Integration.Service, "HydraRingCalculation"); + [Test] public void Initialized_Always_ExpectedPropertiesSet() { @@ -109,11 +124,13 @@ { // Setup var mockRepository = new MockRepository(); - var assessmentSection = mockRepository.StrictMock(); + IAssessmentSection assessmentSection = AssessmentSectionHelper.CreateAssessmentSectionStub(mockRepository); var menuBuilder = mockRepository.StrictMock(); using (mockRepository.Ordered()) { + menuBuilder.Expect(mb => mb.AddCustomItem(null)).IgnoreArguments().Return(menuBuilder); + menuBuilder.Expect(mb => mb.AddSeparator()).Return(menuBuilder); menuBuilder.Expect(mb => mb.AddCollapseAllItem()).Return(menuBuilder); menuBuilder.Expect(mb => mb.AddExpandAllItem()).Return(menuBuilder); menuBuilder.Expect(mb => mb.Build()).Return(null); @@ -146,6 +163,310 @@ } [Test] + public void ContextMenuStrip_HydraulicBoundaryDatabaseNotLinked_ContextMenuItemCalculateAllDisabledAndTooltipSet() + { + // Setup + var mockRepository = new MockRepository(); + IAssessmentSection assessmentSection = AssessmentSectionHelper.CreateAssessmentSectionStub(mockRepository); + + var nodeData = new WaveHeightCalculationsGroupContext(new ObservableList(), + assessmentSection); + + using (var treeViewControl = new TreeViewControl()) + { + var gui = mockRepository.Stub(); + gui.Stub(g => g.ProjectOpened += null).IgnoreArguments(); + gui.Stub(g => g.ProjectOpened -= null).IgnoreArguments(); + gui.Stub(cmp => cmp.Get(nodeData, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + mockRepository.ReplayAll(); + + using (var plugin = new RingtoetsPlugin()) + { + TreeNodeInfo info = GetInfo(plugin); + + plugin.Gui = gui; + + // Call + using (ContextMenuStrip contextMenu = info.ContextMenuStrip(nodeData, null, treeViewControl)) + { + // Assert + ToolStripItem contextMenuItem = contextMenu.Items[contextMenuRunWaveHeightCalculationsIndex]; + + Assert.AreEqual("Alles be&rekenen", contextMenuItem.Text); + StringAssert.Contains("Er is geen hydraulische randvoorwaardendatabase geïmporteerd.", contextMenuItem.ToolTipText); + TestHelper.AssertImagesAreEqual(RingtoetsCommonFormsResources.CalculateAllIcon, contextMenuItem.Image); + Assert.IsFalse(contextMenuItem.Enabled); + } + } + } + + mockRepository.VerifyAll(); // Expect no calls on arguments + } + + [Test] + public void ContextMenuStrip_HydraulicBoundaryDatabaseLinkedToInvalidFile_ContextMenuItemCalculateAllDisabledAndTooltipSet() + { + // Setup + var mockRepository = new MockRepository(); + IAssessmentSection assessmentSection = AssessmentSectionHelper.CreateAssessmentSectionStub(null, mockRepository, "invalidFilePath"); + + var nodeData = new WaveHeightCalculationsGroupContext(new ObservableList(), + assessmentSection); + + using (var treeViewControl = new TreeViewControl()) + { + var gui = mockRepository.Stub(); + gui.Stub(g => g.ProjectOpened += null).IgnoreArguments(); + gui.Stub(g => g.ProjectOpened -= null).IgnoreArguments(); + gui.Stub(cmp => cmp.Get(nodeData, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + mockRepository.ReplayAll(); + + using (var plugin = new RingtoetsPlugin()) + { + TreeNodeInfo info = GetInfo(plugin); + + plugin.Gui = gui; + + // Call + using (ContextMenuStrip contextMenu = info.ContextMenuStrip(nodeData, null, treeViewControl)) + { + // Assert + ToolStripItem contextMenuItem = contextMenu.Items[contextMenuRunWaveHeightCalculationsIndex]; + + Assert.AreEqual("Alles be&rekenen", contextMenuItem.Text); + StringAssert.Contains("Herstellen van de verbinding met de hydraulische randvoorwaardendatabase is mislukt.", contextMenuItem.ToolTipText); + TestHelper.AssertImagesAreEqual(RingtoetsCommonFormsResources.CalculateAllIcon, contextMenuItem.Image); + Assert.IsFalse(contextMenuItem.Enabled); + } + } + } + + mockRepository.VerifyAll(); // Expect no calls on arguments + } + + [Test] + public void ContextMenuStrip_AllRequiredInputSet_ContextMenuItemCalculateAllEnabled() + { + // Setup + var mockRepository = new MockRepository(); + var assessmentSection = mockRepository.Stub(); + assessmentSection.Stub(a => a.HydraulicBoundaryDatabase).Return(new HydraulicBoundaryDatabase + { + FilePath = Path.Combine(TestHelper.GetTestDataPath(TestDataPath.Ringtoets.Common.IO, "HydraulicBoundaryDatabaseImporter"), "complete.sqlite") + }); + + var nodeData = new WaveHeightCalculationsGroupContext(new ObservableList(), + assessmentSection); + + using (var treeViewControl = new TreeViewControl()) + { + var gui = mockRepository.Stub(); + gui.Stub(g => g.ProjectOpened += null).IgnoreArguments(); + gui.Stub(g => g.ProjectOpened -= null).IgnoreArguments(); + gui.Stub(cmp => cmp.Get(nodeData, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + mockRepository.ReplayAll(); + + using (var plugin = new RingtoetsPlugin()) + { + TreeNodeInfo info = GetInfo(plugin); + + plugin.Gui = gui; + + // Call + using (ContextMenuStrip contextMenu = info.ContextMenuStrip(nodeData, null, treeViewControl)) + { + // Assert + const string expectedItemText = @"Alles be&rekenen"; + const string expectedItemTooltip = @"Alle golfhoogtes berekenen."; + + TestHelper.AssertContextMenuStripContainsItem(contextMenu, contextMenuRunWaveHeightCalculationsIndex, + expectedItemText, expectedItemTooltip, RingtoetsCommonFormsResources.CalculateAllIcon); + } + } + } + + mockRepository.VerifyAll(); // Expect no calls on arguments + } + + [Test] + [Apartment(ApartmentState.STA)] + public void CalculateWaveHeightsFromContextMenu_AllRequiredInputSet_SendsRightInputToCalculationService() + { + // Setup + var mockRepository = new MockRepository(); + var assessmentSection = new AssessmentSectionStub + { + HydraulicBoundaryDatabase = + { + FilePath = Path.Combine(testDataPath, "HRD ijsselmeer.sqlite") + } + }; + + var hydraulicBoundaryLocation1 = new TestHydraulicBoundaryLocation("locationName 1"); + var hydraulicBoundaryLocation2 = new TestHydraulicBoundaryLocation("locationName 2"); + assessmentSection.SetHydraulicBoundaryLocationCalculations(new[] + { + hydraulicBoundaryLocation1, + hydraulicBoundaryLocation2 + }); + + var context = new WaveHeightCalculationsGroupContext(new ObservableList(), + assessmentSection); + + using (var treeViewControl = new TreeViewControl()) + { + var gui = mockRepository.Stub(); + gui.Stub(g => g.ProjectOpened += null).IgnoreArguments(); + gui.Stub(g => g.ProjectOpened -= null).IgnoreArguments(); + gui.Stub(cmp => cmp.Get(context, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + gui.Stub(g => g.MainWindow).Return(mockRepository.Stub()); + gui.Stub(g => g.DocumentViewController).Return(mockRepository.Stub()); + + var designWaveHeightCalculator = new TestWaveHeightCalculator(); + var calculatorFactory = mockRepository.Stub(); + calculatorFactory.Expect(cf => cf.CreateWaveHeightCalculator(testDataPath, string.Empty)).Return(designWaveHeightCalculator).Repeat.Times(8); + mockRepository.ReplayAll(); + + DialogBoxHandler = (name, wnd) => + { + // Expect an activity dialog which is automatically closed + }; + + using (var plugin = new RingtoetsPlugin()) + { + TreeNodeInfo info = GetInfo(plugin); + plugin.Gui = gui; + plugin.Activate(); + + using (ContextMenuStrip contextMenuAdapter = info.ContextMenuStrip(context, null, treeViewControl)) + using (new HydraRingCalculatorFactoryConfig(calculatorFactory)) + { + // Call + contextMenuAdapter.Items[contextMenuRunWaveHeightCalculationsIndex].PerformClick(); + + // Assert + double signalingNorm = assessmentSection.FailureMechanismContribution.SignalingNorm; + double factorizedSignalingNorm = signalingNorm / 30; + AssertHydraRingCalculationInput(hydraulicBoundaryLocation1, + factorizedSignalingNorm, + designWaveHeightCalculator.ReceivedInputs.ElementAt(0)); + AssertHydraRingCalculationInput(hydraulicBoundaryLocation2, + factorizedSignalingNorm, + designWaveHeightCalculator.ReceivedInputs.ElementAt(1)); + + AssertHydraRingCalculationInput(hydraulicBoundaryLocation1, + signalingNorm, + designWaveHeightCalculator.ReceivedInputs.ElementAt(2)); + AssertHydraRingCalculationInput(hydraulicBoundaryLocation2, + signalingNorm, + designWaveHeightCalculator.ReceivedInputs.ElementAt(3)); + + double lowerLimitNorm = assessmentSection.FailureMechanismContribution.LowerLimitNorm; + AssertHydraRingCalculationInput(hydraulicBoundaryLocation1, + lowerLimitNorm, + designWaveHeightCalculator.ReceivedInputs.ElementAt(4)); + AssertHydraRingCalculationInput(hydraulicBoundaryLocation2, + lowerLimitNorm, + designWaveHeightCalculator.ReceivedInputs.ElementAt(5)); + + double factorizedLowerLimitNorm = lowerLimitNorm * 30; + AssertHydraRingCalculationInput(hydraulicBoundaryLocation1, + factorizedLowerLimitNorm, + designWaveHeightCalculator.ReceivedInputs.ElementAt(6)); + AssertHydraRingCalculationInput(hydraulicBoundaryLocation2, + factorizedLowerLimitNorm, + designWaveHeightCalculator.ReceivedInputs.ElementAt(7)); + } + } + } + + mockRepository.VerifyAll(); + } + + [Test] + [Apartment(ApartmentState.STA)] + public void GivenHydraulicBoundaryLocationThatSucceeds_CalculatingWaveHeightFromContextMenu_ThenLogMessagesAddedOutputSet() + { + // Given + var mockRepository = new MockRepository(); + var assessmentSection = new AssessmentSectionStub + { + HydraulicBoundaryDatabase = + { + FilePath = Path.Combine(testDataPath, "HRD ijsselmeer.sqlite") + } + }; + + var hydraulicBoundaryLocation = new TestHydraulicBoundaryLocation("locationName"); + assessmentSection.SetHydraulicBoundaryLocationCalculations(new[] + { + hydraulicBoundaryLocation + }); + + var context = new WaveHeightCalculationsGroupContext(new ObservableList(), + assessmentSection); + + using (var treeViewControl = new TreeViewControl()) + { + var gui = mockRepository.Stub(); + gui.Stub(g => g.ProjectOpened += null).IgnoreArguments(); + gui.Stub(g => g.ProjectOpened -= null).IgnoreArguments(); + gui.Stub(cmp => cmp.Get(context, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + gui.Stub(g => g.MainWindow).Return(mockRepository.Stub()); + gui.Stub(g => g.DocumentViewController).Return(mockRepository.Stub()); + + var designWaveHeightCalculator = new TestWaveHeightCalculator + { + Converged = false + }; + var calculatorFactory = mockRepository.Stub(); + calculatorFactory.Expect(cf => cf.CreateWaveHeightCalculator(testDataPath, string.Empty)).Return(designWaveHeightCalculator).Repeat.Times(4); + mockRepository.ReplayAll(); + + DialogBoxHandler = (name, wnd) => + { + // Expect an activity dialog which is automatically closed + }; + + using (var plugin = new RingtoetsPlugin()) + { + TreeNodeInfo info = GetInfo(plugin); + plugin.Gui = gui; + plugin.Activate(); + + using (ContextMenuStrip contextMenuAdapter = info.ContextMenuStrip(context, null, treeViewControl)) + using (new HydraRingCalculatorFactoryConfig(calculatorFactory)) + { + // When + Action call = () => contextMenuAdapter.Items[contextMenuRunWaveHeightCalculationsIndex].PerformClick(); + + // Then + TestHelper.AssertLogMessages(call, messages => + { + string[] msgs = messages.ToArray(); + Assert.AreEqual(32, msgs.Length); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 0, "A+->A"); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 7, "A->B"); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 14, "B->C"); + AssertHydraulicBoundaryLocationCalculationMessages(hydraulicBoundaryLocation, msgs, 21, "C->D"); + + Assert.AreEqual($"Golfhoogte berekenen voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie A+->A) is gelukt.", msgs.ElementAt(28)); + Assert.AreEqual($"Golfhoogte berekenen voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie A->B) is gelukt.", msgs.ElementAt(29)); + Assert.AreEqual($"Golfhoogte berekenen voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie B->C) is gelukt.", msgs.ElementAt(30)); + Assert.AreEqual($"Golfhoogte berekenen voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie C->D) is gelukt.", msgs.ElementAt(31)); + }); + + HydraulicBoundaryLocationCalculationOutput output = assessmentSection.WaveHeightCalculationsForFactorizedSignalingNorm.Single().Output; + Assert.AreEqual(designWaveHeightCalculator.WaveHeight, output.Result, output.Result.GetAccuracy()); + Assert.AreEqual(CalculationConvergence.CalculatedNotConverged, output.CalculationConvergence); + } + } + } + + mockRepository.VerifyAll(); + } + + [Test] public void ChildNodeObjects_Always_ReturnsChildrenOfData() { // Setup @@ -192,6 +513,28 @@ } } + private static void AssertHydraulicBoundaryLocationCalculationMessages(HydraulicBoundaryLocation hydraulicBoundaryLocation, + IEnumerable messages, + int startIndex, + string categoryName) + { + Assert.AreEqual($"Golfhoogte berekenen voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie {categoryName}) is gestart.", messages.ElementAt(startIndex)); + CalculationServiceTestHelper.AssertValidationStartMessage(messages.ElementAt(startIndex + 1)); + CalculationServiceTestHelper.AssertValidationEndMessage(messages.ElementAt(startIndex + 2)); + CalculationServiceTestHelper.AssertCalculationStartMessage(messages.ElementAt(startIndex + 3)); + Assert.AreEqual($"Golfhoogte berekening voor locatie '{hydraulicBoundaryLocation.Name}' (Categorie {categoryName}) is niet geconvergeerd.", messages.ElementAt(startIndex + 4)); + StringAssert.StartsWith("Golfhoogte berekening is uitgevoerd op de tijdelijke locatie", messages.ElementAt(startIndex + 5)); + CalculationServiceTestHelper.AssertCalculationEndMessage(messages.ElementAt(startIndex + 6)); + } + + private static void AssertHydraRingCalculationInput(HydraulicBoundaryLocation hydraulicBoundaryLocation, + double norm, + HydraRingCalculationInput actualCalculationInput) + { + Assert.AreEqual(hydraulicBoundaryLocation.Id, actualCalculationInput.HydraulicBoundaryLocationId); + Assert.AreEqual(StatisticsConverter.ProbabilityToReliability(norm), actualCalculationInput.Beta); + } + private static TreeNodeInfo GetInfo(RingtoetsPlugin plugin) { return plugin.GetTreeNodeInfos().First(tni => tni.TagType == typeof(WaveHeightCalculationsGroupContext));