The great bump

This commit is contained in:
2021-08-06 16:29:01 +00:00
parent f764b73f66
commit 0672a17d2e
195 changed files with 5791 additions and 4983 deletions

View File

@@ -0,0 +1,178 @@
# standard imports
import json
from decimal import Decimal
# external imports
import celery
import pytest
import requests_mock
from chainlib.hash import strip_0x
# local imports
from cic_ussd.account.statement import generate, filter_statement_transactions
from cic_ussd.account.transaction import transaction_actors
from cic_ussd.cache import cache_data_key, get_cached_data
from cic_ussd.db.models.account import Account
from cic_ussd.error import AccountCreationDataNotFound
from cic_ussd.metadata import PreferencesMetadata
# test imports
from tests.helpers.accounts import blockchain_address
def test_account_creation_callback(account_creation_data,
cache_account_creation_data,
celery_session_worker,
custom_metadata,
init_cache,
init_database,
load_chain_spec,
mocker,
setup_metadata_request_handler,
setup_metadata_signer):
phone_number = account_creation_data.get('phone_number')
result = blockchain_address()
task_uuid = account_creation_data.get('task_uuid')
mock_task = mocker.patch('celery.app.task.Task.request')
mock_task.root_id = task_uuid
mock_task.delivery_info = {'routing_key': 'cic-ussd'}
status_code = 1
with pytest.raises(ValueError) as error:
s_account_creation_callback = celery.signature(
'cic_ussd.tasks.callback_handler.account_creation_callback', [task_uuid, '', status_code]
)
s_account_creation_callback.apply_async().get()
assert str(error.value) == f'Unexpected status code: {status_code}'
cached_account_creation_data = get_cached_data(task_uuid)
cached_account_creation_data = json.loads(cached_account_creation_data)
assert cached_account_creation_data.get('status') == account_creation_data.get('status')
mock_add_phone_pointer = mocker.patch('cic_ussd.tasks.metadata.add_phone_pointer.apply_async')
mock_add_custom_metadata = mocker.patch('cic_ussd.tasks.metadata.add_custom_metadata.apply_async')
s_account_creation_callback = celery.signature(
'cic_ussd.tasks.callback_handler.account_creation_callback', [result, '', 0]
)
s_account_creation_callback.apply_async().get()
account = init_database.query(Account).filter_by(phone_number=phone_number).first()
assert account.blockchain_address == result
cached_account_creation_data = get_cached_data(task_uuid)
cached_account_creation_data = json.loads(cached_account_creation_data)
assert cached_account_creation_data.get('status') == 'CREATED'
mock_add_phone_pointer.assert_called_with((result, phone_number), {}, queue='cic-ussd')
mock_add_custom_metadata.assert_called_with((result, custom_metadata), {}, queue='cic-ussd')
task_uuid = celery.uuid()
mock_task.root_id = task_uuid
with pytest.raises(AccountCreationDataNotFound) as error:
s_account_creation_callback = celery.signature(
'cic_ussd.tasks.callback_handler.account_creation_callback', [task_uuid, '', 0]
)
s_account_creation_callback.apply_async().get()
assert str(error.value) == f'No account creation data found for task id: {task_uuid}'
def test_balances_callback(activated_account, balances, celery_session_worker):
status_code = 1
with pytest.raises(ValueError) as error:
s_balances_callback = celery.signature(
'cic_ussd.tasks.callback_handler.balances_callback',
[balances, activated_account.blockchain_address, status_code])
s_balances_callback.apply_async().get()
assert str(error.value) == f'Unexpected status code: {status_code}.'
status_code = 0
s_balances_callback = celery.signature(
'cic_ussd.tasks.callback_handler.balances_callback',
[balances, activated_account.blockchain_address, status_code])
s_balances_callback.apply_async().get()
identifier = bytes.fromhex(strip_0x(activated_account.blockchain_address))
key = cache_data_key(identifier, ':cic.balances')
cached_balances = get_cached_data(key)
cached_balances = json.loads(cached_balances)
assert cached_balances == balances[0]
def test_statement_callback(activated_account, mocker, transactions_list):
status_code = 1
with pytest.raises(ValueError) as error:
s_statement_callback = celery.signature(
'cic_ussd.tasks.callback_handler.statement_callback',
[transactions_list, activated_account.blockchain_address, status_code])
s_statement_callback.apply_async().get()
assert str(error.value) == f'Unexpected status code: {status_code}.'
mock_task = mocker.patch('celery.app.task.Task.request')
mock_task.delivery_info = {'routing_key': 'cic-ussd'}
mock_statement_generate = mocker.patch('cic_ussd.tasks.processor.generate_statement.apply_async')
status_code = 0
s_statement_callback = celery.signature(
'cic_ussd.tasks.callback_handler.statement_callback',
[transactions_list, activated_account.blockchain_address, status_code])
s_statement_callback.apply_async().get()
statement_transactions = filter_statement_transactions(transactions_list)
recipient_transaction, sender_transaction = transaction_actors(statement_transactions[0])
mock_statement_generate.assert_called_with(
(activated_account.blockchain_address, sender_transaction), {}, queue='cic-ussd')
def test_transaction_balances_callback(activated_account,
balances,
cache_balances,
cache_person_metadata,
cache_preferences,
load_chain_spec,
mocker,
preferences,
setup_metadata_signer,
setup_metadata_request_handler,
set_locale_files,
transaction_result):
status_code = 1
recipient_transaction, sender_transaction = transaction_actors(transaction_result)
with pytest.raises(ValueError) as error:
s_transaction_balances_callback = celery.signature(
'cic_ussd.tasks.callback_handler.transaction_balances_callback',
[balances, sender_transaction, status_code])
s_transaction_balances_callback.apply_async().get()
assert str(error.value) == f'Unexpected status code: {status_code}.'
mocked_chain = mocker.patch('celery.chain')
mock_task_request = mocker.patch('celery.app.task.Task.request')
mock_task_request.delivery_info = {'routing_key': 'cic-ussd'}
sender_transaction['transaction_type'] = 'transfer'
status_code = 0
s_transaction_balances_callback = celery.signature(
'cic_ussd.tasks.callback_handler.transaction_balances_callback',
[balances, sender_transaction, status_code])
s_transaction_balances_callback.apply_async().get()
mocked_chain.assert_called()
sender_transaction['transaction_type'] = 'tokengift'
status_code = 0
s_transaction_balances_callback = celery.signature(
'cic_ussd.tasks.callback_handler.transaction_balances_callback',
[balances, sender_transaction, status_code])
s_transaction_balances_callback.apply_async().get()
mocked_chain.assert_called()
def test_transaction_callback(load_chain_spec, mock_async_balance_api_query, transaction_result):
status_code = 1
with pytest.raises(ValueError) as error:
s_transaction_callback = celery.signature(
'cic_ussd.tasks.callback_handler.transaction_callback',
[transaction_result, 'transfer', status_code])
s_transaction_callback.apply_async().get()
assert str(error.value) == f'Unexpected status code: {status_code}.'
status_code = 0
s_transaction_callback = celery.signature(
'cic_ussd.tasks.callback_handler.transaction_callback',
[transaction_result, 'transfer', status_code])
s_transaction_callback.apply_async().get()
recipient_transaction, sender_transaction = transaction_actors(transaction_result)
assert mock_async_balance_api_query.get('address') == recipient_transaction.get('blockchain_address') or sender_transaction.get('blockchain_address')
assert mock_async_balance_api_query.get('token_symbol') == recipient_transaction.get('token_symbol') or sender_transaction.get('token_symbol')

View File

@@ -1,203 +0,0 @@
# standard imports
import json
import logging
from datetime import datetime
# third party imports
import celery
import pytest
# local imports
from cic_ussd.db.models.account import Account
from cic_ussd.error import ActionDataNotFoundError
from cic_ussd.conversions import from_wei
logg = logging.getLogger()
def test_successful_process_account_creation_callback_task(account_creation_action_data,
celery_session_worker,
init_database,
init_redis_cache,
mocker,
set_account_creation_action_data):
phone_number = account_creation_action_data.get('phone_number')
task_id = account_creation_action_data.get('task_id')
mocked_task_request = mocker.patch('celery.app.task.Task.request')
# WARNING: [THE SETTING OF THE ROOT ID IS A HACK AND SHOULD BE REVIEWED OR IMPROVED]
mocked_task_request.root_id = task_id
user = init_database.query(Account).filter_by(phone_number=phone_number).first()
assert user is None
redis_cache = init_redis_cache
action_data = redis_cache.get(task_id)
action_data = json.loads(action_data)
assert action_data.get('status') == 'PENDING'
status_code = 0
result = '0x6315c185fd23bDbbba058E2a504197915aCC5065'
url = ''
s_process_callback_request = celery.signature(
'cic_ussd.tasks.callback_handler.process_account_creation_callback',
[result, url, status_code]
)
s_process_callback_request.apply_async().get()
user = init_database.query(Account).filter_by(phone_number=phone_number).first()
assert user.blockchain_address == result
action_data = redis_cache.get(task_id)
action_data = json.loads(action_data)
assert action_data.get('status') == 'CREATED'
def test_unsuccessful_process_account_creation_callback_task(init_database,
init_redis_cache,
celery_session_worker):
with pytest.raises(ActionDataNotFoundError) as error:
status_code = 0
result = '0x6315c185fd23bDbbba058E2a504197915aCC5065'
url = ''
s_process_callback_request = celery.signature(
'cic_ussd.tasks.callback_handler.process_account_creation_callback',
[result, url, status_code]
)
result = s_process_callback_request.apply_async()
task_id = result.get()
assert str(error.value) == f'Account creation task: {task_id}, returned unexpected response: {status_code}'
def test_successful_token_gift_incoming_transaction(celery_session_worker,
create_activated_user,
mock_notifier_api,
set_locale_files,
successful_incoming_token_gift_callback):
result = successful_incoming_token_gift_callback.get('RESULT')
param = successful_incoming_token_gift_callback.get('PARAM')
status_code = successful_incoming_token_gift_callback.get('STATUS_CODE')
s_process_token_gift = celery.signature(
'cic_ussd.tasks.callback_handler.process_incoming_transfer_callback',
[result, param, status_code]
)
s_process_token_gift.apply_async().get()
balance = from_wei(result.get('destination_value'))
token_symbol = result.get('token_symbol')
messages = mock_notifier_api
assert messages[0].get('recipient') == create_activated_user.phone_number
assert messages[0].get(
'message') == f'Hello {""} you have been registered on Sarafu Network! Your balance is {balance} {token_symbol}. To use dial *483*46#. For help 0757628885.'
def test_successful_transfer_incoming_transaction(celery_session_worker,
create_valid_tx_sender,
create_valid_tx_recipient,
mock_notifier_api,
set_locale_files,
successful_incoming_transfer_callback):
result = successful_incoming_transfer_callback.get('RESULT')
param = successful_incoming_transfer_callback.get('PARAM')
status_code = successful_incoming_transfer_callback.get('STATUS_CODE')
s_process_token_gift = celery.signature(
'cic_ussd.tasks.callback_handler.process_incoming_transfer_callback',
[result, param, status_code]
)
s_process_token_gift.apply_async().get()
value = result.get('destination_value')
balance = ''
token_symbol = result.get('token_symbol')
sender_first_name = ''
sender_last_name = ''
phone_number = create_valid_tx_sender.phone_number
tx_sender_information = f'{phone_number}, {sender_first_name}, {sender_last_name}'
amount = from_wei(value=value)
timestamp = datetime.now().strftime('%d-%m-%y, %H:%M %p')
messages = mock_notifier_api
assert messages[0].get('recipient') == create_valid_tx_recipient.phone_number
assert messages[0].get(
'message') == f'Successfully received {amount} {token_symbol} from {tx_sender_information} {timestamp}. New balance is {balance} {token_symbol}.'
def test_unsuccessful_incoming_transaction_recipient_not_found(celery_session_worker,
create_valid_tx_sender,
successful_incoming_transfer_callback):
result = successful_incoming_transfer_callback.get('RESULT')
param = successful_incoming_transfer_callback.get('PARAM')
status_code = successful_incoming_transfer_callback.get('STATUS_CODE')
with pytest.raises(ValueError) as error:
s_process_token_gift = celery.signature(
'cic_ussd.tasks.callback_handler.process_incoming_transfer_callback',
[result, param, status_code]
)
s_process_token_gift.apply_async().get()
recipient_blockchain_address = result.get('recipient')
assert str(error.value) == f'Tx for recipient: {recipient_blockchain_address} was received but has no matching user in the system.'
def test_successful_incoming_transaction_sender_not_found(caplog,
celery_session_worker,
create_valid_tx_recipient,
mock_notifier_api,
successful_incoming_transfer_callback):
result = successful_incoming_transfer_callback.get('RESULT')
param = successful_incoming_transfer_callback.get('PARAM')
status_code = successful_incoming_transfer_callback.get('STATUS_CODE')
s_process_token_gift = celery.signature(
'cic_ussd.tasks.callback_handler.process_incoming_transfer_callback',
[result, param, status_code]
)
s_process_token_gift.apply_async().get()
sender_blockchain_address = result.get('sender')
assert 'Balance requires implementation of cic-eth integration with balance.' in caplog.text
# assert f'Tx with sender: {sender_blockchain_address} was received but has no matching user in the system.\n' in caplog.text
def test_unsuccessful_incoming_transaction_invalid_status_code(celery_session_worker,
incoming_transfer_callback_invalid_tx_status_code):
result = incoming_transfer_callback_invalid_tx_status_code.get('RESULT')
param = incoming_transfer_callback_invalid_tx_status_code.get('PARAM')
status_code = incoming_transfer_callback_invalid_tx_status_code.get('STATUS_CODE')
with pytest.raises(ValueError) as error:
s_process_token_gift = celery.signature(
'cic_ussd.tasks.callback_handler.process_incoming_transfer_callback',
[result, param, status_code]
)
s_process_token_gift.apply_async().get()
assert str(error.value) == f'Unexpected status code: {status_code}'
def test_unsuccessful_incoming_transaction_invalid_param(celery_session_worker,
incoming_transfer_callback_invalid_tx_param):
result = incoming_transfer_callback_invalid_tx_param.get('RESULT')
param = incoming_transfer_callback_invalid_tx_param.get('PARAM')
status_code = incoming_transfer_callback_invalid_tx_param.get('STATUS_CODE')
with pytest.raises(ValueError) as error:
s_process_token_gift = celery.signature(
'cic_ussd.tasks.callback_handler.process_incoming_transfer_callback',
[result, param, status_code]
)
s_process_token_gift.apply_async().get()
assert str(error.value) == f'Unexpected transaction: param {status_code}'

View File

@@ -0,0 +1,52 @@
# standard imports
import json
import os
# external imports
import celery
import requests_mock
from chainlib.hash import strip_0x
# local imports
from cic_ussd.cache import cache_data_key, get_cached_data
from cic_ussd.metadata import PersonMetadata, PreferencesMetadata
# tests imports
def test_query_person_metadata(activated_account,
celery_session_worker,
init_cache,
person_metadata,
setup_metadata_request_handler,
setup_metadata_signer):
with requests_mock.Mocker(real_http=False) as request_mocker:
identifier = bytes.fromhex(strip_0x(activated_account.blockchain_address))
metadata_client = PersonMetadata(identifier)
request_mocker.register_uri('GET', metadata_client.url, json=person_metadata, reason='OK', status_code=200)
s_query_person_metadata = celery.signature(
'cic_ussd.tasks.metadata.query_person_metadata', [activated_account.blockchain_address])
s_query_person_metadata.apply().get()
key = cache_data_key(identifier, ':cic.person')
cached_person_metadata = get_cached_data(key)
cached_person_metadata = json.loads(cached_person_metadata)
assert cached_person_metadata == person_metadata
def test_query_preferences_metadata(activated_account,
celery_session_worker,
init_cache,
preferences,
setup_metadata_request_handler,
setup_metadata_signer):
with requests_mock.Mocker(real_http=False) as request_mocker:
identifier = bytes.fromhex(strip_0x(activated_account.blockchain_address))
metadata_client = PreferencesMetadata(identifier)
request_mocker.register_uri('GET', metadata_client.url, json=preferences, reason='OK', status_code=200)
query_preferences_metadata = celery.signature(
'cic_ussd.tasks.metadata.query_preferences_metadata', [activated_account.blockchain_address])
query_preferences_metadata.apply().get()
key = cache_data_key(identifier, ':cic.preferences')
cached_preferences_metadata = get_cached_data(key)
cached_preferences_metadata = json.loads(cached_preferences_metadata)
assert cached_preferences_metadata == preferences

View File

@@ -0,0 +1,71 @@
# standard imports
import datetime
# external imports
import celery
# local imports
from cic_ussd.account.transaction import from_wei
from cic_ussd.phone_number import Support
from cic_ussd.translation import translation_for
# tests imports
def test_transaction(celery_session_worker,
load_support_phone,
mock_notifier_api,
notification_data,
set_locale_files):
notification_data['transaction_type'] = 'transfer'
amount = from_wei(notification_data.get('token_value'))
balance = notification_data.get('available_balance')
phone_number = notification_data.get('phone_number')
preferred_language = notification_data.get('preferred_language')
token_symbol = notification_data.get('token_symbol')
transaction_account_metadata = notification_data.get('metadata_id')
timestamp = datetime.datetime.now().strftime('%d-%m-%y, %H:%M %p')
s_transaction = celery.signature(
'cic_ussd.tasks.notifications.transaction', [notification_data]
)
s_transaction.apply_async().get()
assert mock_notifier_api.get('recipient') == phone_number
message = translation_for(key='sms.sent_tokens',
phone_number=phone_number,
preferred_language=preferred_language,
amount=amount,
token_symbol=token_symbol,
tx_recipient_information=transaction_account_metadata,
timestamp=timestamp,
balance=balance)
assert mock_notifier_api.get('message') == message
notification_data['role'] = 'recipient'
notification_data['direction_tag'] = 'From'
s_transaction = celery.signature(
'cic_ussd.tasks.notifications.transaction', [notification_data]
)
s_transaction.apply_async().get()
message = translation_for(key='sms.received_tokens',
phone_number=phone_number,
preferred_language=preferred_language,
amount=amount,
token_symbol=token_symbol,
tx_sender_information=transaction_account_metadata,
timestamp=timestamp,
balance=balance)
assert mock_notifier_api.get('message') == message
notification_data['transaction_type'] = 'tokengift'
s_transaction = celery.signature(
'cic_ussd.tasks.notifications.transaction', [notification_data]
)
s_transaction.apply_async().get()
support_phone = Support.phone_number
message = translation_for(key='sms.account_successfully_created',
preferred_language=preferred_language,
balance=balance,
support_phone=support_phone,
token_symbol=token_symbol)
assert mock_notifier_api.get('message') == message

View File

@@ -1,46 +0,0 @@
# third party imports
import celery
import pytest
# local imports
from cic_ussd.db.models.ussd_session import UssdSession
from cic_ussd.error import SessionNotFoundError
def test_persist_session_to_db_task(
init_database,
create_activated_user,
ussd_session_data,
celery_session_worker,
create_in_redis_ussd_session):
external_session_id = ussd_session_data.get('external_session_id')
s_persist_session_to_db = celery.signature(
'cic_ussd.tasks.ussd_session.persist_session_to_db',
[external_session_id]
)
result = s_persist_session_to_db.apply_async()
result.get()
db_session = init_database.query(UssdSession).filter_by(external_session_id=external_session_id).first()
assert db_session.external_session_id == 'AT974186'
assert db_session.service_code == '*483*46#'
assert db_session.msisdn == '+25498765432'
assert db_session.user_input == '1'
assert db_session.state == 'initial_language_selection'
assert db_session.session_data is None
assert db_session.version == 2
assert UssdSession.have_session_for_phone(create_activated_user.phone_number)
def test_session_not_found_error(
celery_session_worker,
create_in_redis_ussd_session):
with pytest.raises(SessionNotFoundError) as error:
external_session_id = 'SomeRandomValue'
s_persist_session_to_db = celery.signature(
'cic_ussd.tasks.ussd_session.persist_session_to_db',
[external_session_id]
)
result = s_persist_session_to_db.apply_async()
result.get()
assert str(error.value) == "Session does not exist!"

View File

@@ -0,0 +1,75 @@
# standard imports
import json
# external imports
import celery
from chainlib.hash import strip_0x
# local imports
from cic_ussd.account.transaction import transaction_actors
from cic_ussd.cache import cache_data_key, get_cached_data
# test imports
def test_generate_statement(activated_account,
celery_session_worker,
cache_preferences,
mocker,
transaction_result):
mock_task = mocker.patch('celery.app.task.Task.request')
mock_task.delivery_info = {'routing_key': 'cic-ussd'}
mock_chain = mocker.patch('celery.chain')
recipient_transaction, sender_transaction = transaction_actors(transaction_result)
s_generate_statement = celery.signature(
'cic_ussd.tasks.processor.generate_statement', [activated_account.blockchain_address, sender_transaction]
)
result = s_generate_statement.apply_async().get()
mock_chain.assert_called_once()
def test_cache_statement(activated_account,
cache_person_metadata,
celery_session_worker,
init_database,
preferences,
transaction_result):
recipient_transaction, sender_transaction = transaction_actors(transaction_result)
identifier = bytes.fromhex(strip_0x(activated_account.blockchain_address))
key = cache_data_key(identifier, ':cic.statement')
cached_statement = get_cached_data(key)
assert cached_statement is None
s_parse_transaction = celery.signature(
'cic_ussd.tasks.processor.parse_transaction', [preferences, sender_transaction])
result = s_parse_transaction.apply_async().get()
s_cache_statement = celery.signature(
'cic_ussd.tasks.processor.cache_statement', [result, activated_account.blockchain_address]
)
s_cache_statement.apply_async().get()
cached_statement = get_cached_data(key)
cached_statement = json.loads(cached_statement)
assert len(cached_statement) == 1
s_cache_statement = celery.signature(
'cic_ussd.tasks.processor.cache_statement', [result, activated_account.blockchain_address]
)
s_cache_statement.apply_async().get()
cached_statement = get_cached_data(key)
cached_statement = json.loads(cached_statement)
assert len(cached_statement) == 2
def test_parse_transaction(activated_account,
cache_person_metadata,
celery_session_worker,
init_database,
preferences,
transaction_result):
recipient_transaction, sender_transaction = transaction_actors(transaction_result)
assert sender_transaction.get('metadata_id') is None
assert sender_transaction.get('phone_number') is None
s_parse_transaction = celery.signature(
'cic_ussd.tasks.processor.parse_transaction', [preferences, sender_transaction])
result = s_parse_transaction.apply_async().get()
assert result.get('metadata_id') == activated_account.standard_metadata_id()
assert result.get('phone_number') == activated_account.phone_number

View File

@@ -0,0 +1,33 @@
# standard imports
# external imports
import celery
import pytest
# local imports
from cic_ussd.db.models.ussd_session import UssdSession
from cic_ussd.error import SessionNotFoundError
# tests imports
def test_persist_session_to_db(cached_ussd_session, celery_session_worker, init_cache, init_database):
external_session_id = cached_ussd_session.external_session_id
s_persist_session_to_db = celery.signature(
'cic_ussd.tasks.ussd_session.persist_session_to_db', [external_session_id])
s_persist_session_to_db.apply_async().get()
ussd_session = init_database.query(UssdSession).filter_by(external_session_id=external_session_id).first()
assert ussd_session.external_session_id == cached_ussd_session.external_session_id
assert ussd_session.service_code == cached_ussd_session.service_code
assert ussd_session.msisdn == cached_ussd_session.msisdn
assert ussd_session.user_input == cached_ussd_session.user_input
assert ussd_session.state == cached_ussd_session.state
assert ussd_session.data is None
assert ussd_session.version == cached_ussd_session.version
assert UssdSession.has_record_for_phone_number(ussd_session.msisdn, init_database)
with pytest.raises(SessionNotFoundError) as error:
external_session_id = 'SomeRandomValue'
s_persist_session_to_db = celery.signature(
'cic_ussd.tasks.ussd_session.persist_session_to_db', [external_session_id])
result = s_persist_session_to_db.apply_async().get()
assert str(error.value) == "Session does not exist!"