def test_should_return_notifications_only_for_this_service( notify_db, notify_db_session): service_1 = create_service(notify_db, notify_db_session, service_name="one", email_from="one") service_2 = create_service(notify_db, notify_db_session, service_name="two", email_from="two") job_1 = create_job(notify_db, notify_db_session, service=service_1) job_2 = create_job(notify_db, notify_db_session, service=service_2) create_notification(notify_db, notify_db_session, service=service_1, job=job_1, status='created') create_notification(notify_db, notify_db_session, service=service_2, job=job_2, status='created') assert len(dao_get_notification_outcomes_for_job(service_1.id, job_2.id)) == 0
def test_get_permissions_by_user_id_returns_only_active_service(notify_db, notify_db_session, sample_user): active_service = create_service(notify_db, notify_db_session, service_name="Active service", user=sample_user) inactive_service = create_service(notify_db, notify_db_session, service_name="Inactive service", user=sample_user) inactive_service.active = False permissions = permission_dao.get_permissions_by_user_id(user_id=sample_user.id) assert len(permissions) == 8 assert active_service in [i.service for i in permissions] assert inactive_service not in [i.service for i in permissions]
def test_should_return_notifications_only_for_this_service(notify_db, notify_db_session): service_1 = create_service(notify_db, notify_db_session, service_name="one", email_from="one") service_2 = create_service(notify_db, notify_db_session, service_name="two", email_from="two") job_1 = create_job(notify_db, notify_db_session, service=service_1) job_2 = create_job(notify_db, notify_db_session, service=service_2) create_notification(notify_db, notify_db_session, service=service_1, job=job_1, status='created') create_notification(notify_db, notify_db_session, service=service_2, job=job_2, status='created') assert len(dao_get_notification_outcomes_for_job(service_1.id, job_2.id)) == 0
def test_remove_service_whitelist_only_removes_for_my_service(notify_db, notify_db_session): service_1 = create_service(notify_db, notify_db_session, service_name="service 1") service_2 = create_service(notify_db, notify_db_session, service_name="service 2") dao_add_and_commit_whitelisted_contacts([ ServiceWhitelist.from_string(service_1.id, EMAIL_TYPE, '*****@*****.**'), ServiceWhitelist.from_string(service_2.id, EMAIL_TYPE, '*****@*****.**') ]) dao_remove_service_whitelist(service_1.id) assert service_1.whitelist == [] assert len(service_2.whitelist) == 1
def test_get_jobs_for_service(notify_db, notify_db_session, sample_template): one_job = create_job(notify_db, notify_db_session, sample_template.service, sample_template) other_user = create_user(email="*****@*****.**") other_service = create_service(notify_db, notify_db_session, user=other_user, service_name="other service", email_from='other.service') other_template = create_template(notify_db, notify_db_session, service=other_service) other_job = create_job(notify_db, notify_db_session, service=other_service, template=other_template) one_job_from_db = dao_get_jobs_by_service_id(one_job.service_id).items other_job_from_db = dao_get_jobs_by_service_id(other_job.service_id).items assert len(one_job_from_db) == 1 assert one_job == one_job_from_db[0] assert len(other_job_from_db) == 1 assert other_job == other_job_from_db[0] assert one_job_from_db != other_job_from_db
def test_get_jobs_for_service(notify_db, notify_db_session, sample_template): from tests.app.conftest import sample_job as create_job from tests.app.conftest import sample_service as create_service from tests.app.conftest import sample_template as create_template from tests.app.conftest import sample_user as create_user one_job = create_job(notify_db, notify_db_session, sample_template.service, sample_template) other_user = create_user(notify_db, notify_db_session, email="*****@*****.**") other_service = create_service(notify_db, notify_db_session, user=other_user, service_name="other service") other_template = create_template(notify_db, notify_db_session, service=other_service) other_job = create_job(notify_db, notify_db_session, service=other_service, template=other_template) one_job_from_db = get_jobs_by_service(one_job.service_id) other_job_from_db = get_jobs_by_service(other_job.service_id) assert len(one_job_from_db) == 1 assert one_job == one_job_from_db[0] assert len(other_job_from_db) == 1 assert other_job == other_job_from_db[0] assert one_job_from_db != other_job_from_db
def test_that_when_exceed_rate_limit_request_fails( notify_db, notify_db_session, key_type, mocker): with freeze_time("2016-01-01 12:00:00.000000"): if key_type == 'live': api_key_type = 'normal' else: api_key_type = key_type mocker.patch('app.redis_store.exceeded_rate_limit', return_value=True) mocker.patch('app.notifications.validators.services_dao') service = create_service(notify_db, notify_db_session, restricted=True) api_key = sample_api_key(notify_db, notify_db_session, service=service, key_type=api_key_type) with pytest.raises(RateLimitError) as e: check_service_over_api_rate_limit(service, api_key) assert app.redis_store.exceeded_rate_limit.called_with( "{}-{}".format(str(service.id), api_key.key_type), service.rate_limit, 60 ) assert e.value.status_code == 429 assert e.value.message == 'Exceeded rate limit for key type {} of {} requests per {} seconds'.format( key_type.upper(), service.rate_limit, 60 ) assert e.value.fields == []
def test_check_service_message_limit_does_not_send_notifications_if_already_did( notify_db, notify_db_session, mocker): with freeze_time("2016-01-01 12:00:00.000000"): redis_get = mocker.patch("app.redis_store.get", side_effect=[5, True, True]) redis_set = mocker.patch("app.redis_store.set") send_notification = mocker.patch( "app.notifications.validators.send_notification_to_service_users") service = create_service(notify_db, notify_db_session, restricted=True, limit=5) with pytest.raises(TooManyRequestsError) as e: check_service_over_daily_message_limit("normal", service) assert e.value.status_code == 429 assert e.value.message == "Exceeded send limits (5) for today" assert e.value.fields == [] assert redis_get.call_args_list == [ call(f"{service.id}-2016-01-01-count"), call(f"nearing-{service.id}-2016-01-01-count"), call(f"over-{service.id}-2016-01-01-count"), ] redis_set.assert_not_called() send_notification.assert_not_called()
def test_allows_api_calls_with_international_numbers_if_service_does_allow_int_sms( key_type, notify_db, notify_db_session): service = create_service(notify_db, notify_db_session, permissions=[SMS_TYPE, INTERNATIONAL_SMS_TYPE]) result = validate_and_format_recipient("+20-12-1234-1234", key_type, service, SMS_TYPE) assert result == "+201212341234"
def test_service_can_send_to_recipient_passes(key_type, notify_db, notify_db_session): trial_mode_service = create_service(notify_db, notify_db_session, service_name='trial mode', restricted=True) assert service_can_send_to_recipient(trial_mode_service.users[0].email_address, key_type, trial_mode_service) is None assert service_can_send_to_recipient(trial_mode_service.users[0].mobile_number, key_type, trial_mode_service) is None
def test_service_can_send_to_recipient_passes_for_live_service_non_team_member(key_type, notify_db, notify_db_session): live_service = create_service(notify_db, notify_db_session, service_name='live', restricted=False) assert service_can_send_to_recipient("*****@*****.**", key_type, live_service) is None assert service_can_send_to_recipient('07513332413', key_type, live_service) is None
def test_service_can_send_to_recipient_fails_when_mobile_number_is_not_on_team(notify_db, notify_db_session): live_service = create_service(notify_db, notify_db_session, service_name='live mode', restricted=False) with pytest.raises(BadRequestError) as e: service_can_send_to_recipient("0758964221", 'team', live_service) assert e.value.status_code == 400 assert e.value.message == 'Can’t send to this recipient using a team-only API key' assert e.value.fields == []
def test_service_can_send_to_recipient_fails_when_recipient_is_not_on_team(recipient, key_type, error_message, notify_db, notify_db_session): trial_mode_service = create_service(notify_db, notify_db_session, service_name='trial mode', restricted=True) with pytest.raises(BadRequestError) as exec_info: service_can_send_to_recipient(recipient, key_type, trial_mode_service) assert exec_info.value.status_code == 400 assert exec_info.value.message == error_message assert exec_info.value.fields == []
def test_rejects_api_calls_with_international_numbers_if_service_does_not_allow_int_sms( key_type, notify_db, notify_db_session, ): service = create_service(notify_db, notify_db_session, permissions=[SMS_TYPE]) with pytest.raises(BadRequestError) as e: validate_and_format_recipient('+20-12-1234-1234', key_type, service, SMS_TYPE) assert e.value.status_code == 400 assert e.value.message == 'Cannot send to international mobile numbers' assert e.value.fields == []
def test_service_can_send_to_recipient_fails_when_recipient_is_not_on_team( recipient: str, key_type: str, error_message: str, notify_db: RoutingSQLAlchemy, notify_db_session: RoutingSQLAlchemy): trial_mode_service = create_service(notify_db, notify_db_session, service_name='trial mode', restricted=True) with pytest.raises(BadRequestError) as exec_info: service_can_send_to_recipient(recipient, key_type, trial_mode_service) assert exec_info.value.status_code == 400 assert error_message in exec_info.value.message, f'Unexpected error message: {exec_info.value.message}' assert exec_info.value.fields == []
def test_service_can_send_to_recipient_fails_when_mobile_number_is_not_on_team( notify_db, notify_db_session): live_service = create_service(notify_db, notify_db_session, service_name="live mode", restricted=False) with pytest.raises(BadRequestError) as e: service_can_send_to_recipient("0758964221", "team", live_service) assert e.value.status_code == 400 assert (e.value.message == "Can’t send to this recipient using a team-only API key " f'- see {get_document_url("en", "keys.html#team-and-safelist")}') assert e.value.fields == []
def test_should_not_rate_limit_if_limiting_is_disabled(notify_db, notify_db_session, mocker): with freeze_time("2016-01-01 12:00:00.000000"): current_app.config["API_RATE_LIMIT_ENABLED"] = False mocker.patch("app.redis_store.exceeded_rate_limit", return_value=False) mocker.patch("app.notifications.validators.services_dao") service = create_service(notify_db, notify_db_session, restricted=True) api_key = sample_api_key(notify_db, notify_db_session, service=service) check_service_over_api_rate_limit(service, api_key) assert not app.redis_store.exceeded_rate_limit.called
def test_that_when_not_exceeded_rate_limit_request_succeeds( notify_db, notify_db_session, mocker): with freeze_time("2016-01-01 12:00:00.000000"): mocker.patch("app.redis_store.exceeded_rate_limit", return_value=False) mocker.patch("app.notifications.validators.services_dao") service = create_service(notify_db, notify_db_session, restricted=True) api_key = sample_api_key(notify_db, notify_db_session, service=service, key_type="normal") check_service_over_api_rate_limit(service, api_key) assert app.redis_store.exceeded_rate_limit.called_with( "{}-{}".format(str(service.id), api_key.key_type), 3000, 60)
def test_check_service_message_limit_skip_statsd_over_message_no_limit_fails( app_statsd, notify_db, notify_db_session, mocker): # Given mocker.patch("app.redis_store.get", return_value=0) mocker.patch("app.notifications.validators.redis_store.set") # When service = create_service(notify_db, notify_db_session, restricted=True, limit=4) check_service_over_daily_message_limit("normal", service) # Then app_statsd.statsd_client.incr.assert_not_called()
def test_check_service_message_limit_over_message_limit_fails(key_type, notify_db, notify_db_session, mocker): with freeze_time("2016-01-01 12:00:00.000000"): mocker.patch('app.redis_store.get', return_value=None) mocker.patch('app.notifications.validators.redis_store.set') service = create_service(notify_db, notify_db_session, restricted=True, limit=4) for x in range(5): create_notification(notify_db, notify_db_session, service=service) with pytest.raises(TooManyRequestsError) as e: check_service_message_limit(key_type, service) assert e.value.status_code == 429 assert e.value.message == 'Exceeded send limits (4) for today' assert e.value.fields == [] app.notifications.validators.redis_store.set.assert_called_with( str(service.id) + "-2016-01-01-count", 5, ex=3600 )
def test_check_service_message_limit_over_message_limit_fails(key_type, notify_db, notify_db_session, mocker): with freeze_time("2016-01-01 12:00:00.000000"): mocker.patch('app.redis_store.get', return_value=None) mocker.patch('app.notifications.validators.redis_store.set') service = create_service(notify_db, notify_db_session, restricted=True, limit=4) for x in range(5): create_notification(notify_db, notify_db_session, service=service) with pytest.raises(TooManyRequestsError) as e: check_service_over_daily_message_limit(key_type, service) assert e.value.status_code == 429 assert e.value.message == 'Exceeded send limits (4) for today' assert e.value.fields == [] app.notifications.validators.redis_store.set.assert_called_with( str(service.id) + "-2016-01-01-count", 5, ex=3600 )
def test_check_service_message_limit_sends_statsd_over_message_limit_fails( app_statsd, notify_db, notify_db_session, mocker): # Given mocker.patch('app.redis_store.get', return_value=5) mocker.patch('app.notifications.validators.redis_store.set') # When service = create_service(notify_db, notify_db_session, restricted=True, limit=4) with pytest.raises(TooManyRequestsError): check_service_over_daily_message_limit("normal", service) # Then app_statsd.statsd_client.incr.assert_called_once_with( "validators.rate_limit.service_daily")
def test_check_service_message_limit_in_cache_over_message_limit_fails( notify_db, notify_db_session, key_type, mocker): with freeze_time("2016-01-01 12:00:00.000000"): mocker.patch('app.redis_store.get', return_value=5) mocker.patch('app.notifications.validators.redis_store.set') mocker.patch('app.notifications.validators.services_dao') service = create_service(notify_db, notify_db_session, restricted=True, limit=4) with pytest.raises(TooManyRequestsError) as e: check_service_over_daily_message_limit(key_type, service) assert e.value.status_code == 429 assert e.value.message == 'Exceeded send limits (4) for today' assert e.value.fields == [] app.notifications.validators.redis_store.set.assert_not_called() assert not app.notifications.validators.services_dao.mock_calls
def test_check_service_message_limit_in_cache_over_message_limit_fails( notify_db, notify_db_session, key_type, mocker): with freeze_time("2016-01-01 12:00:00.000000"): mocker.patch('app.redis_store.get', return_value=5) mocker.patch('app.notifications.validators.redis_store.set') mocker.patch('app.notifications.validators.services_dao') service = create_service(notify_db, notify_db_session, restricted=True, limit=4) with pytest.raises(TooManyRequestsError) as e: check_service_message_limit(key_type, service) assert e.value.status_code == 429 assert e.value.message == 'Exceeded send limits (4) for today' assert e.value.fields == [] app.notifications.validators.redis_store.set.assert_not_called() assert not app.notifications.validators.services_dao.mock_calls
def test_check_service_message_limit_sends_statsd_over_message_limit_fails( app_statsd, notify_db, notify_db_session, mocker, is_trial_service, expected_counter, ): mocker.patch("app.redis_store.get", return_value=5) mocker.patch("app.notifications.validators.redis_store.set") service = create_service(notify_db, notify_db_session, restricted=is_trial_service, limit=4) with pytest.raises(TooManyRequestsError): check_service_over_daily_message_limit("normal", service) app_statsd.statsd_client.incr.assert_called_once_with(expected_counter)
def test_get_jobs_for_service(notify_db, notify_db_session, sample_template): one_job = create_job(notify_db, notify_db_session, sample_template.service, sample_template) other_user = create_user(notify_db, notify_db_session, email="*****@*****.**") other_service = create_service(notify_db, notify_db_session, user=other_user, service_name="other service", email_from='other.service') other_template = create_template(notify_db, notify_db_session, service=other_service) other_job = create_job(notify_db, notify_db_session, service=other_service, template=other_template) one_job_from_db = dao_get_jobs_by_service_id(one_job.service_id).items other_job_from_db = dao_get_jobs_by_service_id(other_job.service_id).items assert len(one_job_from_db) == 1 assert one_job == one_job_from_db[0] assert len(other_job_from_db) == 1 assert other_job == other_job_from_db[0] assert one_job_from_db != other_job_from_db
def test_check_service_message_limit_over_message_limit_fails( key_type, notify_db, notify_db_session, mocker): with freeze_time("2016-01-01 12:00:00.000000"): redis_get = mocker.patch("app.redis_store.get", side_effect=["5", True, None]) redis_set = mocker.patch("app.redis_store.set") send_notification = mocker.patch( "app.notifications.validators.send_notification_to_service_users") service = create_service(notify_db, notify_db_session, restricted=True, limit=4) for x in range(5): create_notification(notify_db, notify_db_session, service=service) with pytest.raises(TooManyRequestsError) as e: check_service_over_daily_message_limit(key_type, service) assert e.value.status_code == 429 assert e.value.message == "Exceeded send limits (4) for today" assert e.value.fields == [] assert redis_get.call_args_list == [ call(f"{service.id}-2016-01-01-count"), call(f"nearing-{service.id}-2016-01-01-count"), call(f"over-{service.id}-2016-01-01-count"), ] assert redis_set.call_args_list == [ call(f"over-{service.id}-2016-01-01-count", "2016-01-01T12:00:00", ex=86400) ] send_notification.assert_called_once_with( service_id=service.id, template_id=current_app.config["REACHED_DAILY_LIMIT_TEMPLATE_ID"], personalisation={ "service_name": service.name, "contact_url": f"{current_app.config['ADMIN_BASE_URL']}/contact", "message_limit_en": "4", "message_limit_fr": "4", }, include_user_fields=["name"], )
def test_check_service_message_limit_records_nearing_daily_limit( notify_db, notify_db_session, mocker): with freeze_time("2016-01-01 12:00:00.000000"): redis_get = mocker.patch("app.redis_store.get", side_effect=[4, None]) redis_set = mocker.patch("app.redis_store.set") send_notification = mocker.patch( "app.notifications.validators.send_notification_to_service_users") service = create_service(notify_db, notify_db_session, restricted=True, limit=5) for x in range(4): create_notification(notify_db, notify_db_session, service=service) check_service_over_daily_message_limit("normal", service) assert redis_get.call_args_list == [ call(f"{service.id}-2016-01-01-count"), call(f"nearing-{service.id}-2016-01-01-count"), ] assert redis_set.call_args_list == [ call( f"nearing-{service.id}-2016-01-01-count", "2016-01-01T12:00:00", ex=86400, ), ] send_notification.assert_called_once_with( service_id=service.id, template_id=current_app.config["NEAR_DAILY_LIMIT_TEMPLATE_ID"], personalisation={ "service_name": service.name, "contact_url": f"{current_app.config['ADMIN_BASE_URL']}/contact", "message_limit_en": "5", "message_limit_fr": "5", }, include_user_fields=["name"], )
def test_exception_thrown_by_redis_store_get_should_not_be_fatal( notify_db, notify_db_session, notify_api, key_type, mocker): with freeze_time("2016-01-01 12:00:00.000000"): mocker.patch('app.notifications.validators.redis_store.redis_store.get', side_effect=Exception("broken redis")) mocker.patch('app.notifications.validators.redis_store.redis_store.set') service = create_service(notify_db, notify_db_session, restricted=True, limit=4) for x in range(5): create_notification(notify_db, notify_db_session, service=service) with pytest.raises(TooManyRequestsError) as e: check_service_message_limit(key_type, service) assert e.value.status_code == 429 assert e.value.message == 'Exceeded send limits (4) for today' assert e.value.fields == [] app.notifications.validators.redis_store.redis_store.set.assert_called_with( "{}-2016-01-01-count".format(str(service.id)), 5, 3600, None, False, False )
def test_get_jobs(notify_db, notify_db_session, sample_template): one_job = create_job(notify_db, notify_db_session, sample_template.service, sample_template) other_user = create_user(email="*****@*****.**") other_service = create_service(notify_db, notify_db_session, user=other_user, service_name="other service", email_from='other.service') other_template = create_template(notify_db, notify_db_session, service=other_service) other_job = create_job(notify_db, notify_db_session, service=other_service, template=other_template) jobs = dao_get_jobs().all() assert len(jobs) == 2 assert jobs[0] == other_job assert jobs[1] == one_job