Skip to content

Commit

Permalink
test: Add SDNClient tests
Browse files Browse the repository at this point in the history
  • Loading branch information
julianajlk committed Oct 31, 2023
1 parent 29b6b54 commit 5fe52b9
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 16 deletions.
8 changes: 4 additions & 4 deletions sanctions/apps/api/v1/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ def post(self, request):
full_name = payload.get('full_name')
city = payload.get('city')
country = payload.get('country')
sdn_list = payload.get('sdn_list', 'ISN,SDN') # Set SDN lists to a sane default
sdn_api_list = payload.get('sdn_api_list', 'ISN,SDN') # Set SDN lists to a sane default

sdn_check = SDNClient(
api_url=settings.SDN_CHECK_API_URL,
api_key=settings.SDN_CHECK_API_KEY,
sdn_list=sdn_list
sdn_api_url=settings.SDN_CHECK_API_URL,
sdn_api_key=settings.SDN_CHECK_API_KEY,
sdn_api_list=sdn_api_list
)

try:
Expand Down
24 changes: 12 additions & 12 deletions sanctions/apps/api_client/sdn_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@


class SDNClient:
"""A utility class that handles SDN related operations."""
"""API client that handles calls to the US Treasury SDN API."""

def __init__(self, api_url, api_key, sdn_list):
self.api_url = api_url
self.api_key = api_key
self.sdn_list = sdn_list
def __init__(self, sdn_api_url, sdn_api_key, sdn_api_list):
self.sdn_api_url = sdn_api_url
self.sdn_api_key = sdn_api_key
self.sdn_api_list = sdn_api_list

def search(self, lms_user_id, name, city, country):
"""
Expand All @@ -37,7 +37,7 @@ def search(self, lms_user_id, name, city, country):
dict: SDN API response.
"""
params_dict = {
'sources': self.sdn_list,
'sources': self.sdn_api_list,
'type': 'individual',
'name': str(name).encode('utf-8'),
# We are using the city as the address parameter value as indicated in the documentation:
Expand All @@ -47,14 +47,14 @@ def search(self, lms_user_id, name, city, country):
}
params = urlencode(params_dict)
sdn_check_url = '{api_url}?{params}'.format(
api_url=self.api_url,
api_url=self.sdn_api_url,
params=params
)
auth_header = {'subscription-key': '{}'.format(self.api_key)}
auth_header = {'subscription-key': '{}'.format(self.sdn_api_key)}

try:
logger.info(
'SactionsCheck: starting the request to the US Treasury SDN API for %s.',
'Sactions SDNCheck: starting the request to the US Treasury SDN API for %s.',
lms_user_id
)
response = requests.get(
Expand All @@ -64,17 +64,17 @@ def search(self, lms_user_id, name, city, country):
)
except requests.exceptions.Timeout:
logger.warning(
'SanctionsCheck: Connection to US Treasury SDN API timed out for [%s].',
'Sanctions SDNCheck: Connection to the US Treasury SDN API timed out for [%s].',
name
)
raise

if response.status_code != 200:
logger.warning(
'SanctionsCheck: Unable to connect to US Treasury SDN API for [%s].'
'Sanctions SDNCheck: Unable to connect to the US Treasury SDN API for [%s].'
'Status code [%d] with message: [%s]',
name, response.status_code, response.content
)
raise requests.exceptions.HTTPError('Unable to connect to SDN API')
raise requests.exceptions.HTTPError('Unable to connect to the SDN API')

return response.json()
93 changes: 93 additions & 0 deletions sanctions/apps/api_client/tests/test_sdn_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
"""
Tests for SDN API client.
"""
import json
from urllib.parse import urlencode

import mock
import responses
from django.test import TestCase
from requests.exceptions import HTTPError, Timeout

from sanctions.apps.api_client.sdn_client import SDNClient


class TestSDNClient(TestCase):
"""
Test SDN API client.
"""

def setUp(self):
super(TestSDNClient, self).setUp()
self.name = 'Dr. Evil'
self.city = 'Top-secret liar'
self.country = 'EL'
self.lms_user_id = 123
self.sdn_api_url = 'http://sdn-test.fake/'
self.sdn_api_key = 'fake-key'
self.sdn_api_list = 'SDN, ISN'

self.sdn_api_client = SDNClient(
self.sdn_api_url,
self.sdn_api_key,
self.sdn_api_list,
)

def mock_sdn_api_response(self, response, status_code=200):
""" Mock the US Treasury SDN API response. """
params_dict = {
'sources': self.sdn_api_list,
'type': 'individual',
'name': str(self.name).encode('utf-8'),
'city': str(self.city).encode('utf-8'),
'countries': self.country
}

params = urlencode(params_dict)
sdn_check_url = '{api_url}?{params}'.format(
api_url=self.sdn_api_url,
params=params
)
auth_header = {'subscription-key': '{}'.format(self.sdn_api_key)}

responses.add(
responses.GET,
sdn_check_url,
headers=auth_header,
status=status_code,
body=response() if callable(response) else response,
content_type='application/json'
)

@responses.activate
def test_sdn_search_timeout(self):
"""
Verify SDNClient search logs an exception if the request times out.
"""
self.mock_sdn_api_response(Timeout)
with self.assertRaises(Timeout):
with mock.patch('sanctions.apps.api_client.sdn_client.logger.exception') as mock_logger:
response = self.sdn_api_client.search(self.lms_user_id, self.name, self.city, self.country)
self.assertTrue(mock_logger.called)

@responses.activate
def test_sdn_search_failure(self):
"""
Verify SDNClient search logs an exception if SDN API call fails.
"""
self.mock_sdn_api_response(HTTPError, status_code=400)
with self.assertRaises(HTTPError):
with mock.patch('sanctions.apps.api_client.sdn_client.logger.exception') as mock_logger:
response = self.sdn_api_client.search(self.lms_user_id, self.name, self.city, self.country)
self.assertTrue(mock_logger.called)
self.assertEqual(response.status_code, 400)

@responses.activate
def test_sdn_search_success(self):
"""
Verify SDNClient search returns the number of matches.
"""
sdn_response = {'total': 1}
self.mock_sdn_api_response(json.dumps(sdn_response), status_code=200)
response = self.sdn_api_client.search(self.lms_user_id, self.name, self.city, self.country)
self.assertEqual(response, sdn_response)

0 comments on commit 5fe52b9

Please sign in to comment.