189 lines
7.0 KiB
Python
189 lines
7.0 KiB
Python
"""The device-setup dialog: connection and bus initialisation, out of the rail.
|
|
|
|
Both groups are touched once per machine start-up. In the rail they cost ~460 px of
|
|
height above the axis readout, which is read all day — so they moved into a modeless
|
|
dialog opened from the status strip, its state chips, or the File menu.
|
|
|
|
What these tests protect:
|
|
|
|
* the rail no longer carries them, and the dialog is not open at start-up;
|
|
* every entry point works and lands on the right tab;
|
|
* the window's own handlers still receive the panels' signals, from inside the
|
|
dialog — the connect and download code paths did not move, only the widgets did;
|
|
* the dialog survives a language change and remembers its size and tab.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
from orisys_app_shared.i18n import set_locale, t
|
|
|
|
from orisys_autocal.motion import ConnectionSpec
|
|
from orisys_autocal.ui.device_setup import DeviceSetupDialog
|
|
|
|
|
|
def test_the_rail_no_longer_holds_the_startup_panels(make_window):
|
|
"""The point of the change: the rail is the run screen, not the setup form."""
|
|
window = make_window()
|
|
try:
|
|
rail = window.rail_content.findChildren(object)
|
|
names = {type(child).__name__ for child in rail}
|
|
assert "AxisReadoutPanel" in names
|
|
assert "ConnectionPanel" not in names
|
|
assert "BusPanel" not in names
|
|
# And they are in the dialog, once each. (The parent is Qt's internal
|
|
# stacked widget, so ask about ancestry rather than the direct parent.)
|
|
dialog = window.device_setup
|
|
assert window.connection_panel is dialog.connection_panel
|
|
assert window.bus_panel is dialog.bus_panel
|
|
assert dialog.tabs.isAncestorOf(window.connection_panel)
|
|
assert dialog.tabs.isAncestorOf(window.bus_panel)
|
|
finally:
|
|
window.close()
|
|
|
|
|
|
def test_the_dialog_is_hidden_until_it_is_asked_for(make_window):
|
|
window = make_window()
|
|
try:
|
|
assert not window.device_setup.isVisible()
|
|
window._show_device_setup() # noqa: SLF001
|
|
assert window.device_setup.isVisible()
|
|
# Showing it again raises rather than ignores: a second click that appears
|
|
# to do nothing reads as a broken button.
|
|
window._show_device_setup("bus") # noqa: SLF001
|
|
assert window.device_setup.isVisible()
|
|
assert window.device_setup.current_tab() == "bus"
|
|
finally:
|
|
window.close()
|
|
|
|
|
|
def test_the_strip_button_opens_the_setup(make_window):
|
|
window = make_window()
|
|
try:
|
|
window.status_strip.setup_button.click()
|
|
assert window.device_setup.isVisible()
|
|
assert window.status_strip.setup_button.text() == t("setup.open")
|
|
finally:
|
|
window.close()
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"chip, tab",
|
|
[("chip_connection", "connection"), ("chip_bus", "bus"), ("chip_init", "bus")],
|
|
)
|
|
def test_the_state_chips_open_the_tab_they_report(make_window, chip, tab):
|
|
"""A chip that says "not connected" is the natural place to click."""
|
|
window = make_window()
|
|
try:
|
|
getattr(window.status_strip, chip).clicked.emit()
|
|
assert window.device_setup.isVisible()
|
|
assert window.device_setup.current_tab() == tab
|
|
finally:
|
|
window.close()
|
|
|
|
|
|
def test_the_file_menu_opens_the_setup(make_window):
|
|
window = make_window()
|
|
try:
|
|
window.act_device_setup.trigger()
|
|
assert window.device_setup.isVisible()
|
|
assert window.device_setup.current_tab() == "connection"
|
|
assert window.act_device_setup.text() == t("menu.device_setup")
|
|
finally:
|
|
window.close()
|
|
|
|
|
|
def test_connecting_from_the_dialog_reaches_the_window(make_window):
|
|
"""The widgets moved; the code path did not.
|
|
|
|
The connect button lives in the dialog now, so this drives the *button* rather
|
|
than emitting the signal directly: it is the signal wiring across the new
|
|
parent that could have been lost.
|
|
"""
|
|
window = make_window()
|
|
try:
|
|
seen = []
|
|
window.connection_panel.connectRequested.connect(seen.append)
|
|
|
|
panel = window.connection_panel
|
|
panel.mode_combo.setCurrentIndex(panel.mode_combo.findData("demo"))
|
|
window.device_setup.open_for("connection")
|
|
panel.open_button.click()
|
|
|
|
assert seen, "the connection request never left the dialog"
|
|
assert isinstance(seen[0], ConnectionSpec)
|
|
assert seen[0].mode == "demo"
|
|
finally:
|
|
window.close()
|
|
|
|
|
|
def test_downloading_the_bas_from_the_dialog_reaches_the_window(make_window):
|
|
window = make_window()
|
|
try:
|
|
# A path *must* be set first: with none, the window opens a modal file
|
|
# chooser, which offscreen is a hang rather than a test.
|
|
from orisys_autocal.ui.bus_panel import default_bas_dir
|
|
|
|
window.bus_panel.set_bas_path(str(default_bas_dir() / "ECAT.bas"))
|
|
|
|
seen = []
|
|
window.bus_panel.downloadRequested.connect(lambda: seen.append(True))
|
|
window.device_setup.open_for("bus")
|
|
window.bus_panel.download_button.click()
|
|
assert seen, "the download request never left the dialog"
|
|
finally:
|
|
window.close()
|
|
|
|
|
|
def test_the_dialog_survives_a_language_change(make_window):
|
|
window = make_window()
|
|
try:
|
|
window._set_language("en_US") # noqa: SLF001
|
|
assert window.device_setup.windowTitle() == t("setup.title")
|
|
assert window.device_setup.tabs.tabText(1) == t("setup.tab_bus")
|
|
assert window.status_strip.setup_button.text() == t("setup.open")
|
|
# The panels inside are retranslated too, not just the dialog's own labels.
|
|
assert window.connection_panel.open_button.text() == t("connection.open")
|
|
window._set_language("zh_CN") # noqa: SLF001
|
|
set_locale("zh_CN")
|
|
finally:
|
|
window.close()
|
|
|
|
|
|
def test_the_dialog_remembers_its_size_and_tab(make_window):
|
|
window = make_window()
|
|
try:
|
|
window.device_setup.select_tab("bus")
|
|
window.device_setup.resize(640, 480)
|
|
stored = window.device_setup.settings()
|
|
assert stored["tab"] == "bus"
|
|
assert stored["size"] == [640, 480]
|
|
|
|
fresh = DeviceSetupDialog(ConnectionSpec(mode="eth", ip="10.0.0.1"))
|
|
try:
|
|
fresh.apply_settings(stored)
|
|
assert fresh.size().width() == 640
|
|
assert fresh.current_tab() == "bus"
|
|
# Anything malformed is ignored, not raised on: this comes from a file
|
|
# a human may have edited.
|
|
fresh.apply_settings({"size": ["wide", 2], "tab": 7})
|
|
fresh.apply_settings(None)
|
|
finally:
|
|
fresh.deleteLater()
|
|
finally:
|
|
window.close()
|
|
|
|
|
|
def test_opening_the_setup_does_not_touch_the_connection(make_window):
|
|
"""Opening a dialog is not a command: it must not connect or disconnect."""
|
|
window = make_window()
|
|
try:
|
|
window.device_setup.open_for("connection")
|
|
assert not window._last_snapshot.connected # noqa: SLF001
|
|
window.device_setup.close()
|
|
assert window.connection_panel.close_button.isEnabled() is False
|
|
assert window.connection_panel.open_button.isEnabled() is True
|
|
finally:
|
|
window.close()
|