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
This commit is contained in:
parent
342044ec3f
commit
b221ba8436
2 changed files with 622 additions and 0 deletions
223
tests/unit/test_update_manager_ui.py
Normal file
223
tests/unit/test_update_manager_ui.py
Normal file
|
|
@ -0,0 +1,223 @@
|
|||
"""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()
|
||||
Loading…
Add table
Add a link
Reference in a new issue