Exemplo n.º 1
0
def test_reduce_sms_provider_priority_adjusts_provider_priorities(
    mocker,
    restore_provider_details,
    notify_user,
    starting_priorities,
    expected_priorities,
):
    mock_adjust = mocker.patch(
        'app.dao.provider_details_dao._adjust_provider_priority')

    mmg = get_provider_details_by_identifier('mmg')
    firetext = get_provider_details_by_identifier('firetext')

    mmg.priority = starting_priorities['mmg']
    firetext.priority = starting_priorities['firetext']
    # need to update these manually to avoid triggering the `onupdate` clause of the updated_at column
    ProviderDetails.query.filter(
        ProviderDetails.notification_type == 'sms').update(
            {'updated_at': datetime.min})

    # switch away from mmg. currently both 50/50
    dao_reduce_sms_provider_priority('mmg',
                                     time_threshold=timedelta(minutes=10))

    mock_adjust.assert_any_call(firetext, expected_priorities['firetext'])
    mock_adjust.assert_any_call(mmg, expected_priorities['mmg'])
def test_reduce_sms_provider_priority_switches_provider(
    notify_db_session,
    mocker,
    restore_provider_details,
    sample_user,
    starting_priorities,
    expected_priorities,
):
    mocker.patch('app.dao.provider_details_dao.get_user_by_id',
                 return_value=sample_user)
    mmg = get_provider_details_by_identifier('mmg')
    firetext = get_provider_details_by_identifier('firetext')

    mmg.priority = starting_priorities['mmg']
    firetext.priority = starting_priorities['firetext']
    # need to update these manually to avoid triggering the `onupdate` clause of the updated_at column
    ProviderDetails.query.filter(
        ProviderDetails.notification_type == 'sms').update(
            {'updated_at': datetime.min})

    # switch away from mmg. currently both 50/50
    dao_reduce_sms_provider_priority('mmg',
                                     time_threshold=timedelta(minutes=10))

    assert firetext.priority == expected_priorities['firetext']
    assert mmg.priority == expected_priorities['mmg']
    assert mmg.created_by is sample_user
    assert firetext.created_by is sample_user
Exemplo n.º 3
0
def sms_providers(notify_db):
    """
    In production we randomly choose which provider to use based on their priority. To guarantee tests run the same each
    time, make sure we always choose mmg. You'll need to override them in your tests if you wish to do something
    different.
    """
    get_provider_details_by_identifier('mmg').priority = 100
    get_provider_details_by_identifier('firetext').priority = 0
Exemplo n.º 4
0
def get_sms_provider_client(provider, notification_id):
    try:
        get_provider_details_by_identifier(provider)
    except NoResultFound:
        raise Exception(
            f"Could not find {provider} provider when trying to send notification {notification_id}"
        )

    return clients.get_client_by_name_and_type(provider, SMS_TYPE)
Exemplo n.º 5
0
def set_primary_sms_provider(identifier):
    primary_provider = get_provider_details_by_identifier(identifier)
    secondary_provider = get_provider_details_by_identifier(get_alternative_sms_provider(identifier))

    primary_provider.priority = 10
    secondary_provider.priority = 20

    dao_update_provider_details(primary_provider)
    dao_update_provider_details(secondary_provider)
Exemplo n.º 6
0
def test_provider_to_use_should_only_return_active_providers(mocker, restore_provider_details):
    mmg = get_provider_details_by_identifier('mmg')
    firetext = get_provider_details_by_identifier('firetext')
    mmg.active = False
    mock_choices = mocker.patch('app.delivery.send_to_providers.random.choices', return_value=[firetext])

    ret = send_to_providers.provider_to_use('sms')

    mock_choices.assert_called_once_with([firetext], weights=[0])
    assert ret.get_name() == 'firetext'
Exemplo n.º 7
0
def test_should_send_sms_to_international_providers(
    sample_template,
    sample_user,
    mocker
):
    mocker.patch('app.mmg_client.send_sms')
    mocker.patch('app.firetext_client.send_sms')

    # set firetext to active
    get_provider_details_by_identifier('firetext').priority = 100
    get_provider_details_by_identifier('mmg').priority = 0

    notification_uk = create_notification(
        template=sample_template,
        to_field="+447234123999",
        personalisation={"name": "Jo"},
        status='created',
        international=False,
        reply_to_text=sample_template.service.get_default_sms_sender()
    )

    notification_international = create_notification(
        template=sample_template,
        to_field="+6011-17224412",
        personalisation={"name": "Jo"},
        status='created',
        international=True,
        reply_to_text=sample_template.service.get_default_sms_sender()
    )
    send_to_providers.send_sms_to_provider(
        notification_uk
    )

    firetext_client.send_sms.assert_called_once_with(
        to="447234123999",
        content=ANY,
        reference=str(notification_uk.id),
        sender=current_app.config['FROM_NUMBER']
    )

    send_to_providers.send_sms_to_provider(
        notification_international
    )

    mmg_client.send_sms.assert_called_once_with(
        to="601117224412",
        content=ANY,
        reference=str(notification_international.id),
        sender=current_app.config['FROM_NUMBER']
    )

    assert notification_uk.status == 'sending'
    assert notification_uk.sent_by == 'firetext'
    assert notification_international.status == 'sent'
    assert notification_international.sent_by == 'mmg'
Exemplo n.º 8
0
def test_provider_to_use_should_return_random_provider(mocker, notify_db_session):
    mmg = get_provider_details_by_identifier('mmg')
    firetext = get_provider_details_by_identifier('firetext')
    mmg.priority = 25
    firetext.priority = 75
    mock_choices = mocker.patch('app.delivery.send_to_providers.random.choices', return_value=[mmg])

    ret = send_to_providers.provider_to_use('sms', international=False)

    mock_choices.assert_called_once_with([mmg, firetext], weights=[25, 75])
    assert ret.get_name() == 'mmg'
Exemplo n.º 9
0
def test_adjust_provider_priority_back_to_resting_points_does_nothing_if_theyre_already_at_right_values(
    restore_provider_details,
    mocker,
):
    mmg = get_provider_details_by_identifier('mmg')
    firetext = get_provider_details_by_identifier('firetext')
    mmg.priority = 60
    firetext.priority = 40

    mock_adjust = mocker.patch('app.dao.provider_details_dao._adjust_provider_priority')
    mocker.patch('app.dao.provider_details_dao._get_sms_providers_for_update', return_value=[mmg, firetext])

    dao_adjust_provider_priority_back_to_resting_points()

    assert mock_adjust.called is False
def test_provider_to_use_raises_if_no_active_providers(
        mocker, restore_provider_details):
    mmg = get_provider_details_by_identifier('mmg')
    mmg.active = False

    with pytest.raises(Exception):
        send_to_providers.provider_to_use('sms', international=True)
Exemplo n.º 11
0
def test_update_sms_provider_to_inactive_sets_inactive(restore_provider_details):
    mmg = get_provider_details_by_identifier('mmg')

    mmg.active = False
    dao_update_provider_details(mmg)

    assert not mmg.active
def test_reduce_sms_provider_priority_adds_rows_to_history_table(
        mocker, restore_provider_details, sample_user):
    mocker.patch('app.dao.provider_details_dao.get_user_by_id',
                 return_value=sample_user)
    mmg = get_provider_details_by_identifier('mmg')
    # need to update these manually to avoid triggering the `onupdate` clause of the updated_at column
    ProviderDetails.query.filter(
        ProviderDetails.notification_type == 'sms').update(
            {'updated_at': datetime.min})

    provider_history_rows = ProviderDetailsHistory.query.filter(
        ProviderDetailsHistory.id == mmg.id).order_by(
            desc(ProviderDetailsHistory.version)).all()

    dao_reduce_sms_provider_priority(mmg.identifier,
                                     time_threshold=timedelta(minutes=10))

    updated_provider_history_rows = ProviderDetailsHistory.query.filter(
        ProviderDetailsHistory.id == mmg.id).order_by(
            desc(ProviderDetailsHistory.version)).all()

    assert len(updated_provider_history_rows) - len(provider_history_rows) == 1
    assert updated_provider_history_rows[0].version - provider_history_rows[
        0].version == 1
    assert updated_provider_history_rows[0].priority == 90
Exemplo n.º 13
0
def test_dao_get_provider_stats(notify_db_session):
    service_1 = create_service(service_name="1")
    service_2 = create_service(service_name="2")
    sms_template_1 = create_template(service_1, "sms")
    sms_template_2 = create_template(service_2, "sms")

    create_ft_billing("2017-06-05", "sms", sms_template_2, service_1, provider="mmg", billable_unit=4)
    create_ft_billing("2018-05-31", "sms", sms_template_1, service_1, provider="sns", billable_unit=1)
    create_ft_billing(
        "2018-06-01",
        "sms",
        sms_template_1,
        service_1,
        provider="sns",
        rate_multiplier=2,
        billable_unit=1,
    )
    create_ft_billing("2018-06-03", "sms", sms_template_2, service_1, provider="mmg", billable_unit=4)
    create_ft_billing("2018-06-15", "sms", sms_template_1, service_2, provider="mmg", billable_unit=1)
    create_ft_billing("2018-06-28", "sms", sms_template_2, service_2, provider="sns", billable_unit=2)

    provider = get_provider_details_by_identifier("pinpoint")
    provider.priority = 50
    dao_update_provider_details(provider)

    result = dao_get_provider_stats()

    assert len(result) == 7

    assert result[0].identifier == "ses"
    assert result[0].display_name == "AWS SES"
    assert result[0].created_by_name is None
    assert result[0].current_month_billable_sms == 0

    assert result[1].identifier == "sns"
    assert result[1].display_name == "AWS SNS"
    assert result[1].supports_international is False
    assert result[1].active is True
    assert result[1].current_month_billable_sms == 4

    assert result[2].identifier == "mmg"
    assert result[2].notification_type == "sms"
    assert result[2].supports_international is True
    assert result[2].active is False
    assert result[2].current_month_billable_sms == 5

    assert result[3].identifier == "firetext"
    assert result[3].active is False
    assert result[3].current_month_billable_sms == 0

    assert result[4].identifier == "loadtesting"
    assert result[4].active is False
    assert result[4].current_month_billable_sms == 0
    assert result[4].supports_international is False

    assert result[5].identifier == "pinpoint"
    assert result[5].notification_type == "sms"
    assert result[5].supports_international is False
    assert result[5].active is False
    assert result[5].current_month_billable_sms == 0
Exemplo n.º 14
0
def test_provider_to_use_should_only_return_mmg_for_international(mocker, notify_db_session):
    mmg = get_provider_details_by_identifier('mmg')
    mock_choices = mocker.patch('app.delivery.send_to_providers.random.choices', return_value=[mmg])

    ret = send_to_providers.provider_to_use('sms', international=True)

    mock_choices.assert_called_once_with([mmg], weights=[100])
    assert ret.get_name() == 'mmg'
Exemplo n.º 15
0
def with_active_telstra_provider():
    # Simulate the Telstra provider actually being active.
    # This is required because at the time of writing Telstra is not currently
    # active in the DB but we have some behaviour that we want to test that
    # relies on being able to switch providers to another active provider.
    telstra = get_provider_details_by_identifier('telstra')
    telstra.active = True
    dao_update_provider_details(telstra)
Exemplo n.º 16
0
def test_toggle_sms_provider_switches_provider(mocker, restore_provider_details, current_sms_provider, sample_user):
    mocker.patch("app.provider_details.switch_providers.get_user_by_id", return_value=sample_user)
    dao_toggle_sms_provider(current_sms_provider.identifier)
    new_provider = get_current_provider("sms")

    old_starting_provider = get_provider_details_by_identifier(current_sms_provider.identifier)

    assert new_provider.identifier != old_starting_provider.identifier
    assert new_provider.priority < old_starting_provider.priority
Exemplo n.º 17
0
def test_provider_details_schema_returns_user_details(
        mocker, sample_user, restore_provider_details):
    from app.schemas import provider_details_schema
    current_sms_provider = get_provider_details_by_identifier('mmg')
    current_sms_provider.created_by = sample_user
    data = provider_details_schema.dump(current_sms_provider).data

    assert sorted(data['created_by'].keys()) == sorted(
        ['id', 'email_address', 'name'])
Exemplo n.º 18
0
def test_adjust_provider_priority_back_to_resting_points_updates_all_providers(
        restore_provider_details, mocker, existing_mmg, existing_firetext,
        new_mmg, new_firetext):
    mmg = get_provider_details_by_identifier('mmg')
    firetext = get_provider_details_by_identifier('firetext')
    mmg.priority = existing_mmg
    firetext.priority = existing_firetext

    mock_adjust = mocker.patch(
        'app.dao.provider_details_dao._adjust_provider_priority')
    mock_get_providers = mocker.patch(
        'app.dao.provider_details_dao._get_sms_providers_for_update',
        return_value=[mmg, firetext])

    dao_adjust_provider_priority_back_to_resting_points()

    mock_get_providers.assert_called_once_with(timedelta(hours=1))
    mock_adjust.assert_any_call(mmg, new_mmg)
    mock_adjust.assert_any_call(firetext, new_firetext)
def test_switch_current_sms_provider_on_slow_delivery_switches_when_one_provider_is_slow(
    mocker,
    restore_provider_details,
):
    is_slow_dict = {'mmg': False, 'firetext': True}
    mock_is_slow = mocker.patch('app.celery.scheduled_tasks.is_delivery_slow_for_providers', return_value=is_slow_dict)
    mock_reduce = mocker.patch('app.celery.scheduled_tasks.dao_reduce_sms_provider_priority')
    # updated_at times are older than the 10 minute window
    get_provider_details_by_identifier('mmg').updated_at = datetime(2017, 5, 1, 13, 49)
    get_provider_details_by_identifier('firetext').updated_at = None

    switch_current_sms_provider_on_slow_delivery()

    mock_is_slow.assert_called_once_with(
        threshold=0.3,
        created_at=datetime(2017, 5, 1, 13, 50),
        delivery_time=timedelta(minutes=4)
    )
    mock_reduce.assert_called_once_with('firetext', time_threshold=timedelta(minutes=10))
Exemplo n.º 20
0
def test_switch_current_sms_provider_on_slow_delivery_does_nothing_if_no_need(
        mocker, restore_provider_details, is_slow_dict):
    mocker.patch('app.celery.scheduled_tasks.is_delivery_slow_for_providers',
                 return_value=is_slow_dict)
    mock_reduce = mocker.patch(
        'app.celery.scheduled_tasks.dao_reduce_sms_provider_priority')
    get_provider_details_by_identifier('mmg').updated_at = datetime(
        2017, 5, 1, 13, 51)

    switch_current_sms_provider_on_slow_delivery()

    assert mock_reduce.called is False
def test_dao_get_provider_stats(notify_db_session):
    service_1 = create_service(service_name='1')
    service_2 = create_service(service_name='2')
    sms_template_1 = create_template(service_1, 'sms')
    sms_template_2 = create_template(service_2, 'sms')

    create_ft_billing('2017-06-05', 'sms', sms_template_2, service_1, provider='mmg', billable_unit=4)
    create_ft_billing('2018-05-31', 'sms', sms_template_1, service_1, provider='sns', billable_unit=1)
    create_ft_billing('2018-06-01', 'sms', sms_template_1, service_1, provider='sns',
                      rate_multiplier=2, billable_unit=1)
    create_ft_billing('2018-06-03', 'sms', sms_template_2, service_1, provider='mmg', billable_unit=4)
    create_ft_billing('2018-06-15', 'sms', sms_template_1, service_2, provider='mmg', billable_unit=1)
    create_ft_billing('2018-06-28', 'sms', sms_template_2, service_2, provider='sns', billable_unit=2)

    provider = get_provider_details_by_identifier('pinpoint')
    provider.priority = 50
    dao_update_provider_details(provider)

    result = dao_get_provider_stats()

    assert len(result) == 7

    assert result[0].identifier == 'ses'
    assert result[0].display_name == 'AWS SES'
    assert result[0].created_by_name is None
    assert result[0].current_month_billable_sms == 0

    assert result[1].identifier == 'sns'
    assert result[1].display_name == 'AWS SNS'
    assert result[1].supports_international is False
    assert result[1].active is True
    assert result[1].current_month_billable_sms == 4

    assert result[2].identifier == 'mmg'
    assert result[2].notification_type == 'sms'
    assert result[2].supports_international is True
    assert result[2].active is True
    assert result[2].current_month_billable_sms == 5

    assert result[3].identifier == 'firetext'
    assert result[3].current_month_billable_sms == 0

    assert result[4].identifier == 'loadtesting'
    assert result[4].current_month_billable_sms == 0
    assert result[4].supports_international is False

    assert result[5].identifier == 'pinpoint'
    assert result[5].notification_type == 'sms'
    assert result[5].supports_international is False
    assert result[5].active is True
    assert result[5].current_month_billable_sms == 0
Exemplo n.º 22
0
def test_toggle_sms_provider_switches_when_provider_priorities_are_equal(mocker, restore_provider_details, sample_user):
    mocker.patch("app.provider_details.switch_providers.get_user_by_id", return_value=sample_user)
    current_provider = get_current_provider("sms")
    new_provider = get_alternative_sms_provider(current_provider.identifier)

    current_provider.priority = new_provider.priority
    dao_update_provider_details(current_provider)

    dao_toggle_sms_provider(current_provider.identifier)

    old_starting_provider = get_provider_details_by_identifier(current_provider.identifier)

    assert new_provider.identifier != old_starting_provider.identifier
    assert new_provider.priority < old_starting_provider.priority
Exemplo n.º 23
0
def test_get_provider_details_in_type_and_identifier_order(client, notify_db):
    provider = get_provider_details_by_identifier("pinpoint")
    provider.priority = 50
    dao_update_provider_details(provider)

    response = client.get("/provider-details",
                          headers=[create_authorization_header()])
    assert response.status_code == 200
    json_resp = json.loads(response.get_data(as_text=True))["provider_details"]
    assert len(json_resp) == 7

    assert json_resp[0]["identifier"] == "ses"
    assert json_resp[1]["identifier"] == "sns"
    assert json_resp[2]["identifier"] == "mmg"
    assert json_resp[3]["identifier"] == "firetext"
    assert json_resp[4]["identifier"] == "loadtesting"
    assert json_resp[5]["identifier"] == "pinpoint"
    assert json_resp[6]["identifier"] == "dvla"
Exemplo n.º 24
0
def test_get_provider_details_in_type_and_identifier_order(client, notify_db):
    provider = get_provider_details_by_identifier('pinpoint')
    provider.priority = 50
    dao_update_provider_details(provider)

    response = client.get('/provider-details',
                          headers=[create_authorization_header()])
    assert response.status_code == 200
    json_resp = json.loads(response.get_data(as_text=True))['provider_details']
    assert len(json_resp) == 7

    assert json_resp[0]['identifier'] == 'ses'
    assert json_resp[1]['identifier'] == 'sns'
    assert json_resp[2]['identifier'] == 'mmg'
    assert json_resp[3]['identifier'] == 'firetext'
    assert json_resp[4]['identifier'] == 'loadtesting'
    assert json_resp[5]['identifier'] == 'pinpoint'
    assert json_resp[6]['identifier'] == 'dvla'
Exemplo n.º 25
0
def test_provider_details_history_schema_returns_user_details(
    mocker,
    sample_user,
    restore_provider_details,
):
    from app.schemas import provider_details_schema
    current_sms_provider = get_provider_details_by_identifier('mmg')
    current_sms_provider.created_by_id = sample_user.id
    data = provider_details_schema.dump(current_sms_provider).data

    dao_update_provider_details(current_sms_provider)

    current_sms_provider_in_history = ProviderDetailsHistory.query.filter(
        ProviderDetailsHistory.id == current_sms_provider.id).order_by(
            desc(ProviderDetailsHistory.version)).first()
    data = provider_details_schema.dump(current_sms_provider_in_history).data

    assert sorted(data['created_by'].keys()) == sorted(
        ['id', 'email_address', 'name'])
Exemplo n.º 26
0
def firetext_provider():
    return get_provider_details_by_identifier('firetext')
Exemplo n.º 27
0
def twilio_provider():
    return get_provider_details_by_identifier('twilio')
Exemplo n.º 28
0
def mmg_provider():
    return get_provider_details_by_identifier('mmg')
Exemplo n.º 29
0
def ses_provider():
    return get_provider_details_by_identifier('ses')
Exemplo n.º 30
0
def with_active_sap_provider():
    # Simulate the SAP provider actually being active.
    sap = get_provider_details_by_identifier('sap')
    sap.active = True
    dao_update_provider_details(sap)