Skip to content

Commit 29e8e46

Browse files
committed
Improving UTs: refactoring of TestMIANodeController methods, 2
- test_filter_widget
1 parent c6a5b08 commit 29e8e46

File tree

1 file changed

+117
-102
lines changed

1 file changed

+117
-102
lines changed

populse_mia/tests/run_mia_test.py

Lines changed: 117 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -321,16 +321,16 @@ class TestMIACase(unittest.TestCase):
321321
- tearDownClass: called after tests in the individual class
322322
"""
323323

324-
def add_visualized_tag(self, input_filter, tag, timeout=5000):
324+
def add_visualized_tag(self, widget, tag, timeout=5000):
325325
"""
326326
Selects a tag to display from the "Visualized tags" pop-up.
327327
328328
This method waits for the tag selection dialog to become available
329329
within the given timeout period, locates the specified tag in the
330330
tag list, selects it, and confirms the dialog.
331331
332-
:param input_filter: The input filter containing the dialog
333-
with visualized tags.
332+
:param widget: The input filter containing the dialog
333+
with visualized tags.
334334
:param tag (str): The tag name to select and visualize.
335335
:param timeout (int): Maximum time to wait for the dialog to appear,
336336
in milliseconds. Defaults to 5000 ms.
@@ -344,7 +344,7 @@ def add_visualized_tag(self, input_filter, tag, timeout=5000):
344344

345345
while time.time() - start_time < timeout_secs:
346346

347-
if getattr(input_filter, "dialog", None):
347+
if getattr(widget, "dialog", None):
348348
break
349349

350350
self._app.processEvents()
@@ -353,7 +353,7 @@ def add_visualized_tag(self, input_filter, tag, timeout=5000):
353353
else:
354354
raise RuntimeError("Dialog not available")
355355

356-
dialog = input_filter.dialog
356+
dialog = widget.dialog
357357
visualized_tags = dialog.layout().itemAt(0).widget()
358358

359359
if not visualized_tags:
@@ -7443,146 +7443,126 @@ def test_display_filter(self):
74437443
# system in order to make the necessary corrections.
74447444
# @unittest.skip("skip this test until it has been repaired.")
74457445
def test_filter_widget(self):
7446-
"""Places a node of the "Input_Filter" process, feeds in documents
7447-
and opens up the "FilterWidget()" to modify its parameters.
7446+
"""
7447+
Tests the `FilterWidget` class used for filtering input data within a
7448+
Capsul pipeline node.
7449+
7450+
This test:
7451+
- Switches to the V1 node controller (if not already active)
7452+
- Adds an `Input_Filter` process to the pipeline
7453+
- Feeds in documents from a test project
7454+
- Opens the filter widget for the added node
7455+
- Performs various filtering actions:
7456+
* Searching for documents by name
7457+
* Toggling tag visibility
7458+
* Filtering by a specific tag (mocking user interaction)
7459+
7460+
The `FilterWidget` is GUI-independent and works in both V1 and V2 node
7461+
controller UIs. Only the V1 GUI is exercised here.
74487462
7449-
Tests the class FilterWidget() within the Node Controller V1
7450-
(class NodeController()). The class FilterWidget() is
7451-
independent on the Node
7452-
Controller version (V1 or V2) and can be used in both of them.
7463+
Mocks:
7464+
- `PopUpSelectTagCountTable.exec_()`
74537465
"""
74547466
config = Config(properties_path=self.properties_path)
7455-
controlV1_ver = config.isControlV1()
7467+
controlV1 = config.isControlV1()
74567468

74577469
# Switch to V1 node controller GUI, if necessary
7458-
if not controlV1_ver:
7470+
if not controlV1:
74597471
config.setControlV1(True)
74607472
self.restart_MIA()
74617473

74627474
# Opens project 8 and switches to it
74637475
project_8_path = self.get_new_test_project()
74647476
self.main_window.switch_project(project_8_path, "project_8")
74657477

7466-
with self.main_window.project.database.data() as database_data:
7467-
DOCUMENT_1 = database_data.get_document_names(COLLECTION_CURRENT)[
7468-
0
7469-
]
7470-
DOCUMENT_2 = database_data.get_document_names(COLLECTION_CURRENT)[
7471-
1
7472-
]
7478+
with self.main_window.project.database.data() as db:
7479+
doc1, doc2 = db.get_document_names(COLLECTION_CURRENT)[:2]
74737480

74747481
ppl_edt_tabs = self.main_window.pipeline_manager.pipelineEditorTabs
74757482
node_ctrler = self.main_window.pipeline_manager.nodeController
74767483
self.main_window.tabs.setCurrentIndex(2)
74777484

7478-
# Adds the process "input_filter_1"
7479-
process_class = Input_Filter
7480-
ppl_edt_tabs.get_current_editor().click_pos = QPoint(450, 500)
7481-
ppl_edt_tabs.get_current_editor().add_named_process(process_class)
7485+
# Add Input_Filter node
7486+
editor = ppl_edt_tabs.get_current_editor()
7487+
editor.click_pos = QPoint(450, 500)
7488+
editor.add_named_process(Input_Filter)
74827489
pipeline = ppl_edt_tabs.get_current_pipeline()
74837490

7484-
# Exports the input plugs for "input_filter_1"
7485-
ppl_edt_tabs.get_current_editor().current_node_name = "input_filter_1"
7486-
(
7487-
ppl_edt_tabs.get_current_editor
7488-
)().export_node_unconnected_mandatory_plugs()
7489-
7490-
# Displays parameters of the "inputs" node
7491+
# Export mandatory plugs and display parameters
7492+
editor.current_node_name = "input_filter_1"
7493+
editor.export_node_unconnected_mandatory_plugs()
74917494
input_process = pipeline.nodes[""].process
74927495
node_ctrler.display_parameters(
74937496
"inputs", get_process_instance(input_process), pipeline
74947497
)
74957498

7496-
# Opens a filter for the plug "input" of the "inputs" node
7497-
parameters = (0, pipeline, type(Undefined))
7499+
# Show filter for input plug of "inputs" node
74987500
node_ctrler.display_filter(
7499-
"inputs", "input", parameters, input_process
7501+
"inputs", "input", (0, pipeline, type(Undefined)), input_process
75007502
)
7503+
node_ctrler.pop_up.ok_clicked() # Select all records
75017504

7502-
# Selects all records in the "input" node
7503-
plug_filter = node_ctrler.pop_up
7504-
7505-
plug_filter.ok_clicked()
7506-
7507-
# Opens the filter widget for the node "input_filter_1"
7505+
# Open FilterWidget
75087506
ppl_edt_tabs.open_filter("input_filter_1")
75097507
input_filter = ppl_edt_tabs.filter_widget
75107508

7511-
index_DOCUMENT_1 = input_filter.table_data.get_scan_row(DOCUMENT_1)
7512-
index_DOCUMENT_2 = input_filter.table_data.get_scan_row(DOCUMENT_2)
7509+
idx_doc1 = input_filter.table_data.get_scan_row(doc1)
7510+
idx_doc2 = input_filter.table_data.get_scan_row(doc2)
75137511

7514-
# Tries to search for an empty string and asserts that none of the
7515-
# documents are hidden
7512+
# Filter with empty string, all rows should be visible
75167513
input_filter.search_str("")
75177514

7518-
# Test "DOCUMENT_1" is not hidden
7515+
# Test doc1 and doc2 are not hidden
75197516
if platform.system() == "Windows":
75207517
print(
7521-
"L7522input_filter.table_data.isRowHidden(index_DOCUMENT_1): ",
7522-
input_filter.table_data.isRowHidden(index_DOCUMENT_1),
7518+
"L7517 input_filter.table_data.isRowHidden(idx_doc1): ",
7519+
input_filter.table_data.isRowHidden(idx_doc1),
75237520
)
7524-
7525-
else:
7526-
self.assertFalse(
7527-
input_filter.table_data.isRowHidden(index_DOCUMENT_1)
7528-
)
7529-
7530-
# Test "DOCUMENT_2" is not hidden
7531-
if platform.system() == "Windows":
75327521
print(
7533-
"L7534input_filter.table_data.isRowHidden(index_DOCUMENT_2): ",
7534-
input_filter.table_data.isRowHidden(index_DOCUMENT_2),
7522+
"L7521 input_filter.table_data.isRowHidden(idx_doc2): ",
7523+
input_filter.table_data.isRowHidden(idx_doc2),
75357524
)
75367525

75377526
else:
7538-
self.assertFalse(
7539-
input_filter.table_data.isRowHidden(index_DOCUMENT_2)
7540-
)
7527+
self.assertFalse(input_filter.table_data.isRowHidden(idx_doc1))
7528+
self.assertFalse(input_filter.table_data.isRowHidden(idx_doc2))
75417529

7542-
# Searches for "DOCUMENT_2" and verifies that "DOCUMENT_1" is hidden
7543-
input_filter.search_str(DOCUMENT_2)
7544-
self.assertTrue(input_filter.table_data.isRowHidden(index_DOCUMENT_1))
7530+
# Search for doc2: doc1 hidden, doc2 visible
7531+
input_filter.search_str(doc2)
7532+
self.assertTrue(input_filter.table_data.isRowHidden(idx_doc1))
75457533

75467534
if platform.system() == "Windows":
75477535
print(
7548-
"L7547input_filter.table_data.isRowHidden(index_DOCUMENT_2): ",
7549-
input_filter.table_data.isRowHidden(index_DOCUMENT_2),
7536+
"L7535 input_filter.table_data.isRowHidden(idx_doc2): ",
7537+
input_filter.table_data.isRowHidden(idx_doc2),
75507538
)
75517539

75527540
else:
7553-
self.assertFalse(
7554-
input_filter.table_data.isRowHidden(index_DOCUMENT_2)
7555-
)
7541+
self.assertFalse(input_filter.table_data.isRowHidden(idx_doc2))
75567542

7557-
# Resets the search bar and assert that none of the documents
7558-
# are hidden
7543+
# Reset search, both documents visible again
75597544
input_filter.reset_search_bar()
75607545

7561-
# Test "DOCUMENT_1" is not hidden
75627546
if platform.system() == "Windows":
75637547
print(
7564-
"L7563input_filter.table_data.isRowHidden(index_DOCUMENT_1): ",
7565-
input_filter.table_data.isRowHidden(index_DOCUMENT_1),
7548+
"L7547 input_filter.table_data.isRowHidden(idx_doc1): ",
7549+
input_filter.table_data.isRowHidden(idx_doc1),
75667550
)
7567-
7568-
else:
7569-
self.assertFalse(
7570-
input_filter.table_data.isRowHidden(index_DOCUMENT_1)
7571-
)
7572-
7573-
# Test "DOCUMENT_2" is not hidden
7574-
if platform.system() == "Windows":
75757551
print(
7576-
"L7575input_filter.table_data.isRowHidden(index_DOCUMENT_2): ",
7577-
input_filter.table_data.isRowHidden(index_DOCUMENT_2),
7552+
"L7551 input_filter.table_data.isRowHiddenidx_doc2): ",
7553+
input_filter.table_data.isRowHidden(idx_doc2),
75787554
)
75797555

75807556
else:
7581-
self.assertFalse(
7582-
input_filter.table_data.isRowHidden(index_DOCUMENT_2)
7583-
)
7557+
self.assertFalse(input_filter.table_data.isRowHidden(idx_doc1))
7558+
self.assertFalse(input_filter.table_data.isRowHidden(idx_doc2))
7559+
7560+
tag_col_idx = input_filter.table_data.get_tag_column("AcquisitionDate")
7561+
7562+
# Test "AcquisitionDate" header name column is hidden
7563+
self.assertTrue(input_filter.table_data.isColumnHidden(tag_col_idx))
75847564

7585-
# Opens the "Visualized tags" pop up and adds the "AcquisitionDate" tag
7565+
# Add "AcquisitionDate" as a visualized tag
75867566
QTimer.singleShot(
75877567
100,
75887568
lambda: self.add_visualized_tag(
@@ -7591,29 +7571,64 @@ def test_filter_widget(self):
75917571
)
75927572
input_filter.update_tags()
75937573

7594-
# FIXME: The following statement is always True (not the correct test)
7595-
self.assertTrue(
7596-
type(input_filter.table_data.get_tag_column("AcquisitionDate"))
7597-
== int
7598-
)
7574+
# Test "AcquisitionDate" header name column is not hidden
7575+
self.assertFalse(input_filter.table_data.isColumnHidden(tag_col_idx))
7576+
7577+
# Mock selection of the tag to filter
7578+
def create_mock_exec(tag_name):
7579+
"""
7580+
Create a mock function for PopUpSelectTagCountTable.exec_() that
7581+
simulates user tag selection behavior.
7582+
7583+
This function returns a mock implementation that programmatically
7584+
selects a specific tag from the popup's list widget and triggers
7585+
the OK action, simulating the user workflow without requiring
7586+
actual UI interaction.
7587+
7588+
:param tag_name (str): The name of the tag to select from the
7589+
list. This should match the text of one of
7590+
the items in the popup's list widget.
7591+
7592+
:return: A mock function that can be used to replace exec_()
7593+
method.
7594+
"""
7595+
7596+
def mock_exec(self):
7597+
"""
7598+
Mock implementation of exec_() that simulates tag selection.
7599+
7600+
Searches through the popup's list widget for an item with text
7601+
matching the specified tag name, checks it, and calls
7602+
ok_clicked() to simulate the user confirming their selection.
7603+
7604+
:param self: The PopUpSelectTagCountTable instance
7605+
7606+
:return: True to simulate successful dialog execution
7607+
"""
7608+
# Find and select the specific tag
7609+
for i in range(self.list_widget_tags.count()):
7610+
item = self.list_widget_tags.item(i)
7611+
7612+
if item.text() == tag_name:
7613+
item.setCheckState(Qt.Checked)
7614+
break
7615+
7616+
self.ok_clicked()
7617+
return True
7618+
7619+
return mock_exec
75997620

7600-
# Updates the tag to filter with
76017621
with patch.object(
7602-
PopUpSelectTagCountTable, "exec_", return_value=True
7622+
PopUpSelectTagCountTable, "exec_", create_mock_exec(TAG_FILENAME)
76037623
):
76047624
input_filter.update_tag_to_filter()
76057625

7606-
input_filter.push_button_tag_filter.setText(TAG_FILENAME)
7607-
# TODO: select tag to filter with
7608-
7609-
# Closes the filter
7610-
input_filter.ok_clicked()
7626+
input_filter.ok_clicked() # Close widget
76117627

7612-
# Switches back to node controller V2, if necessary (return to initial
7613-
# state)
7628+
# Restore controller to V2 if needed
76147629
config = Config(properties_path=self.properties_path)
76157630

7616-
if not controlV1_ver:
7631+
if not controlV1:
76177632
config.setControlV1(False)
76187633

76197634
def test_node_controller(self):

0 commit comments

Comments
 (0)