Index: Ringtoets/HeightStructures/test/Ringtoets.HeightStructures.Plugin.Test/TreeNodeInfos/HeightStructuresCalculationContextTreeNodeInfoTest.cs =================================================================== diff -u -rbf926725b3c2994fb1f2d7c8b4294ab66691b3d2 -r5d0d5ccc8bce2348ca2df9d6e35401abc1f41bee --- Ringtoets/HeightStructures/test/Ringtoets.HeightStructures.Plugin.Test/TreeNodeInfos/HeightStructuresCalculationContextTreeNodeInfoTest.cs (.../HeightStructuresCalculationContextTreeNodeInfoTest.cs) (revision bf926725b3c2994fb1f2d7c8b4294ab66691b3d2) +++ Ringtoets/HeightStructures/test/Ringtoets.HeightStructures.Plugin.Test/TreeNodeInfos/HeightStructuresCalculationContextTreeNodeInfoTest.cs (.../HeightStructuresCalculationContextTreeNodeInfoTest.cs) (revision 5d0d5ccc8bce2348ca2df9d6e35401abc1f41bee) @@ -25,6 +25,7 @@ using System.Linq; using System.Windows.Forms; using Core.Common.Base; +using Core.Common.Base.Data; using Core.Common.Base.Geometry; using Core.Common.Controls.TreeView; using Core.Common.Gui; @@ -41,6 +42,7 @@ using Ringtoets.Common.Data.Contribution; using Ringtoets.Common.Data.FailureMechanism; using Ringtoets.Common.Data.Hydraulics; +using Ringtoets.Common.Data.Probabilistics; using Ringtoets.Common.Data.Probability; using Ringtoets.Common.Data.Structures; using Ringtoets.Common.Data.TestUtil; @@ -339,6 +341,363 @@ } [Test] + public void GivenCalculationWithStructureWithoutOutput_WhenStructureUpdatedAndUpdateClicked_ThenNoInquiryAndCalculationUpdatedAndInputObserverNotified() + { + // Given + var assessmentSection = mocks.Stub(); + var structure = new TestHeightStructure(); + var calculation = new StructuresCalculation + { + InputParameters = + { + Structure = structure + } + }; + var failureMechanism = new HeightStructuresFailureMechanism(); + var nodeData = new HeightStructuresCalculationContext(calculation, failureMechanism, assessmentSection); + + var inputObserver = mocks.StrictMock(); + inputObserver.Expect(obs => obs.UpdateObserver()); + calculation.InputParameters.Attach(inputObserver); + + var calculationObserver = mocks.StrictMock(); + calculation.Attach(calculationObserver); + + using (var treeViewControl = new TreeViewControl()) + { + var mainWindow = mocks.Stub(); + var gui = mocks.Stub(); + gui.Stub(cmp => cmp.Get(nodeData, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + gui.Stub(g => g.MainWindow).Return(mainWindow); + mocks.ReplayAll(); + + plugin.Gui = gui; + + using (ContextMenuStrip menu = info.ContextMenuStrip(nodeData, assessmentSection, treeViewControl)) + { + // When + UpdateStructure(structure); + menu.Items[contextMenuUpdateStructureIndex].PerformClick(); + + // Then + Assert.IsFalse(calculation.HasOutput); + + HeightStructuresInput inputParameters = calculation.InputParameters; + Assert.AreSame(structure, inputParameters.Structure); + Assert.AreEqual(structure.StructureNormalOrientation, inputParameters.StructureNormalOrientation); + Assert.AreEqual(structure.LevelCrestStructure, inputParameters.LevelCrestStructure); + Assert.AreEqual(structure.FlowWidthAtBottomProtection, inputParameters.FlowWidthAtBottomProtection); + Assert.AreEqual(structure.CriticalOvertoppingDischarge, inputParameters.CriticalOvertoppingDischarge); + Assert.AreEqual(structure.WidthFlowApertures, inputParameters.WidthFlowApertures); + Assert.AreEqual(structure.FailureProbabilityStructureWithErosion, inputParameters.FailureProbabilityStructureWithErosion); + Assert.AreEqual(structure.StorageStructureArea, inputParameters.StorageStructureArea); + Assert.AreEqual(structure.AllowedLevelIncreaseStorage, inputParameters.AllowedLevelIncreaseStorage); + + // Note: observer assertions are verified in the Teardown() + } + } + } + + [Test] + public void GivenCalculationWithStructureWithOutput_WhenStructureHasChangesAndUpdateClickedAndCancelled_ThenInquiryAndCalculationNotUpdatedAndObserversNotNotified() + { + // Given + var assessmentSection = mocks.Stub(); + var structure = new TestHeightStructure(); + var calculation = new StructuresCalculation + { + InputParameters = + { + Structure = structure + }, + Output = new TestStructuresOutput() + }; + + HeightStructuresInput calculationInput = calculation.InputParameters; + + RoundedDouble expectedStructureNormalOrientation = calculationInput.StructureNormalOrientation; + NormalDistribution expectedLevelCrestStructure = calculationInput.LevelCrestStructure; + LogNormalDistribution expectedFlowWidthAtBottomProtection = calculationInput.FlowWidthAtBottomProtection; + VariationCoefficientLogNormalDistribution expectedCriticalOvertoppingDischarge = calculationInput.CriticalOvertoppingDischarge; + NormalDistribution expectedWidthFlowApertures = calculationInput.WidthFlowApertures; + double expectedFailureProbabilityStructureWithErosion = calculationInput.FailureProbabilityStructureWithErosion; + VariationCoefficientLogNormalDistribution expectedStorageStructureArea = calculationInput.StorageStructureArea; + LogNormalDistribution expectedAllowedLevelIncreaseStorage = calculationInput.AllowedLevelIncreaseStorage; + + var failureMechanism = new HeightStructuresFailureMechanism(); + var nodeData = new HeightStructuresCalculationContext(calculation, failureMechanism, assessmentSection); + + var inputObserver = mocks.StrictMock(); + calculationInput.Attach(inputObserver); + + var calculationObserver = mocks.StrictMock(); + calculation.Attach(calculationObserver); + + string textBoxMessage = null; + DialogBoxHandler = (name, wnd) => + { + var helper = new MessageBoxTester(wnd); + textBoxMessage = helper.Text; + helper.ClickCancel(); + }; + + using (var treeViewControl = new TreeViewControl()) + { + var mainWindow = mocks.Stub(); + var gui = mocks.Stub(); + gui.Stub(cmp => cmp.Get(nodeData, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + gui.Stub(g => g.MainWindow).Return(mainWindow); + mocks.ReplayAll(); + + plugin.Gui = gui; + using (ContextMenuStrip menu = info.ContextMenuStrip(nodeData, assessmentSection, treeViewControl)) + { + // When + UpdateStructure(structure); + menu.Items[contextMenuUpdateStructureIndex].PerformClick(); + + // Then + Assert.IsTrue(calculation.HasOutput); + + Assert.AreSame(structure, calculationInput.Structure); + + Assert.AreEqual(expectedStructureNormalOrientation, calculationInput.StructureNormalOrientation); + Assert.AreEqual(expectedLevelCrestStructure, calculationInput.LevelCrestStructure); + Assert.AreEqual(expectedFlowWidthAtBottomProtection, calculationInput.FlowWidthAtBottomProtection); + Assert.AreEqual(expectedCriticalOvertoppingDischarge, calculationInput.CriticalOvertoppingDischarge); + Assert.AreEqual(expectedWidthFlowApertures, calculationInput.WidthFlowApertures); + Assert.AreEqual(expectedFailureProbabilityStructureWithErosion, calculationInput.FailureProbabilityStructureWithErosion); + Assert.AreEqual(expectedStorageStructureArea, calculationInput.StorageStructureArea); + Assert.AreEqual(expectedAllowedLevelIncreaseStorage, calculationInput.AllowedLevelIncreaseStorage); + + string expectedMessage = "Wanneer het kunstwerk wijzigt als gevolg van het bijwerken, " + + "zal het resultaat van deze berekening worden " + + $"verwijderd.{Environment.NewLine}{Environment.NewLine}Weet u zeker dat u wilt doorgaan?"; + Assert.AreEqual(expectedMessage, textBoxMessage); + + // Note: observer assertions are verified in the Teardown() + } + } + } + + [Test] + public void GivenCalculationWithStructureWithOutput_WhenStructureHasChangesUpdateStructureClickedAndContinued_ThenInquiryAndUpdatesCalculationAndObserversNotified() + { + // Given + var assessmentSection = mocks.Stub(); + var structure = new TestHeightStructure(); + var calculation = new StructuresCalculation + { + InputParameters = + { + Structure = structure + }, + Output = new TestStructuresOutput() + }; + var failureMechanism = new HeightStructuresFailureMechanism(); + var nodeData = new HeightStructuresCalculationContext(calculation, failureMechanism, assessmentSection); + + var inputObserver = mocks.StrictMock(); + inputObserver.Expect(obs => obs.UpdateObserver()); + calculation.InputParameters.Attach(inputObserver); + + var calculationObserver = mocks.StrictMock(); + calculationObserver.Expect(obs => obs.UpdateObserver()); + calculation.Attach(calculationObserver); + + string textBoxMessage = null; + DialogBoxHandler = (name, wnd) => + { + var helper = new MessageBoxTester(wnd); + textBoxMessage = helper.Text; + helper.ClickOk(); + }; + + using (var treeViewControl = new TreeViewControl()) + { + var mainWindow = mocks.Stub(); + var gui = mocks.Stub(); + gui.Stub(cmp => cmp.Get(nodeData, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + gui.Stub(g => g.MainWindow).Return(mainWindow); + mocks.ReplayAll(); + + plugin.Gui = gui; + + using (ContextMenuStrip menu = info.ContextMenuStrip(nodeData, assessmentSection, treeViewControl)) + { + // When + UpdateStructure(structure); + menu.Items[contextMenuUpdateStructureIndex].PerformClick(); + + // Then + Assert.IsFalse(calculation.HasOutput); + + HeightStructuresInput inputParameters = calculation.InputParameters; + Assert.AreSame(structure, inputParameters.Structure); + Assert.AreSame(structure, inputParameters.Structure); + Assert.AreEqual(structure.StructureNormalOrientation, inputParameters.StructureNormalOrientation); + Assert.AreEqual(structure.LevelCrestStructure, inputParameters.LevelCrestStructure); + Assert.AreEqual(structure.FlowWidthAtBottomProtection, inputParameters.FlowWidthAtBottomProtection); + Assert.AreEqual(structure.CriticalOvertoppingDischarge, inputParameters.CriticalOvertoppingDischarge); + Assert.AreEqual(structure.WidthFlowApertures, inputParameters.WidthFlowApertures); + Assert.AreEqual(structure.FailureProbabilityStructureWithErosion, inputParameters.FailureProbabilityStructureWithErosion); + Assert.AreEqual(structure.StorageStructureArea, inputParameters.StorageStructureArea); + Assert.AreEqual(structure.AllowedLevelIncreaseStorage, inputParameters.AllowedLevelIncreaseStorage); + + string expectedMessage = "Wanneer het kunstwerk wijzigt als gevolg van het bijwerken, " + + "zal het resultaat van deze berekening worden " + + $"verwijderd.{Environment.NewLine}{Environment.NewLine}Weet u zeker dat u wilt doorgaan?"; + Assert.AreEqual(expectedMessage, textBoxMessage); + + // Note: observer assertions are verified in the Teardown() + } + } + } + + [Test] + public void GivenCalculationWithStructureWithOutput_WhenStructureHasNoChangeAndUpdateClickedAndContinued_ThenInquiryAndCalculationNotUpdatedAndObserversNotNotified() + { + // Given + var assessmentSection = mocks.Stub(); + + var structure = new TestHeightStructure(); + UpdateStructure(structure); + + var calculation = new StructuresCalculation + { + InputParameters = + { + Structure = structure + }, + Output = new TestStructuresOutput() + }; + + var inputObserver = mocks.StrictMock(); + calculation.InputParameters.Attach(inputObserver); + + var calculationObserver = mocks.StrictMock(); + calculation.Attach(calculationObserver); + + var failureMechanism = new HeightStructuresFailureMechanism(); + var nodeData = new HeightStructuresCalculationContext(calculation, failureMechanism, assessmentSection); + + string textBoxMessage = null; + DialogBoxHandler = (name, wnd) => + { + var helper = new MessageBoxTester(wnd); + textBoxMessage = helper.Text; + helper.ClickOk(); + }; + + using (var treeViewControl = new TreeViewControl()) + { + var mainWindow = mocks.Stub(); + var gui = mocks.Stub(); + gui.Stub(cmp => cmp.Get(nodeData, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + gui.Stub(g => g.MainWindow).Return(mainWindow); + mocks.ReplayAll(); + + plugin.Gui = gui; + + using (ContextMenuStrip menu = info.ContextMenuStrip(nodeData, assessmentSection, treeViewControl)) + { + // When + menu.Items[contextMenuUpdateStructureIndex].PerformClick(); + + // Then + Assert.IsTrue(calculation.HasOutput); + + HeightStructuresInput inputParameters = calculation.InputParameters; + + Assert.AreSame(structure, inputParameters.Structure); + Assert.AreEqual(structure.StructureNormalOrientation, inputParameters.StructureNormalOrientation); + Assert.AreEqual(structure.LevelCrestStructure, inputParameters.LevelCrestStructure); + Assert.AreEqual(structure.FlowWidthAtBottomProtection, inputParameters.FlowWidthAtBottomProtection); + Assert.AreEqual(structure.CriticalOvertoppingDischarge, inputParameters.CriticalOvertoppingDischarge); + Assert.AreEqual(structure.WidthFlowApertures, inputParameters.WidthFlowApertures); + Assert.AreEqual(structure.FailureProbabilityStructureWithErosion, inputParameters.FailureProbabilityStructureWithErosion); + Assert.AreEqual(structure.StorageStructureArea, inputParameters.StorageStructureArea); + Assert.AreEqual(structure.AllowedLevelIncreaseStorage, inputParameters.AllowedLevelIncreaseStorage); + + string expectedMessage = "Wanneer het kunstwerk wijzigt als gevolg van het bijwerken, " + + "zal het resultaat van deze berekening worden " + + $"verwijderd.{Environment.NewLine}{Environment.NewLine}Weet u zeker dat u wilt doorgaan?"; + Assert.AreEqual(expectedMessage, textBoxMessage); + + // Note: observer assertions are verified in the Teardown() + } + } + } + + [Test] + public void GivenCalculationWithStructureWithOutput_WhenStructurePartiallyDifferentAndUpdateClicked_ThenInquiryAndUpdatesCalculationAndNotifiesObserver() + { + // Given + var assessmentSection = mocks.Stub(); + + var structure = new TestHeightStructure(); + UpdateStructure(structure); + + var calculation = new StructuresCalculation + { + InputParameters = + { + Structure = structure + }, + Output = new TestStructuresOutput() + }; + + var inputObserver = mocks.StrictMock(); + inputObserver.Expect(obs => obs.UpdateObserver()); + calculation.InputParameters.Attach(inputObserver); + + var calculationObserver = mocks.StrictMock(); + calculationObserver.Expect(obs => obs.UpdateObserver()); + calculation.Attach(calculationObserver); + + var failureMechanism = new HeightStructuresFailureMechanism(); + var nodeData = new HeightStructuresCalculationContext(calculation, failureMechanism, assessmentSection); + + string textBoxMessage = null; + DialogBoxHandler = (name, wnd) => + { + var helper = new MessageBoxTester(wnd); + textBoxMessage = helper.Text; + helper.ClickOk(); + }; + + using (var treeViewControl = new TreeViewControl()) + { + var mainWindow = mocks.Stub(); + var gui = mocks.Stub(); + gui.Stub(cmp => cmp.Get(nodeData, treeViewControl)).Return(new CustomItemsOnlyContextMenuBuilder()); + gui.Stub(g => g.MainWindow).Return(mainWindow); + mocks.ReplayAll(); + + plugin.Gui = gui; + + using (ContextMenuStrip menu = info.ContextMenuStrip(nodeData, assessmentSection, treeViewControl)) + { + // When + HeightStructuresInput inputParameters = calculation.InputParameters; + inputParameters.StructureNormalOrientation = (RoundedDouble) 1.1; + menu.Items[contextMenuUpdateStructureIndex].PerformClick(); + + // Then + Assert.IsFalse(calculation.HasOutput); + Assert.AreEqual(structure.StructureNormalOrientation, inputParameters.StructureNormalOrientation); + + string expectedMessage = "Wanneer het kunstwerk wijzigt als gevolg van het bijwerken, " + + "zal het resultaat van deze berekening worden " + + $"verwijderd.{Environment.NewLine}{Environment.NewLine}Weet u zeker dat u wilt doorgaan?"; + Assert.AreEqual(expectedMessage, textBoxMessage); + + // Note: observer assertions are verified in the Teardown() + } + } + } + + [Test] public void ContextMenuStrip_NoHydraulicBoundaryDatabase_ContextMenuItemPerformCalculationDisabledAndTooltipSet() { // Setup @@ -829,6 +1188,50 @@ Assert.IsNull(result.Calculation); } + private static void UpdateStructure(HeightStructure structure) + { + var structureToUpdateFrom = new HeightStructure( + new HeightStructure.ConstructionProperties + { + Id = structure.Id, + Name = structure.Name, + Location = structure.Location, + LevelCrestStructure = + { + Mean = (RoundedDouble) 1.0, + StandardDeviation = (RoundedDouble) 2.0 + }, + FlowWidthAtBottomProtection = + { + Mean = (RoundedDouble) 3.0, + StandardDeviation = (RoundedDouble) 4.0 + }, + CriticalOvertoppingDischarge = + { + Mean = (RoundedDouble) 5.0, + CoefficientOfVariation = (RoundedDouble) 6.0 + }, + WidthFlowApertures = + { + Mean = (RoundedDouble) 7.0, + StandardDeviation = (RoundedDouble) 8.0 + }, + StorageStructureArea = + { + Mean = (RoundedDouble) 9.0, + CoefficientOfVariation = (RoundedDouble) 10.0 + }, + AllowedLevelIncreaseStorage = + { + Mean = (RoundedDouble) 11.0, + StandardDeviation = (RoundedDouble) 12.0 + }, + FailureProbabilityStructureWithErosion = 0.13 + }); + + structure.CopyProperties(structureToUpdateFrom); + } + public override void TearDown() { plugin.Dispose();