from urllib import parse import pytest import requests from app.cronitor import cronitor from tests.conftest import set_config_values def _cronitor_url(key, command): return parse.urlunparse(parse.ParseResult( scheme='https', netloc='cronitor.link', path='{}/{}'.format(key, command), params='', query=parse.urlencode({'host': 'http://localhost:6011'}), fragment='' )) RUN_LINK = _cronitor_url('secret', 'run') FAIL_LINK = _cronitor_url('secret', 'fail') COMPLETE_LINK = _cronitor_url('secret', 'complete') @cronitor('hello') def successful_task(): return 1 @cronitor('hello') def crashing_task(): raise ValueError def test_cronitor_sends_run_and_complete(notify_api, rmock): rmock.get(RUN_LINK, status_code=200) rmock.get(COMPLETE_LINK, status_code=200) with set_config_values(notify_api, { 'CRONITOR_ENABLED': True, 'CRONITOR_KEYS': {'hello': 'secret'} }): assert successful_task() == 1 assert rmock.call_count == 2 assert rmock.request_history[0].url == RUN_LINK assert rmock.request_history[1].url == COMPLETE_LINK def test_cronitor_sends_run_and_fail_if_exception(notify_api, rmock): rmock.get(RUN_LINK, status_code=200) rmock.get(FAIL_LINK, status_code=200) with set_config_values(notify_api, { 'CRONITOR_ENABLED': True, 'CRONITOR_KEYS': {'hello': 'secret'} }): with pytest.raises(ValueError): crashing_task() assert rmock.call_count == 2 assert rmock.request_history[0].url == RUN_LINK assert rmock.request_history[1].url == FAIL_LINK def test_cronitor_does_nothing_if_cronitor_not_enabled(notify_api, rmock): with set_config_values(notify_api, { 'CRONITOR_ENABLED': False, 'CRONITOR_KEYS': {'hello': 'secret'} }): assert successful_task() == 1 assert rmock.called is False def test_cronitor_does_nothing_if_name_not_recognised(notify_api, rmock, mocker): mock_logger = mocker.patch('app.cronitor.current_app.logger') with set_config_values(notify_api, { 'CRONITOR_ENABLED': True, 'CRONITOR_KEYS': {'not-hello': 'other'} }): assert successful_task() == 1 mock_logger.error.assert_called_with( 'Cronitor enabled but task_name hello not found in environment' ) assert rmock.called is False def test_cronitor_doesnt_crash_if_request_fails(notify_api, rmock): rmock.get(RUN_LINK, exc=requests.exceptions.ConnectTimeout) rmock.get(COMPLETE_LINK, status_code=500) with set_config_values(notify_api, { 'CRONITOR_ENABLED': True, 'CRONITOR_KEYS': {'hello': 'secret'} }): assert successful_task() == 1 assert rmock.call_count == 2