""" Tests for ribbon_widget module """ import pytest from unittest.mock import Mock, MagicMock, patch class TestRibbonWidgetInit: """Tests for RibbonWidget initialization""" def test_init_with_custom_config(self, qtbot): """Test initialization with custom ribbon config""" from pyPhotoAlbum.ribbon_widget import RibbonWidget mock_main_window = Mock() config = { "File": { "groups": [ {"name": "Project", "actions": [{"label": "New", "action": "new_project", "tooltip": "Create new"}]} ] } } widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) assert widget.main_window == mock_main_window assert widget.ribbon_config == config assert widget.buttons_per_row == 4 # default def test_init_with_custom_buttons_per_row(self, qtbot): """Test initialization with custom buttons_per_row""" from pyPhotoAlbum.ribbon_widget import RibbonWidget mock_main_window = Mock() config = {"Test": {"groups": []}} widget = RibbonWidget(mock_main_window, ribbon_config=config, buttons_per_row=6) qtbot.addWidget(widget) assert widget.buttons_per_row == 6 def test_init_creates_tab_widget(self, qtbot): """Test that initialization creates a tab widget""" from pyPhotoAlbum.ribbon_widget import RibbonWidget mock_main_window = Mock() config = {"Tab1": {"groups": []}} widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) assert widget.tab_widget is not None assert widget.tab_widget.count() == 1 class TestBuildRibbon: """Tests for _build_ribbon method""" def test_build_ribbon_creates_tabs(self, qtbot): """Test that _build_ribbon creates tabs from config""" from pyPhotoAlbum.ribbon_widget import RibbonWidget mock_main_window = Mock() config = {"File": {"groups": []}, "Edit": {"groups": []}, "View": {"groups": []}} widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) assert widget.tab_widget.count() == 3 # Tab names should be present tab_names = [widget.tab_widget.tabText(i) for i in range(widget.tab_widget.count())] assert "File" in tab_names assert "Edit" in tab_names assert "View" in tab_names def test_build_ribbon_empty_config(self, qtbot): """Test _build_ribbon with empty config""" from pyPhotoAlbum.ribbon_widget import RibbonWidget mock_main_window = Mock() config = {} widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) assert widget.tab_widget.count() == 0 class TestCreateTab: """Tests for _create_tab method""" def test_create_tab_with_groups(self, qtbot): """Test tab creation with groups""" from pyPhotoAlbum.ribbon_widget import RibbonWidget mock_main_window = Mock() config = {"Test": {"groups": [{"name": "Group1", "actions": []}, {"name": "Group2", "actions": []}]}} widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) # Get the tab widget content tab_content = widget.tab_widget.widget(0) assert tab_content is not None def test_create_tab_empty_groups(self, qtbot): """Test tab creation with no groups""" from pyPhotoAlbum.ribbon_widget import RibbonWidget mock_main_window = Mock() config = {"Test": {"groups": []}} widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) tab_content = widget.tab_widget.widget(0) assert tab_content is not None class TestCreateGroup: """Tests for _create_group method""" def test_create_group_with_actions(self, qtbot): """Test group creation with action buttons""" from pyPhotoAlbum.ribbon_widget import RibbonWidget from PyQt6.QtWidgets import QPushButton mock_main_window = Mock() config = { "Test": { "groups": [ { "name": "Actions", "actions": [ {"label": "Action1", "action": "do_action1"}, {"label": "Action2", "action": "do_action2"}, ], } ] } } widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) tab_content = widget.tab_widget.widget(0) # Find buttons in the tab buttons = tab_content.findChildren(QPushButton) assert len(buttons) == 2 button_labels = [btn.text() for btn in buttons] assert "Action1" in button_labels assert "Action2" in button_labels def test_create_group_respects_buttons_per_row(self, qtbot): """Test that group respects buttons_per_row from config""" from pyPhotoAlbum.ribbon_widget import RibbonWidget from PyQt6.QtWidgets import QPushButton mock_main_window = Mock() config = { "Test": { "groups": [ { "name": "Grid", "buttons_per_row": 2, "actions": [ {"label": "A", "action": "a"}, {"label": "B", "action": "b"}, {"label": "C", "action": "c"}, {"label": "D", "action": "d"}, ], } ] } } widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) tab_content = widget.tab_widget.widget(0) buttons = tab_content.findChildren(QPushButton) assert len(buttons) == 4 class TestCreateActionButton: """Tests for _create_action_button method""" def test_button_has_correct_label(self, qtbot): """Test that button has correct label""" from pyPhotoAlbum.ribbon_widget import RibbonWidget from PyQt6.QtWidgets import QPushButton mock_main_window = Mock() config = {"Test": {"groups": [{"name": "Test", "actions": [{"label": "My Button", "action": "my_action"}]}]}} widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) buttons = widget.tab_widget.widget(0).findChildren(QPushButton) assert len(buttons) == 1 assert buttons[0].text() == "My Button" def test_button_has_tooltip(self, qtbot): """Test that button has correct tooltip""" from pyPhotoAlbum.ribbon_widget import RibbonWidget from PyQt6.QtWidgets import QPushButton mock_main_window = Mock() config = { "Test": { "groups": [ {"name": "Test", "actions": [{"label": "Button", "action": "action", "tooltip": "My tooltip"}]} ] } } widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) buttons = widget.tab_widget.widget(0).findChildren(QPushButton) assert buttons[0].toolTip() == "My tooltip" def test_button_without_tooltip(self, qtbot): """Test button without tooltip configured""" from pyPhotoAlbum.ribbon_widget import RibbonWidget from PyQt6.QtWidgets import QPushButton mock_main_window = Mock() config = {"Test": {"groups": [{"name": "Test", "actions": [{"label": "Button", "action": "action"}]}]}} widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) buttons = widget.tab_widget.widget(0).findChildren(QPushButton) assert buttons[0].toolTip() == "" def test_button_minimum_size(self, qtbot): """Test that button has minimum size set""" from pyPhotoAlbum.ribbon_widget import RibbonWidget from PyQt6.QtWidgets import QPushButton mock_main_window = Mock() config = {"Test": {"groups": [{"name": "Test", "actions": [{"label": "Button", "action": "action"}]}]}} widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) buttons = widget.tab_widget.widget(0).findChildren(QPushButton) assert buttons[0].minimumWidth() == 60 assert buttons[0].minimumHeight() == 40 class TestExecuteAction: """Tests for _execute_action method""" def test_execute_action_calls_main_window_method(self, qtbot): """Test that _execute_action calls the method on main_window""" from pyPhotoAlbum.ribbon_widget import RibbonWidget mock_main_window = Mock() mock_main_window.my_action = Mock() config = {"Test": {"groups": []}} widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) widget._execute_action("my_action") mock_main_window.my_action.assert_called_once() def test_execute_action_missing_method_prints_warning(self, qtbot, capsys): """Test that _execute_action prints warning for missing method""" from pyPhotoAlbum.ribbon_widget import RibbonWidget mock_main_window = Mock(spec=[]) # No methods config = {"Test": {"groups": []}} widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) widget._execute_action("nonexistent_action") captured = capsys.readouterr() assert "Warning" in captured.out assert "nonexistent_action" in captured.out def test_execute_action_non_callable_not_called(self, qtbot): """Test that non-callable attributes are not called""" from pyPhotoAlbum.ribbon_widget import RibbonWidget mock_main_window = Mock() mock_main_window.not_a_method = "just a string" config = {"Test": {"groups": []}} widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) # Should not raise widget._execute_action("not_a_method") def test_button_click_executes_action(self, qtbot): """Test that clicking a button executes the action""" from pyPhotoAlbum.ribbon_widget import RibbonWidget from PyQt6.QtWidgets import QPushButton mock_main_window = Mock() mock_main_window.do_something = Mock() config = {"Test": {"groups": [{"name": "Test", "actions": [{"label": "Do It", "action": "do_something"}]}]}} widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) # Find the button and click it buttons = widget.tab_widget.widget(0).findChildren(QPushButton) assert len(buttons) == 1 qtbot.mouseClick(buttons[0], Qt.MouseButton.LeftButton) mock_main_window.do_something.assert_called_once() class TestGroupLabel: """Tests for group label creation""" def test_group_has_label(self, qtbot): """Test that group has a label""" from pyPhotoAlbum.ribbon_widget import RibbonWidget from PyQt6.QtWidgets import QLabel mock_main_window = Mock() config = {"Test": {"groups": [{"name": "My Group", "actions": []}]}} widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) tab_content = widget.tab_widget.widget(0) labels = tab_content.findChildren(QLabel) # Should have at least one label with the group name label_texts = [lbl.text() for lbl in labels] assert "My Group" in label_texts class TestRibbonLayoutIntegration: """Integration tests for ribbon layout""" def test_full_ribbon_structure(self, qtbot): """Test complete ribbon structure with multiple tabs and groups""" from pyPhotoAlbum.ribbon_widget import RibbonWidget from PyQt6.QtWidgets import QPushButton mock_main_window = Mock() config = { "File": { "groups": [ { "name": "Project", "actions": [ {"label": "New", "action": "new_project"}, {"label": "Open", "action": "open_project"}, {"label": "Save", "action": "save_project"}, ], }, {"name": "Export", "actions": [{"label": "Export PDF", "action": "export_pdf"}]}, ] }, "Edit": { "groups": [ { "name": "Clipboard", "actions": [{"label": "Copy", "action": "copy"}, {"label": "Paste", "action": "paste"}], } ] }, } widget = RibbonWidget(mock_main_window, ribbon_config=config) qtbot.addWidget(widget) # Check tabs assert widget.tab_widget.count() == 2 # Check File tab has 4 buttons file_tab = widget.tab_widget.widget(0) file_buttons = file_tab.findChildren(QPushButton) assert len(file_buttons) == 4 # Check Edit tab has 2 buttons edit_tab = widget.tab_widget.widget(1) edit_buttons = edit_tab.findChildren(QPushButton) assert len(edit_buttons) == 2 # Import Qt for click simulation from PyQt6.QtCore import Qt