| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- """
- Tests for the Version Checker UI component (Story 7.26).
- """
- import pytest
- from datetime import datetime
- from pathlib import Path
- import tempfile
- from PyQt6.QtWidgets import QApplication
- from src.ui.version_checker import (
- UpdateSeverity,
- VersionInfo,
- CurrentVersion,
- VersionCheckResult,
- VersionCheckThread,
- CURRENT_VERSION,
- get_version_checker,
- )
- @pytest.fixture
- def app(qtbot):
- """Create QApplication for tests."""
- return QApplication.instance() or QApplication([])
- @pytest.fixture
- def sample_version_info():
- """Create sample version info."""
- return VersionInfo(
- version="1.2.0",
- release_date=datetime.now(),
- download_url="https://example.com/download/v1.2.0",
- release_notes="New features and bug fixes",
- file_size=50000000,
- severity=UpdateSeverity.OPTIONAL
- )
- @pytest.fixture
- def sample_current_version():
- """Create sample current version."""
- return CurrentVersion(
- version="1.0.0",
- build_date=datetime.now(),
- commit_hash="abc123",
- channel="stable"
- )
- class TestUpdateSeverity:
- """Tests for UpdateSeverity enum."""
- def test_severity_values(self):
- """Test UpdateSeverity enum values."""
- assert UpdateSeverity.OPTIONAL.value == "optional"
- assert UpdateSeverity.RECOMMENDED.value == "recommended"
- assert UpdateSeverity.CRITICAL.value == "critical"
- class TestVersionInfo:
- """Tests for VersionInfo."""
- def test_creation(self):
- """Test creating version info."""
- info = VersionInfo(
- version="1.0.0",
- release_date=datetime.now(),
- download_url="https://example.com",
- release_notes="Release notes"
- )
- assert info.version == "1.0.0"
- assert info.severity == UpdateSeverity.OPTIONAL
- def test_with_all_fields(self):
- """Test creating with all fields."""
- info = VersionInfo(
- version="2.0.0",
- release_date=datetime.now(),
- download_url="https://example.com",
- release_notes="Notes",
- file_size=1000000,
- checksum="abc123",
- severity=UpdateSeverity.CRITICAL,
- minimum_compatible_version="1.5.0",
- breaking_changes=True
- )
- assert info.file_size == 1000000
- assert info.severity == UpdateSeverity.CRITICAL
- assert info.breaking_changes is True
- class TestCurrentVersion:
- """Tests for CurrentVersion."""
- def test_creation(self):
- """Test creating current version."""
- version = CurrentVersion(
- version="1.0.0",
- build_date=datetime.now(),
- commit_hash="abc123",
- channel="stable"
- )
- assert version.version == "1.0.0"
- assert version.channel == "stable"
- def test_partial_fields(self):
- """Test creating with partial fields."""
- version = CurrentVersion(version="1.0.0")
- assert version.version == "1.0.0"
- assert version.build_date is None
- class TestVersionCheckResult:
- """Tests for VersionCheckResult."""
- def test_has_update_true(self, sample_current_version, sample_version_info):
- """Test has_update when update is available."""
- result = VersionCheckResult(sample_current_version, sample_version_info)
- assert result.has_update is True
- def test_has_update_false(self, sample_current_version):
- """Test has_update when no update available."""
- old_version = VersionInfo(
- version="0.9.0",
- release_date=datetime.now(),
- download_url="https://example.com",
- release_notes="Old version"
- )
- result = VersionCheckResult(sample_current_version, old_version)
- assert result.has_update is False
- def test_has_update_no_latest(self, sample_current_version):
- """Test has_update when latest is None."""
- result = VersionCheckResult(sample_current_version, None)
- assert result.has_update is False
- def test_is_critical(self, sample_current_version):
- """Test is_critical property."""
- critical_version = VersionInfo(
- version="2.0.0",
- release_date=datetime.now(),
- download_url="https://example.com",
- release_notes="Critical update",
- severity=UpdateSeverity.CRITICAL
- )
- result = VersionCheckResult(sample_current_version, critical_version)
- assert result.is_critical is True
- def test_version_comparison(self, sample_current_version):
- """Test version comparison logic."""
- result = VersionCheckResult(sample_current_version)
- # Test greater than
- assert result._compare_versions("1.2.0", "1.0.0") > 0
- assert result._compare_versions("2.0.0", "1.9.9") > 0
- # Test less than
- assert result._compare_versions("1.0.0", "1.2.0") < 0
- assert result._compare_versions("1.0.0", "2.0.0") < 0
- # Test equal
- assert result._compare_versions("1.0.0", "1.0.0") == 0
- # Test with different lengths
- assert result._compare_versions("1.0", "1.0.0") == 0
- assert result._compare_versions("1.0.0", "1.0") == 0
- class TestVersionCheckThread:
- """Tests for VersionCheckThread."""
- def test_initialization(self, sample_current_version):
- """Test thread initialization."""
- thread = VersionCheckThread(
- sample_current_version,
- "https://api.example.com/version"
- )
- assert thread._current == sample_current_version
- assert thread._check_url == "https://api.example.com"
- def test_with_custom_timeout(self, sample_current_version):
- """Test with custom timeout."""
- thread = VersionCheckThread(
- sample_current_version,
- "https://api.example.com/version",
- timeout=30.0
- )
- assert thread._timeout == 30.0
- class TestVersionChecker:
- """Tests for VersionChecker."""
- def test_initialization(self, sample_current_version):
- """Test checker initialization."""
- from src.ui.version_checker import VersionChecker
- checker = VersionChecker(sample_current_version)
- assert checker._current == sample_current_version
- assert checker._auto_check is True
- def test_set_check_url(self, sample_current_version):
- """Test setting check URL."""
- from src.ui.version_checker import VersionChecker
- checker = VersionChecker(sample_current_version)
- checker.set_check_url("https://custom.api.com/version")
- assert checker._check_url == "https://custom.api.com/version"
- def test_set_auto_check(self, sample_current_version):
- """Test setting auto check."""
- from src.ui.version_checker import VersionChecker
- checker = VersionChecker(sample_current_version)
- checker.set_auto_check(False)
- assert checker._auto_check is False
- def test_skip_version(self, sample_current_version):
- """Test skipping a version."""
- from src.ui.version_checker import VersionChecker
- checker = VersionChecker(sample_current_version)
- checker.skip_version("1.2.0")
- # Version should be in settings
- from PyQt6.QtCore import QSettings
- settings = QSettings("BMAD", "NovelTranslator")
- skipped = settings.value("update/skip_version", "")
- assert skipped == "1.2.0"
- def test_clear_skipped_version(self, sample_current_version):
- """Test clearing skipped version."""
- from src.ui.version_checker import VersionChecker
- from PyQt6.QtCore import QSettings
- checker = VersionChecker(sample_current_version)
- # First skip a version
- checker.skip_version("1.2.0")
- # Then clear it
- checker.clear_skipped_version()
- settings = QSettings("BMAD", "NovelTranslator")
- skipped = settings.value("update/skip_version", "")
- assert skipped == ""
- class TestCurrentVersionModule:
- """Tests for the module-level CURRENT_VERSION."""
- def test_current_version_exists(self):
- """Test that CURRENT_VERSION is defined."""
- assert CURRENT_VERSION is not None
- assert isinstance(CURRENT_VERSION, CurrentVersion)
- def test_current_version_format(self):
- """Test that version string is valid."""
- # Should be valid semver
- parts = CURRENT_VERSION.version.split(".")
- assert len(parts) >= 2
- class TestGetVersionChecker:
- """Tests for get_version_checker function."""
- def test_returns_instance(self):
- """Test that get_version_checker returns an instance."""
- from src.ui.version_checker import VersionChecker
- checker = get_version_checker()
- assert isinstance(checker, VersionChecker)
- def test_singleton_behavior(self):
- """Test that repeated calls return new instances (default)."""
- checker1 = get_version_checker()
- checker2 = get_version_checker()
- # Each call creates a new instance with CURRENT_VERSION
- assert isinstance(checker1, VersionChecker)
- assert isinstance(checker2, VersionChecker)
|