Exemplo n.º 1
0
def test_fetch_exchange_rate(mocker, test_client, init_database,
                             initialised_blockchain_network, user_type,
                             preferred_language, exchange_text, limit_text):
    user = UserFactory(preferred_language=preferred_language, phone=phone())
    if user_type == "group":
        user.set_held_role('GROUP_ACCOUNT', 'grassroots_group_account')
        user.is_phone_verified = True
        kyc = KycApplication(type='INDIVIDUAL')
        kyc.user = user
        kyc.kyc_status = 'VERIFIED'

    token1 = Token.query.filter_by(symbol="SM1").first()
    create_transfer_account_for_user(user, token1, 20000)

    def mock_convert(exchange_contract, from_token, to_token, from_amount):
        return from_amount * 1.2

    mocker.patch('server.bt.get_conversion_amount', mock_convert)

    def mock_send_message(phone, message):
        assert exchange_text in message
        assert limit_text in message

    mocker.patch('server.utils.phone.send_message', mock_send_message)
    TokenProcessor.fetch_exchange_rate(user)
Exemplo n.º 2
0
def test_agent_recipient(test_client, init_database, standard_user):
    session = send_enter_recipient_state()

    agent_recipient = UserFactory(phone=make_kenyan_phone(phone()))
    agent_recipient.set_held_role('TOKEN_AGENT', 'grassroots_token_agent')

    state_machine = KenyaUssdStateMachine(session, standard_user)
    state_machine.feed_char(agent_recipient.phone)

    assert state_machine.state == "exit_use_exchange_menu"
    assert session.session_data is None
def test_reset_pin_flow(test_client, init_database, create_organisation,
                        authed_sempo_admin_user):

    # define different session id
    other_session_id = 'ATUid_05af06225e6163ec2dc9dc9cf8bc97aa000'

    # create organisation
    organisation = create_organisation
    organisation.external_auth_password = config.EXTERNAL_AUTH_PASSWORD

    # create highest tier admin
    admin = authed_sempo_admin_user
    admin.set_held_role('ADMIN', 'sempoadmin')

    # get admin's auth token
    auth = get_complete_auth_token(authed_sempo_admin_user)

    # create self signup user
    user = UserFactory(id=21,
                       phone='+6185274136',
                       first_name='Unknown first name',
                       last_name='Unknown last name',
                       pin_hash=User.salt_hash_secret('0000'),
                       failed_pin_attempts=0,
                       preferred_language="en",
                       registration_method=RegistrationMethodEnum.USSD_SIGNUP)

    # bind user to organisation
    user.add_user_to_organisation(organisation, False)

    # reset pin as admin
    response = test_client.post('/api/v1/user/reset_pin/',
                                headers=dict(Authorization=auth,
                                             Accept='application/json'),
                                content_type='application/json',
                                json={'user_id': user.id})
    assert response.status_code == 200
    assert len(user.pin_reset_tokens) > 0

    # test user's reset process
    ussd_resp = req("", test_client, user.phone, session_id=other_session_id)
    assert "CON Please enter a PIN to manage your account." in ussd_resp

    ussd_resp = req("1212",
                    test_client,
                    user.phone,
                    session_id=other_session_id)
    assert "CON Enter your PIN again" in ussd_resp

    ussd_resp = req("1212",
                    test_client,
                    user.phone,
                    session_id=other_session_id)
    assert "CON Welcome to Sarafu" in ussd_resp
def test_agent_recipient(test_client, init_database):
    session = exchange_token_agent_number_entry_state()
    user = standard_user()
    user.phone = phone()

    agent_recipient = UserFactory(phone=make_kenyan_phone(phone()))
    agent_recipient.set_held_role('TOKEN_AGENT', 'grassroots_token_agent')

    state_machine = KenyaUssdStateMachine(session, user)
    state_machine.feed_char(agent_recipient.phone)

    assert state_machine.state == "exchange_token_amount_entry"
    assert session.get_data('agent_phone') == agent_recipient.phone
def test_send_token(mocker, test_client, init_database,
                    initialised_blockchain_network, lang, token1_symbol,
                    token2_symbol, recipient_balance, expected_send_msg,
                    expected_receive_msg):

    org = OrganisationFactory()
    sender = UserFactory(preferred_language=lang,
                         phone=phone(),
                         first_name="Bob",
                         last_name="Foo",
                         default_organisation=org)
    token1 = Token.query.filter_by(symbol=token1_symbol).first()
    create_transfer_account_for_user(sender, token1, 20000)

    recipient = UserFactory(preferred_language=lang,
                            phone=phone(),
                            first_name="Joe",
                            last_name="Bar",
                            default_organisation=org)
    token2 = Token.query.filter_by(symbol=token2_symbol).first()
    create_transfer_account_for_user(recipient, token2, 30000)

    def mock_convert(exchange_contract, from_token, to_token, from_amount,
                     signing_address):
        if from_token.symbol == "SM1":
            return from_amount * 1.5
        else:
            return from_amount * 0.75

    mocker.patch('server.bt.get_conversion_amount', mock_convert)

    messages = []

    def mock_send_message(phone, message):
        messages.append({'phone': phone, 'message': message})

    mocker.patch('server.message_processor.send_message', mock_send_message)

    TokenProcessor.send_token(sender, recipient, 1000, "A reason", 1)
    assert default_transfer_account(sender).balance == 19000
    assert default_transfer_account(recipient).balance == recipient_balance

    assert len(messages) == 2
    sent_message = messages[0]
    assert sent_message['phone'] == sender.phone
    assert expected_send_msg in sent_message['message']
    received_message = messages[1]
    assert received_message['phone'] == recipient.phone
    assert expected_receive_msg in received_message['message']
def dl_processor(initialised_blockchain_network, create_transfer_usage):
    transfer_usage = create_transfer_usage

    user = UserFactory(phone=phone(), business_usage_id=transfer_usage.id)
    token = Token.query.filter_by(symbol="SM1").first()
    create_transfer_account_for_user(user, token, 200)
    return DirectoryListingProcessor(user, transfer_usage)
Exemplo n.º 7
0
def test_send_welcome_sms(mocker, test_client, init_database, mock_sms_apis,
                          preferred_language, org_key, expected_welcome,
                          expected_terms):
    from flask import g

    token = TokenFactory(name='Sarafu', symbol='SARAFU')
    organisation = OrganisationFactory(custom_welcome_message_key=org_key,
                                       token=token,
                                       country_code='AU')
    g.active_organisation = organisation
    transfer_account = TransferAccountFactory(balance=10000,
                                              token=token,
                                              organisation=organisation)
    user = UserFactory(first_name='Magoo',
                       phone='123456789',
                       preferred_language=preferred_language,
                       organisations=[organisation],
                       default_organisation=organisation,
                       transfer_accounts=[transfer_account])

    send_onboarding_sms_messages(user)

    messages = mock_sms_apis
    assert messages == [
        {
            'phone': '+61123456789',
            'message': expected_welcome
        },
        {
            'phone': '+61123456789',
            'message': expected_terms
        },
    ]
Exemplo n.º 8
0
def test_send_balance_sms(mocker, test_client, init_database,
                          initialised_blockchain_network, user_type, limit,
                          preferred_language, sample_text):
    user = UserFactory(preferred_language=preferred_language, phone=phone())
    if user_type == "group":
        user.set_held_role('GROUP_ACCOUNT', 'grassroots_group_account')
        user.is_phone_verified = True
        kyc = KycApplication(type='INDIVIDUAL')
        kyc.user = user
        kyc.kyc_status = 'VERIFIED'

    token1 = Token.query.filter_by(symbol="SM1").first()
    token2 = Token.query.filter_by(symbol="SM2").first()
    token3 = Token.query.filter_by(symbol="SM3").first()
    create_transfer_account_for_user(user, token1, 20000)
    create_transfer_account_for_user(user, token2, 35000, is_default=False)
    # this one should not show up in balance
    create_transfer_account_for_user(user,
                                     token3,
                                     0,
                                     is_default=False,
                                     is_ghost=True)

    def mock_convert(exchange_contract, from_token, to_token, from_amount):
        if from_token.symbol == "SM1":
            return from_amount * 1.4124333344353534
        else:
            return from_amount * 0.8398339289133232

    mocker.patch('server.bt.get_conversion_amount', mock_convert)

    def mock_send_message(phone, message):
        assert sample_text in message
        assert "SM1 200" in message
        assert "SM2 350" in message
        assert "SM3" not in message
        if limit:
            assert "{:.2f} SM1 (1 SM1 = 1.41 AUD)".format(limit *
                                                          200) in message
            assert "{:.2f} SM2 (1 SM2 = 0.84 AUD)".format(limit *
                                                          350) in message

    mocker.patch('server.utils.phone.send_message', mock_send_message)
    TokenProcessor.send_balance_sms(user)
Exemplo n.º 9
0
def test_standard_recipient(test_client, init_database, standard_user):
    session = send_enter_recipient_state()

    recipient_user = UserFactory(phone=make_kenyan_phone(phone()))

    state_machine = KenyaUssdStateMachine(session, standard_user)
    state_machine.feed_char(recipient_user.phone)

    assert state_machine.state == "send_token_amount"
    assert session.get_data('recipient_phone') == recipient_user.phone
def test_get_legacy_location(test_client, init_database, create_organisation,
                             authed_sempo_admin_user, param_latitude,
                             param_longitude, param_common_name):
    """
    GIVEN coordinates and a name
    WHEN storing this to the legacy fields for location in db
    THEN they are retrievable through the legacy location http api call
    """

    # create organisation
    organisation = create_organisation
    organisation.external_auth_password = config.EXTERNAL_AUTH_PASSWORD

    # create admin
    admin = authed_sempo_admin_user
    admin.set_held_role('ADMIN', 'admin')

    # create user with legacy location information
    user = UserFactory(
        id=42,
        lat=param_latitude,
        lng=param_longitude,
        _location=param_common_name,
    )

    user.add_user_to_organisation(organisation, False)

    # get admin auth token
    auth = get_complete_auth_token(authed_sempo_admin_user)

    response = test_client.get(
        '/api/v2/geolocation/legacy/user/42/',
        headers=dict(
            Authorization=auth,
            Accept='application/json',
        ),
    )

    assert response.status_code == 200
    assert response.json['lat'] == param_latitude
    assert response.json['lng'] == param_longitude
    assert response.json['location'] == param_common_name
def test_user_recipient(test_client, init_database):
    session = exchange_token_agent_number_entry_state()
    user = standard_user()
    user.phone = phone()

    user_recipient = UserFactory(phone=make_kenyan_phone(phone()))

    state_machine = KenyaUssdStateMachine(session, user)
    state_machine.feed_char(user_recipient.phone)

    assert state_machine.state == "exit_invalid_token_agent"
    assert session.session_data is None
def test_invalid_service_code(mocker, test_client, init_database,
                              initialised_blockchain_network, init_seed):
    org = OrganisationFactory()
    sender = UserFactory(preferred_language="en",
                         phone=make_kenyan_phone(phone()),
                         first_name="Bob",
                         last_name="Foo",
                         pin_hash=User.salt_hash_secret('0000'),
                         default_organisation=org)

    resp = req("", test_client, sender.phone, '*42*666#')
    assert 'END Bonyeza {} kutumia mtandao'.format(valid_service_code) in resp
def test_send_directory_listing(mocker, test_client, init_database,
                                dl_processor):
    user = dl_processor.recipient
    transfer_account = default_transfer_account(user)
    transfer_account.token.name = "A Token"

    user1 = UserFactory(phone=phone())
    attrs = {"custom_attributes": {"bio": "some bio"}}
    set_custom_attributes(attrs, user1)
    user2 = UserFactory(phone=phone())
    dl_processor.get_directory_listing_users = mocker.MagicMock(
        return_value=[user1, user2])
    dl_processor.get_business_category_translation = mocker.MagicMock(
        return_value="Test")
    dl_processor.send_sms = mocker.MagicMock()

    dl_processor.send_directory_listing()
    dl_processor.send_sms.assert_called_with(
        'send_directory_listing_message',
        community_token_name="A Token",
        business_type="Test",
        directory_listing_users=f"{user1.phone} some bio\n{user2.phone}")
Exemplo n.º 14
0
def standard_user(test_client, init_database):
    from flask import g

    token = TokenFactory(name='Sarafu', symbol='SARAFU')
    organisation = OrganisationFactory(token=token, country_code='AU')
    g.active_organisation = organisation

    return UserFactory(first_name="Foo",
                       last_name="Bar",
                       pin_hash=User.salt_hash_secret('0000'),
                       failed_pin_attempts=0,
                       phone=phone(),
                       default_organisation=organisation)
Exemplo n.º 15
0
def test_exchange_token(mocker, test_client, init_database,
                        initialised_blockchain_network):
    org = OrganisationFactory()
    sender = UserFactory(preferred_language="en",
                         phone=phone(),
                         first_name="Bob",
                         last_name="Foo",
                         default_organisation=org)
    sender.set_held_role('GROUP_ACCOUNT', 'grassroots_group_account')

    token1 = Token.query.filter_by(symbol="SM1").first()
    create_transfer_account_for_user(sender, token1, 20000)

    agent = UserFactory(phone=phone(),
                        first_name="Joe",
                        last_name="Bar",
                        default_organisation=org)
    agent.set_held_role('TOKEN_AGENT', 'grassroots_token_agent')
    # this is under the assumption that token agent would have default token being the reserve token. is this the case?
    reserve = Token.query.filter_by(symbol="AUD").first()
    create_transfer_account_for_user(agent, reserve, 30000)

    def mock_convert(exchange_contract, from_token, to_token, from_amount,
                     signing_address):
        return from_amount * 1.2

    mocker.patch('server.bt.get_conversion_amount', mock_convert)

    messages = []

    def mock_send_message(phone, message):
        messages.append({'phone': phone, 'message': message})

    mocker.patch('server.message_processor.send_message', mock_send_message)

    TokenProcessor.exchange_token(sender, agent, 1000)
    assert default_transfer_account(sender).balance == 19000
    assert default_transfer_account(agent).balance == 31200

    assert len(messages) == 2
    sent_message = messages[0]
    assert sent_message['phone'] == sender.phone
    assert 'sent a payment of 10.00 SM1 = 12.00 AUD' in sent_message['message']
    received_message = messages[1]
    assert received_message['phone'] == agent.phone
    assert 'received a payment of 12.00 AUD = 10.00 SM1' in received_message[
        'message']
Exemplo n.º 16
0
def test_create_or_update_session(test_client, init_database):
    from flask import g
    g.active_organisation = OrganisationFactory(country_code='AU')

    user = UserFactory(phone="123")

    # create a session in db

    menu3 = UssdMenu(id=3, name='foo', display_key='foo')
    db.session.add(menu3)

    session = UssdSession(session_id="1",
                          user_id=user.id,
                          msisdn="123",
                          ussd_menu=menu3,
                          state="foo",
                          service_code="*123#")
    db.session.add(session)
    db.session.commit()

    # test updating existing
    create_or_update_session("1", user,
                             UssdMenu(id=4, name="bar", display_key='bar'),
                             "input", "*123#")
    sessions = UssdSession.query.filter_by(session_id="1")
    assert sessions.count() == 1
    session = sessions.first()
    assert session.state == "bar"
    assert session.user_input == "input"
    assert session.ussd_menu_id == 4

    # test creating a new one
    sessions = UssdSession.query.filter_by(session_id="2")
    assert sessions.count() == 0
    create_or_update_session("2", user,
                             UssdMenu(id=5, name="bat", display_key='bat'), "",
                             "*123#")
    sessions = UssdSession.query.filter_by(session_id="2")
    assert sessions.count() == 1
    session = sessions.first()
    assert session.state == "bat"
    assert session.user_input == ""
    assert session.ussd_menu_id == 5
def test_ussd_self_signup_wrong_pin_entry(test_client, init_database,
                                          create_temporary_user,
                                          create_organisation):
    # create organisation
    organisation = create_organisation
    organisation.external_auth_password = config.EXTERNAL_AUTH_PASSWORD

    # define username to match the external_auth_username as defined in : /app/migrations/versions/961ab9adc300_.py
    external_auth_username = '******' + (organisation.name
                                         or '').lower().replace(' ', '_')

    # set active organisation
    g.active_organisation = organisation
    other_unregistered_user_phone = '+611256465214'

    resp = req("", test_client, other_unregistered_user_phone)
    assert "CON Welcome to Sarafu" in resp

    # create self signup user
    user = UserFactory(id=22,
                       phone=other_unregistered_user_phone,
                       first_name='Unknown first name',
                       last_name='Unknown last name',
                       registration_method=RegistrationMethodEnum.USSD_SIGNUP)

    resp = req("1",
               test_client,
               user.phone,
               auth_username=external_auth_username)
    assert "CON Please enter a PIN" in resp

    resp = req("0000",
               test_client,
               user.phone,
               auth_username=external_auth_username)
    assert "CON Enter your PIN again" in resp

    resp = req("1212",
               test_client,
               user.phone,
               auth_username=external_auth_username)
    assert "END The new PIN does not match the one you entered." in resp
Exemplo n.º 18
0
def test_send_welcome_sms(mocker, test_client, init_database,
                          preferred_language, org_key, expected_welcome, expected_terms):
    from flask import g

    token = TokenFactory(name='Sarafu', symbol='SARAFU')
    organisation = OrganisationFactory(custom_welcome_message_key=org_key, token=token, country_code='AU')
    g.active_organisation = organisation
    transfer_account = TransferAccountFactory(balance=10000, token=token, organisation=organisation)
    user = UserFactory(first_name='Magoo',
                       phone='123456789',
                       preferred_language=preferred_language,
                       organisations=[organisation],
                       default_organisation=organisation,
                       transfer_accounts=[transfer_account])

    send_message = mocker.MagicMock()
    mocker.patch('server.message_processor.send_message', send_message)

    send_onboarding_sms_messages(user)

    send_message.assert_has_calls(
        [mocker.call('+61123456789', expected_welcome),
         mocker.call('+61123456789', expected_terms)])
 def create_user(cat, token, is_market_enabled):
     _user = UserFactory(phone=phone(),
                         business_usage_id=cat.id,
                         is_market_enabled=is_market_enabled)
     create_transfer_account_for_user(_user, token, 200)
     return _user
def test_golden_path_send_token(mocker, test_client, init_database,
                                initialised_blockchain_network, init_seed):
    token = Token.query.filter_by(symbol="SM1").first()
    org = OrganisationFactory(country_code=config.DEFAULT_COUNTRY)
    sender = UserFactory(preferred_language="en",
                         phone='+6110011223344',
                         first_name="Bob",
                         last_name="Foo",
                         pin_hash=User.salt_hash_secret('0000'),
                         default_organisation=org)
    create_transfer_account_for_user(sender, token, 4220)

    recipient = UserFactory(preferred_language="sw",
                            phone='+6114433221100',
                            first_name="Joe",
                            last_name="Bar",
                            default_organisation=org)
    create_transfer_account_for_user(recipient, token, 1980)

    usages = TransferUsage.query.filter_by(default=True).order_by(
        TransferUsage.priority).all()
    top_priority = usages[0]
    # Take the last to ensure that we're not going to simply reinforce the existing order
    usage = usages[-1]
    # do two of these transfers to ensure last is is the first shown
    make_payment_transfer(100,
                          token=token,
                          send_user=sender,
                          receive_user=recipient,
                          transfer_use=str(int(usage.id)),
                          is_ghost_transfer=False,
                          require_sender_approved=False,
                          require_recipient_approved=False)

    make_payment_transfer(100,
                          token=token,
                          send_user=sender,
                          receive_user=recipient,
                          transfer_use=str(int(usage.id)),
                          is_ghost_transfer=False,
                          require_sender_approved=False,
                          require_recipient_approved=False)

    def mock_send_message(phone, message):
        messages.append({'phone': phone, 'message': message})

    mocker.patch(f'server.utils.phone._send_twilio_message.submit',
                 mock_send_message)
    mocker.patch(f'server.utils.phone._send_messagebird_message.submit',
                 mock_send_message)
    mocker.patch(f'server.utils.phone._send_at_message.submit',
                 mock_send_message)

    assert get_session() is None
    resp = req("", test_client, sender.phone)
    assert get_session() is not None
    assert "CON Welcome" in resp

    resp = req("1", test_client, sender.phone)
    assert "CON Enter Phone" in resp

    resp = req(recipient.phone, test_client, sender.phone)
    assert "CON Enter Amount" in resp

    resp = req("12.5", test_client, sender.phone)
    assert f"{recipient.user_details()} will receive 12.5 {token.symbol} from {sender.user_details()}" in resp

    resp = req("0000", test_client, sender.phone)
    assert "END Your request has been sent." in resp

    assert default_transfer_account(sender).balance == (4220 - 100 - 100 -
                                                        1250)
    assert default_transfer_account(recipient).balance == (1980 + 100 + 100 +
                                                           1250)

    assert len(messages) == 2
    sent_message = messages[0]
    assert sent_message['phone'] == sender.phone
    assert f"sent 12 SM1 to {recipient.first_name}" in sent_message['message']
    received_message = messages[1]
    assert received_message['phone'] == recipient.phone
    assert f"Umepokea 12 SM1 kutoka kwa {sender.first_name}" in received_message[
        'message']
Exemplo n.º 21
0
def test_golden_path_send_token(mocker, test_client, init_database,
                                initialised_blockchain_network, init_seed):
    token = Token.query.filter_by(symbol="SM1").first()
    org = OrganisationFactory(country_code='KE')
    sender = UserFactory(preferred_language="en",
                         phone=make_kenyan_phone(phone()),
                         first_name="Bob",
                         last_name="Foo",
                         pin_hash=User.salt_hash_secret('0000'),
                         default_organisation=org)
    create_transfer_account_for_user(sender, token, 4220)

    recipient = UserFactory(preferred_language="sw",
                            phone=make_kenyan_phone(phone()),
                            first_name="Joe",
                            last_name="Bar",
                            default_organisation=org)
    create_transfer_account_for_user(recipient, token, 1980)

    messages = []
    session_id = 'ATUid_05af06225e6163ec2dc9dc9cf8bc97aa'

    usages = TransferUsage.query.filter_by(default=True).order_by(
        TransferUsage.priority).all()
    top_priority = usages[0]
    # Take the last to ensure that we're not going to simply reinforce the existing order
    usage = usages[-1]
    # do two of these transfers to ensure last is is the first shown
    make_payment_transfer(100,
                          token=token,
                          send_user=sender,
                          receive_user=recipient,
                          transfer_use=str(int(usage.id)),
                          is_ghost_transfer=False,
                          require_sender_approved=False,
                          require_recipient_approved=False)

    make_payment_transfer(100,
                          token=token,
                          send_user=sender,
                          receive_user=recipient,
                          transfer_use=str(int(usage.id)),
                          is_ghost_transfer=False,
                          require_sender_approved=False,
                          require_recipient_approved=False)

    def mock_send_message(phone, message):
        messages.append({'phone': phone, 'message': message})

    mocker.patch(f'server.utils.phone._send_twilio_message.submit',
                 mock_send_message)
    mocker.patch(f'server.utils.phone._send_messagebird_message.submit',
                 mock_send_message)
    mocker.patch(f'server.utils.phone._send_at_message.submit',
                 mock_send_message)

    def req(text):
        response = test_client.post(
            f'/api/v1/ussd/kenya?username={config.EXTERNAL_AUTH_USERNAME}&password={config.EXTERNAL_AUTH_PASSWORD}',
            headers=dict(Accept='application/json'),
            json={
                'sessionId': session_id,
                'phoneNumber': sender.phone,
                'text': text,
                'serviceCode': '*384*23216#'
            })
        assert response.status_code == 200
        return response.data.decode("utf-8")

    def get_session():
        return UssdSession.query.filter_by(session_id=session_id).first()

    assert get_session() is None
    resp = req("")
    assert get_session() is not None
    assert "CON Welcome" in resp

    resp = req("1")
    assert "CON Enter Phone" in resp

    resp = req(recipient.phone)
    assert "CON Enter Amount" in resp

    resp = req("12.5")
    assert "CON Transfer Reason" in resp
    assert f"1. {top_priority.translations['en']}" in resp
    assert "9." in resp

    resp = req("9")
    assert "CON Please specify" in resp
    assert "10. Show previous" in resp
    assert "9." not in resp

    resp = req("10")

    resp = req("4")
    assert "CON Please enter your PIN" in resp

    resp = req("0000")
    assert "CON Send 12.5 SM1" in resp
    # went to second page, should not be the first
    assert f"for {top_priority.translations['en']}" not in resp

    resp = req("1")
    assert "END Your request has been sent." in resp

    assert default_transfer_account(sender).balance == (4220 - 100 - 100 -
                                                        1250)
    assert default_transfer_account(recipient).balance == (1980 + 100 + 100 +
                                                           1250)

    assert len(messages) == 3
    sent_message = messages[1]
    assert sent_message['phone'] == sender.phone
    assert f"sent a payment of 12.50 SM1 to {recipient.first_name}" in sent_message[
        'message']
    received_message = messages[2]
    assert received_message['phone'] == recipient.phone
    assert f"Umepokea 12.50 SM1 kutoka kwa {sender.first_name}" in received_message[
        'message']