-
Notifications
You must be signed in to change notification settings - Fork 74
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #339 from bcgov/feature/334-unit-test-critical-cod…
…e-sections #334 Add unit tests for critical code sections [2.0]
- Loading branch information
Showing
13 changed files
with
643 additions
and
17 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
[run] | ||
omit = | ||
**/tests/* | ||
*test* | ||
*__init__* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
presentation_request_configuration = { | ||
'name': 'proof_requested', | ||
'version': '0.0.1', | ||
'requested_attributes': { | ||
'req_attr_0': { | ||
'names': ['email'], | ||
'restrictions': [ | ||
{'schema_name': 'verified-email', | ||
'issuer_did': 'MTYqmTBoLT7KLP5RNfgK3b'} | ||
], | ||
'non_revoked': { | ||
'from': 1695320203, 'to': 1695320203 | ||
} | ||
} | ||
}, | ||
'requested_predicates': {} | ||
} | ||
|
||
presentation_request = { | ||
'nonce': '136042354083201173353396', | ||
'name': 'proof_requested', | ||
'version': '0.0.1', | ||
'requested_attributes':{ | ||
'req_attr_0': { | ||
'non_revoked': {'from': 1695321803, 'to': 1695321803}, | ||
'restrictions': [{'schema_name': 'verified-email', 'issuer_did': 'MTYqmTBoLT7KLP5RNfgK3b'}], | ||
'names': ['email'] | ||
} | ||
}, | ||
'requested_predicates': {} | ||
} | ||
|
||
create_presentation_response_http = { | ||
'updated_at': '2023-09-21T18:43:23.470373Z', | ||
'role': 'verifier', | ||
'presentation_exchange_id': 'b2945790-79c4-4059-9f93-6bd43b2186f7', | ||
'created_at': '2023-09-21T18:43:23.470373Z', | ||
'trace': False, | ||
'thread_id': 'ab2e3f02-6e16-4e08-8165-5ddc7aad3090', | ||
'initiator': 'self', | ||
'state': 'request_sent', | ||
'presentation_request': presentation_request, | ||
'auto_verify': True, | ||
'presentation_request_dict': { | ||
'@type': 'did:sov:BzCbsNYhMrjHiqZDTUASHg;spec/present-proof/1.0/request-presentation', | ||
'@id': 'ab2e3f02-6e16-4e08-8165-5ddc7aad3090', | ||
'request_presentations~attach': [{'@id': 'libindy-request-presentation-0', 'mime-type': 'application/json', 'data': {'base64': 'eyJuYW1lIjogInByb29mX3JlcXVlc3RlZCIsICJ2ZXJzaW9uIjogIjAuMC4xIiwgInJlcXVlc3RlZF9hdHRyaWJ1dGVzIjogeyJyZXFfYXR0cl8wIjogeyJuYW1lcyI6IFsiZW1haWwiXSwgInJlc3RyaWN0aW9ucyI6IFt7InNjaGVtYV9uYW1lIjogInZlcmlmaWVkLWVtYWlsIiwgImlzc3Vlcl9kaWQiOiAiTVRZcW1UQm9MVDdLTFA1Uk5mZ0szYiJ9XSwgIm5vbl9yZXZva2VkIjogeyJmcm9tIjogMTY5NTMyMTgwMywgInRvIjogMTY5NTMyMTgwM319fSwgInJlcXVlc3RlZF9wcmVkaWNhdGVzIjoge30sICJub25jZSI6ICIxMzYwNDIzNTQwODMyMDExNzMzNTMzOTYifQ=='}}] | ||
}, | ||
'auto_present': False | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,216 @@ | ||
import json | ||
|
||
import mock | ||
import pytest | ||
from api.core.acapy.client import (CREATE_PRESENTATION_REQUEST_URL, | ||
PRESENT_PROOF_RECORDS, | ||
PUBLIC_WALLET_DID_URI, WALLET_DID_URI, | ||
AcapyClient) | ||
from api.core.acapy.config import MultiTenantAcapy, SingleTenantAcapy | ||
from api.core.acapy.models import CreatePresentationResponse, WalletDid | ||
from api.core.acapy.tests.__mocks__ import (create_presentation_response_http, | ||
presentation_request_configuration) | ||
from api.core.config import settings | ||
|
||
|
||
@pytest.mark.asyncio | ||
@mock.patch.object(settings, "ACAPY_TENANCY", None) | ||
async def test_init_no_setting_returns_client_with_single_tenancy_config(): | ||
client = AcapyClient() | ||
assert client is not None | ||
assert isinstance(client.agent_config, SingleTenantAcapy) is True | ||
|
||
|
||
@pytest.mark.asyncio | ||
@mock.patch.object(settings, "ACAPY_TENANCY", "single") | ||
async def test_init_single_returns_client_with_single_tenancy_config(): | ||
client = AcapyClient() | ||
assert client is not None | ||
assert isinstance(client.agent_config, SingleTenantAcapy) is True | ||
|
||
|
||
@pytest.mark.asyncio | ||
@mock.patch.object(settings, "ACAPY_TENANCY", "multi") | ||
async def test_init_multi_returns_client_with_multi_tenancy_config(): | ||
client = AcapyClient() | ||
assert client is not None | ||
assert isinstance(client.agent_config, MultiTenantAcapy) is True | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_create_presentation_returns_sucessfully_with_valid_data(requests_mock): | ||
requests_mock.post( | ||
settings.ACAPY_ADMIN_URL + CREATE_PRESENTATION_REQUEST_URL, | ||
headers={}, | ||
json=json.dumps(create_presentation_response_http), | ||
status_code=200, | ||
) | ||
|
||
with mock.patch.object(CreatePresentationResponse, "parse_obj", return_value={'result': 'success'}): | ||
client = AcapyClient() | ||
client.agent_config.get_headers = mock.MagicMock( | ||
return_value={'x-api-key': ''}) | ||
presentation_request = client.create_presentation_request( | ||
presentation_request_configuration) | ||
assert presentation_request is not None | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_create_presentation_throws_assertion_error_with_non_200_response_from_acapy(requests_mock): | ||
requests_mock.post( | ||
settings.ACAPY_ADMIN_URL + CREATE_PRESENTATION_REQUEST_URL, | ||
headers={}, | ||
json=json.dumps(create_presentation_response_http), | ||
status_code=400, | ||
) | ||
|
||
with mock.patch.object(CreatePresentationResponse, "parse_obj", return_value={'result': 'success'}): | ||
client = AcapyClient() | ||
client.agent_config.get_headers = mock.MagicMock( | ||
return_value={'x-api-key': ''}) | ||
try: | ||
presentation_request = client.create_presentation_request( | ||
presentation_request_configuration) | ||
assert presentation_request is not None | ||
except AssertionError as e: | ||
assert e is not None | ||
|
||
# TODO: determine if this function should assert a valid json response | ||
@pytest.mark.asyncio | ||
async def test_create_presentation_throws_error_with_non_json_from_acapy(requests_mock): | ||
requests_mock.post( | ||
settings.ACAPY_ADMIN_URL + CREATE_PRESENTATION_REQUEST_URL, | ||
headers={}, | ||
status_code=200, | ||
) | ||
|
||
with mock.patch.object(CreatePresentationResponse, "parse_obj", return_value={'result': 'success'}): | ||
client = AcapyClient() | ||
client.agent_config.get_headers = mock.MagicMock( | ||
return_value={'x-api-key': ''}) | ||
try: | ||
presentation_request = client.create_presentation_request( | ||
presentation_request_configuration) | ||
assert presentation_request is not None | ||
except json.JSONDecodeError as e: | ||
assert e is not None | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_get_presentation_returns_sucessfully_with_valid_data(requests_mock): | ||
requests_mock.get( | ||
settings.ACAPY_ADMIN_URL + PRESENT_PROOF_RECORDS + "/" + "1234-567890", | ||
headers={}, | ||
json={"result": "success"}, | ||
status_code=200, | ||
) | ||
|
||
client = AcapyClient() | ||
client.agent_config.get_headers = mock.MagicMock( | ||
return_value={'x-api-key': ''}) | ||
presentation = client.get_presentation_request("1234-567890") | ||
assert presentation is not None | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_get_presentation_throws_assertion_error_for_non_200_response_from_acapy(requests_mock): | ||
requests_mock.get( | ||
settings.ACAPY_ADMIN_URL + PRESENT_PROOF_RECORDS + "/" + "1234-567890", | ||
headers={}, | ||
json={"result": "success"}, | ||
status_code=400, | ||
) | ||
|
||
client = AcapyClient() | ||
client.agent_config.get_headers = mock.MagicMock( | ||
return_value={'x-api-key': ''}) | ||
try: | ||
client.get_presentation_request("1234-567890") | ||
except AssertionError as e: | ||
assert e is not None | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_verify_presentation_returns_sucessfully_with_valid_data(requests_mock): | ||
requests_mock.post( | ||
settings.ACAPY_ADMIN_URL + PRESENT_PROOF_RECORDS + | ||
"/" + "1234-567890" + "/verify-presentation", | ||
headers={}, | ||
json={"result": "success"}, | ||
status_code=200, | ||
) | ||
|
||
client = AcapyClient() | ||
client.agent_config.get_headers = mock.MagicMock( | ||
return_value={'x-api-key': ''}) | ||
verification = client.verify_presentation("1234-567890") | ||
assert verification is not None | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_verify_presentation_throws_assertion_error_for_non_200_response_from_acapy(requests_mock): | ||
requests_mock.post( | ||
settings.ACAPY_ADMIN_URL + PRESENT_PROOF_RECORDS + | ||
"/" + "1234-567890" + "/verify-presentation", | ||
headers={}, | ||
json={"result": "success"}, | ||
status_code=400, | ||
) | ||
|
||
client = AcapyClient() | ||
client.agent_config.get_headers = mock.MagicMock( | ||
return_value={'x-api-key': ''}) | ||
try: | ||
client.verify_presentation("1234-567890") | ||
except AssertionError as e: | ||
assert e is not None | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_get_wallet_did_public_returns_sucessfully_on_public_url_and_simple_resp(requests_mock): | ||
requests_mock.get( | ||
settings.ACAPY_ADMIN_URL + PUBLIC_WALLET_DID_URI, | ||
headers={}, | ||
json={"result": "success"}, | ||
status_code=200, | ||
) | ||
with mock.patch.object(WalletDid, "parse_obj", return_value={'result': 'success'}): | ||
client = AcapyClient() | ||
client.agent_config.get_headers = mock.MagicMock( | ||
return_value={'x-api-key': ''}) | ||
wallet_resp = client.get_wallet_did(public=True) | ||
assert wallet_resp is not None | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_get_wallet_did_public_throws_assertion_error_on_non_200_response(requests_mock): | ||
requests_mock.get( | ||
settings.ACAPY_ADMIN_URL + PUBLIC_WALLET_DID_URI, | ||
headers={}, | ||
json={"result": "success"}, | ||
status_code=400, | ||
) | ||
with mock.patch.object(WalletDid, "parse_obj", return_value={'result': 'success'}): | ||
client = AcapyClient() | ||
client.agent_config.get_headers = mock.MagicMock( | ||
return_value={'x-api-key': ''}) | ||
try: | ||
client.get_wallet_did(public=True) | ||
except AssertionError as e: | ||
assert e is not None | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_get_wallet_did_not_public_returns_sucessfully_on_correct_url_and_processes_array(requests_mock): | ||
requests_mock.get( | ||
settings.ACAPY_ADMIN_URL + WALLET_DID_URI, | ||
headers={}, | ||
json={"results": ["success"]}, | ||
status_code=200, | ||
) | ||
with mock.patch.object(WalletDid, "parse_obj", return_value={'result': 'success'}): | ||
client = AcapyClient() | ||
client.agent_config.get_headers = mock.MagicMock( | ||
return_value={'x-api-key': ''}) | ||
wallet_resp = client.get_wallet_did(public=False) | ||
assert wallet_resp is not None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import mock | ||
import pytest | ||
from api.core.acapy.config import MultiTenantAcapy, SingleTenantAcapy | ||
from api.core.config import settings | ||
|
||
|
||
@pytest.mark.asyncio | ||
@mock.patch.object(settings, "ST_ACAPY_ADMIN_API_KEY_NAME", 'name') | ||
@mock.patch.object(settings, "ST_ACAPY_ADMIN_API_KEY", 'key') | ||
async def test_single_tenant_has_expected_headers(): | ||
acapy = SingleTenantAcapy() | ||
headers = acapy.get_headers() | ||
assert headers == {'name': 'key'} | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_multi_tenant_get_headers_returns_bearer_token_auth(requests_mock): | ||
acapy = MultiTenantAcapy() | ||
acapy.get_wallet_token = mock.MagicMock(return_value='token') | ||
headers = acapy.get_headers() | ||
assert headers == {"Authorization": "Bearer token"} | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_multi_tenant_get_wallet_token_returns_token_at_token_key(requests_mock): | ||
requests_mock.post( | ||
settings.ACAPY_ADMIN_URL + "/multitenancy/wallet/wallet_id/token", | ||
headers={}, | ||
json={'token': 'token'}, | ||
status_code=200, | ||
) | ||
acapy = MultiTenantAcapy() | ||
acapy.wallet_id = 'wallet_id' | ||
token = acapy.get_wallet_token() | ||
assert token == 'token' | ||
|
||
|
||
@pytest.mark.asyncio | ||
async def test_multi_tenant_throws_assertion_error_for_non_200_response(requests_mock): | ||
requests_mock.post( | ||
settings.ACAPY_ADMIN_URL + "/multitenancy/wallet/wallet_id/token", | ||
headers={}, | ||
json={'token': 'token'}, | ||
status_code=400, | ||
) | ||
acapy = MultiTenantAcapy() | ||
acapy.wallet_id = 'wallet_id' | ||
try: | ||
acapy.get_wallet_token() | ||
except AssertionError as e: | ||
assert e is not None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.