Minor refactors:
- Renames s_assemble to s_brief - Link s_local to s_brief
This commit is contained in:
30
apps/cic-ussd/tests/cic_ussd/db/test_db.py
Normal file
30
apps/cic-ussd/tests/cic_ussd/db/test_db.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# standard imports
|
||||
import os
|
||||
|
||||
# third-party imports
|
||||
|
||||
# local imports
|
||||
from cic_ussd.db import dsn_from_config
|
||||
|
||||
|
||||
def test_dsn_from_config(load_config):
|
||||
"""
|
||||
"""
|
||||
# test dsn for sqlite engine
|
||||
dsn = dsn_from_config(load_config)
|
||||
scheme = f'{load_config.get("DATABASE_ENGINE")}+{load_config.get("DATABASE_DRIVER")}'
|
||||
assert dsn == f'{scheme}:///{load_config.get("DATABASE_NAME")}'
|
||||
|
||||
# test dsn for other db formats
|
||||
overrides = {
|
||||
'DATABASE_PASSWORD': 'password',
|
||||
'DATABASE_DRIVER': 'psycopg2',
|
||||
'DATABASE_ENGINE': 'postgresql'
|
||||
}
|
||||
load_config.dict_override(dct=overrides, dct_description='Override values to test different db formats.')
|
||||
|
||||
scheme = f'{load_config.get("DATABASE_ENGINE")}+{load_config.get("DATABASE_DRIVER")}'
|
||||
|
||||
dsn = dsn_from_config(load_config)
|
||||
assert dsn == f"{scheme}://{load_config.get('DATABASE_USER')}:{load_config.get('DATABASE_PASSWORD')}@{load_config.get('DATABASE_HOST')}:{load_config.get('DATABASE_PORT')}/{load_config.get('DATABASE_NAME')}"
|
||||
|
||||
80
apps/cic-ussd/tests/cic_ussd/metadata/test_metadata.py
Normal file
80
apps/cic-ussd/tests/cic_ussd/metadata/test_metadata.py
Normal file
@@ -0,0 +1,80 @@
|
||||
# standard imports
|
||||
import json
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
import requests
|
||||
import requests_mock
|
||||
|
||||
# local imports
|
||||
from cic_ussd.error import UnsupportedMethodError
|
||||
from cic_ussd.metadata import blockchain_address_to_metadata_pointer, make_request
|
||||
|
||||
|
||||
def test_make_request(define_metadata_pointer_url, mock_meta_get_response, mock_meta_post_response, person_metadata):
|
||||
with requests_mock.Mocker(real_http=False) as request_mocker:
|
||||
request_mocker.register_uri(
|
||||
'GET',
|
||||
define_metadata_pointer_url,
|
||||
status_code=200,
|
||||
reason='OK',
|
||||
content=json.dumps(mock_meta_get_response).encode('utf-8')
|
||||
)
|
||||
response = make_request(method='GET', url=define_metadata_pointer_url)
|
||||
assert response.content == requests.get(define_metadata_pointer_url).content
|
||||
|
||||
with requests_mock.Mocker(real_http=False) as request_mocker:
|
||||
request_mocker.register_uri(
|
||||
'POST',
|
||||
define_metadata_pointer_url,
|
||||
status_code=201,
|
||||
reason='CREATED',
|
||||
content=json.dumps(mock_meta_post_response).encode('utf-8')
|
||||
)
|
||||
response = make_request(
|
||||
method='POST',
|
||||
url=define_metadata_pointer_url,
|
||||
data=json.dumps(person_metadata).encode('utf-8'),
|
||||
headers={
|
||||
'X-CIC-AUTOMERGE': 'server',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
)
|
||||
assert response.content == requests.post(define_metadata_pointer_url).content
|
||||
|
||||
with requests_mock.Mocker(real_http=False) as request_mocker:
|
||||
request_mocker.register_uri(
|
||||
'PUT',
|
||||
define_metadata_pointer_url,
|
||||
status_code=200,
|
||||
reason='OK'
|
||||
)
|
||||
response = make_request(
|
||||
method='PUT',
|
||||
url=define_metadata_pointer_url,
|
||||
data=json.dumps(person_metadata).encode('utf-8'),
|
||||
headers={
|
||||
'X-CIC-AUTOMERGE': 'server',
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
)
|
||||
assert response.content == requests.put(define_metadata_pointer_url).content
|
||||
|
||||
with pytest.raises(UnsupportedMethodError) as error:
|
||||
with requests_mock.Mocker(real_http=False) as request_mocker:
|
||||
request_mocker.register_uri(
|
||||
'DELETE',
|
||||
define_metadata_pointer_url,
|
||||
status_code=200,
|
||||
reason='OK'
|
||||
)
|
||||
make_request(
|
||||
method='DELETE',
|
||||
url=define_metadata_pointer_url
|
||||
)
|
||||
assert str(error.value) == 'Unsupported method: DELETE'
|
||||
|
||||
|
||||
def test_blockchain_address_to_metadata_pointer(create_activated_user):
|
||||
blockchain_address = create_activated_user.blockchain_address
|
||||
assert type(blockchain_address_to_metadata_pointer(blockchain_address)) == bytes
|
||||
34
apps/cic-ussd/tests/cic_ussd/metadata/test_signer.py
Normal file
34
apps/cic-ussd/tests/cic_ussd/metadata/test_signer.py
Normal file
@@ -0,0 +1,34 @@
|
||||
# standard imports
|
||||
import shutil
|
||||
|
||||
# third-party imports
|
||||
|
||||
# local imports
|
||||
from cic_ussd.metadata.signer import Signer
|
||||
|
||||
|
||||
def test_client(load_config, setup_metadata_signer, person_metadata):
|
||||
signer = Signer()
|
||||
# get gpg used
|
||||
digest = 'a4337bc45a8fc544c03f52dc550cd6e1e87021bc896588bd79e901e2'
|
||||
person_metadata['digest'] = digest
|
||||
gpg = signer.gpg
|
||||
|
||||
# check that key data was loaded
|
||||
assert signer.key_data is not None
|
||||
|
||||
# check that correct operational key is returned
|
||||
gpg.import_keys(key_data=signer.key_data)
|
||||
gpg_keys = gpg.list_keys()
|
||||
assert signer.get_operational_key() == gpg_keys[0]
|
||||
|
||||
# check that correct signature is returned
|
||||
key_id = signer.get_operational_key().get('keyid')
|
||||
signature = gpg.sign(message=digest, passphrase=load_config.get('KEYS_PASSPHRASE'), keyid=key_id)
|
||||
assert str(signature) == signer.sign_digest(data=person_metadata)
|
||||
|
||||
# remove tmp gpg file
|
||||
shutil.rmtree(Signer.gpg_path)
|
||||
|
||||
|
||||
|
||||
123
apps/cic-ussd/tests/cic_ussd/metadata/test_user_metadata.py
Normal file
123
apps/cic-ussd/tests/cic_ussd/metadata/test_user_metadata.py
Normal file
@@ -0,0 +1,123 @@
|
||||
# standard imports
|
||||
import json
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
import requests_mock
|
||||
from cic_types.models.person import generate_metadata_pointer
|
||||
|
||||
# local imports
|
||||
from cic_ussd.metadata import blockchain_address_to_metadata_pointer
|
||||
from cic_ussd.metadata.signer import Signer
|
||||
from cic_ussd.metadata.user import UserMetadata
|
||||
from cic_ussd.redis import get_cached_data
|
||||
|
||||
|
||||
def test_user_metadata(create_activated_user, define_metadata_pointer_url, load_config):
|
||||
UserMetadata.base_url = load_config.get('CIC_META_URL')
|
||||
identifier = blockchain_address_to_metadata_pointer(blockchain_address=create_activated_user.blockchain_address)
|
||||
user_metadata_client = UserMetadata(identifier=identifier)
|
||||
|
||||
assert user_metadata_client.url == define_metadata_pointer_url
|
||||
|
||||
|
||||
def test_create_user_metadata(caplog,
|
||||
create_activated_user,
|
||||
define_metadata_pointer_url,
|
||||
load_config,
|
||||
mock_meta_post_response,
|
||||
person_metadata):
|
||||
identifier = blockchain_address_to_metadata_pointer(blockchain_address=create_activated_user.blockchain_address)
|
||||
user_metadata_client = UserMetadata(identifier=identifier)
|
||||
|
||||
with requests_mock.Mocker(real_http=False) as request_mocker:
|
||||
request_mocker.register_uri(
|
||||
'POST',
|
||||
define_metadata_pointer_url,
|
||||
status_code=201,
|
||||
reason='CREATED',
|
||||
content=json.dumps(mock_meta_post_response).encode('utf-8')
|
||||
)
|
||||
user_metadata_client.create(data=person_metadata)
|
||||
assert 'Get signed material response status: 201' in caplog.text
|
||||
|
||||
with pytest.raises(RuntimeError) as error:
|
||||
with requests_mock.Mocker(real_http=False) as request_mocker:
|
||||
request_mocker.register_uri(
|
||||
'POST',
|
||||
define_metadata_pointer_url,
|
||||
status_code=400,
|
||||
reason='BAD REQUEST'
|
||||
)
|
||||
user_metadata_client.create(data=person_metadata)
|
||||
assert str(error.value) == f'400 Client Error: BAD REQUEST for url: {define_metadata_pointer_url}'
|
||||
|
||||
|
||||
def test_edit_user_metadata(caplog,
|
||||
create_activated_user,
|
||||
define_metadata_pointer_url,
|
||||
load_config,
|
||||
person_metadata,
|
||||
setup_metadata_signer):
|
||||
Signer.gpg_passphrase = load_config.get('KEYS_PASSPHRASE')
|
||||
identifier = blockchain_address_to_metadata_pointer(blockchain_address=create_activated_user.blockchain_address)
|
||||
user_metadata_client = UserMetadata(identifier=identifier)
|
||||
with requests_mock.Mocker(real_http=False) as request_mocker:
|
||||
request_mocker.register_uri(
|
||||
'PUT',
|
||||
define_metadata_pointer_url,
|
||||
status_code=200,
|
||||
reason='OK'
|
||||
)
|
||||
user_metadata_client.edit(data=person_metadata, engine='pgp')
|
||||
assert 'Signed content submission status: 200' in caplog.text
|
||||
|
||||
with pytest.raises(RuntimeError) as error:
|
||||
with requests_mock.Mocker(real_http=False) as request_mocker:
|
||||
request_mocker.register_uri(
|
||||
'PUT',
|
||||
define_metadata_pointer_url,
|
||||
status_code=400,
|
||||
reason='BAD REQUEST'
|
||||
)
|
||||
user_metadata_client.edit(data=person_metadata, engine='pgp')
|
||||
assert str(error.value) == f'400 Client Error: BAD REQUEST for url: {define_metadata_pointer_url}'
|
||||
|
||||
|
||||
def test_get_user_metadata(caplog,
|
||||
create_activated_user,
|
||||
define_metadata_pointer_url,
|
||||
init_redis_cache,
|
||||
load_config,
|
||||
person_metadata,
|
||||
setup_metadata_signer):
|
||||
identifier = blockchain_address_to_metadata_pointer(blockchain_address=create_activated_user.blockchain_address)
|
||||
user_metadata_client = UserMetadata(identifier=identifier)
|
||||
with requests_mock.Mocker(real_http=False) as request_mocker:
|
||||
request_mocker.register_uri(
|
||||
'GET',
|
||||
define_metadata_pointer_url,
|
||||
status_code=200,
|
||||
content=json.dumps(person_metadata).encode('utf-8'),
|
||||
reason='OK'
|
||||
)
|
||||
user_metadata_client.query()
|
||||
assert 'Get latest data status: 200' in caplog.text
|
||||
key = generate_metadata_pointer(
|
||||
identifier=identifier,
|
||||
cic_type='cic.person'
|
||||
)
|
||||
cached_user_metadata = get_cached_data(key=key)
|
||||
assert cached_user_metadata
|
||||
|
||||
with pytest.raises(RuntimeError) as error:
|
||||
with requests_mock.Mocker(real_http=False) as request_mocker:
|
||||
request_mocker.register_uri(
|
||||
'GET',
|
||||
define_metadata_pointer_url,
|
||||
status_code=404,
|
||||
reason='NOT FOUND'
|
||||
)
|
||||
user_metadata_client.query()
|
||||
assert 'The data is not available and might need to be added.' in caplog.text
|
||||
assert str(error.value) == f'400 Client Error: NOT FOUND for url: {define_metadata_pointer_url}'
|
||||
@@ -5,7 +5,6 @@ import json
|
||||
import pytest
|
||||
|
||||
# local imports
|
||||
from cic_ussd.state_machine import UssdStateMachine
|
||||
from cic_ussd.state_machine.logic.transaction import (has_sufficient_balance,
|
||||
is_valid_recipient,
|
||||
is_valid_transaction_amount,
|
||||
@@ -100,8 +99,8 @@ def test_process_transaction_request(create_valid_tx_recipient,
|
||||
create_valid_tx_sender,
|
||||
load_config,
|
||||
mock_outgoing_transactions,
|
||||
setup_chain_spec,
|
||||
ussd_session_data):
|
||||
UssdStateMachine.chain_str = load_config.get('CIC_CHAIN_SPEC')
|
||||
ussd_session_data['session_data'] = {
|
||||
'recipient_phone_number': create_valid_tx_recipient.phone_number,
|
||||
'transaction_amount': '50'
|
||||
@@ -0,0 +1,155 @@
|
||||
# standard imports
|
||||
import json
|
||||
|
||||
# third-party-imports
|
||||
import pytest
|
||||
|
||||
# local imports
|
||||
from cic_ussd.chain import Chain
|
||||
from cic_ussd.redis import InMemoryStore
|
||||
from cic_ussd.state_machine.logic.user import (
|
||||
change_preferred_language_to_en,
|
||||
change_preferred_language_to_sw,
|
||||
edit_user_metadata_attribute,
|
||||
format_user_metadata,
|
||||
get_user_metadata,
|
||||
save_complete_user_metadata,
|
||||
process_gender_user_input,
|
||||
save_profile_attribute_to_session_data,
|
||||
update_account_status_to_active)
|
||||
|
||||
|
||||
def test_change_preferred_language(create_pending_user, create_in_db_ussd_session):
|
||||
state_machine_data = ('', create_in_db_ussd_session, create_pending_user)
|
||||
assert create_pending_user.preferred_language is None
|
||||
change_preferred_language_to_en(state_machine_data)
|
||||
assert create_pending_user.preferred_language == 'en'
|
||||
change_preferred_language_to_sw(state_machine_data)
|
||||
assert create_pending_user.preferred_language == 'sw'
|
||||
|
||||
|
||||
def test_update_account_status_to_active(create_pending_user, create_in_db_ussd_session):
|
||||
state_machine_data = ('', create_in_db_ussd_session, create_pending_user)
|
||||
update_account_status_to_active(state_machine_data)
|
||||
assert create_pending_user.get_account_status() == 'ACTIVE'
|
||||
|
||||
|
||||
@pytest.mark.parametrize("current_state, expected_key, expected_result, user_input", [
|
||||
("enter_given_name", "given_name", "John", "John"),
|
||||
("enter_family_name", "family_name", "Doe", "Doe"),
|
||||
("enter_gender", "gender", "Male", "1"),
|
||||
("enter_location", "location", "Kangemi", "Kangemi"),
|
||||
("enter_products", "products", "Mandazi", "Mandazi"),
|
||||
])
|
||||
def test_save_save_profile_attribute_to_session_data(current_state,
|
||||
expected_key,
|
||||
expected_result,
|
||||
user_input,
|
||||
celery_session_worker,
|
||||
create_activated_user,
|
||||
create_in_db_ussd_session,
|
||||
create_in_redis_ussd_session):
|
||||
create_in_db_ussd_session.state = current_state
|
||||
serialized_in_db_ussd_session = create_in_db_ussd_session.to_json()
|
||||
state_machine_data = (user_input, serialized_in_db_ussd_session, create_activated_user)
|
||||
in_memory_ussd_session = InMemoryStore.cache.get('AT974186')
|
||||
in_memory_ussd_session = json.loads(in_memory_ussd_session)
|
||||
assert in_memory_ussd_session.get('session_data') == {}
|
||||
serialized_in_db_ussd_session['state'] = current_state
|
||||
save_profile_attribute_to_session_data(state_machine_data=state_machine_data)
|
||||
|
||||
in_memory_ussd_session = InMemoryStore.cache.get('AT974186')
|
||||
in_memory_ussd_session = json.loads(in_memory_ussd_session)
|
||||
|
||||
assert in_memory_ussd_session.get('session_data')[expected_key] == expected_result
|
||||
|
||||
|
||||
@pytest.mark.parametrize("preferred_language, user_input, expected_gender_value", [
|
||||
("en", "1", "Male"),
|
||||
("en", "2", "Female"),
|
||||
("sw", "1", "Mwanaume"),
|
||||
("sw", "2", "Mwanamke"),
|
||||
])
|
||||
def test_process_gender_user_input(create_activated_user, expected_gender_value, preferred_language, user_input):
|
||||
create_activated_user.preferred_language = preferred_language
|
||||
gender = process_gender_user_input(user=create_activated_user, user_input=user_input)
|
||||
assert gender == expected_gender_value
|
||||
|
||||
|
||||
def test_format_user_metadata(create_activated_user,
|
||||
complete_user_metadata,
|
||||
setup_chain_spec):
|
||||
from cic_types.models.person import Person
|
||||
formatted_user_metadata = format_user_metadata(metadata=complete_user_metadata, user=create_activated_user)
|
||||
person = Person()
|
||||
user_metadata = person.deserialize(metadata=formatted_user_metadata)
|
||||
assert formatted_user_metadata == user_metadata.serialize()
|
||||
|
||||
|
||||
def test_save_complete_user_metadata(celery_session_worker,
|
||||
complete_user_metadata,
|
||||
create_activated_user,
|
||||
create_in_redis_ussd_session,
|
||||
mocker,
|
||||
setup_chain_spec,
|
||||
ussd_session_data):
|
||||
ussd_session = create_in_redis_ussd_session.get(ussd_session_data.get('external_session_id'))
|
||||
ussd_session = json.loads(ussd_session)
|
||||
ussd_session['session_data'] = complete_user_metadata
|
||||
user_metadata = format_user_metadata(metadata=ussd_session.get('session_data'), user=create_activated_user)
|
||||
state_machine_data = ('', ussd_session, create_activated_user)
|
||||
mocked_create_metadata_task = mocker.patch('cic_ussd.tasks.metadata.create_user_metadata.apply_async')
|
||||
save_complete_user_metadata(state_machine_data=state_machine_data)
|
||||
mocked_create_metadata_task.assert_called_with(
|
||||
(user_metadata, create_activated_user.blockchain_address),
|
||||
{},
|
||||
queue='cic-ussd'
|
||||
)
|
||||
|
||||
|
||||
def test_edit_user_metadata_attribute(celery_session_worker,
|
||||
cached_user_metadata,
|
||||
create_activated_user,
|
||||
create_in_redis_ussd_session,
|
||||
init_redis_cache,
|
||||
mocker,
|
||||
person_metadata,
|
||||
setup_chain_spec,
|
||||
ussd_session_data):
|
||||
ussd_session = create_in_redis_ussd_session.get(ussd_session_data.get('external_session_id'))
|
||||
ussd_session = json.loads(ussd_session)
|
||||
|
||||
assert person_metadata['location']['area_name'] == 'kayaba'
|
||||
|
||||
# appropriately format session
|
||||
ussd_session['session_data'] = {
|
||||
'location': 'nairobi'
|
||||
}
|
||||
state_machine_data = ('', ussd_session, create_activated_user)
|
||||
|
||||
mocked_edit_metadata = mocker.patch('cic_ussd.tasks.metadata.edit_user_metadata.apply_async')
|
||||
edit_user_metadata_attribute(state_machine_data=state_machine_data)
|
||||
person_metadata['location']['area_name'] = 'nairobi'
|
||||
mocked_edit_metadata.assert_called_with(
|
||||
(create_activated_user.blockchain_address, person_metadata, Chain.spec.engine()),
|
||||
{},
|
||||
queue='cic-ussd'
|
||||
)
|
||||
|
||||
|
||||
def test_get_user_metadata_attribute(celery_session_worker,
|
||||
create_activated_user,
|
||||
create_in_redis_ussd_session,
|
||||
mocker,
|
||||
ussd_session_data):
|
||||
ussd_session = create_in_redis_ussd_session.get(ussd_session_data.get('external_session_id'))
|
||||
ussd_session = json.loads(ussd_session)
|
||||
state_machine_data = ('', ussd_session, create_activated_user)
|
||||
|
||||
mocked_get_metadata = mocker.patch('cic_ussd.tasks.metadata.query_user_metadata.apply_async')
|
||||
get_user_metadata(state_machine_data=state_machine_data)
|
||||
mocked_get_metadata.assert_called_with(
|
||||
(create_activated_user.blockchain_address,),
|
||||
{},
|
||||
queue='cic-ussd'
|
||||
)
|
||||
@@ -0,0 +1,55 @@
|
||||
# standard imports
|
||||
import json
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
from cic_types.models.person import generate_metadata_pointer
|
||||
|
||||
# local imports
|
||||
from cic_ussd.metadata import blockchain_address_to_metadata_pointer
|
||||
from cic_ussd.redis import cache_data
|
||||
from cic_ussd.state_machine.logic.validator import (is_valid_name,
|
||||
is_valid_gender_selection,
|
||||
has_cached_user_metadata)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("user_input, expected_result", [
|
||||
("Arya", True),
|
||||
("1234", False)
|
||||
])
|
||||
def test_is_valid_name(create_in_db_ussd_session, create_pending_user, user_input, expected_result):
|
||||
serialized_in_db_ussd_session = create_in_db_ussd_session.to_json()
|
||||
state_machine_data = (user_input, serialized_in_db_ussd_session, create_pending_user)
|
||||
result = is_valid_name(state_machine_data=state_machine_data)
|
||||
assert result is expected_result
|
||||
|
||||
|
||||
def test_has_cached_user_metadata(create_in_db_ussd_session,
|
||||
create_activated_user,
|
||||
init_redis_cache,
|
||||
person_metadata):
|
||||
serialized_in_db_ussd_session = create_in_db_ussd_session.to_json()
|
||||
state_machine_data = ('', serialized_in_db_ussd_session, create_activated_user)
|
||||
result = has_cached_user_metadata(state_machine_data=state_machine_data)
|
||||
assert result is False
|
||||
# cache metadata
|
||||
user = create_activated_user
|
||||
key = generate_metadata_pointer(
|
||||
identifier=blockchain_address_to_metadata_pointer(blockchain_address=user.blockchain_address),
|
||||
cic_type='cic.person'
|
||||
)
|
||||
cache_data(key=key, data=json.dumps(person_metadata))
|
||||
result = has_cached_user_metadata(state_machine_data=state_machine_data)
|
||||
assert result
|
||||
|
||||
|
||||
@pytest.mark.parametrize("user_input, expected_result", [
|
||||
("1", True),
|
||||
("2", True),
|
||||
("3", False)
|
||||
])
|
||||
def test_is_valid_gender_selection(create_in_db_ussd_session, create_pending_user, user_input, expected_result):
|
||||
serialized_in_db_ussd_session = create_in_db_ussd_session.to_json()
|
||||
state_machine_data = (user_input, serialized_in_db_ussd_session, create_pending_user)
|
||||
result = is_valid_gender_selection(state_machine_data=state_machine_data)
|
||||
assert result is expected_result
|
||||
@@ -10,7 +10,7 @@ import pytest
|
||||
# local imports
|
||||
from cic_ussd.db.models.user import User
|
||||
from cic_ussd.error import ActionDataNotFoundError
|
||||
from cic_ussd.transactions import from_wei
|
||||
from cic_ussd.conversions import from_wei
|
||||
|
||||
logg = logging.getLogger()
|
||||
|
||||
@@ -155,6 +155,7 @@ def test_unsuccessful_incoming_transaction_recipient_not_found(celery_session_wo
|
||||
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')
|
||||
@@ -15,7 +15,7 @@ def test_persist_session_to_db_task(
|
||||
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.persist_session_to_db',
|
||||
'cic_ussd.tasks.ussd_session.persist_session_to_db',
|
||||
[external_session_id]
|
||||
)
|
||||
result = s_persist_session_to_db.apply_async()
|
||||
@@ -38,7 +38,7 @@ def test_session_not_found_error(
|
||||
with pytest.raises(SessionNotFoundError) as error:
|
||||
external_session_id = 'SomeRandomValue'
|
||||
s_persist_session_to_db = celery.signature(
|
||||
'cic_ussd.tasks.ussd.persist_session_to_db',
|
||||
'cic_ussd.tasks.ussd_session.persist_session_to_db',
|
||||
[external_session_id]
|
||||
)
|
||||
result = s_persist_session_to_db.apply_async()
|
||||
20
apps/cic-ussd/tests/cic_ussd/test_accounts.py
Normal file
20
apps/cic-ussd/tests/cic_ussd/test_accounts.py
Normal file
@@ -0,0 +1,20 @@
|
||||
# standard imports
|
||||
|
||||
# third-party imports
|
||||
|
||||
# local imports
|
||||
from cic_ussd.balance import BalanceManager
|
||||
from cic_ussd.chain import Chain
|
||||
|
||||
|
||||
def test_balance_manager(create_valid_tx_recipient, load_config, mocker, setup_chain_spec):
|
||||
chain_str = Chain.spec.__str__()
|
||||
balance_manager = BalanceManager(
|
||||
address=create_valid_tx_recipient.blockchain_address,
|
||||
chain_str=chain_str,
|
||||
token_symbol='SRF'
|
||||
)
|
||||
balance_manager.get_balances = mocker.MagicMock()
|
||||
balance_manager.get_balances()
|
||||
|
||||
balance_manager.get_balances.assert_called_once()
|
||||
@@ -18,6 +18,7 @@ def test_send_sms_notification(celery_session_worker,
|
||||
recipient,
|
||||
set_locale_files,
|
||||
mock_notifier_api):
|
||||
|
||||
notifier = Notifier()
|
||||
notifier.queue = None
|
||||
|
||||
@@ -27,3 +28,9 @@ def test_send_sms_notification(celery_session_worker,
|
||||
assert messages[0].get('message') == expected_message
|
||||
assert messages[0].get('recipient') == recipient
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import uuid
|
||||
import pytest
|
||||
|
||||
# local imports
|
||||
from cic_ussd.chain import Chain
|
||||
from cic_ussd.db.models.task_tracker import TaskTracker
|
||||
from cic_ussd.menu.ussd_menu import UssdMenu
|
||||
from cic_ussd.operations import (add_tasks_to_tracker,
|
||||
@@ -17,13 +18,12 @@ from cic_ussd.operations import (add_tasks_to_tracker,
|
||||
get_latest_input,
|
||||
initiate_account_creation_request,
|
||||
process_current_menu,
|
||||
process_phone_number,
|
||||
process_menu_interaction_requests,
|
||||
cache_account_creation_task_id,
|
||||
get_user_by_phone_number,
|
||||
reset_pin,
|
||||
update_ussd_session,
|
||||
save_to_in_memory_ussd_session_data)
|
||||
from cic_ussd.phone_number import get_user_by_phone_number,process_phone_number
|
||||
from cic_ussd.transactions import truncate
|
||||
from cic_ussd.redis import InMemoryStore
|
||||
from cic_ussd.session.ussd_session import UssdSession as InMemoryUssdSession
|
||||
@@ -99,6 +99,7 @@ def test_initiate_account_creation_request(account_creation_action_data,
|
||||
load_config,
|
||||
load_ussd_menu,
|
||||
mocker,
|
||||
setup_chain_spec,
|
||||
set_locale_files,
|
||||
ussd_session_data):
|
||||
external_session_id = ussd_session_data.get('external_session_id')
|
||||
@@ -112,7 +113,8 @@ def test_initiate_account_creation_request(account_creation_action_data,
|
||||
mocked_cache_function = mocker.patch('cic_ussd.operations.cache_account_creation_task_id')
|
||||
mocked_cache_function(phone_number, task_id)
|
||||
|
||||
response = initiate_account_creation_request(chain_str=load_config.get('CIC_CHAIN_SPEC'),
|
||||
chain_str = Chain.spec.__str__()
|
||||
response = initiate_account_creation_request(chain_str=chain_str,
|
||||
external_session_id=external_session_id,
|
||||
phone_number=ussd_session_data.get('msisdn'),
|
||||
service_code=ussd_session_data.get('service_code'),
|
||||
@@ -204,11 +206,13 @@ def test_process_menu_interaction_requests(external_session_id,
|
||||
load_ussd_menu,
|
||||
load_data_into_state_machine,
|
||||
load_config,
|
||||
setup_chain_spec,
|
||||
celery_session_worker,
|
||||
create_activated_user,
|
||||
create_in_db_ussd_session):
|
||||
chain_str = Chain.spec.__str__()
|
||||
response = process_menu_interaction_requests(
|
||||
chain_str=load_config.get('CIC_CHAIN_SPEC'),
|
||||
chain_str=chain_str,
|
||||
external_session_id=external_session_id,
|
||||
phone_number=phone_number,
|
||||
queue='cic-ussd',
|
||||
@@ -12,7 +12,7 @@ from cic_ussd.processor import (custom_display_text,
|
||||
def test_process_pin_authorization(create_activated_user,
|
||||
load_ussd_menu,
|
||||
set_locale_files):
|
||||
ussd_menu = UssdMenu.find_by_name(name='name_management_pin_authorization')
|
||||
ussd_menu = UssdMenu.find_by_name(name='standard_pin_authorization')
|
||||
response = process_pin_authorization(
|
||||
display_key=ussd_menu.get('display_key'),
|
||||
user=create_activated_user
|
||||
@@ -4,6 +4,7 @@
|
||||
import pytest
|
||||
|
||||
# local imports
|
||||
from cic_ussd.chain import Chain
|
||||
from cic_ussd.transactions import OutgoingTransactionProcessor, truncate
|
||||
|
||||
|
||||
@@ -11,8 +12,9 @@ def test_outgoing_transaction_processor(load_config,
|
||||
create_valid_tx_recipient,
|
||||
create_valid_tx_sender,
|
||||
mock_outgoing_transactions):
|
||||
chain_str = Chain.spec.__str__()
|
||||
outgoing_tx_processor = OutgoingTransactionProcessor(
|
||||
chain_str=load_config.get('CIC_CHAIN_SPEC'),
|
||||
chain_str=chain_str,
|
||||
from_address=create_valid_tx_sender.blockchain_address,
|
||||
to_address=create_valid_tx_recipient.blockchain_address
|
||||
)
|
||||
@@ -1,3 +1,7 @@
|
||||
# third-party imports
|
||||
from cic_types.pytest import *
|
||||
|
||||
|
||||
# local imports
|
||||
from tests.fixtures.config import *
|
||||
from tests.fixtures.db import *
|
||||
@@ -8,41 +12,3 @@ from tests.fixtures.redis import *
|
||||
from tests.fixtures.callback import *
|
||||
from tests.fixtures.requests import *
|
||||
from tests.fixtures.mocks import *
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
3
apps/cic-ussd/tests/fixtures/celery.py
vendored
3
apps/cic-ussd/tests/fixtures/celery.py
vendored
@@ -12,7 +12,8 @@ def celery_includes():
|
||||
return [
|
||||
'cic_ussd.tasks.ussd',
|
||||
'cic_ussd.tasks.callback_handler',
|
||||
'cic_notify.tasks.sms'
|
||||
'cic_notify.tasks.sms',
|
||||
'cic_ussd.tasks.metadata'
|
||||
]
|
||||
|
||||
|
||||
|
||||
34
apps/cic-ussd/tests/fixtures/config.py
vendored
34
apps/cic-ussd/tests/fixtures/config.py
vendored
@@ -2,18 +2,24 @@
|
||||
import i18n
|
||||
import logging
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
# third party imports
|
||||
import pytest
|
||||
from chainlib.chain import ChainSpec
|
||||
from confini import Config
|
||||
from sqlalchemy import create_engine
|
||||
|
||||
# local imports
|
||||
from cic_ussd.chain import Chain
|
||||
from cic_ussd.db import dsn_from_config
|
||||
from cic_ussd.encoder import PasswordEncoder
|
||||
from cic_ussd.files.local_files import create_local_file_data_stores, json_file_parser
|
||||
from cic_ussd.menu.ussd_menu import UssdMenu
|
||||
from cic_ussd.metadata import blockchain_address_to_metadata_pointer
|
||||
from cic_ussd.metadata.signer import Signer
|
||||
from cic_ussd.metadata.user import UserMetadata
|
||||
from cic_ussd.state_machine import UssdStateMachine
|
||||
from cic_ussd.encoder import PasswordEncoder
|
||||
|
||||
|
||||
logg = logging.getLogger()
|
||||
@@ -102,3 +108,29 @@ def uwsgi_env():
|
||||
'uwsgi.node': b'mango-habanero'
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def setup_metadata_signer(load_config):
|
||||
temp_dir = tempfile.mkdtemp(dir='/tmp')
|
||||
logg.debug(f'Created temp dir: {temp_dir}')
|
||||
Signer.gpg_path = temp_dir
|
||||
Signer.key_file_path = load_config.get('KEYS_PRIVATE')
|
||||
Signer.gpg_passphrase = load_config.get('KEYS_PASSPHRASE')
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def define_metadata_pointer_url(load_config, create_activated_user):
|
||||
identifier = blockchain_address_to_metadata_pointer(blockchain_address=create_activated_user.blockchain_address)
|
||||
UserMetadata.base_url = load_config.get('CIC_META_URL')
|
||||
user_metadata_client = UserMetadata(identifier=identifier)
|
||||
return user_metadata_client.url
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def setup_chain_spec(load_config):
|
||||
chain_spec = ChainSpec(
|
||||
common_name=load_config.get('CIC_COMMON_NAME'),
|
||||
engine=load_config.get('CIC_ENGINE'),
|
||||
network_id=load_config.get('CIC_NETWORK_ID')
|
||||
)
|
||||
Chain.spec = chain_spec
|
||||
|
||||
48
apps/cic-ussd/tests/fixtures/mocks.py
vendored
48
apps/cic-ussd/tests/fixtures/mocks.py
vendored
@@ -1,4 +1,6 @@
|
||||
# standard imports
|
||||
import json
|
||||
from io import StringIO
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
@@ -8,7 +10,49 @@ from cic_ussd.translation import translation_for
|
||||
from cic_ussd.transactions import truncate
|
||||
|
||||
|
||||
@pytest.fixture(scope='function', autouse=True)
|
||||
@pytest.fixture(scope='function')
|
||||
def mock_meta_post_response():
|
||||
return {
|
||||
'name': 'cic',
|
||||
'version': '1',
|
||||
'ext': {
|
||||
'network': {
|
||||
'name': 'pgp',
|
||||
'version': '2'
|
||||
},
|
||||
'engine': {
|
||||
'name': 'automerge',
|
||||
'version': '0.14.1'
|
||||
}
|
||||
},
|
||||
'payload': '["~#iL",[["~#iM",["ops",["^0",[["^1",["action","set","obj","00000000-0000-0000-0000-000000000000",'
|
||||
'"key","id","value","7e2f58335a69ac82f9a965a8fc35403c8585ea601946d858ee97684a285bf857"]],["^1",'
|
||||
'["action","set","obj","00000000-0000-0000-0000-000000000000","key","timestamp","value",'
|
||||
'1613487781]], '
|
||||
'["^1",["action","set","obj","00000000-0000-0000-0000-000000000000","key","data","value",'
|
||||
'"{\\"foo\\": '
|
||||
'\\"bar\\", \\"xyzzy\\": 42}"]]]],"actor","2b738a75-2aad-4ac8-ae8d-294a5ea4afad","seq",1,"deps",'
|
||||
'["^1", '
|
||||
'[]],"message","Initialization","undoable",false]],["^1",["ops",["^0",[["^1",["action","makeMap",'
|
||||
'"obj","a921a5ae-0554-497a-ac2e-4e829d8a12b6"]],["^1",["action","set","obj",'
|
||||
'"a921a5ae-0554-497a-ac2e-4e829d8a12b6","key","digest","value","W10="]],["^1",["action","link",'
|
||||
'"obj", '
|
||||
'"00000000-0000-0000-0000-000000000000","key","signature","value",'
|
||||
'"a921a5ae-0554-497a-ac2e-4e829d8a12b6"]]]],"actor","2b738a75-2aad-4ac8-ae8d-294a5ea4afad","seq",2,'
|
||||
'"deps",["^1",[]],"message","sign"]]]]',
|
||||
'digest': 'W10='
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def mock_meta_get_response():
|
||||
return {
|
||||
"foo": "bar",
|
||||
"xyzzy": 42
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def mock_notifier_api(mocker):
|
||||
messages = []
|
||||
|
||||
@@ -43,7 +87,7 @@ def mock_outgoing_transactions(mocker):
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def mock_balance(mocker):
|
||||
mocked_operational_balance = mocker.patch('cic_ussd.accounts.BalanceManager.get_operational_balance')
|
||||
mocked_operational_balance = mocker.patch('cic_ussd.accounts.BalanceManager.get_balances')
|
||||
|
||||
def _mock_operational_balance(balance: int):
|
||||
mocked_operational_balance.return_value = truncate(value=balance, decimals=2)
|
||||
|
||||
28
apps/cic-ussd/tests/fixtures/user.py
vendored
28
apps/cic-ussd/tests/fixtures/user.py
vendored
@@ -1,13 +1,17 @@
|
||||
# standard imports
|
||||
from random import randint
|
||||
import json
|
||||
import uuid
|
||||
from random import randint
|
||||
|
||||
# third party imports
|
||||
import pytest
|
||||
from cic_types.models.person import generate_metadata_pointer
|
||||
from faker import Faker
|
||||
|
||||
# local imports
|
||||
from cic_ussd.db.models.user import AccountStatus, User
|
||||
from cic_ussd.redis import cache_data
|
||||
from cic_ussd.metadata import blockchain_address_to_metadata_pointer
|
||||
|
||||
|
||||
fake = Faker()
|
||||
@@ -92,3 +96,25 @@ def create_locked_accounts(init_database, set_fernet_key):
|
||||
user.account_status = AccountStatus.LOCKED.value
|
||||
user.session.add(user)
|
||||
user.session.commit()
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def complete_user_metadata(create_activated_user):
|
||||
return {
|
||||
"date_registered": create_activated_user.created,
|
||||
"family_name": "Snow",
|
||||
"given_name": "Name",
|
||||
"gender": 'Male',
|
||||
"location": "Kangemi",
|
||||
"products": "Mandazi"
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope='function')
|
||||
def cached_user_metadata(create_activated_user, init_redis_cache, person_metadata):
|
||||
user_metadata = json.dumps(person_metadata)
|
||||
key = generate_metadata_pointer(
|
||||
identifier=blockchain_address_to_metadata_pointer(blockchain_address=create_activated_user.blockchain_address),
|
||||
cic_type='cic.person'
|
||||
)
|
||||
cache_data(key=key, data=user_metadata)
|
||||
|
||||
@@ -1,57 +0,0 @@
|
||||
# standard imports
|
||||
import json
|
||||
|
||||
# third-party-imports
|
||||
import pytest
|
||||
|
||||
# local imports
|
||||
from cic_ussd.redis import InMemoryStore
|
||||
from cic_ussd.state_machine.logic.user import (
|
||||
change_preferred_language_to_en,
|
||||
change_preferred_language_to_sw,
|
||||
save_profile_attribute_to_session_data,
|
||||
update_account_status_to_active)
|
||||
|
||||
|
||||
def test_change_preferred_language(create_pending_user, create_in_db_ussd_session):
|
||||
state_machine_data = ('', create_in_db_ussd_session, create_pending_user)
|
||||
assert create_pending_user.preferred_language is None
|
||||
change_preferred_language_to_en(state_machine_data)
|
||||
assert create_pending_user.preferred_language == 'en'
|
||||
change_preferred_language_to_sw(state_machine_data)
|
||||
assert create_pending_user.preferred_language == 'sw'
|
||||
|
||||
|
||||
def test_update_account_status_to_active(create_pending_user, create_in_db_ussd_session):
|
||||
state_machine_data = ('', create_in_db_ussd_session, create_pending_user)
|
||||
update_account_status_to_active(state_machine_data)
|
||||
assert create_pending_user.get_account_status() == 'ACTIVE'
|
||||
|
||||
|
||||
@pytest.mark.parametrize("current_state, expected_key, expected_result, user_input", [
|
||||
("enter_first_name", "first_name", "John", "John"),
|
||||
("enter_last_name", "last_name", "Doe", "Doe"),
|
||||
("enter_location", "location", "Kangemi", "Kangemi"),
|
||||
("enter_business_profile", "business_profile", "Mandazi", "Mandazi")
|
||||
])
|
||||
def test_save_profile_attribute_to_session_data(current_state,
|
||||
expected_key,
|
||||
expected_result,
|
||||
user_input,
|
||||
celery_session_worker,
|
||||
create_activated_user,
|
||||
create_in_db_ussd_session,
|
||||
create_in_redis_ussd_session):
|
||||
create_in_db_ussd_session.state = current_state
|
||||
serialized_in_db_ussd_session = create_in_db_ussd_session.to_json()
|
||||
state_machine_data = (user_input, serialized_in_db_ussd_session, create_activated_user)
|
||||
in_memory_ussd_session = InMemoryStore.cache.get('AT974186')
|
||||
in_memory_ussd_session = json.loads(in_memory_ussd_session)
|
||||
assert in_memory_ussd_session.get('session_data') == {}
|
||||
serialized_in_db_ussd_session['state'] = current_state
|
||||
save_profile_attribute_to_session_data(state_machine_data=state_machine_data)
|
||||
|
||||
in_memory_ussd_session = InMemoryStore.cache.get('AT974186')
|
||||
in_memory_ussd_session = json.loads(in_memory_ussd_session)
|
||||
|
||||
assert in_memory_ussd_session.get('session_data')[expected_key] == expected_result
|
||||
@@ -1,67 +0,0 @@
|
||||
# standard imports
|
||||
|
||||
# third-party imports
|
||||
import pytest
|
||||
|
||||
# local imports
|
||||
from cic_ussd.state_machine.logic.validator import (is_valid_name,
|
||||
has_complete_profile_data,
|
||||
has_empty_username_data,
|
||||
has_empty_gender_data,
|
||||
has_empty_location_data,
|
||||
has_empty_business_profile_data)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("user_input, expected_result", [
|
||||
("Arya", True),
|
||||
("1234", False)
|
||||
])
|
||||
def test_is_valid_name(create_in_db_ussd_session, create_pending_user, user_input, expected_result):
|
||||
serialized_in_db_ussd_session = create_in_db_ussd_session.to_json()
|
||||
state_machine_data = (user_input, serialized_in_db_ussd_session, create_pending_user)
|
||||
result = is_valid_name(state_machine_data=state_machine_data)
|
||||
assert result is expected_result
|
||||
|
||||
|
||||
def test_has_complete_profile_data(caplog,
|
||||
create_in_db_ussd_session,
|
||||
create_activated_user):
|
||||
serialized_in_db_ussd_session = create_in_db_ussd_session.to_json()
|
||||
state_machine_data = ('', serialized_in_db_ussd_session, create_activated_user)
|
||||
has_complete_profile_data(state_machine_data=state_machine_data)
|
||||
assert 'This section requires implementation of user metadata.' in caplog.text
|
||||
|
||||
|
||||
def test_has_empty_username_data(caplog,
|
||||
create_in_db_ussd_session,
|
||||
create_activated_user):
|
||||
state_machine_data = ('', create_in_db_ussd_session, create_activated_user)
|
||||
has_empty_username_data(state_machine_data=state_machine_data)
|
||||
assert 'This section requires implementation of user metadata.' in caplog.text
|
||||
|
||||
|
||||
def test_has_empty_gender_data(caplog,
|
||||
create_in_db_ussd_session,
|
||||
create_activated_user):
|
||||
serialized_in_db_ussd_session = create_in_db_ussd_session.to_json()
|
||||
state_machine_data = ('', serialized_in_db_ussd_session, create_activated_user)
|
||||
has_empty_gender_data(state_machine_data=state_machine_data)
|
||||
assert 'This section requires implementation of user metadata.' in caplog.text
|
||||
|
||||
|
||||
def test_has_empty_location_data(caplog,
|
||||
create_in_db_ussd_session,
|
||||
create_activated_user):
|
||||
serialized_in_db_ussd_session = create_in_db_ussd_session.to_json()
|
||||
state_machine_data = ('', serialized_in_db_ussd_session, create_activated_user)
|
||||
has_empty_location_data(state_machine_data=state_machine_data)
|
||||
assert 'This section requires implementation of user metadata.' in caplog.text
|
||||
|
||||
|
||||
def test_has_empty_business_profile_data(caplog,
|
||||
create_in_db_ussd_session,
|
||||
create_activated_user):
|
||||
serialized_in_db_ussd_session = create_in_db_ussd_session.to_json()
|
||||
state_machine_data = ('', serialized_in_db_ussd_session, create_activated_user)
|
||||
has_empty_business_profile_data(state_machine_data=state_machine_data)
|
||||
assert 'This section requires implementation of user metadata.' in caplog.text
|
||||
@@ -1,19 +0,0 @@
|
||||
# standard imports
|
||||
|
||||
# third-party imports
|
||||
|
||||
# local imports
|
||||
from cic_ussd.accounts import BalanceManager
|
||||
|
||||
|
||||
def test_balance_manager(mocker, load_config, create_valid_tx_recipient):
|
||||
|
||||
balance_manager = BalanceManager(
|
||||
address=create_valid_tx_recipient.blockchain_address,
|
||||
chain_str=load_config.get('CIC_CHAIN_SPEC'),
|
||||
token_symbol='SRF'
|
||||
)
|
||||
balance_manager.get_operational_balance = mocker.MagicMock()
|
||||
balance_manager.get_operational_balance()
|
||||
|
||||
balance_manager.get_operational_balance.assert_called_once()
|
||||
Reference in New Issue
Block a user