Skip to content

Commit

Permalink
Adding unit tests for error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
VineetBala-AOT committed Jan 22, 2024
1 parent 03bd0d9 commit 85ceb5c
Show file tree
Hide file tree
Showing 26 changed files with 1,474 additions and 68 deletions.
2 changes: 1 addition & 1 deletion met-api/src/met_api/models/widget_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def get_map(cls, widget_id) -> list[WidgetMap]:
@classmethod
def update_map(cls, widget_id, map_data: dict) -> WidgetMap:
"""Update map."""
query = WidgetMap.query.filter_by(WidgetMap.widget_id == widget_id)
query = WidgetMap.query.filter_by(widget_id=widget_id)
widget_map: WidgetMap = query.first()
if not widget_map:
return map_data
Expand Down
3 changes: 2 additions & 1 deletion met-api/src/met_api/services/engagement_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ def get_engagement(self, engagement_id) -> EngagementSchema:

engagement = EngagementSchema().dump(engagement_model)
engagement['banner_url'] = self.object_storage.get_url(engagement['banner_filename'])
return engagement
return engagement
return None

def get_engagements_paginated(
self,
Expand Down
44 changes: 40 additions & 4 deletions met-api/tests/unit/api/test_cac_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,11 @@
"""
import json
from http import HTTPStatus
from unittest.mock import MagicMock
from unittest.mock import MagicMock, patch
import pytest

from met_api.exceptions.business_exception import BusinessException
from met_api.services.cac_form_service import CACFormService
from met_api.utils.enums import ContentType
from tests.utilities.factory_scenarios import TestCACForm, TestJwtClaims, TestSubscribeInfo, TestWidgetInfo
from tests.utilities.factory_utils import factory_auth_header, factory_engagement_model, factory_widget_model
Expand Down Expand Up @@ -49,7 +52,12 @@ def create_cac_form_submission(client, jwt, engagement_id, widget_id, form_data,
)


def test_create_form_submission(client, jwt, session): # pylint:disable=unused-argument
@pytest.mark.parametrize('side_effect, expected_status', [
(KeyError('Test error'), HTTPStatus.BAD_REQUEST),
(ValueError('Test error'), HTTPStatus.BAD_REQUEST),
])
def test_create_form_submission(client, jwt, session, side_effect,
expected_status): # pylint:disable=unused-argument
"""Assert that cac form submission can be POSTed."""
engagement = factory_engagement_model()
TestWidgetInfo.widget_subscribe['engagement_id'] = engagement.id
Expand All @@ -69,8 +77,31 @@ def test_create_form_submission(client, jwt, session): # pylint:disable=unused-
response_data = json.loads(rv.data)
assert response_data.get('engagement_id') == engagement.id


def test_get_cac_form_spreadsheet(mocker, client, jwt, session,
with patch.object(CACFormService, 'create_form_submission', side_effect=side_effect):
rv = client.post(
f'/api/engagements/{engagement.id}/cacform/{widget.id}',
data=json.dumps(form_data),
headers=headers,
content_type=ContentType.JSON.value,
)
assert rv.status_code == expected_status

with patch.object(CACFormService, 'create_form_submission',
side_effect=BusinessException('Test error', status_code=HTTPStatus.BAD_REQUEST)):
rv = client.post(
f'/api/engagements/{engagement.id}/cacform/{widget.id}',
data=json.dumps(form_data),
headers=headers,
content_type=ContentType.JSON.value,
)
assert rv.status_code == HTTPStatus.BAD_REQUEST


@pytest.mark.parametrize('side_effect, expected_status', [
(KeyError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
(ValueError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
])
def test_get_cac_form_spreadsheet(mocker, client, jwt, session, side_effect, expected_status,
setup_admin_user_and_claims): # pylint:disable=unused-argument
"""Assert that cac form submissions sheet can be fetched."""
user, claims = setup_admin_user_and_claims
Expand Down Expand Up @@ -118,3 +149,8 @@ def test_get_cac_form_spreadsheet(mocker, client, jwt, session,
mock_post_generate_document.assert_called()
mock_get_access_token.assert_called()
mock_post_upload_template.assert_called()

with patch.object(CACFormService, 'export_cac_form_submissions_to_spread_sheet', side_effect=side_effect):
rv = client.get(f'/api/engagements/{engagement.id}/cacform/sheet',
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == expected_status
18 changes: 18 additions & 0 deletions met-api/tests/unit/api/test_comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@

from met_api.constants.membership_type import MembershipType
from met_api.constants.staff_note_type import StaffNoteType
from met_api.services.comment_service import CommentService
from met_api.utils import notification
from met_api.utils.enums import ContentType
from tests.utilities.factory_scenarios import TestJwtClaims
Expand All @@ -47,6 +48,11 @@ def test_get_comments(client, jwt, session): # pylint:disable=unused-argument
rv = client.get(f'/api/comments/survey/{survey.id}', headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == 200

with patch.object(CommentService, 'get_comments_paginated', side_effect=ValueError('Test error')):
rv = client.get(f'/api/comments/survey/{survey.id}', headers=headers, content_type=ContentType.JSON.value)

assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR


def test_review_comment(client, jwt, session): # pylint:disable=unused-argument
"""Assert that a comment can be reviewed."""
Expand Down Expand Up @@ -215,6 +221,12 @@ def test_get_comments_spreadsheet_staff(mocker, client, jwt, session,
mock_get_access_token.assert_called()
mock_post_upload_template.assert_called()

with patch.object(CommentService, 'export_comments_to_spread_sheet_staff',
side_effect=ValueError('Test error')):
rv = client.get(f'/api/comments/survey/{survey.id}/sheet/staff',
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR


def test_get_comments_spreadsheet_proponent(mocker, client, jwt, session,
setup_admin_user_and_claims): # pylint:disable=unused-argument
Expand Down Expand Up @@ -256,6 +268,12 @@ def test_get_comments_spreadsheet_proponent(mocker, client, jwt, session,
mock_get_access_token.assert_called()
mock_post_upload_template.assert_called()

with patch.object(CommentService, 'export_comments_to_spread_sheet_proponent',
side_effect=ValueError('Test error')):
rv = client.get(f'/api/comments/survey/{survey.id}/sheet/proponent',
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR


def test_get_comments_spreadsheet_without_role(mocker, client, jwt, session): # pylint:disable=unused-argument
"""Assert that proponent comments sheet can be fetched."""
Expand Down
73 changes: 69 additions & 4 deletions met-api/tests/unit/api/test_contact.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@
from http import HTTPStatus

from faker import Faker

from marshmallow import ValidationError
from unittest.mock import patch
import pytest

from met_api.services.contact_service import ContactService
from met_api.utils.enums import ContentType
from tests.utilities.factory_scenarios import TestContactInfo, TestJwtClaims
from tests.utilities.factory_utils import factory_auth_header
Expand All @@ -31,8 +33,13 @@
fake = Faker()


@pytest.mark.parametrize('side_effect, expected_status', [
(KeyError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
(ValueError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
])
@pytest.mark.parametrize('contact_info', [TestContactInfo.contact1])
def test_create_contact(client, jwt, session, contact_info): # pylint:disable=unused-argument
def test_create_contact(client, jwt, session, contact_info, side_effect,
expected_status): # pylint:disable=unused-argument
"""Assert that a contact can be POSTed."""
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.no_role)
rv = client.post('/api/contacts/', data=json.dumps(contact_info),
Expand All @@ -45,9 +52,24 @@ def test_create_contact(client, jwt, session, contact_info): # pylint:disable=u
assert rv.json.get('address') == contact_info.get('address')
assert rv.json.get('bio') == contact_info.get('bio')

with patch.object(ContactService, 'create_contact', side_effect=side_effect):
rv = client.post('/api/contacts/', data=json.dumps(contact_info),
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == expected_status

with patch.object(ContactService, 'create_contact', side_effect=ValidationError('Test error')):
rv = client.post('/api/contacts/', data=json.dumps(contact_info),
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR


@pytest.mark.parametrize('side_effect, expected_status', [
(KeyError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
(ValueError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
])
@pytest.mark.parametrize('contact_info', [TestContactInfo.contact1])
def test_get_contact(client, jwt, session, contact_info): # pylint:disable=unused-argument
def test_get_contact(client, jwt, session, contact_info, side_effect,
expected_status): # pylint:disable=unused-argument
"""Assert that a contact can be fetched."""
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.no_role)
rv = client.post('/api/contacts/', data=json.dumps(contact_info),
Expand All @@ -58,9 +80,18 @@ def test_get_contact(client, jwt, session, contact_info): # pylint:disable=unus
assert rv.status_code == HTTPStatus.OK
assert rv.json[0].get('name') == contact_info.get('name')

with patch.object(ContactService, 'get_contacts', side_effect=side_effect):
rv = client.get('/api/contacts/', headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == expected_status


@pytest.mark.parametrize('side_effect, expected_status', [
(KeyError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
(ValueError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
])
@pytest.mark.parametrize('contact_info', [TestContactInfo.contact1])
def test_patch_contact(client, jwt, session, contact_info): # pylint:disable=unused-argument
def test_patch_contact(client, jwt, session, contact_info, side_effect,
expected_status): # pylint:disable=unused-argument
"""Assert that a contact can be PATCHed."""
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.no_role)
rv = client.post('/api/contacts/', data=json.dumps(contact_info),
Expand All @@ -85,3 +116,37 @@ def test_patch_contact(client, jwt, session, contact_info): # pylint:disable=un
rv = client.get('/api/contacts/', headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == HTTPStatus.OK
assert rv.json[0].get('name') == contact_edits.get('name')

with patch.object(ContactService, 'update_contact', side_effect=side_effect):
rv = client.patch('/api/contacts/', data=json.dumps(contact_edits),
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == expected_status

with patch.object(ContactService, 'update_contact', side_effect=ValidationError('Test error')):
rv = client.patch('/api/contacts/', data=json.dumps(contact_edits),
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR


@pytest.mark.parametrize('side_effect, expected_status', [
(KeyError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
(ValueError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
])
@pytest.mark.parametrize('contact_info', [TestContactInfo.contact1])
def test_get_contact_by_id(client, jwt, session, contact_info, side_effect,
expected_status): # pylint:disable=unused-argument
"""Assert that a contact can be POSTed."""
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.no_role)
rv = client.post('/api/contacts/', data=json.dumps(contact_info),
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == HTTPStatus.OK
contact_id = rv.json.get('id')
name = rv.json.get('name')

rv = client.get(f'/api/contacts/{contact_id}', headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == HTTPStatus.OK
assert rv.json.get('name') == name

with patch.object(ContactService, 'get_contact_by_id', side_effect=side_effect):
rv = client.get(f'/api/contacts/{contact_id}', headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == expected_status
52 changes: 50 additions & 2 deletions met-api/tests/unit/api/test_email_verification_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@
"""
import json

from http import HTTPStatus
from faker import Faker
from unittest.mock import patch
import pytest

from met_api.constants.email_verification import EmailVerificationType
from met_api.constants.subscription_type import SubscriptionTypes
from met_api.services.email_verification_service import EmailVerificationService
from met_api.utils.enums import ContentType
from tests.utilities.factory_scenarios import TestJwtClaims
from tests.utilities.factory_utils import (
Expand All @@ -45,7 +50,12 @@ def test_email_verification(client, jwt, session, notify_mock, ): # pylint:disa
assert rv.status_code == 200


def test_get_email_verification_by_token(client, jwt, session): # pylint:disable=unused-argument
@pytest.mark.parametrize('side_effect, expected_status', [
(KeyError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
(ValueError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
])
def test_get_email_verification_by_token(client, jwt, session, side_effect,
expected_status): # pylint:disable=unused-argument
"""Assert that an email verification can be fetched."""
claims = TestJwtClaims.public_user_role
set_global_tenant()
Expand All @@ -60,6 +70,17 @@ def test_get_email_verification_by_token(client, jwt, session): # pylint:disabl
assert rv.json.get('verification_token') == email_verification.verification_token
assert rv.json.get('is_active') is True

with patch.object(EmailVerificationService, 'get_active', side_effect=side_effect):
rv = client.get(f'/api/email_verification/{email_verification.verification_token}',
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == expected_status

# test email verification not found
email_verification_token = fake.text(max_nb_chars=20)
rv = client.get(f'/api/email_verification/{email_verification_token}',
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR


def test_patch_email_verification_by_token(client, jwt, session): # pylint:disable=unused-argument
"""Assert that an email verification can be fetched."""
Expand All @@ -76,8 +97,29 @@ def test_patch_email_verification_by_token(client, jwt, session): # pylint:disa
assert rv.json.get('verification_token') == email_verification.verification_token
assert rv.json.get('is_active') is False

with patch.object(EmailVerificationService, 'verify', side_effect=KeyError('Test error')):
rv = client.put(f'/api/email_verification/{email_verification.verification_token}',
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == HTTPStatus.NOT_FOUND

with patch.object(EmailVerificationService, 'verify', side_effect=ValueError('Test error')):
rv = client.put(f'/api/email_verification/{email_verification.verification_token}',
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR

def test_post_subscription_email_verification(client, jwt, session, notify_mock): # pylint:disable=unused-argument
# test email verification not found to update the data
email_verification_token = fake.text(max_nb_chars=20)
rv = client.put(f'/api/email_verification/{email_verification_token}',
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR


@pytest.mark.parametrize('side_effect, expected_status', [
(KeyError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
(ValueError('Test error'), HTTPStatus.INTERNAL_SERVER_ERROR),
])
def test_post_subscription_email_verification(client, jwt, session, notify_mock,
side_effect, expected_status): # pylint:disable=unused-argument
"""Assert that an Subscription Email can be sent."""
claims = TestJwtClaims.public_user_role
set_global_tenant()
Expand All @@ -100,3 +142,9 @@ def test_post_subscription_email_verification(client, jwt, session, notify_mock)

assert rv.status_code == 200
assert rv.json.get('type') == EmailVerificationType.Subscribe

with patch.object(EmailVerificationService, 'create', side_effect=side_effect):
rv = client.post(f'/api/email_verification/{SubscriptionTypes.PROJECT.value}/subscribe',
data=json.dumps(to_dict),
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == expected_status
Loading

0 comments on commit 85ceb5c

Please sign in to comment.