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 }, ]
def test_kenya_state_machine(test_client, init_database, user_factory, session_factory, user_input, expected): from flask import g g.active_organisation = OrganisationFactory(country_code='AU') session = session_factory() user = user_factory() user.phone = phone() state_machine = KenyaUssdStateMachine(session, user) state_machine.feed_char(user_input) assert state_machine.state == expected
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 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)
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 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']
def test_name_change(test_client, init_database, session_factory, user_factory, user_input, expected_first_name, expected_last_name, expected_state): from flask import g g.active_organisation = OrganisationFactory(country_code='KE') session = session_factory() user = user_factory() user.phone = phone() session.session_data = {'first_name': 'Foo'} state_machine = KenyaUssdStateMachine(session, user) state_machine.feed_char(user_input) assert state_machine.state == expected_state assert session.get_data('first_name') == expected_first_name assert session.get_data('last_name') == expected_last_name
def test_kenya_state_machine(test_client, init_database, user_factory, session_factory, user_input, expected): from flask import g g.active_organisation = OrganisationFactory(country_code='AU') session = session_factory() session.session_data = { 'transfer_usage_mapping': fake_transfer_mapping(10), 'usage_menu': 1, 'usage_index_stack': [0, 8] } user = user_factory() user.phone = phone() db.session.commit() state_machine = KenyaUssdStateMachine(session, user) state_machine.feed_char(user_input) assert state_machine.state == expected
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_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 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']
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']