test update

This commit is contained in:
Pierre committed 2026-11-13 13:10:37 +01:00
1 parent 4d502c5911
commit 8cd2a414cd
4 files changed
+380 -4

No files matched your search

@@ -0,0 +1,78 @@
"""Notification logging must avoid stack inspection without changing delivery."""
import logging
from pathlib import Path
import sys
from types import SimpleNamespace
import unittest
from unittest.mock import Mock, call, patch
sys.path[:0] = [str(Path(__file__).resolve().parents[1] / 'apps'),
str(Path(__file__).resolve().parents[1] / 'apps/ad_toolbox')]
from appdaemon.adapi import ADAPI
from notificationsmanager import NotificationsManager, Notification, SmartCondition
class NotificationLoggingTests(unittest.TestCase):
def setUp(self):
self.api = ADAPI.__new__(ADAPI)
self.api.AD = SimpleNamespace(config=SimpleNamespace(ascii_encode=False))
self.api.logger = Mock()
self.sinks = {'main_log': Mock(), 'error_log': Mock()}
self.api.get_user_log = Mock(side_effect=self.sinks.__getitem__)
self.app = NotificationsManager.__new__(NotificationsManager)
self.app.get_ad_api = Mock(return_value=self.api)
self.app.args = {}
self.app.call_service = Mock()
self.app.run_in = Mock()
self.app.stop_app = Mock()
self.app._config_model = SimpleNamespace(name='notifications_manager')
self.app.initialize()
self.config = {
'message': {'title': 'Alarme', 'content': 'Activée', 'timeout': 10,
'data': {'tag': 'alarm'}},
'recipients': {'phones': {'services': ['notify/one', 'notify/two']}}
}
self.notification = Notification(self.app, {'message': {}, 'recipients': {}}, 'alarm')
self.notification.config = self.config
def test_send_and_clear_keep_delivery_without_inspecting_stack(self):
with patch('appdaemon.adapi.inspect.stack', side_effect=AssertionError('stack inspection')):
self.notification.send_notification('phones')
self.notification.clear_notification('phones', 'alarm')
self.app.call_service.assert_has_calls([
call('notify/one', title='Alarme', message='Activée', data={'tag': 'alarm'}),
call('notify/two', title='Alarme', message='Activée', data={'tag': 'alarm'}),
call('notify/one', message='clear_notification', data={'tag': 'alarm'}),
call('notify/two', message='clear_notification', data={'tag': 'alarm'}),
])
self.app.run_in.assert_called_once_with(self.notification.on_timeout_expired, 10,
tag='alarm', recipient='phones')
self.assertEqual(self.api.logger.log.call_count, 4)
self.api.get_user_log.assert_not_called()
def test_errors_use_app_logger_and_error_log_and_stop(self):
with patch('appdaemon.adapi.inspect.stack', side_effect=AssertionError('stack inspection')):
self.app.log_error('Échec', stop_app=True)
for sink in (self.api.logger, self.sinks['error_log']):
self.assertEqual(sink.log.call_args.args, (logging.ERROR, 'Échec'))
self.sinks['main_log'].log.assert_not_called()
self.app.stop_app.assert_called_once_with('notifications_manager')
def test_smartcondition_fallback_uses_initialized_interface(self):
self.config['recipients']['phones']['conditions'] = True
self.app.args = {'notifications': {'alarm': self.config}}
real_class = SmartCondition.Evaluator
def factory(api, *args, **kwargs):
condition = real_class.__new__(real_class)
condition._Evaluator__logger_interface = None
condition._Evaluator__appdaemon_api = api
condition._Evaluator__log_info('Condition évaluée')
return condition
with patch('appdaemon.adapi.inspect.stack', side_effect=AssertionError('stack inspection')):
with patch.object(SmartCondition, 'Evaluator', side_effect=factory):
self.app.initialize()
self.assertEqual(self.api.logger.log.call_args.args, (logging.INFO, 'Condition évaluée'))
if __name__ == '__main__':
unittest.main()