mirror of
https://github.com/bec-project/bec_widgets.git
synced 2026-07-21 10:42:59 +02:00
165 lines
6.2 KiB
Python
165 lines
6.2 KiB
Python
import pytest
|
|
from bec_lib.scan_history import ScanHistory
|
|
from qtpy.QtCore import Qt
|
|
|
|
from bec_widgets.widgets.utility.scan_index_combobox.scan_index_combobox import ScanIndexComboBox
|
|
|
|
# pylint: disable=unused-import
|
|
from tests.unit_tests.client_mocks import mocked_client
|
|
from tests.unit_tests.conftest import create_widget
|
|
|
|
|
|
@pytest.fixture
|
|
def scan_index_combo(qtbot, mocked_client, scan_history_factory):
|
|
"""ScanIndexComboBox with two history scans injected into the client."""
|
|
msgs = [
|
|
scan_history_factory(scan_id="hid1", scan_number=1),
|
|
scan_history_factory(scan_id="hid2", scan_number=2),
|
|
]
|
|
mocked_client.history = ScanHistory(mocked_client, False)
|
|
for msg in msgs:
|
|
mocked_client.history._scan_data[msg.scan_id] = msg
|
|
mocked_client.history._scan_ids.append(msg.scan_id)
|
|
mocked_client.history._scan_numbers.append(msg.scan_number)
|
|
combo = create_widget(qtbot, ScanIndexComboBox, client=mocked_client)
|
|
return combo
|
|
|
|
|
|
def test_scan_index_combobox_populates_history(scan_index_combo):
|
|
"""The combobox lists 'live' plus all scan numbers (latest first) with scan IDs as item data."""
|
|
assert scan_index_combo.count() == 3
|
|
assert scan_index_combo.itemText(0) == "live"
|
|
assert scan_index_combo.itemData(0) is None
|
|
assert scan_index_combo.itemText(1) == "2"
|
|
assert scan_index_combo.itemData(1) == "hid2"
|
|
assert scan_index_combo.itemText(2) == "1"
|
|
assert scan_index_combo.itemData(2) == "hid1"
|
|
|
|
|
|
def test_scan_index_combobox_scan_id_and_number(scan_index_combo):
|
|
"""scan_id/scan_number map the selection to live (None) or a history scan."""
|
|
assert scan_index_combo.currentText() == "live"
|
|
assert scan_index_combo.scan_id is None
|
|
assert scan_index_combo.scan_number is None
|
|
|
|
scan_index_combo.setCurrentIndex(1)
|
|
assert scan_index_combo.scan_id == "hid2"
|
|
assert scan_index_combo.scan_number == 2
|
|
|
|
# Typing a scan number does not move the current index; scan_id must follow the text
|
|
scan_index_combo.setCurrentText("live")
|
|
scan_index_combo.setCurrentText("1")
|
|
assert scan_index_combo.scan_id == "hid1"
|
|
assert scan_index_combo.scan_number == 1
|
|
|
|
|
|
def test_scan_index_combobox_set_scan_id(scan_index_combo):
|
|
"""set_scan_id selects the matching scan or falls back to 'live'."""
|
|
scan_index_combo.set_scan_id("hid1")
|
|
assert scan_index_combo.currentText() == "1"
|
|
|
|
scan_index_combo.set_scan_id("unknown")
|
|
assert scan_index_combo.currentText() == "live"
|
|
|
|
scan_index_combo.set_scan_id("hid2")
|
|
assert scan_index_combo.currentText() == "2"
|
|
scan_index_combo.set_scan_id(None)
|
|
assert scan_index_combo.currentText() == "live"
|
|
|
|
|
|
def test_scan_index_combobox_refresh_keeps_selection(scan_index_combo):
|
|
"""refresh_scan_indices repopulates the items without losing the current selection."""
|
|
scan_index_combo.set_scan_id("hid2")
|
|
scan_index_combo.refresh_scan_indices()
|
|
assert scan_index_combo.count() == 3
|
|
assert scan_index_combo.currentText() == "2"
|
|
assert scan_index_combo.scan_id == "hid2"
|
|
|
|
|
|
@pytest.mark.parametrize("history", [None, "empty"])
|
|
def test_scan_index_combobox_empty_history(qtbot, mocked_client, history):
|
|
"""
|
|
With no scan history (client not started) or an empty one, only 'live' is offered
|
|
and any typed scan number is flagged as invalid.
|
|
"""
|
|
mocked_client.history = ScanHistory(mocked_client, False) if history == "empty" else None
|
|
combo = create_widget(qtbot, ScanIndexComboBox, client=mocked_client)
|
|
|
|
assert combo.count() == 1
|
|
assert combo.currentText() == "live"
|
|
assert combo.scan_id is None
|
|
assert combo.scan_number is None
|
|
assert combo.is_valid_input
|
|
|
|
# Typing is not blocked by a validator, but scan numbers are flagged since none exist
|
|
assert combo.lineEdit().validator() is None
|
|
combo.lineEdit().clear()
|
|
qtbot.keyClicks(combo.lineEdit(), "1")
|
|
assert combo.currentText() == "1"
|
|
assert not combo.is_valid_input
|
|
with pytest.raises(ValueError):
|
|
_ = combo.scan_id
|
|
|
|
|
|
def test_scan_index_combobox_typing_multi_digit_scan(qtbot, mocked_client, scan_history_factory):
|
|
"""
|
|
Multi-digit scan numbers can be typed even when their prefixes are not scan numbers
|
|
themselves, and the completer autocompletes against the listed entries.
|
|
"""
|
|
msgs = [
|
|
scan_history_factory(scan_id="hid101", scan_number=101),
|
|
scan_history_factory(scan_id="hid105", scan_number=105),
|
|
]
|
|
mocked_client.history = ScanHistory(mocked_client, False)
|
|
for msg in msgs:
|
|
mocked_client.history._scan_data[msg.scan_id] = msg
|
|
mocked_client.history._scan_ids.append(msg.scan_id)
|
|
mocked_client.history._scan_numbers.append(msg.scan_number)
|
|
combo = create_widget(qtbot, ScanIndexComboBox, client=mocked_client)
|
|
|
|
combo.lineEdit().clear()
|
|
qtbot.keyClicks(combo.lineEdit(), "101")
|
|
assert combo.currentText() == "101"
|
|
assert combo.is_valid_input
|
|
assert combo.styleSheet() == ""
|
|
assert combo.scan_id == "hid101"
|
|
assert combo.scan_number == 101
|
|
|
|
# The default editable-combobox completer offers the listed entries while typing
|
|
completer = combo.completer()
|
|
assert completer is not None
|
|
completer.setCompletionPrefix("l")
|
|
assert completer.currentCompletion() == "live"
|
|
completer.setCompletionPrefix("10")
|
|
assert completer.currentCompletion() == "105"
|
|
|
|
|
|
def test_scan_index_combobox_invalid_input_flagged(scan_index_combo, qtbot):
|
|
"""
|
|
Unknown scan numbers can be typed; they are flagged with a red border, raise on
|
|
read-out, and are not inserted as new items when committed.
|
|
"""
|
|
combo = scan_index_combo
|
|
combo.lineEdit().clear()
|
|
qtbot.keyClicks(combo.lineEdit(), "99")
|
|
assert combo.currentText() == "99"
|
|
assert not combo.is_valid_input
|
|
assert "red" in combo.styleSheet()
|
|
with pytest.raises(ValueError):
|
|
_ = combo.scan_id
|
|
with pytest.raises(ValueError):
|
|
_ = combo.scan_number
|
|
|
|
qtbot.keyClick(combo.lineEdit(), Qt.Key_Return)
|
|
assert combo.count() == 3
|
|
|
|
# A refresh with invalid text falls back to 'live' instead of raising
|
|
combo.refresh_scan_indices()
|
|
assert combo.currentText() == "live"
|
|
assert combo.is_valid_input
|
|
|
|
combo.setCurrentText("2")
|
|
assert combo.is_valid_input
|
|
assert combo.styleSheet() == ""
|
|
assert combo.scan_id == "hid2"
|