Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@
"wiki_text": "Follow the blog instructions and use Mission Planner instead of this tool to configure the mandatory hardware parameters.",
"wiki_url": "",
"external_tool_text": "Mission Planner",
"external_tool_url": "https://github.com/ArduPilot/MethodicConfigurator/blob/latest/TUNING_GUIDE_ArduCopter.md#212-configure-mandatory-hardware-parameters-17",
"external_tool_url": "https://ardupilot.org/copter/docs/configuring-hardware.html",
"mandatory_text": "100% mandatory (0% optional)",
"auto_changed_by": "Mission Planner. If you have not done this step in Mission Planner yet, close this application and use Mission Planner",
"old_filenames": ["11_mp_setup_mandatory_hardware.param"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -541,6 +541,18 @@ def __should_copy_fc_values_to_file(self, selected_file: str) -> None: # pylint
message_label = tk.Label(dialog, text=msg, justify=tk.LEFT, padx=20, pady=10)
message_label.pack(padx=10, pady=10)

# Clickable link to tuning guide
safe_font_config = get_safe_font_config()
link_label = tk.Label(
dialog,
text=_("Click here to open the Tuning Guide relevant Section"),
fg="blue",
cursor="hand2",
font=(str(safe_font_config["family"]), int(safe_font_config["size"]), "underline"),
)
link_label.pack(pady=(0, 10))
link_label.bind("<Button-1>", lambda _e: self.configuration_manager.open_documentation_in_browser(selected_file))

# Result variable
result: list[Optional[Literal[True, False]]] = [None]

Expand Down
43 changes: 40 additions & 3 deletions tests/test_frontend_tkinter_parameter_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"""

from typing import Any
from unittest.mock import MagicMock, patch
from unittest.mock import ANY, MagicMock, patch

import pytest

Expand Down Expand Up @@ -245,7 +245,7 @@ def side_effect(*args, **kwargs) -> None: # noqa: ARG001 # pylint: disable=unus
@patch("tkinter.Label")
@patch("tkinter.Frame")
@patch("tkinter.Button")
def test_dialog_creation(
def test_dialog_creation( # pylint: disable=too-many-locals
self,
mock_button: MagicMock,
mock_frame: MagicMock,
Expand Down Expand Up @@ -281,5 +281,42 @@ def fake_wait_window(*args: Any, **kwargs: Any) -> None: # noqa: ANN401 # pylin
mock_toplevel.assert_called_once()

# Check for label, buttons, and frame creation
mock_label.assert_called_once()
assert mock_label.call_count == 2 # message label and link label
assert mock_button.call_count == 3 # Close, Yes, No buttons
mock_frame.assert_called_once()

# Verify message label creation
message_label_call = mock_label.call_args_list[0]
assert message_label_call[1]["text"].startswith("This configuration step requires external changes by: External Tool")
assert message_label_call[1]["justify"] == "left"
assert message_label_call[1]["padx"] == 20
assert message_label_call[1]["pady"] == 10

# Verify link label creation
link_label_call = mock_label.call_args_list[1]
assert link_label_call[1]["text"] == "Click here to open the Tuning Guide relevant Section"
assert link_label_call[1]["fg"] == "blue"
assert link_label_call[1]["cursor"] == "hand2"
# Font should be a tuple with underline
font_arg = link_label_call[1]["font"]
assert isinstance(font_arg, tuple)
assert len(font_arg) == 3
assert font_arg[2] == "underline"

# Verify link label is packed and bound correctly
link_label_mock = mock_label.return_value
# Both labels call pack, so check that the link label's pack call was made
assert link_label_mock.pack.call_count == 2
link_label_mock.pack.assert_any_call(pady=(0, 10)) # link label pack call
link_label_mock.pack.assert_any_call(padx=10, pady=10) # message label pack call
link_label_mock.bind.assert_called_once_with("<Button-1>", ANY) # lambda function, so use ANY

# Verify buttons are created with correct text
button_calls = mock_button.call_args_list
assert button_calls[0][1]["text"] == "Close"
assert button_calls[1][1]["text"] == "Yes"
assert button_calls[2][1]["text"] == "No"

# Verify button frame is packed correctly
frame_mock = mock_frame.return_value
frame_mock.pack.assert_called_once_with(pady=10)