diff --git a/tests/unit_tests/test_scan_history_browser.py b/tests/unit_tests/test_scan_history_browser.py index 4a62cfdb..8d688ad7 100644 --- a/tests/unit_tests/test_scan_history_browser.py +++ b/tests/unit_tests/test_scan_history_browser.py @@ -5,6 +5,7 @@ from bec_lib.messages import ScanHistoryMessage from pytestqt import qtbot from qtpy import QtCore +from bec_widgets.utils.colors import get_accent_colors from bec_widgets.widgets.services.scan_history_browser.components import ( ScanHistoryDeviceViewer, ScanHistoryMetadataViewer, @@ -28,7 +29,7 @@ def scan_history_msg(): exit_status="closed", num_points=10, request_inputs={"some_input": "value"}, - device_data_info={"device1": 10, "device2": 20, "device3": 1}, + device_data_info={"device1": (10,), "device2": (20,), "device3": (1,)}, ) @@ -40,37 +41,257 @@ def scan_history_device_viewer(qtbot, mocked_client): yield widget -def test_scan_history_device_viewer_init(scan_history_device_viewer): - """Test the initialization of ScanHistoryDeviceViewer.""" - assert scan_history_device_viewer.scan_history_msg is None - assert scan_history_device_viewer._selected_device == "" - assert scan_history_device_viewer.device_model.devices == [] - assert scan_history_device_viewer.device_model.rowCount() == 0 +@pytest.fixture +def scan_history_metadata_viewer(qtbot, mocked_client): + widget = ScanHistoryMetadataViewer(client=mocked_client) + qtbot.addWidget(widget) + qtbot.waitExposed(widget) + yield widget -def test_scan_history_device_viewer_update_logic( +@pytest.fixture +def scan_history_view(qtbot, mocked_client): + widget = ScanHistoryView(client=mocked_client) + qtbot.addWidget(widget) + qtbot.waitExposed(widget) + yield widget + + +def test_scan_history_device_viewer_receive_msg( qtbot, scan_history_device_viewer, scan_history_msg ): """Test updating devices from scan history.""" # Update with first scan history message assert scan_history_device_viewer.scan_history_msg is None + assert scan_history_device_viewer.device_model.devices == [] + assert scan_history_device_viewer.device_model.rowCount() == 0 scan_history_device_viewer.update_devices_from_scan_history(scan_history_msg) assert scan_history_device_viewer.scan_history_msg == scan_history_msg assert scan_history_device_viewer.device_model.devices == [ - ("device2", 20), - ("device1", 10), - ("device3", 1), - ] # sorted by number of points - with qtbot.waitExposed(scan_history_device_viewer.device_combo.view()): - qtbot.mouseClick(scan_history_device_viewer.device_combo, qtbot.MouseButton.LeftButton) - # qtbot.waitExposed(scan_history_device_viewer.device_combo.view()) - index = scan_history_device_viewer.device_combo.model().index(1, 0) - rect = scan_history_device_viewer.device_combo.view().visualRect(index) - with qtbot.waitExposed(scan_history_device_viewer.device_combo.currentIndexChanged): - qtbot.mouseClick( - scan_history_device_viewer.device_combo.view().viewport(), - QtCore.Qt.LeftButton, - pos=rect.center(), - ) + ("device2", (20,)), + ("device1", (10,)), + ("device3", (1,)), + ] + current_index = scan_history_device_viewer.device_combo.currentIndex() + assert current_index == 0 + device_name = scan_history_device_viewer.device_combo.model().data( + scan_history_device_viewer.device_combo.model().index(current_index, 0), QtCore.Qt.UserRole + ) + assert device_name == "device2" - # Now + ## Update of second message should not change the device if still available + new_msg = ScanHistoryMessage( + scan_id="test_scan_2", + dataset_number=2, + scan_number=2, + scan_name="Test Scan 2", + file_path="/path/to/scan_2", + start_time=1751957908.3310962, + end_time=1751957909.3310962, # 1s later + exit_status="closed", + num_points=5, + request_inputs={"some_input": "new_value"}, + device_data_info={"device0": (15,), "device5": (25,), "device2313": (3,), "device2": (20,)}, + ) + scan_history_device_viewer.update_devices_from_scan_history(new_msg) + assert scan_history_device_viewer.scan_history_msg == new_msg + assert scan_history_device_viewer.device_model.devices == [ + ("device5", (25,)), + ("device2", (20,)), + ("device0", (15,)), + ("device2313", (3,)), + ] + current_index = scan_history_device_viewer.device_combo.currentIndex() + assert current_index == 1 + device_name = scan_history_device_viewer.device_combo.model().data( + scan_history_device_viewer.device_combo.model().index(current_index, 0), QtCore.Qt.UserRole + ) + assert device_name == "device2" + + +def test_scan_history_device_viewer_clear_view(qtbot, scan_history_device_viewer, scan_history_msg): + """Test clearing the device viewer.""" + scan_history_device_viewer.update_devices_from_scan_history(scan_history_msg) + assert scan_history_device_viewer.scan_history_msg == scan_history_msg + scan_history_device_viewer.clear_view() + assert scan_history_device_viewer.scan_history_msg is None + assert scan_history_device_viewer.device_combo.model().rowCount() == 0 + + +def test_scan_history_device_viewer_on_request_plotting_clicked( + qtbot, scan_history_device_viewer, scan_history_msg +): + """Test the request plotting button click.""" + scan_history_device_viewer.update_devices_from_scan_history(scan_history_msg) + + def plotting_callback(device_name, msg): + """Callback to check if the request plotting signal is emitted.""" + assert device_name == "device2" + assert msg == scan_history_msg + + scan_history_device_viewer.request_history_plot.connect(plotting_callback) + qtbot.mouseClick(scan_history_device_viewer.request_plotting_button, QtCore.Qt.LeftButton) + + +def test_scan_history_metadata_viewer_receive_msg( + qtbot, scan_history_metadata_viewer, scan_history_msg +): + """Test the initialization of ScanHistoryMetadataViewer.""" + assert scan_history_metadata_viewer.scan_history_msg is None + assert scan_history_metadata_viewer.title() == "No Scan Selected" + scan_history_metadata_viewer.update_view(scan_history_msg) + assert scan_history_metadata_viewer.scan_history_msg == scan_history_msg + assert scan_history_metadata_viewer.title() == f"Metadata - Scan {scan_history_msg.scan_number}" + for row, k in enumerate(scan_history_metadata_viewer._scan_history_msg_labels.keys()): + if k == "elapsed_time": + scan_history_metadata_viewer.layout().itemAtPosition(row, 1).widget().text() == "1.000s" + if k == "scan_name": + scan_history_metadata_viewer.layout().itemAtPosition( + row, 1 + ).widget().text() == "Test Scan" + + +def test_scan_history_metadata_viewer_clear_view( + qtbot, scan_history_metadata_viewer, scan_history_msg +): + """Test clearing the metadata viewer.""" + scan_history_metadata_viewer.update_view(scan_history_msg) + assert scan_history_metadata_viewer.scan_history_msg == scan_history_msg + scan_history_metadata_viewer.clear_view() + assert scan_history_metadata_viewer.scan_history_msg is None + assert scan_history_metadata_viewer.title() == "No Scan Selected" + + +def test_scan_history_view(qtbot, scan_history_view, scan_history_msg): + """Test the initialization of ScanHistoryView.""" + assert scan_history_view.scan_history == [] + assert scan_history_view.topLevelItemCount() == 0 + header = scan_history_view.headerItem() + assert [header.text(i) for i in range(header.columnCount())] == [ + "Scan Nr", + "Scan Name", + "Status", + ] + + +def test_scan_history_view_add_remove_scan(qtbot, scan_history_view, scan_history_msg): + """Test adding a scan to the ScanHistoryView.""" + scan_history_view.update_history(scan_history_msg.content, scan_history_msg.metadata) + assert len(scan_history_view.scan_history) == 1 + assert scan_history_view.scan_history[0] == scan_history_msg + assert scan_history_view.topLevelItemCount() == 1 + tree_item = scan_history_view.topLevelItem(0) + tree_item.text(0) == str(scan_history_msg.scan_number) + tree_item.text(1) == scan_history_msg.scan_name + tree_item.text(2) == "" + + # remove scan + def remove_callback(msg): + """Callback to check if the scan_removed signal is emitted.""" + assert msg == scan_history_msg + + scan_history_view.remove_scan(0) + assert len(scan_history_view.scan_history) == 0 + assert scan_history_view.topLevelItemCount() == 0 + + +def test_scan_history_view_current_scan_item_changed( + qtbot, scan_history_view, scan_history_msg, scan_history_device_viewer +): + """Test the current scan item changed signal.""" + scan_history_view.update_history(scan_history_msg.content, scan_history_msg.metadata) + scan_history_view.update_history(scan_history_msg.content, scan_history_msg.metadata) + scan_history_view.update_history(scan_history_msg.content, scan_history_msg.metadata) + assert len(scan_history_view.scan_history) == 3 + + def scan_selected_callback(msg): + """Callback to check if the scan_selected signal is emitted.""" + assert msg == scan_history_msg + + scan_history_view.scan_selected.connect(scan_selected_callback) + + qtbot.mouseClick( + scan_history_view.viewport(), + QtCore.Qt.LeftButton, + pos=scan_history_view.visualItemRect(scan_history_view.topLevelItem(0)).center(), + ) + + +# TODO add tests for compact view of popup, mostly relying on mouseclicks +# qtbot.mouseClick(scan_history_device_viewer.device_combo, QtCore.Qt.LeftButton) +# qtbot.waitUntil( +# lambda: scan_history_device_viewer.device_combo.view().isVisible(), timeout=1000 +# ) +# # qtbot.waitExposed(scan_history_device_viewer.device_combo.view()) +# index = scan_history_device_viewer.device_combo.model().index(1, 0) +# rect = scan_history_device_viewer.device_combo.view().visualRect(index) + +# index_changed = False + +# def index_cb(index): +# """Callback to check if the device combo text is updated.""" +# device_name = scan_history_device_viewer.device_combo.model().data( +# scan_history_device_viewer.device_combo.model().index(index, 0), QtCore.Qt.UserRole +# ) +# if device_name == "device2": +# index_changed = True + +# scan_history_device_viewer.device_combo.currentIndexChanged.connect(index_cb) + +# qtbot.mouseClick( +# scan_history_device_viewer.device_combo.view().viewport(), +# QtCore.Qt.LeftButton, +# pos=rect.center(), +# ) + +# qtbot.waitUntil(lambda: index_changed is True, timeout=3000) +# assert scan_history_device_viewer.device_combo.currentText() == "device1" + + +# def test_scan_history_device_viewer_request_plotting( +# qtbot, scan_history_device_viewer, scan_history_msg +# ): +# """Test requesting plotting from the device viewer.""" +# # Connect simple callback to request plotting signal +# data = [] + +# def plot_cb(device_name, msg): +# """Simple callback to check request plotting signal.""" +# data.append((device_name, msg)) + +# scan_history_device_viewer.update_devices_from_scan_history(scan_history_msg) + +# scan_history_device_viewer.request_history_plot.connect(plot_cb) +# with qtbot.waitExposed(scan_history_device_viewer.request_plotting_button): +# qtbot.mouseClick(scan_history_device_viewer.request_plotting_button, QtCore.Qt.LeftButton) +# assert len(data) == 1 +# assert data[0][0] == "device2" +# assert data[0][1] == scan_history_msg + +# # Now change the scan_history_msg and check if the device combo updates +# # But keep the same device name somewhere in the list +# new_msg = ScanHistoryMessage( +# scan_id="test_scan_2", +# dataset_number=2, +# scan_number=2, +# scan_name="Test Scan 2", +# file_path="/path/to/scan_2", +# start_time=1751957908.3310962, +# end_time=1751957909.3310962, # 1s later +# exit_status="closed", +# num_points=5, +# request_inputs={"some_input": "new_value"}, +# device_data_info={"device0": 15, "device5": 25, "device2313": 3, "device2": 20}, +# ) +# # Update the device viewer with the new message +# scan_history_device_viewer.update_devices_from_scan_history(new_msg) +# assert scan_history_device_viewer.scan_history_msg == new_msg +# # The same device should be selected still +# with qtbot.waitExposed(scan_history_device_viewer.request_plotting_button): +# qtbot.mouseClick( +# scan_history_device_viewer.request_plotting_button, qtbot.MouseButton.LeftButton +# ) + +# assert len(data) == 2 +# assert data[1][0] == "device2" +# assert data[1][1] == new_msg