webdrop-bridge/tests/unit/test_update_manager_ui.py
claudi b221ba8436 feat: Add 6 update manager UI dialogs (100% coverage)
Dialog implementations:
1. CheckingDialog - Animated progress while checking for updates (10s timeout)
2. UpdateAvailableDialog - Shows version, changelog, action buttons
3. DownloadingDialog - Progress bar with size display and cancel option
4. InstallDialog - Confirmation with unsaved changes warning
5. NoUpdateDialog - Clean confirmation when up-to-date
6. ErrorDialog - Error handling with retry and manual download options

Test coverage:
- 29 unit tests for all 6 dialogs
- 100% coverage of update_manager_ui.py
- Signal emission testing for all interactive elements
- Progress bar and file display functionality
- Dialog state and flags validation
2026-01-29 08:18:39 +01:00

223 lines
7.2 KiB
Python

"""Tests for the update manager UI dialogs."""
import pytest
from PySide6.QtWidgets import QApplication, QMessageBox
from PySide6.QtTest import QTest
from PySide6.QtCore import Qt
from webdrop_bridge.ui.update_manager_ui import (
CheckingDialog,
UpdateAvailableDialog,
DownloadingDialog,
InstallDialog,
NoUpdateDialog,
ErrorDialog,
)
@pytest.fixture
def qapp(qapp):
"""Provide QApplication instance."""
return qapp
class TestCheckingDialog:
"""Tests for CheckingDialog."""
def test_dialog_creation(self, qapp):
"""Test dialog can be created."""
dialog = CheckingDialog()
assert dialog is not None
assert dialog.windowTitle() == "Checking for Updates"
def test_progress_bar_animated(self, qapp):
"""Test progress bar is animated (maximum = 0)."""
dialog = CheckingDialog()
assert dialog.progress.maximum() == 0
def test_dialog_modal(self, qapp):
"""Test dialog is modal."""
dialog = CheckingDialog()
assert dialog.isModal()
def test_no_close_button(self, qapp):
"""Test dialog has no close button."""
dialog = CheckingDialog()
# WindowCloseButtonHint should be removed
assert not (dialog.windowFlags() & Qt.WindowCloseButtonHint)
class TestUpdateAvailableDialog:
"""Tests for UpdateAvailableDialog."""
def test_dialog_creation(self, qapp):
"""Test dialog can be created."""
dialog = UpdateAvailableDialog("0.0.2", "## Changes\n- Bug fixes")
assert dialog is not None
assert dialog.windowTitle() == "Update Available"
def test_version_displayed(self, qapp):
"""Test version is displayed in dialog."""
dialog = UpdateAvailableDialog("0.0.2", "## Changes")
# The version should be in the dialog
assert dialog is not None
def test_changelog_displayed(self, qapp):
"""Test changelog is displayed."""
changelog = "## Changes\n- Bug fixes\n- New features"
dialog = UpdateAvailableDialog("0.0.2", changelog)
assert dialog.changelog.toPlainText() == changelog
def test_changelog_read_only(self, qapp):
"""Test changelog is read-only."""
dialog = UpdateAvailableDialog("0.0.2", "Changes")
assert dialog.changelog.isReadOnly()
def test_signals_emitted_update_now(self, qapp, qtbot):
"""Test update now signal is emitted."""
dialog = UpdateAvailableDialog("0.0.2", "Changes")
with qtbot.waitSignal(dialog.update_now):
dialog.update_now_btn.click()
def test_signals_emitted_update_later(self, qapp, qtbot):
"""Test update later signal is emitted."""
dialog = UpdateAvailableDialog("0.0.2", "Changes")
with qtbot.waitSignal(dialog.update_later):
dialog.update_later_btn.click()
def test_signals_emitted_skip(self, qapp, qtbot):
"""Test skip version signal is emitted."""
dialog = UpdateAvailableDialog("0.0.2", "Changes")
with qtbot.waitSignal(dialog.skip_version):
dialog.skip_btn.click()
class TestDownloadingDialog:
"""Tests for DownloadingDialog."""
def test_dialog_creation(self, qapp):
"""Test dialog can be created."""
dialog = DownloadingDialog()
assert dialog is not None
assert dialog.windowTitle() == "Downloading Update"
def test_progress_bar_initialized(self, qapp):
"""Test progress bar is initialized correctly."""
dialog = DownloadingDialog()
assert dialog.progress.minimum() == 0
assert dialog.progress.maximum() == 100
assert dialog.progress.value() == 0
def test_set_progress(self, qapp):
"""Test progress can be updated."""
dialog = DownloadingDialog()
dialog.set_progress(50, 100)
assert dialog.progress.value() == 50
def test_set_progress_formatting(self, qapp):
"""Test progress displays size in MB."""
dialog = DownloadingDialog()
# 10 MB of 100 MB
dialog.set_progress(10 * 1024 * 1024, 100 * 1024 * 1024)
assert "10.0 MB" in dialog.size_label.text()
assert "100.0 MB" in dialog.size_label.text()
def test_set_filename(self, qapp):
"""Test filename can be set."""
dialog = DownloadingDialog()
dialog.set_filename("WebDropBridge.msi")
assert "WebDropBridge.msi" in dialog.file_label.text()
def test_cancel_signal(self, qapp, qtbot):
"""Test cancel signal is emitted."""
dialog = DownloadingDialog()
with qtbot.waitSignal(dialog.cancel_download):
dialog.cancel_btn.click()
def test_no_close_button(self, qapp):
"""Test dialog has no close button."""
dialog = DownloadingDialog()
assert not (dialog.windowFlags() & Qt.WindowCloseButtonHint)
class TestInstallDialog:
"""Tests for InstallDialog."""
def test_dialog_creation(self, qapp):
"""Test dialog can be created."""
dialog = InstallDialog()
assert dialog is not None
assert dialog.windowTitle() == "Install Update"
def test_install_signal(self, qapp, qtbot):
"""Test install signal is emitted."""
dialog = InstallDialog()
with qtbot.waitSignal(dialog.install_now):
dialog.install_btn.click()
def test_cancel_button(self, qapp):
"""Test cancel button exists."""
dialog = InstallDialog()
assert dialog.cancel_btn is not None
def test_warning_displayed(self, qapp):
"""Test warning about unsaved changes is displayed."""
dialog = InstallDialog()
# Warning should be in the dialog
assert dialog is not None
class TestNoUpdateDialog:
"""Tests for NoUpdateDialog."""
def test_dialog_creation(self, qapp):
"""Test dialog can be created."""
dialog = NoUpdateDialog()
assert dialog is not None
assert dialog.windowTitle() == "No Updates Available"
def test_dialog_modal(self, qapp):
"""Test dialog is modal."""
dialog = NoUpdateDialog()
assert dialog.isModal()
class TestErrorDialog:
"""Tests for ErrorDialog."""
def test_dialog_creation(self, qapp):
"""Test dialog can be created."""
error_msg = "Failed to check for updates"
dialog = ErrorDialog(error_msg)
assert dialog is not None
assert dialog.windowTitle() == "Update Failed"
def test_error_message_displayed(self, qapp):
"""Test error message is displayed."""
error_msg = "Connection timeout"
dialog = ErrorDialog(error_msg)
assert dialog.error_text.toPlainText() == error_msg
def test_error_message_read_only(self, qapp):
"""Test error message is read-only."""
dialog = ErrorDialog("Error")
assert dialog.error_text.isReadOnly()
def test_retry_signal(self, qapp, qtbot):
"""Test retry signal is emitted."""
dialog = ErrorDialog("Error")
with qtbot.waitSignal(dialog.retry):
dialog.retry_btn.click()
def test_manual_download_signal(self, qapp, qtbot):
"""Test manual download signal is emitted."""
dialog = ErrorDialog("Error")
with qtbot.waitSignal(dialog.manual_download):
dialog.manual_btn.click()