"""An expired timer queued before reactivation must not end the new window.""" import ast from pathlib import Path from types import SimpleNamespace import unittest from unittest.mock import Mock from test_continuous_condition import FakeScheduler source = Path(__file__).resolve().parents[1] / 'virtualsensors.py' node = next(node for node in ast.parse(source.read_text()).body if isinstance(node, ast.ClassDef) and node.name == 'EventSensor') namespace = {'VirtualSensorBase': object, 'EventHandler': Mock()} exec(compile(ast.Module(body=[node], type_ignores=[]), str(source), 'exec'), namespace) EventSensor = namespace['EventSensor'] class EventSensorTests(unittest.TestCase): def setUp(self): self.scheduler = FakeScheduler() self.state = 'off' entity = Mock() entity.exists.return_value = True entity.set_state.side_effect = lambda *, state: setattr(self, 'state', state) self.sensor = EventSensor() self.sensor.ad_api = SimpleNamespace( get_entity=lambda name: entity, run_in=self.scheduler.run_in, cancel_timer=self.scheduler.cancel_timer, ) self.sensor.sensor_name = 'binary_sensor.red_shelly_home' self.sensor.yaml_block = {'retain_time': 120} self.sensor.initialize() def activate(self): self.sensor.on_activation_event('signal_strength', {}, {}) return self.sensor.cb_handle def test_current_expiry_turns_sensor_off(self): handle = self.activate() self.assertEqual(self.state, 'on') self.scheduler.expire(handle)() self.assertEqual(self.state, 'off') self.assertIsNone(self.sensor.cb_handle) def test_reactivation_cancels_running_timer(self): old = self.activate() current = self.activate() self.assertNotIn(old, self.scheduler.timers) self.assertIn(current, self.scheduler.timers) self.assertEqual(self.state, 'on') self.assertEqual(self.scheduler.warnings, []) def test_queued_expiry_preserves_reactivated_sensor_and_timer(self): queued = self.scheduler.expire(self.activate()) current = self.activate() queued() self.assertEqual(self.state, 'on') self.assertEqual(self.sensor.cb_handle, current) self.assertEqual(self.scheduler.warnings, []) self.scheduler.expire(current)() self.assertEqual(self.state, 'off') self.assertIsNone(self.sensor.cb_handle) def test_multiple_queued_expiries_cannot_end_latest_window(self): first = self.scheduler.expire(self.activate()) second = self.scheduler.expire(self.activate()) current = self.activate() second() first() self.assertEqual(self.state, 'on') self.assertEqual(self.sensor.cb_handle, current) self.assertEqual(self.scheduler.warnings, []) self.scheduler.expire(current)() self.assertEqual(self.state, 'off') if __name__ == '__main__': unittest.main()