@@ -1489,6 +1489,99 @@ def test_refresh_now_queues_when_refresh_is_busy() -> None:
14891489 assert delegate ._refresh_queued is True
14901490
14911491
1492+ def test_schedule_settled_refreshes_replaces_pending_timers (
1493+ monkeypatch : pytest .MonkeyPatch ,
1494+ ) -> None :
1495+ class FakeTimer :
1496+ def __init__ (self , delay : float ) -> None :
1497+ self .delay = delay
1498+ self .invalidated = False
1499+
1500+ def invalidate (self ) -> None :
1501+ self .invalidated = True
1502+
1503+ def isValid (self ) -> bool :
1504+ return not self .invalidated
1505+
1506+ class FakeNSTimer :
1507+ created : list [FakeTimer ] = []
1508+
1509+ @staticmethod
1510+ def scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_ (
1511+ delay : float ,
1512+ _target : object ,
1513+ _selector : str ,
1514+ _user_info : object ,
1515+ _repeats : bool ,
1516+ ) -> FakeTimer :
1517+ timer = FakeTimer (delay )
1518+ FakeNSTimer .created .append (timer )
1519+ return timer
1520+
1521+ class FakeRunLoop :
1522+ added : list [FakeTimer ] = []
1523+
1524+ @staticmethod
1525+ def currentRunLoop () -> type [FakeRunLoop ]:
1526+ return FakeRunLoop
1527+
1528+ @staticmethod
1529+ def addTimer_forMode_ (timer : FakeTimer , _mode : object ) -> None :
1530+ FakeRunLoop .added .append (timer )
1531+
1532+ class Delegate :
1533+ _settled_refresh_timers : list [FakeTimer ]
1534+
1535+ def __init__ (self ) -> None :
1536+ self ._settled_refresh_timers = [FakeTimer (1.0 )]
1537+
1538+ old_timer = Delegate ()._settled_refresh_timers [0 ]
1539+ delegate = Delegate ()
1540+ delegate ._settled_refresh_timers = [old_timer ]
1541+ monkeypatch .setattr (menubar , "NSTimer" , FakeNSTimer )
1542+ monkeypatch .setattr (menubar , "NSRunLoop" , FakeRunLoop )
1543+
1544+ menubar .AppDelegate ._schedule_settled_refreshes (cast (Any , delegate ))
1545+
1546+ assert old_timer .invalidated is True
1547+ assert [timer .delay for timer in delegate ._settled_refresh_timers ] == list (
1548+ menubar .SETTLED_REFRESH_DELAYS
1549+ )
1550+ assert FakeRunLoop .added == delegate ._settled_refresh_timers
1551+
1552+
1553+ def test_settled_refresh_timer_fires_queued_refresh (
1554+ monkeypatch : pytest .MonkeyPatch ,
1555+ ) -> None :
1556+ class FakeTimer :
1557+ def __init__ (self , valid : bool ) -> None :
1558+ self ._valid = valid
1559+
1560+ def isValid (self ) -> bool :
1561+ return self ._valid
1562+
1563+ refresh_calls = 0
1564+ queue_flags : list [bool ] = []
1565+
1566+ def fake_refresh (_self : object , * , queue_if_busy : bool = False ) -> None :
1567+ nonlocal refresh_calls
1568+ refresh_calls += 1
1569+ queue_flags .append (queue_if_busy )
1570+
1571+ delegate = menubar .AppDelegate .alloc ().initWithMock_interval_ (True , 60 )
1572+ fired = FakeTimer (True )
1573+ pending = FakeTimer (True )
1574+ invalid = FakeTimer (False )
1575+ delegate ._settled_refresh_timers = [fired , pending , invalid ]
1576+ monkeypatch .setattr (menubar .AppDelegate , "_refresh" , fake_refresh )
1577+
1578+ delegate .settledRefreshTimerFired_ (fired )
1579+
1580+ assert delegate ._settled_refresh_timers == [pending ]
1581+ assert refresh_calls == 1
1582+ assert queue_flags == [True ]
1583+
1584+
14921585def test_apply_refresh_result_clears_busy_flag_when_ui_update_fails () -> None :
14931586 class FailingPopover :
14941587 def isShown (self ) -> bool :
0 commit comments