1
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2026-03-04 16:02:51 +01:00
Files
bec_widgets/tests/unit_tests/test_busy_loader.py

145 lines
4.6 KiB
Python

import numpy as np
import pytest
from qtpy.QtWidgets import QLabel, QVBoxLayout, QWidget
from bec_widgets import BECWidget
from bec_widgets.widgets.utility.spinner.spinner import SpinnerWidget
from .client_mocks import mocked_client
class _TestBusyWidget(BECWidget, QWidget):
def __init__(
self, parent=None, *, start_busy: bool = False, theme_update: bool = False, **kwargs
):
super().__init__(parent=parent, theme_update=theme_update, start_busy=start_busy, **kwargs)
lay = QVBoxLayout(self)
lay.setContentsMargins(0, 0, 0, 0)
lay.addWidget(QLabel("content", self))
@pytest.fixture
def widget_busy(qtbot, mocked_client):
w = _TestBusyWidget(client=mocked_client, start_busy=True)
qtbot.addWidget(w)
w.resize(320, 200)
w.show()
qtbot.waitExposed(w)
return w
@pytest.fixture
def widget_idle(qtbot):
w = _TestBusyWidget(client=mocked_client, start_busy=False)
qtbot.addWidget(w)
w.resize(320, 200)
w.show()
qtbot.waitExposed(w)
return w
def test_becwidget_start_busy_shows_overlay(qtbot, widget_busy):
overlay = getattr(widget_busy, "_busy_overlay", None)
assert overlay is not None, "BECWidget should create a busy overlay in __init__"
qtbot.waitUntil(lambda: overlay.geometry() == widget_busy.rect())
qtbot.waitUntil(lambda: overlay.isVisible())
def test_becwidget_set_busy_toggle_and_text(qtbot, widget_idle):
overlay = getattr(widget_idle, "_busy_overlay", None)
assert overlay is not None
widget_idle.set_busy(True)
overlay = getattr(widget_idle, "_busy_overlay")
qtbot.waitUntil(lambda: overlay.isVisible())
assert hasattr(widget_idle, "_busy_state_widget")
assert overlay._custom_widget is not None
label = overlay._custom_widget.findChild(QLabel)
assert label is not None
assert label.text() == "Loading..."
spinner = overlay._custom_widget.findChild(SpinnerWidget)
assert spinner is not None
assert spinner.isVisible()
assert spinner._started is True
widget_idle.set_busy(False)
qtbot.waitUntil(lambda: overlay.isHidden())
def test_becwidget_busy_overlay_set_opacity(qtbot, widget_busy):
overlay = getattr(widget_busy, "_busy_overlay")
qtbot.waitUntil(lambda: overlay.isVisible())
# Default opacity is 0.7
frame = getattr(overlay, "_frame", None)
assert frame is not None
sheet = frame.styleSheet()
_, _, _, a = overlay.scrim_color.getRgb()
assert np.isclose(a / 255, 0.35, atol=0.02)
# Change opacity
overlay.set_opacity(0.7)
qtbot.waitUntil(lambda: overlay.isVisible())
_, _, _, a = overlay.scrim_color.getRgb()
assert np.isclose(a / 255, 0.7, atol=0.02)
def test_becwidget_overlay_tracks_resize(qtbot, widget_busy):
overlay = getattr(widget_busy, "_busy_overlay")
qtbot.waitUntil(lambda: overlay.geometry() == widget_busy.rect())
widget_busy.resize(480, 260)
qtbot.waitUntil(lambda: overlay.geometry() == widget_busy.rect())
def test_becwidget_overlay_frame_geometry_and_style(qtbot, widget_busy):
overlay = getattr(widget_busy, "_busy_overlay")
qtbot.waitUntil(lambda: overlay.isVisible())
frame = getattr(overlay, "_frame", None)
assert frame is not None, "Busy overlay must use an internal QFrame for visuals"
# Insets are 10 px in the implementation
outer = overlay.rect()
# Ensure resizeEvent has run and frame geometry is updated
qtbot.waitUntil(
lambda: frame.geometry().width() == outer.width() - 20
and frame.geometry().height() == outer.height() - 20
)
inner = frame.geometry()
assert inner.left() == outer.left() + 10
assert inner.top() == outer.top() + 10
assert inner.right() == outer.right() - 10
assert inner.bottom() == outer.bottom() - 10
# Style: dashed border + semi-transparent grey background
ss = frame.styleSheet()
assert "dashed" in ss
assert "border" in ss
def test_becwidget_busy_cycle_start_on_off_on(qtbot, widget_busy):
overlay = getattr(widget_busy, "_busy_overlay", None)
assert overlay is not None, "Busy overlay should exist on a start_busy widget"
# Initially visible because start_busy=True
qtbot.waitUntil(lambda: overlay.isVisible())
# Switch OFF
widget_busy.set_busy(False)
qtbot.waitUntil(lambda: overlay.isHidden())
# Switch ON again (with new text)
widget_busy.set_busy(True)
qtbot.waitUntil(lambda: overlay.isVisible())
# Same overlay instance reused (no duplication)
assert getattr(widget_busy, "_busy_overlay") is overlay
# Geometry follows parent after re-show
qtbot.waitUntil(lambda: overlay.geometry() == widget_busy.rect())