bec-widgets 0.76.0__py3-none-any.whl → 0.77.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. CHANGELOG.md +42 -44
  2. PKG-INFO +2 -1
  3. bec_widgets/cli/client.py +73 -196
  4. bec_widgets/examples/jupyter_console/jupyter_console_window.py +25 -4
  5. bec_widgets/utils/bec_connector.py +66 -8
  6. bec_widgets/utils/colors.py +38 -0
  7. bec_widgets/utils/generate_designer_plugin.py +15 -14
  8. bec_widgets/utils/yaml_dialog.py +27 -3
  9. bec_widgets/widgets/console/console.py +496 -0
  10. bec_widgets/widgets/dock/dock.py +2 -2
  11. bec_widgets/widgets/dock/dock_area.py +2 -2
  12. bec_widgets/widgets/figure/figure.py +149 -195
  13. bec_widgets/widgets/figure/plots/image/image.py +62 -49
  14. bec_widgets/widgets/figure/plots/image/image_item.py +4 -3
  15. bec_widgets/widgets/figure/plots/motor_map/motor_map.py +98 -29
  16. bec_widgets/widgets/figure/plots/plot_base.py +1 -1
  17. bec_widgets/widgets/figure/plots/waveform/waveform.py +7 -8
  18. bec_widgets/widgets/figure/plots/waveform/waveform_curve.py +2 -2
  19. bec_widgets/widgets/ring_progress_bar/ring.py +3 -3
  20. bec_widgets/widgets/ring_progress_bar/ring_progress_bar.py +3 -3
  21. {bec_widgets-0.76.0.dist-info → bec_widgets-0.77.0.dist-info}/METADATA +2 -1
  22. {bec_widgets-0.76.0.dist-info → bec_widgets-0.77.0.dist-info}/RECORD +40 -38
  23. pyproject.toml +2 -1
  24. tests/end-2-end/test_bec_dock_rpc_e2e.py +16 -16
  25. tests/end-2-end/test_bec_figure_rpc_e2e.py +7 -7
  26. tests/end-2-end/test_rpc_register_e2e.py +8 -8
  27. tests/unit_tests/client_mocks.py +1 -0
  28. tests/unit_tests/test_bec_figure.py +49 -26
  29. tests/unit_tests/test_bec_motor_map.py +179 -41
  30. tests/unit_tests/test_color_validation.py +15 -0
  31. tests/unit_tests/test_device_input_base.py +1 -1
  32. tests/unit_tests/test_device_input_widgets.py +2 -0
  33. tests/unit_tests/test_generate_plugin.py +155 -0
  34. tests/unit_tests/test_motor_control.py +5 -4
  35. tests/unit_tests/test_plot_base.py +3 -3
  36. tests/unit_tests/test_waveform1d.py +18 -17
  37. tests/unit_tests/test_yaml_dialog.py +7 -7
  38. {bec_widgets-0.76.0.dist-info → bec_widgets-0.77.0.dist-info}/WHEEL +0 -0
  39. {bec_widgets-0.76.0.dist-info → bec_widgets-0.77.0.dist-info}/entry_points.txt +0 -0
  40. {bec_widgets-0.76.0.dist-info → bec_widgets-0.77.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,100 +1,106 @@
1
+ import numpy as np
1
2
  import pytest
2
3
 
3
4
  from bec_widgets.widgets.figure.plots.motor_map.motor_map import BECMotorMap, MotorMapConfig
4
5
  from bec_widgets.widgets.figure.plots.waveform.waveform_curve import SignalData
5
6
 
6
7
  from .client_mocks import mocked_client
8
+ from .test_bec_figure import bec_figure
7
9
 
8
10
 
9
- @pytest.fixture(scope="function")
10
- def bec_motor_map(qtbot, mocked_client):
11
- widget = BECMotorMap(client=mocked_client, gui_id="BECMotorMap_test")
12
- # qtbot.addWidget(widget)
13
- # qtbot.waitExposed(widget)
14
- yield widget
11
+ def test_motor_map_init(bec_figure):
12
+ default_config = MotorMapConfig(widget_class="BECMotorMap")
15
13
 
14
+ mm = bec_figure.motor_map(config=default_config.model_dump())
15
+ default_config.gui_id = mm.gui_id
16
16
 
17
- def test_motor_map_init(bec_motor_map):
18
- default_config = MotorMapConfig(widget_class="BECMotorMap", gui_id="BECMotorMap_test")
17
+ assert mm.config == default_config
19
18
 
20
- assert bec_motor_map.config == default_config
21
19
 
20
+ def test_motor_map_change_motors(bec_figure):
21
+ mm = bec_figure.motor_map("samx", "samy")
22
22
 
23
- def test_motor_map_change_motors(bec_motor_map):
24
- bec_motor_map.change_motors("samx", "samy")
23
+ assert mm.motor_x == "samx"
24
+ assert mm.motor_y == "samy"
25
+ assert mm.config.signals.x == SignalData(name="samx", entry="samx", limits=[-10, 10])
26
+ assert mm.config.signals.y == SignalData(name="samy", entry="samy", limits=[-5, 5])
25
27
 
26
- assert bec_motor_map.config.signals.x == SignalData(name="samx", entry="samx", limits=[-10, 10])
27
- assert bec_motor_map.config.signals.y == SignalData(name="samy", entry="samy", limits=[-5, 5])
28
+ mm.change_motors("samx", "samz")
28
29
 
30
+ assert mm.config.signals.x == SignalData(name="samx", entry="samx", limits=[-10, 10])
31
+ assert mm.config.signals.y == SignalData(name="samz", entry="samz", limits=[-8, 8])
29
32
 
30
- def test_motor_map_get_limits(bec_motor_map):
33
+
34
+ def test_motor_map_get_limits(bec_figure):
35
+ mm = bec_figure.motor_map("samx", "samy")
31
36
  expected_limits = {"samx": [-10, 10], "samy": [-5, 5]}
32
37
 
33
38
  for motor_name, expected_limit in expected_limits.items():
34
- actual_limit = bec_motor_map._get_motor_limit(motor_name)
39
+ actual_limit = mm._get_motor_limit(motor_name)
35
40
  assert actual_limit == expected_limit
36
41
 
37
42
 
38
- def test_motor_map_get_init_position(bec_motor_map):
39
- bec_motor_map.set_precision(2)
43
+ def test_motor_map_get_init_position(bec_figure):
44
+ mm = bec_figure.motor_map("samx", "samy")
45
+ mm.set_precision(2)
40
46
 
41
- motor_map_dev = bec_motor_map.client.device_manager.devices
47
+ motor_map_dev = mm.client.device_manager.devices
42
48
 
43
49
  expected_positions = {
44
50
  ("samx", "samx"): motor_map_dev["samx"].read()["samx"]["value"],
45
51
  ("samy", "samy"): motor_map_dev["samy"].read()["samy"]["value"],
46
- ("aptrx", "aptrx"): motor_map_dev["aptrx"].read()["aptrx"]["value"],
47
- ("aptry", "aptry"): motor_map_dev["aptry"].read()["aptry"]["value"],
48
52
  }
49
53
 
50
54
  for (motor_name, entry), expected_position in expected_positions.items():
51
- actual_position = bec_motor_map._get_motor_init_position(motor_name, entry, 2)
55
+ actual_position = mm._get_motor_init_position(motor_name, entry, 2)
52
56
  assert actual_position == expected_position
53
57
 
54
58
 
55
- def test_motor_movement_updates_position_and_database(bec_motor_map):
56
- motor_map_dev = bec_motor_map.client.device_manager.devices
59
+ def test_motor_movement_updates_position_and_database(bec_figure):
60
+ mm = bec_figure.motor_map("samx", "samy")
61
+ motor_map_dev = mm.client.device_manager.devices
57
62
 
58
63
  init_positions = {
59
64
  "samx": [motor_map_dev["samx"].read()["samx"]["value"]],
60
65
  "samy": [motor_map_dev["samy"].read()["samy"]["value"]],
61
66
  }
62
67
 
63
- bec_motor_map.change_motors("samx", "samy")
68
+ mm.change_motors("samx", "samy")
64
69
 
65
- assert bec_motor_map.database_buffer["x"] == init_positions["samx"]
66
- assert bec_motor_map.database_buffer["y"] == init_positions["samy"]
70
+ assert mm.database_buffer["x"] == init_positions["samx"]
71
+ assert mm.database_buffer["y"] == init_positions["samy"]
67
72
 
68
73
  # Simulate motor movement for 'samx' only
69
74
  new_position_samx = 4.0
70
- bec_motor_map.on_device_readback({"signals": {"samx": {"value": new_position_samx}}})
75
+ mm.on_device_readback({"signals": {"samx": {"value": new_position_samx}}})
71
76
 
72
77
  init_positions["samx"].append(new_position_samx)
73
78
  init_positions["samy"].append(init_positions["samy"][-1])
74
79
  # Verify database update for 'samx'
75
- assert bec_motor_map.database_buffer["x"] == init_positions["samx"]
80
+ assert mm.database_buffer["x"] == init_positions["samx"]
76
81
 
77
82
  # Verify 'samy' retains its last known position
78
- assert bec_motor_map.database_buffer["y"] == init_positions["samy"]
83
+ assert mm.database_buffer["y"] == init_positions["samy"]
79
84
 
80
85
 
81
- def test_scatter_plot_rendering(bec_motor_map):
82
- motor_map_dev = bec_motor_map.client.device_manager.devices
86
+ def test_scatter_plot_rendering(bec_figure):
87
+ mm = bec_figure.motor_map("samx", "samy")
88
+ motor_map_dev = mm.client.device_manager.devices
83
89
 
84
90
  init_positions = {
85
91
  "samx": [motor_map_dev["samx"].read()["samx"]["value"]],
86
92
  "samy": [motor_map_dev["samy"].read()["samy"]["value"]],
87
93
  }
88
94
 
89
- bec_motor_map.change_motors("samx", "samy")
95
+ mm.change_motors("samx", "samy")
90
96
 
91
97
  # Simulate motor movement for 'samx' only
92
98
  new_position_samx = 4.0
93
- bec_motor_map.on_device_readback({"signals": {"samx": {"value": new_position_samx}}})
94
- bec_motor_map._update_plot()
99
+ mm.on_device_readback({"signals": {"samx": {"value": new_position_samx}}})
100
+ mm._update_plot()
95
101
 
96
102
  # Get the scatter plot item
97
- scatter_plot_item = bec_motor_map.plot_components["scatter"]
103
+ scatter_plot_item = mm.plot_components["scatter"]
98
104
 
99
105
  # Check the scatter plot item properties
100
106
  assert len(scatter_plot_item.data) > 0, "Scatter plot data is empty"
@@ -106,16 +112,148 @@ def test_scatter_plot_rendering(bec_motor_map):
106
112
  ), "Scatter plot Y data should retain last known position"
107
113
 
108
114
 
109
- def test_plot_visualization_consistency(bec_motor_map):
110
- bec_motor_map.change_motors("samx", "samy")
115
+ def test_plot_visualization_consistency(bec_figure):
116
+ mm = bec_figure.motor_map("samx", "samy")
117
+ mm.change_motors("samx", "samy")
111
118
  # Simulate updating the plot with new data
112
- bec_motor_map.on_device_readback({"signals": {"samx": {"value": 5}}})
113
- bec_motor_map.on_device_readback({"signals": {"samy": {"value": 9}}})
114
- bec_motor_map._update_plot()
119
+ mm.on_device_readback({"signals": {"samx": {"value": 5}}})
120
+ mm.on_device_readback({"signals": {"samy": {"value": 9}}})
121
+ mm._update_plot()
115
122
 
116
- scatter_plot_item = bec_motor_map.plot_components["scatter"]
123
+ scatter_plot_item = mm.plot_components["scatter"]
117
124
 
118
125
  # Check if the scatter plot reflects the new data correctly
119
126
  assert (
120
127
  scatter_plot_item.data["x"][-1] == 5 and scatter_plot_item.data["y"][-1] == 9
121
128
  ), "Plot not updated correctly with new data"
129
+
130
+
131
+ def test_change_background_value(bec_figure, qtbot):
132
+ mm = bec_figure.motor_map("samx", "samy")
133
+
134
+ assert mm.config.background_value == 25
135
+ assert np.all(mm.plot_components["limit_map"].image == 25.0)
136
+
137
+ mm.set_background_value(50)
138
+ qtbot.wait(200)
139
+
140
+ assert mm.config.background_value == 50
141
+ assert np.all(mm.plot_components["limit_map"].image == 50.0)
142
+
143
+
144
+ def test_motor_map_init_from_config(bec_figure):
145
+ config = {
146
+ "widget_class": "BECMotorMap",
147
+ "gui_id": "mm_id",
148
+ "parent_id": bec_figure.gui_id,
149
+ "row": 0,
150
+ "col": 0,
151
+ "axis": {
152
+ "title": "Motor position: (-0.0, 0.0)",
153
+ "title_size": None,
154
+ "x_label": "Motor X (samx)",
155
+ "x_label_size": None,
156
+ "y_label": "Motor Y (samy)",
157
+ "y_label_size": None,
158
+ "legend_label_size": None,
159
+ "x_scale": "linear",
160
+ "y_scale": "linear",
161
+ "x_lim": None,
162
+ "y_lim": None,
163
+ "x_grid": True,
164
+ "y_grid": True,
165
+ },
166
+ "signals": {
167
+ "source": "device_readback",
168
+ "x": {
169
+ "name": "samx",
170
+ "entry": "samx",
171
+ "unit": None,
172
+ "modifier": None,
173
+ "limits": [-10.0, 10.0],
174
+ },
175
+ "y": {
176
+ "name": "samy",
177
+ "entry": "samy",
178
+ "unit": None,
179
+ "modifier": None,
180
+ "limits": [-5.0, 5.0],
181
+ },
182
+ "z": None,
183
+ "dap": None,
184
+ },
185
+ "color": (255, 255, 255, 255),
186
+ "scatter_size": 5,
187
+ "max_points": 50,
188
+ "num_dim_points": 10,
189
+ "precision": 5,
190
+ "background_value": 50,
191
+ }
192
+ mm = bec_figure.motor_map(config=config)
193
+ config["gui_id"] = mm.gui_id
194
+
195
+ assert mm._config_dict == config
196
+
197
+
198
+ def test_motor_map_set_scatter_size(bec_figure, qtbot):
199
+ mm = bec_figure.motor_map("samx", "samy")
200
+
201
+ assert mm.config.scatter_size == 5
202
+ assert mm.plot_components["scatter"].opts["size"] == 5
203
+
204
+ mm.set_scatter_size(10)
205
+ qtbot.wait(200)
206
+
207
+ assert mm.config.scatter_size == 10
208
+ assert mm.plot_components["scatter"].opts["size"] == 10
209
+
210
+
211
+ def test_motor_map_change_precision(bec_figure):
212
+ mm = bec_figure.motor_map("samx", "samy")
213
+
214
+ assert mm.config.precision == 2
215
+ mm.set_precision(10)
216
+ assert mm.config.precision == 10
217
+
218
+
219
+ def test_motor_map_set_color(bec_figure, qtbot):
220
+ mm = bec_figure.motor_map("samx", "samy")
221
+
222
+ assert mm.config.color == (255, 255, 255, 255)
223
+
224
+ mm.set_color((0, 0, 0, 255))
225
+ qtbot.wait(200)
226
+ assert mm.config.color == (0, 0, 0, 255)
227
+
228
+
229
+ def test_motor_map_get_data_max_points(bec_figure, qtbot):
230
+ mm = bec_figure.motor_map("samx", "samy")
231
+ motor_map_dev = mm.client.device_manager.devices
232
+
233
+ init_positions = {
234
+ "samx": [motor_map_dev["samx"].read()["samx"]["value"]],
235
+ "samy": [motor_map_dev["samy"].read()["samy"]["value"]],
236
+ }
237
+ mm.on_device_readback({"signals": {"samx": {"value": 5.0}}})
238
+ mm.on_device_readback({"signals": {"samy": {"value": 9.0}}})
239
+ mm.on_device_readback({"signals": {"samx": {"value": 6.0}}})
240
+ mm.on_device_readback({"signals": {"samy": {"value": 7.0}}})
241
+
242
+ expected_x = [init_positions["samx"][-1], 5.0, 5.0, 6.0, 6.0]
243
+ expected_y = [init_positions["samy"][-1], init_positions["samy"][-1], 9.0, 9.0, 7.0]
244
+ get_data = mm.get_data()
245
+
246
+ assert mm.database_buffer["x"] == expected_x
247
+ assert mm.database_buffer["y"] == expected_y
248
+ assert get_data["x"] == expected_x
249
+ assert get_data["y"] == expected_y
250
+
251
+ mm.set_max_points(3)
252
+ qtbot.wait(200)
253
+ get_data = mm.get_data()
254
+ assert len(get_data["x"]) == 3
255
+ assert len(get_data["y"]) == 3
256
+ assert get_data["x"] == expected_x[-3:]
257
+ assert get_data["y"] == expected_y[-3:]
258
+ assert mm.database_buffer["x"] == expected_x[-3:]
259
+ assert mm.database_buffer["y"] == expected_y[-3:]
@@ -58,3 +58,18 @@ def test_color_validation_RGBA():
58
58
  assert "The color values must be between 0 and 255 in RGBA format (R,G,B,A)" in str(
59
59
  excinfo.value
60
60
  )
61
+
62
+
63
+ def test_hex_to_rgba():
64
+ assert Colors.hex_to_rgba("#FF5733") == (255, 87, 51, 255)
65
+ assert Colors.hex_to_rgba("#FF573380") == (255, 87, 51, 128)
66
+ assert Colors.hex_to_rgba("#FF5733", 128) == (255, 87, 51, 128)
67
+
68
+ with pytest.raises(ValueError):
69
+ Colors.hex_to_rgba("#FF573")
70
+
71
+
72
+ def test_rgba_to_hex():
73
+ assert Colors.rgba_to_hex(255, 87, 51, 255) == "#FF5733FF"
74
+ assert Colors.rgba_to_hex(255, 87, 51, 128) == "#FF573380"
75
+ assert Colors.rgba_to_hex(255, 87, 51) == "#FF5733FF"
@@ -58,7 +58,7 @@ def test_device_input_base_set_default_device_error(device_input_base):
58
58
 
59
59
  def test_device_input_base_get_device_list(device_input_base):
60
60
  devices = device_input_base.get_device_list("FakePositioner")
61
- assert devices == ["samx", "samy", "aptrx", "aptry"]
61
+ assert devices == ["samx", "samy", "samz", "aptrx", "aptry"]
62
62
 
63
63
 
64
64
  def test_device_input_base_get_filters(device_input_base):
@@ -56,6 +56,7 @@ def test_device_input_combobox_init(device_input_combobox):
56
56
  assert device_input_combobox.devices == [
57
57
  "samx",
58
58
  "samy",
59
+ "samz",
59
60
  "aptrx",
60
61
  "aptry",
61
62
  "gauss_bpm",
@@ -141,6 +142,7 @@ def test_device_input_line_edit_init(device_input_line_edit):
141
142
  assert device_input_line_edit.devices == [
142
143
  "samx",
143
144
  "samy",
145
+ "samz",
144
146
  "aptrx",
145
147
  "aptry",
146
148
  "gauss_bpm",
@@ -0,0 +1,155 @@
1
+ import importlib
2
+ import inspect
3
+ import os
4
+ import sys
5
+
6
+ import pytest
7
+
8
+ from bec_widgets.utils.generate_designer_plugin import DesignerPluginGenerator
9
+
10
+
11
+ def load_plugin(dir_path, content, plugin_name="MyWidget"):
12
+ plugin_path = dir_path.mkdir("plugin").join("plugin.py")
13
+ plugin_path.write(content)
14
+ sys.path.append(str(dir_path))
15
+ plugin = importlib.import_module("plugin.plugin")
16
+ importlib.reload(plugin)
17
+ yield getattr(plugin, plugin_name)
18
+ sys.path.pop()
19
+
20
+
21
+ @pytest.fixture(
22
+ params=[
23
+ """
24
+ from qtpy.QtWidgets import QWidget
25
+ class MyWidget(QWidget):
26
+ def __init__(self, parent=None):
27
+ QWidget.__init__(self, parent)
28
+ """,
29
+ """
30
+ from qtpy.QtWidgets import QWidget
31
+ class MyWidget(QWidget):
32
+ def __init__(self, parent=None):
33
+ QWidget.__init__(self, parent=parent)
34
+ """,
35
+ """
36
+ from qtpy.QtWidgets import QWidget
37
+ class MyWidget(QWidget):
38
+ def __init__(self, parent=None):
39
+ super().__init__(parent)
40
+ """,
41
+ """
42
+ from qtpy.QtWidgets import QWidget
43
+ class MyWidget(QWidget):
44
+ def __init__(self, parent=None):
45
+ super().__init__(parent=parent)
46
+ """,
47
+ """
48
+ from qtpy.QtWidgets import QWidget
49
+ class MyWidget(QWidget):
50
+ def __init__(self, parent=None):
51
+ super(QWidget, self).__init__(parent)"""
52
+ """
53
+ from qtpy.QtWidgets import QWidget
54
+ class MyWidget(QWidget):
55
+ def __init__(self, parent=None):
56
+ super(QWidget, self).__init__(parent=parent)
57
+ """,
58
+ ]
59
+ )
60
+ def plugin_with_correct_parent(tmpdir, request):
61
+ yield from load_plugin(tmpdir, request.param)
62
+
63
+
64
+ @pytest.fixture(
65
+ params=[
66
+ """
67
+ from qtpy.QtWidgets import QWidget
68
+ class MyWidget(QWidget):
69
+ def __init__(self, parent=None):
70
+ QWidget.__init__(self)
71
+ """,
72
+ """
73
+ from qtpy.QtWidgets import QWidget
74
+ class MyWidget(QWidget):
75
+ def __init__(self, parent=None):
76
+ super().__init__()
77
+ """,
78
+ """
79
+ from qtpy.QtWidgets import QWidget
80
+ class MyWidget(QWidget):
81
+ def __init__(self, parent=None):
82
+ super(QWidget, self).__init__()
83
+ """,
84
+ ]
85
+ )
86
+ def plugin_with_missing_parent(tmpdir, request):
87
+ yield from load_plugin(tmpdir, request.param)
88
+
89
+
90
+ def test_generate_plugin(plugin_with_correct_parent):
91
+ generator = DesignerPluginGenerator(plugin_with_correct_parent)
92
+ generator.run()
93
+ assert os.path.exists(f"{generator.info.base_path}/register_my_widget.py")
94
+ assert os.path.exists(f"{generator.info.base_path}/my_widget_plugin.py")
95
+ assert os.path.exists(f"{generator.info.base_path}/my_widget.pyproject")
96
+
97
+
98
+ def test_generate_plugin_with_missing_parent(plugin_with_missing_parent):
99
+ with pytest.raises(ValueError) as excinfo:
100
+ generator = DesignerPluginGenerator(plugin_with_missing_parent)
101
+ generator.run()
102
+ assert "Widget class MyWidget must call the super constructor with parent." in str(
103
+ excinfo.value
104
+ )
105
+
106
+
107
+ @pytest.fixture()
108
+ def plugin_with_excluded_widget(tmpdir):
109
+ content = """
110
+ from qtpy.QtWidgets import QWidget
111
+ class BECDock(QWidget):
112
+ def __init__(self, parent=None):
113
+ QWidget.__init__(self, parent)
114
+ """
115
+ yield from load_plugin(tmpdir, content, plugin_name="BECDock")
116
+
117
+
118
+ def test_generate_plugin_with_excluded_widget(plugin_with_excluded_widget, capsys):
119
+ generator = DesignerPluginGenerator(plugin_with_excluded_widget)
120
+ generator.run()
121
+ captured = capsys.readouterr()
122
+
123
+ assert "Plugin BECDock is excluded from generation." in captured.out
124
+ assert not os.path.exists(f"{generator.info.base_path}/register_bec_dock.py")
125
+ assert not os.path.exists(f"{generator.info.base_path}/bec_dock_plugin.py")
126
+ assert not os.path.exists(f"{generator.info.base_path}/bec_dock.pyproject")
127
+
128
+
129
+ @pytest.fixture(
130
+ params=[
131
+ """
132
+ from qtpy.QtWidgets import QWidget
133
+ class MyWidget(QWidget):
134
+ def __init__(self):
135
+ QWidget.__init__(self)
136
+ """,
137
+ """
138
+ from qtpy.QtWidgets import QWidget
139
+ class MyWidget(QWidget):
140
+ def __init__(self, config, parent=None):
141
+ super().__init__()
142
+ """,
143
+ ]
144
+ )
145
+ def plugin_with_no_parent_as_first_arg(tmpdir, request):
146
+ yield from load_plugin(tmpdir, request.param)
147
+
148
+
149
+ def test_generate_plugin_raises_exception_when_first_argument_is_not_parent(
150
+ plugin_with_no_parent_as_first_arg,
151
+ ):
152
+ with pytest.raises(ValueError) as excinfo:
153
+ generator = DesignerPluginGenerator(plugin_with_no_parent_as_first_arg)
154
+ generator.run()
155
+ assert "Widget class MyWidget must have parent as the first argument." in str(excinfo.value)
@@ -74,7 +74,7 @@ def test_motor_thread_initialization(mocked_client):
74
74
  def test_get_all_motors_names(mocked_client):
75
75
  motor_thread = MotorThread(client=mocked_client)
76
76
  motor_names = motor_thread.get_all_motors_names()
77
- expected_names = ["samx", "samy", "aptrx", "aptry"]
77
+ expected_names = ["samx", "samy", "samz", "aptrx", "aptry"]
78
78
  assert sorted(motor_names) == sorted(expected_names)
79
79
  assert all(name in motor_names for name in expected_names)
80
80
  assert len(motor_names) == len(expected_names) # Ensure only these motors are returned
@@ -155,11 +155,12 @@ def motor_selection_widget(qtbot, mocked_client, motor_thread):
155
155
 
156
156
 
157
157
  def test_initialization_and_population(motor_selection_widget):
158
- assert motor_selection_widget.comboBox_motor_x.count() == 4
158
+ assert motor_selection_widget.comboBox_motor_x.count() == 5
159
159
  assert motor_selection_widget.comboBox_motor_x.itemText(0) == "samx"
160
160
  assert motor_selection_widget.comboBox_motor_y.itemText(1) == "samy"
161
- assert motor_selection_widget.comboBox_motor_x.itemText(2) == "aptrx"
162
- assert motor_selection_widget.comboBox_motor_y.itemText(3) == "aptry"
161
+ assert motor_selection_widget.comboBox_motor_y.itemText(2) == "samz"
162
+ assert motor_selection_widget.comboBox_motor_x.itemText(3) == "aptrx"
163
+ assert motor_selection_widget.comboBox_motor_y.itemText(4) == "aptry"
163
164
 
164
165
 
165
166
  def test_selection_and_signal_emission(motor_selection_widget):
@@ -9,14 +9,14 @@ from .test_bec_figure import bec_figure
9
9
 
10
10
 
11
11
  def test_init_plot_base(bec_figure):
12
- plot_base = bec_figure.add_widget(widget_type="PlotBase", widget_id="test_plot")
12
+ plot_base = bec_figure.add_widget(widget_type="BECPlotBase", widget_id="test_plot")
13
13
  assert plot_base is not None
14
14
  assert plot_base.config.widget_class == "BECPlotBase"
15
15
  assert plot_base.config.gui_id == "test_plot"
16
16
 
17
17
 
18
18
  def test_plot_base_axes_by_separate_methods(bec_figure):
19
- plot_base = bec_figure.add_widget(widget_type="PlotBase", widget_id="test_plot")
19
+ plot_base = bec_figure.add_widget(widget_type="BECPlotBase", widget_id="test_plot")
20
20
 
21
21
  plot_base.set_title("Test Title")
22
22
  plot_base.set_x_label("Test x Label")
@@ -66,7 +66,7 @@ def test_plot_base_axes_by_separate_methods(bec_figure):
66
66
 
67
67
 
68
68
  def test_plot_base_axes_added_by_kwargs(bec_figure):
69
- plot_base = bec_figure.add_widget(widget_type="PlotBase", widget_id="test_plot")
69
+ plot_base = bec_figure.add_widget(widget_type="BECPlotBase", widget_id="test_plot")
70
70
 
71
71
  plot_base.set(
72
72
  title="Test Title",