From c1bce5299a0ae38e3931c7906d474eda0d47570c Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Sat, 12 Sep 2026 17:37:28 +0200 Subject: [PATCH] #14741 Add individual Ric*Feature command tests Curated feature tests exercising specific Ric*Feature commands (close case, new view, delete well path, toggle items, new intersection, Eclipse property/cell filters, well path lateral, perforation interval, summary plot, well log plot, polygon, cell index filter), grouped under FeatureTests/Tests with their own CMakeLists_files.cmake. --- .../FeatureTests/Tests/CMakeLists_files.cmake | 17 ++ .../Tests/RicCloseCaseFeature-Test.cpp | 63 ++++++++ .../Tests/RicCreatePolygonFeature-Test.cpp | 61 ++++++++ .../Tests/RicDeleteWellPathFeature-Test.cpp | 108 +++++++++++++ .../RicEclipsePropertyFilterFeature-Test.cpp | 64 ++++++++ .../Tests/RicNewCellFilterFeature-Test.cpp | 62 ++++++++ .../RicNewCellIndexFilterFeature-Test.cpp | 82 ++++++++++ .../RicNewDefaultSummaryPlotFeature-Test.cpp | 63 ++++++++ .../Tests/RicNewIntersectionFeature-Test.cpp | 90 +++++++++++ .../RicNewPerforationIntervalFeature-Test.cpp | 63 ++++++++ .../Tests/RicNewViewFeature-Test.cpp | 83 ++++++++++ .../Tests/RicNewWellLogPlotFeature-Test.cpp | 66 ++++++++ .../RicNewWellPathLateralFeature-Test.cpp | 61 ++++++++ .../Tests/RicToggleItemsFeature-Test.cpp | 147 ++++++++++++++++++ 14 files changed, 1030 insertions(+) create mode 100644 ApplicationLibCode/FeatureTests/Tests/CMakeLists_files.cmake create mode 100644 ApplicationLibCode/FeatureTests/Tests/RicCloseCaseFeature-Test.cpp create mode 100644 ApplicationLibCode/FeatureTests/Tests/RicCreatePolygonFeature-Test.cpp create mode 100644 ApplicationLibCode/FeatureTests/Tests/RicDeleteWellPathFeature-Test.cpp create mode 100644 ApplicationLibCode/FeatureTests/Tests/RicEclipsePropertyFilterFeature-Test.cpp create mode 100644 ApplicationLibCode/FeatureTests/Tests/RicNewCellFilterFeature-Test.cpp create mode 100644 ApplicationLibCode/FeatureTests/Tests/RicNewCellIndexFilterFeature-Test.cpp create mode 100644 ApplicationLibCode/FeatureTests/Tests/RicNewDefaultSummaryPlotFeature-Test.cpp create mode 100644 ApplicationLibCode/FeatureTests/Tests/RicNewIntersectionFeature-Test.cpp create mode 100644 ApplicationLibCode/FeatureTests/Tests/RicNewPerforationIntervalFeature-Test.cpp create mode 100644 ApplicationLibCode/FeatureTests/Tests/RicNewViewFeature-Test.cpp create mode 100644 ApplicationLibCode/FeatureTests/Tests/RicNewWellLogPlotFeature-Test.cpp create mode 100644 ApplicationLibCode/FeatureTests/Tests/RicNewWellPathLateralFeature-Test.cpp create mode 100644 ApplicationLibCode/FeatureTests/Tests/RicToggleItemsFeature-Test.cpp diff --git a/ApplicationLibCode/FeatureTests/Tests/CMakeLists_files.cmake b/ApplicationLibCode/FeatureTests/Tests/CMakeLists_files.cmake new file mode 100644 index 0000000000..5d2190c7c5 --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/CMakeLists_files.cmake @@ -0,0 +1,17 @@ +set(SOURCE_GROUP_SOURCE_FILES + ${CMAKE_CURRENT_LIST_DIR}/RicDeleteWellPathFeature-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicNewViewFeature-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicCloseCaseFeature-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicToggleItemsFeature-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicNewIntersectionFeature-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicEclipsePropertyFilterFeature-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicNewCellFilterFeature-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicNewWellPathLateralFeature-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicNewPerforationIntervalFeature-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicNewDefaultSummaryPlotFeature-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicNewWellLogPlotFeature-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicCreatePolygonFeature-Test.cpp + ${CMAKE_CURRENT_LIST_DIR}/RicNewCellIndexFilterFeature-Test.cpp +) + +list(APPEND SOURCE_FEATURETEST_FILES ${SOURCE_GROUP_SOURCE_FILES}) diff --git a/ApplicationLibCode/FeatureTests/Tests/RicCloseCaseFeature-Test.cpp b/ApplicationLibCode/FeatureTests/Tests/RicCloseCaseFeature-Test.cpp new file mode 100644 index 0000000000..c351469908 --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/RicCloseCaseFeature-Test.cpp @@ -0,0 +1,63 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "RiaFeatureTestModelBuilder.h" + +#include "RimEclipseCase.h" +#include "RimProject.h" + +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" +#include "cafSelectionManager.h" + +//-------------------------------------------------------------------------------------------------- +/// Executes RicCloseCaseFeature against a selected Eclipse case and asserts the case is removed from +/// the project. +/// +/// This is a curated deep test: it drives a feature end-to-end through the selection system with a +/// valid selection context and asserts the resulting model change. +//-------------------------------------------------------------------------------------------------- +class RicCloseCaseFeatureTest : public ::testing::Test +{ +protected: + void TearDown() override + { + caf::SelectionManager::instance()->clearAll(); + RiaFeatureTestModelBuilder::closeProject(); + } +}; + +TEST_F( RicCloseCaseFeatureTest, CloseSelectedEclipseCaseRemovesItFromProject ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::eclipseCaseWithResults(); + ASSERT_TRUE( model.eclipseCase != nullptr ); + ASSERT_EQ( 1u, RimProject::current()->eclipseCases().size() ); + + caf::SelectionManager::instance()->setSelectedItem( model.eclipseCase ); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicCloseCaseFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + // The case (and its views) are deleted, so model.eclipseCase is now dangling; query the project. + EXPECT_TRUE( RimProject::current()->eclipseCases().empty() ); +} diff --git a/ApplicationLibCode/FeatureTests/Tests/RicCreatePolygonFeature-Test.cpp b/ApplicationLibCode/FeatureTests/Tests/RicCreatePolygonFeature-Test.cpp new file mode 100644 index 0000000000..b919cd4fc4 --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/RicCreatePolygonFeature-Test.cpp @@ -0,0 +1,61 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "RiaFeatureTestModelBuilder.h" + +#include "Polygons/RimPolygonCollection.h" +#include "RimTools.h" + +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" +#include "cafSelectionManager.h" + +//-------------------------------------------------------------------------------------------------- +/// Curated test for RicCreatePolygonFeature, which appends a user-defined polygon to the project's +/// polygon collection. The feature falls back to the global polygon collection when nothing is +/// selected, so no selection or active view is required. +//-------------------------------------------------------------------------------------------------- +class RicCreatePolygonFeatureTest : public ::testing::Test +{ +protected: + void TearDown() override + { + caf::SelectionManager::instance()->clearAll(); + RiaFeatureTestModelBuilder::closeProject(); + } +}; + +TEST_F( RicCreatePolygonFeatureTest, CreatePolygonAddedToCollection ) +{ + // Start from a clean, empty project; the polygon collection exists on the active oil field. + RiaFeatureTestModelBuilder::closeProject(); + + RimPolygonCollection* polygonCollection = RimTools::polygonCollection(); + ASSERT_TRUE( polygonCollection != nullptr ); + const size_t countBefore = polygonCollection->allPolygons().size(); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicCreatePolygonFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + EXPECT_EQ( countBefore + 1, polygonCollection->allPolygons().size() ); +} diff --git a/ApplicationLibCode/FeatureTests/Tests/RicDeleteWellPathFeature-Test.cpp b/ApplicationLibCode/FeatureTests/Tests/RicDeleteWellPathFeature-Test.cpp new file mode 100644 index 0000000000..ed48b596e2 --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/RicDeleteWellPathFeature-Test.cpp @@ -0,0 +1,108 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "RiaFeatureTestModelBuilder.h" + +#include "RimOilField.h" +#include "RimProject.h" +#include "RimWellPath.h" +#include "RimWellPathCollection.h" + +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" +#include "cafSelectionManager.h" + +//-------------------------------------------------------------------------------------------------- +/// Executes RicDeleteWellPathFeature against a selected well path and asserts the well path is +/// removed from the project and dropped from the selection. +/// +/// This is a curated deep test: it drives a feature end-to-end through the selection system with a +/// valid selection context and asserts the resulting model change. +//-------------------------------------------------------------------------------------------------- +class RicDeleteWellPathFeatureTest : public ::testing::Test +{ +protected: + void TearDown() override + { + caf::SelectionManager::instance()->clearAll(); + RiaFeatureTestModelBuilder::closeProject(); + } +}; + +TEST_F( RicDeleteWellPathFeatureTest, DeleteSelectedWellPathRemovesItFromProject ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::wellPath(); + ASSERT_TRUE( model.wellPath != nullptr ); + ASSERT_EQ( 1u, RimProject::current()->allWellPaths().size() ); + + caf::SelectionManager::instance()->setSelectedItem( model.wellPath ); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicDeleteWellPathFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + EXPECT_EQ( 0u, RimProject::current()->allWellPaths().size() ); + + // The deleted object must no longer be part of the selection (dangling-pointer cleanup). + EXPECT_TRUE( caf::SelectionManager::instance()->selectedItems().empty() ); +} + +TEST_F( RicDeleteWellPathFeatureTest, DeleteSelectedWellPathKeepsOtherWellPaths ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::wellPath(); + ASSERT_TRUE( model.wellPath != nullptr ); + + // Add a second well path so the feature must delete only the selected one. + RimOilField* oilField = RimProject::current()->activeOilField(); + ASSERT_TRUE( oilField != nullptr && oilField->wellPathCollection() != nullptr ); + + auto* otherWellPath = new RimWellPath; + otherWellPath->setName( "OtherWellPath" ); + oilField->wellPathCollection()->addWellPath( otherWellPath ); + + ASSERT_EQ( 2u, RimProject::current()->allWellPaths().size() ); + + caf::SelectionManager::instance()->setSelectedItem( model.wellPath ); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicDeleteWellPathFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + const std::vector remaining = RimProject::current()->allWellPaths(); + ASSERT_EQ( 1u, remaining.size() ); + EXPECT_EQ( otherWellPath, remaining.front() ); +} + +TEST_F( RicDeleteWellPathFeatureTest, EmptySelectionIsNotExecutable ) +{ + RiaFeatureTestModelBuilder::wellPath(); + caf::SelectionManager::instance()->clearAll(); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicDeleteWellPathFeature" ); + ASSERT_TRUE( feature != nullptr ); + + // With nothing selected the feature must report itself disabled and leave the project untouched. + EXPECT_FALSE( feature->canFeatureBeExecuted() ); + EXPECT_EQ( 1u, RimProject::current()->allWellPaths().size() ); +} diff --git a/ApplicationLibCode/FeatureTests/Tests/RicEclipsePropertyFilterFeature-Test.cpp b/ApplicationLibCode/FeatureTests/Tests/RicEclipsePropertyFilterFeature-Test.cpp new file mode 100644 index 0000000000..add515762c --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/RicEclipsePropertyFilterFeature-Test.cpp @@ -0,0 +1,64 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "RiaApplication.h" +#include "RiaFeatureTestModelBuilder.h" + +#include "RimEclipsePropertyFilterCollection.h" +#include "RimEclipseView.h" + +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" +#include "cafSelectionManager.h" + +//-------------------------------------------------------------------------------------------------- +/// Curated test for RicEclipsePropertyFilterNewInViewFeature, which adds an Eclipse property filter +/// to the active view's property-filter collection. The feature resolves its context from the active +/// view (RiaApplication::activeMainOrComparisonGridView()), not the selection. +//-------------------------------------------------------------------------------------------------- +class RicEclipsePropertyFilterFeatureTest : public ::testing::Test +{ +protected: + void TearDown() override + { + caf::SelectionManager::instance()->clearAll(); + RiaApplication::instance()->setActiveReservoirView( nullptr ); + RiaFeatureTestModelBuilder::closeProject(); + } +}; + +TEST_F( RicEclipsePropertyFilterFeatureTest, NewPropertyFilterAddedToActiveView ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::eclipseCaseWithResults(); + auto* eclipseView = dynamic_cast( model.eclipseView ); + ASSERT_TRUE( eclipseView != nullptr ); + + RimEclipsePropertyFilterCollection* filterCollection = eclipseView->eclipsePropertyFilterCollection(); + ASSERT_TRUE( filterCollection != nullptr ); + const size_t countBefore = filterCollection->propertyFilters().size(); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicEclipsePropertyFilterNewInViewFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + EXPECT_EQ( countBefore + 1, filterCollection->propertyFilters().size() ); +} diff --git a/ApplicationLibCode/FeatureTests/Tests/RicNewCellFilterFeature-Test.cpp b/ApplicationLibCode/FeatureTests/Tests/RicNewCellFilterFeature-Test.cpp new file mode 100644 index 0000000000..1b1c25a574 --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/RicNewCellFilterFeature-Test.cpp @@ -0,0 +1,62 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "RiaApplication.h" +#include "RiaFeatureTestModelBuilder.h" + +#include "RimCellFilterCollection.h" +#include "RimEclipseView.h" + +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" +#include "cafSelectionManager.h" + +//-------------------------------------------------------------------------------------------------- +/// Curated test for RicNewPolygonFilter3dviewFeature, which adds a polygon cell filter to the active +/// view's cell-filter collection. The feature resolves its context from the active view. +//-------------------------------------------------------------------------------------------------- +class RicNewCellFilterFeatureTest : public ::testing::Test +{ +protected: + void TearDown() override + { + caf::SelectionManager::instance()->clearAll(); + RiaApplication::instance()->setActiveReservoirView( nullptr ); + RiaFeatureTestModelBuilder::closeProject(); + } +}; + +TEST_F( RicNewCellFilterFeatureTest, NewPolygonFilterAddedToActiveView ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::eclipseCaseWithResults(); + ASSERT_TRUE( model.eclipseView != nullptr ); + + RimCellFilterCollection* filterCollection = model.eclipseView->cellFilterCollection(); + ASSERT_TRUE( filterCollection != nullptr ); + const size_t countBefore = filterCollection->filters().size(); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicNewPolygonFilter3dviewFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + EXPECT_EQ( countBefore + 1, filterCollection->filters().size() ); +} diff --git a/ApplicationLibCode/FeatureTests/Tests/RicNewCellIndexFilterFeature-Test.cpp b/ApplicationLibCode/FeatureTests/Tests/RicNewCellIndexFilterFeature-Test.cpp new file mode 100644 index 0000000000..a3bc486500 --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/RicNewCellIndexFilterFeature-Test.cpp @@ -0,0 +1,82 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "RiaApplication.h" +#include "RiaFeatureTestModelBuilder.h" + +#include "RimCellFilterCollection.h" +#include "RimGeoMechCase.h" +#include "RimGridView.h" + +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" +#include "cafSelectionManager.h" + +//-------------------------------------------------------------------------------------------------- +/// Curated test for RicNewCellIndexFilterFeature ("New Element Set Filter"), which is only enabled +/// when the active grid view belongs to a GeoMech case. It adds a cell index filter to that view's +/// cell filter collection. +/// +/// The GeoMech model is the small VTK (.pvd) model from the unit test data, so no Abaqus/ODB +/// dependency is needed. +//-------------------------------------------------------------------------------------------------- +class RicNewCellIndexFilterFeatureTest : public ::testing::Test +{ +protected: + void TearDown() override + { + caf::SelectionManager::instance()->clearAll(); + RiaApplication::instance()->setActiveReservoirView( nullptr ); + RiaFeatureTestModelBuilder::closeProject(); + } +}; + +TEST_F( RicNewCellIndexFilterFeatureTest, NewCellIndexFilterAddedToActiveGeoMechView ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::geoMechCase(); + ASSERT_TRUE( model.geoMechCase != nullptr ); + ASSERT_TRUE( model.geoMechView != nullptr ); + + RimCellFilterCollection* filterCollection = model.geoMechView->cellFilterCollection(); + ASSERT_TRUE( filterCollection != nullptr ); + const size_t countBefore = filterCollection->filters().size(); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicNewCellIndexFilterFeature" ); + ASSERT_TRUE( feature != nullptr ); + + // Enabled only because the active view's owner case is a GeoMech case. + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + EXPECT_EQ( countBefore + 1, filterCollection->filters().size() ); +} + +TEST_F( RicNewCellIndexFilterFeatureTest, NotExecutableForEclipseView ) +{ + // The same feature must stay disabled when the active view belongs to an Eclipse case. + FeatureTestModel model = RiaFeatureTestModelBuilder::eclipseCaseWithResults(); + ASSERT_TRUE( model.eclipseView != nullptr ); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicNewCellIndexFilterFeature" ); + ASSERT_TRUE( feature != nullptr ); + + EXPECT_FALSE( feature->canFeatureBeExecuted() ); +} diff --git a/ApplicationLibCode/FeatureTests/Tests/RicNewDefaultSummaryPlotFeature-Test.cpp b/ApplicationLibCode/FeatureTests/Tests/RicNewDefaultSummaryPlotFeature-Test.cpp new file mode 100644 index 0000000000..64083f5826 --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/RicNewDefaultSummaryPlotFeature-Test.cpp @@ -0,0 +1,63 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "RiaFeatureTestModelBuilder.h" + +#include "RimMainPlotCollection.h" +#include "RimSummaryCase.h" +#include "RimSummaryMultiPlotCollection.h" + +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" +#include "cafSelectionManager.h" + +//-------------------------------------------------------------------------------------------------- +/// Curated test for RicNewDefaultSummaryPlotFeature, which creates a summary multi plot from a +/// selected summary case. Uses an in-memory RimMockSummaryCase (no .SMSPEC file). +//-------------------------------------------------------------------------------------------------- +class RicNewDefaultSummaryPlotFeatureTest : public ::testing::Test +{ +protected: + void TearDown() override + { + caf::SelectionManager::instance()->clearAll(); + RiaFeatureTestModelBuilder::closeProject(); + } +}; + +TEST_F( RicNewDefaultSummaryPlotFeatureTest, NewDefaultSummaryPlotFromSelectedCaseIsAdded ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::summaryCase(); + ASSERT_TRUE( model.summaryCase != nullptr ); + + RimSummaryMultiPlotCollection* plotCollection = RimMainPlotCollection::current()->summaryMultiPlotCollection(); + ASSERT_TRUE( plotCollection != nullptr ); + const size_t countBefore = plotCollection->multiPlots().size(); + + caf::SelectionManager::instance()->setSelectedItem( model.summaryCase ); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicNewDefaultSummaryPlotFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + EXPECT_EQ( countBefore + 1, plotCollection->multiPlots().size() ); +} diff --git a/ApplicationLibCode/FeatureTests/Tests/RicNewIntersectionFeature-Test.cpp b/ApplicationLibCode/FeatureTests/Tests/RicNewIntersectionFeature-Test.cpp new file mode 100644 index 0000000000..59eea02d29 --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/RicNewIntersectionFeature-Test.cpp @@ -0,0 +1,90 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "RiaApplication.h" +#include "RiaFeatureTestModelBuilder.h" + +#include "RimEclipseView.h" +#include "RimIntersectionCollection.h" + +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" +#include "cafSelectionManager.h" + +//-------------------------------------------------------------------------------------------------- +/// Curated tests for the intersection-creation features that read the active 3D view rather than the +/// selection (RiaApplication::activeReservoirView() / activeGridView()). +/// +/// These exercise the active-view path of the harness: RiaFeatureTestModelBuilder sets the active +/// reservoir view when it builds an Eclipse model, so features that resolve their context from the +/// active view have a valid context without depending on the project tree selection. +//-------------------------------------------------------------------------------------------------- +class RicNewIntersectionFeatureTest : public ::testing::Test +{ +protected: + void TearDown() override + { + caf::SelectionManager::instance()->clearAll(); + RiaApplication::instance()->setActiveReservoirView( nullptr ); + RiaFeatureTestModelBuilder::closeProject(); + } +}; + +TEST_F( RicNewIntersectionFeatureTest, BuilderActivatesReservoirView ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::eclipseCaseWithResults(); + ASSERT_TRUE( model.eclipseView != nullptr ); + + // The builder must publish the view as the active reservoir view so active-view features work. + EXPECT_EQ( model.eclipseView, RiaApplication::instance()->activeReservoirView() ); +} + +TEST_F( RicNewIntersectionFeatureTest, AzimuthDipIntersectionAddedToActiveViewCollection ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::eclipseCaseWithResults(); + ASSERT_TRUE( model.eclipseView != nullptr ); + + const size_t countBefore = model.eclipseView->intersectionCollection()->intersections().size(); + + // No selection is set: the feature must resolve the view from RiaApplication::activeGridView(). + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicNewAzimuthDipIntersectionFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + EXPECT_EQ( countBefore + 1, model.eclipseView->intersectionCollection()->intersections().size() ); +} + +TEST_F( RicNewIntersectionFeatureTest, PolylineIntersectionAddedToActiveViewCollection ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::eclipseCaseWithResults(); + ASSERT_TRUE( model.eclipseView != nullptr ); + + const size_t countBefore = model.eclipseView->intersectionCollection()->intersections().size(); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicNewPolylineIntersectionFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + EXPECT_EQ( countBefore + 1, model.eclipseView->intersectionCollection()->intersections().size() ); +} diff --git a/ApplicationLibCode/FeatureTests/Tests/RicNewPerforationIntervalFeature-Test.cpp b/ApplicationLibCode/FeatureTests/Tests/RicNewPerforationIntervalFeature-Test.cpp new file mode 100644 index 0000000000..174a52a10f --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/RicNewPerforationIntervalFeature-Test.cpp @@ -0,0 +1,63 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "RiaFeatureTestModelBuilder.h" + +#include "RimPerforationCollection.h" +#include "RimWellPath.h" + +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" +#include "cafSelectionManager.h" + +//-------------------------------------------------------------------------------------------------- +/// Curated test for RicNewPerforationIntervalFeature, which appends a perforation interval to the +/// perforation collection of the selected well path. The selected well path resolves to its +/// perforation collection, and its unit system (set by the builder) avoids a unit-system dialog. +//-------------------------------------------------------------------------------------------------- +class RicNewPerforationIntervalFeatureTest : public ::testing::Test +{ +protected: + void TearDown() override + { + caf::SelectionManager::instance()->clearAll(); + RiaFeatureTestModelBuilder::closeProject(); + } +}; + +TEST_F( RicNewPerforationIntervalFeatureTest, NewPerforationIntervalAddedToSelectedWellPath ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::wellPath(); + ASSERT_TRUE( model.wellPath != nullptr ); + + RimPerforationCollection* perforationCollection = model.wellPath->perforationIntervalCollection(); + ASSERT_TRUE( perforationCollection != nullptr ); + const size_t countBefore = perforationCollection->perforations().size(); + + caf::SelectionManager::instance()->setSelectedItem( model.wellPath ); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicNewPerforationIntervalFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + EXPECT_EQ( countBefore + 1, perforationCollection->perforations().size() ); +} diff --git a/ApplicationLibCode/FeatureTests/Tests/RicNewViewFeature-Test.cpp b/ApplicationLibCode/FeatureTests/Tests/RicNewViewFeature-Test.cpp new file mode 100644 index 0000000000..805504a178 --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/RicNewViewFeature-Test.cpp @@ -0,0 +1,83 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "RiaFeatureTestModelBuilder.h" + +#include "RimEclipseCase.h" +#include "RimEclipseView.h" + +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" +#include "cafSelectionManager.h" + +//-------------------------------------------------------------------------------------------------- +/// Executes RicNewViewFeature against a selected Eclipse case and asserts that a new reservoir view +/// is added to the case. +/// +/// This is a curated deep test: it drives a feature end-to-end through the selection system with a +/// valid selection context and asserts the resulting model change. +//-------------------------------------------------------------------------------------------------- +class RicNewViewFeatureTest : public ::testing::Test +{ +protected: + void TearDown() override + { + caf::SelectionManager::instance()->clearAll(); + RiaFeatureTestModelBuilder::closeProject(); + } +}; + +TEST_F( RicNewViewFeatureTest, NewViewFromSelectedEclipseCaseAddsAView ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::eclipseCaseWithResults(); + ASSERT_TRUE( model.eclipseCase != nullptr ); + + const size_t viewCountBefore = model.eclipseCase->reservoirViews().size(); + + caf::SelectionManager::instance()->setSelectedItem( model.eclipseCase ); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicNewViewFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + EXPECT_EQ( viewCountBefore + 1, model.eclipseCase->reservoirViews().size() ); +} + +TEST_F( RicNewViewFeatureTest, NewViewFromSelectedViewAddsAViewToSameCase ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::eclipseCaseWithResults(); + ASSERT_TRUE( model.eclipseCase != nullptr ); + ASSERT_TRUE( model.eclipseView != nullptr ); + + const size_t viewCountBefore = model.eclipseCase->reservoirViews().size(); + + // Selecting a view (rather than the case) must also create a new view in the view's own case. + caf::SelectionManager::instance()->setSelectedItem( model.eclipseView ); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicNewViewFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + EXPECT_EQ( viewCountBefore + 1, model.eclipseCase->reservoirViews().size() ); +} diff --git a/ApplicationLibCode/FeatureTests/Tests/RicNewWellLogPlotFeature-Test.cpp b/ApplicationLibCode/FeatureTests/Tests/RicNewWellLogPlotFeature-Test.cpp new file mode 100644 index 0000000000..5a75133fd0 --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/RicNewWellLogPlotFeature-Test.cpp @@ -0,0 +1,66 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "RiaFeatureTestModelBuilder.h" + +#include "RimMainPlotCollection.h" +#include "RimWellLogPlotCollection.h" + +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" +#include "cafSelectionManager.h" + +//-------------------------------------------------------------------------------------------------- +/// Curated test for RicNewWellLogPlotFeature, which creates a new well log plot (with a track and an +/// extraction curve) in the well log plot collection. The feature needs no selection. +//-------------------------------------------------------------------------------------------------- +class RicNewWellLogPlotFeatureTest : public ::testing::Test +{ +protected: + void TearDown() override + { + caf::SelectionManager::instance()->clearAll(); + RiaFeatureTestModelBuilder::closeProject(); + } +}; + +// Disabled: segfaults on Linux (seen on Ubuntu 24.04 clang-19 in CI) while it passes on Windows and +// on Ubuntu gcc. The same feature was the one that crashed in the execution sweep until the sweep +// stopped pumping the event loop, so the plot and curve construction here looks fragile without a +// real rendering context rather than the test being wrong. Re-enable once that is understood, most +// likely together with the software-OpenGL test tier. +TEST_F( RicNewWellLogPlotFeatureTest, DISABLED_NewWellLogPlotIsAddedToCollection ) +{ + // A well path (with geometry) gives the extraction curve something to reference. + FeatureTestModel model = RiaFeatureTestModelBuilder::combinedModel(); + ASSERT_TRUE( model.eclipseView != nullptr ); + + RimWellLogPlotCollection* plotCollection = RimMainPlotCollection::current()->wellLogPlotCollection(); + ASSERT_TRUE( plotCollection != nullptr ); + const size_t countBefore = plotCollection->wellLogPlots().size(); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicNewWellLogPlotFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + EXPECT_EQ( countBefore + 1, plotCollection->wellLogPlots().size() ); +} diff --git a/ApplicationLibCode/FeatureTests/Tests/RicNewWellPathLateralFeature-Test.cpp b/ApplicationLibCode/FeatureTests/Tests/RicNewWellPathLateralFeature-Test.cpp new file mode 100644 index 0000000000..904544c7b8 --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/RicNewWellPathLateralFeature-Test.cpp @@ -0,0 +1,61 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "RiaFeatureTestModelBuilder.h" + +#include "RimProject.h" +#include "RimWellPath.h" + +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" +#include "cafSelectionManager.h" + +//-------------------------------------------------------------------------------------------------- +/// Curated test for RicNewWellPathLateralFeature, which creates a well path lateral from a selected +/// well path. Requires the parent well path to have a real trajectory (more than two measured +/// depths), which RiaFeatureTestModelBuilder provides. +//-------------------------------------------------------------------------------------------------- +class RicNewWellPathLateralFeatureTest : public ::testing::Test +{ +protected: + void TearDown() override + { + caf::SelectionManager::instance()->clearAll(); + RiaFeatureTestModelBuilder::closeProject(); + } +}; + +TEST_F( RicNewWellPathLateralFeatureTest, NewLateralFromSelectedWellPathIsAdded ) +{ + FeatureTestModel model = RiaFeatureTestModelBuilder::wellPath(); + ASSERT_TRUE( model.wellPath != nullptr ); + ASSERT_EQ( 1u, RimProject::current()->allWellPaths().size() ); + + caf::SelectionManager::instance()->setSelectedItem( model.wellPath ); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicNewWellPathLateralFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + // The new lateral is a modeled well path added to the collection. + EXPECT_EQ( 2u, RimProject::current()->allWellPaths().size() ); +} diff --git a/ApplicationLibCode/FeatureTests/Tests/RicToggleItemsFeature-Test.cpp b/ApplicationLibCode/FeatureTests/Tests/RicToggleItemsFeature-Test.cpp new file mode 100644 index 0000000000..b29ab00bff --- /dev/null +++ b/ApplicationLibCode/FeatureTests/Tests/RicToggleItemsFeature-Test.cpp @@ -0,0 +1,147 @@ +///////////////////////////////////////////////////////////////////////////////// +// +// Copyright (C) 2026 Equinor ASA +// +// ResInsight is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// ResInsight is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. +// +// See the GNU General Public License at +// for more details. +// +///////////////////////////////////////////////////////////////////////////////// + +#include "gtest/gtest.h" + +#include "RiaFeatureTestModelBuilder.h" +#include "RiaFeatureTestTreeView.h" + +#include "RimOilField.h" +#include "RimProject.h" +#include "RimWellPath.h" +#include "RimWellPathCollection.h" + +#include "cafCmdFeature.h" +#include "cafCmdFeatureManager.h" +#include "cafSelectionManager.h" + +#include + +//-------------------------------------------------------------------------------------------------- +/// Exercises the RicToggleItems*Feature family against the children of a selected collection. +/// +/// These features are tree-driven: with a single object selected they toggle the objectToggleField +/// of that object's tree children (see RicToggleItemsFeatureImpl). Because the feature-test +/// main window project tree is not populated with the model built here, the tree is supplied by +/// RiaFeatureTestTreeView, which registers a +/// headless project tree view via RiaFeatureCommandContext. +/// +/// The well path collection is used as the selected object: its tree children are the well paths, +/// each of which has a boolean objectToggleField (RimWellPath::showWellPath). +//-------------------------------------------------------------------------------------------------- +class RicToggleItemsFeatureTest : public ::testing::Test +{ +protected: + void SetUp() override + { + RiaFeatureTestModelBuilder::wellPath(); + + RimOilField* oilField = RimProject::current()->activeOilField(); + m_wellPathCollection = ( oilField != nullptr ) ? oilField->wellPathCollection() : nullptr; + + if ( m_wellPathCollection != nullptr ) + { + // A single-child collection is enough, but add a second so the toggle must touch more + // than one field. + auto* secondWellPath = new RimWellPath; + secondWellPath->setName( "TestWellPath2" ); + m_wellPathCollection->addWellPath( secondWellPath ); + } + } + + void TearDown() override + { + caf::SelectionManager::instance()->clearAll(); + RiaFeatureTestModelBuilder::closeProject(); + } + + void setShowStateForAllWellPaths( bool show ) + { + for ( RimWellPath* wellPath : m_wellPathCollection->allWellPaths() ) + { + wellPath->setShowWellPath( show ); + } + } + + RimWellPathCollection* m_wellPathCollection = nullptr; +}; + +TEST_F( RicToggleItemsFeatureTest, ToggleOffHidesAllChildWellPaths ) +{ + ASSERT_TRUE( m_wellPathCollection != nullptr ); + ASSERT_EQ( 2u, m_wellPathCollection->allWellPaths().size() ); + setShowStateForAllWellPaths( true ); + + RiaFeatureTestTreeView treeView; + caf::SelectionManager::instance()->setSelectedItem( m_wellPathCollection ); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicToggleItemsOffFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + for ( RimWellPath* wellPath : m_wellPathCollection->allWellPaths() ) + { + EXPECT_FALSE( wellPath->showWellPath() ); + } +} + +TEST_F( RicToggleItemsFeatureTest, ToggleOnShowsAllChildWellPaths ) +{ + ASSERT_TRUE( m_wellPathCollection != nullptr ); + setShowStateForAllWellPaths( false ); + + RiaFeatureTestTreeView treeView; + caf::SelectionManager::instance()->setSelectedItem( m_wellPathCollection ); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicToggleItemsOnFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + for ( RimWellPath* wellPath : m_wellPathCollection->allWellPaths() ) + { + EXPECT_TRUE( wellPath->showWellPath() ); + } +} + +TEST_F( RicToggleItemsFeatureTest, ToggleFlipsEachChildShowState ) +{ + ASSERT_TRUE( m_wellPathCollection != nullptr ); + + const std::vector wellPaths = m_wellPathCollection->allWellPaths(); + ASSERT_EQ( 2u, wellPaths.size() ); + + // Give the two well paths opposite states, then assert each is individually flipped. + wellPaths[0]->setShowWellPath( true ); + wellPaths[1]->setShowWellPath( false ); + + RiaFeatureTestTreeView treeView; + caf::SelectionManager::instance()->setSelectedItem( m_wellPathCollection ); + + caf::CmdFeature* feature = caf::CmdFeatureManager::instance()->getCommandFeature( "RicToggleItemsFeature" ); + ASSERT_TRUE( feature != nullptr ); + ASSERT_TRUE( feature->canFeatureBeExecuted() ); + + feature->actionTriggered( false ); + + EXPECT_FALSE( wellPaths[0]->showWellPath() ); + EXPECT_TRUE( wellPaths[1]->showWellPath() ); +}