zapretgui/tests/test_holiday_effects_performance.py
loop-uh 253fdf373b fix
2026-06-22 21:09:22 +03:00

157 lines
5.9 KiB
Python

from __future__ import annotations
import os
import unittest
from types import SimpleNamespace
from unittest.mock import Mock, patch
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")
from PyQt6.QtWidgets import QApplication, QWidget
from app.state_store import AppUiState, MainWindowStateStore
from main.window_state_actions import WindowStateActions
from ui.holiday_effects import _Snowflake, GarlandOverlay, HolidayEffectsManager, SnowflakesOverlay
from ui.window_appearance_state import apply_garland_enabled, apply_snowflakes_enabled, on_animations_changed
class _CountingSnowflakesOverlay(SnowflakesOverlay):
def __init__(self, parent: QWidget):
self.raise_count = 0
super().__init__(parent)
def raise_(self) -> None:
self.raise_count += 1
super().raise_()
class HolidayEffectsPerformanceTests(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls._app = QApplication.instance() or QApplication([])
def test_snowflake_motion_rect_covers_old_and_new_positions(self) -> None:
host = QWidget()
overlay = SnowflakesOverlay(host)
flake = _Snowflake(40.0, 50.0)
flake.size = 4.0
self.assertTrue(hasattr(overlay, "_snowflake_paint_rect"))
self.assertTrue(hasattr(overlay, "_snowflake_motion_rect"))
old_rect = overlay._snowflake_paint_rect(flake)
flake.x = 44.0
flake.y = 57.0
new_rect = overlay._snowflake_paint_rect(flake)
dirty_rect = overlay._snowflake_motion_rect(flake, 40.0, 50.0)
self.assertTrue(dirty_rect.contains(old_rect))
self.assertTrue(dirty_rect.contains(new_rect))
self.assertLess(dirty_rect.width(), overlay.width() or 640)
def test_snowflake_pixmap_is_reused_for_same_visual_bucket(self) -> None:
host = QWidget()
overlay = SnowflakesOverlay(host)
flake = _Snowflake(40.0, 50.0)
flake.size = 3.1
flake.opacity = 0.31
first = overlay._snowflake_pixmap(flake, 1.0)
second = overlay._snowflake_pixmap(flake, 1.0)
self.assertFalse(first.isNull())
self.assertEqual(first.cacheKey(), second.cacheKey())
self.assertEqual(len(overlay._flake_pixmap_cache), 1)
def test_snowflake_density_stays_bounded_on_large_windows(self) -> None:
host = QWidget()
overlay = SnowflakesOverlay(host)
self.assertLessEqual(overlay._max_flake_count(1920, 1080), 150)
self.assertLessEqual(overlay._initial_flake_count(1920, 1080), 70)
def test_holiday_effects_do_not_pause_for_ui_work(self) -> None:
self.assertFalse(hasattr(SnowflakesOverlay, "suspend_for_ui_work"))
self.assertFalse(hasattr(GarlandOverlay, "suspend_for_ui_work"))
def test_snowflake_animation_does_not_raise_overlay_every_frame(self) -> None:
host = QWidget()
host.resize(640, 480)
overlay = _CountingSnowflakesOverlay(host)
overlay.set_enabled(True)
overlay.raise_count = 0
overlay._animate()
self.assertEqual(overlay.raise_count, 0)
def test_holiday_manager_pauses_and_resumes_timers_without_disabling_effects(self) -> None:
host = QWidget()
host.resize(640, 480)
manager = HolidayEffectsManager(host)
manager.set_garland_enabled(True)
manager.set_snowflakes_enabled(True)
self.assertTrue(manager._garland._timer.isActive())
self.assertTrue(manager._snowflakes._animate_timer.isActive())
self.assertTrue(manager._snowflakes._spawn_timer.isActive())
manager.set_animation_active(False)
self.assertTrue(manager._garland.is_enabled())
self.assertTrue(manager._snowflakes.is_enabled())
self.assertFalse(manager._garland._timer.isActive())
self.assertFalse(manager._snowflakes._animate_timer.isActive())
self.assertFalse(manager._snowflakes._spawn_timer.isActive())
manager.set_animation_active(True)
self.assertTrue(manager._garland._timer.isActive())
self.assertTrue(manager._snowflakes._animate_timer.isActive())
self.assertTrue(manager._snowflakes._spawn_timer.isActive())
def test_disabling_holiday_effects_does_not_create_overlay_manager(self) -> None:
host = QWidget()
host.visual_state = SimpleNamespace(holiday_effects=None)
apply_garland_enabled(host, False)
apply_snowflakes_enabled(host, False)
self.assertIsNone(host.visual_state.holiday_effects)
def test_animation_master_disables_existing_holiday_overlays(self) -> None:
effects = SimpleNamespace(
set_garland_enabled=Mock(),
set_snowflakes_enabled=Mock(),
set_animation_active=Mock(),
)
host = QWidget()
host.visual_state = SimpleNamespace(holiday_effects=effects)
with patch("ui.window_appearance_state.apply_window_animation_policy"):
on_animations_changed(host, False)
effects.set_garland_enabled.assert_called_once_with(False)
effects.set_snowflakes_enabled.assert_called_once_with(False)
effects.set_animation_active.assert_called_once_with(False)
def test_window_actions_keep_holiday_overlays_off_when_animation_master_is_off(self) -> None:
effects = SimpleNamespace(set_snowflakes_enabled=Mock())
host = QWidget()
host.visual_state = SimpleNamespace(holiday_effects=effects)
store = MainWindowStateStore(AppUiState(garland_enabled=True, snowflakes_enabled=True))
actions = WindowStateActions(host, store)
with patch("main.window_state_actions._holiday_effects_allowed", return_value=False):
actions.set_snowflakes_enabled(True)
snapshot = store.snapshot()
self.assertFalse(snapshot.garland_enabled)
self.assertFalse(snapshot.snowflakes_enabled)
effects.set_snowflakes_enabled.assert_called_once_with(False)
if __name__ == "__main__":
unittest.main()