Skip to content

Commit

Permalink
DESENG-436: MET - Rewrite unit tests (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
VineetBala-AOT authored Jan 12, 2024
1 parent 70f74ab commit b4df083
Show file tree
Hide file tree
Showing 16 changed files with 250 additions and 115 deletions.
2 changes: 1 addition & 1 deletion analytics-api/src/analytics_api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class _Config(): # pylint: disable=too-few-public-methods
JWT_OIDC_JWKS_CACHE_TIMEOUT = 300

# default tenant configs ; Set to EAO for now.Overwrite using openshift variables
DEFAULT_TENANT_SHORT_NAME = os.getenv('DEFAULT_TENANT_SHORT_NAME', 'EAO')
DEFAULT_TENANT_SHORT_NAME = os.getenv('DEFAULT_TENANT_SHORT_NAME', 'GDX')
DEFAULT_TENANT_NAME = os.getenv('DEFAULT_TENANT_NAME', 'Environment Assessment Office')
DEFAULT_TENANT_DESCRIPTION = os.getenv('DEFAULT_TENANT_DESCRIPTION', 'Environment Assessment Office')

Expand Down
3 changes: 3 additions & 0 deletions met-api/src/met_api/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ def SQLALCHEMY_DATABASE_URI(self) -> str:
'TOKEN_URL': os.getenv('CDOGS_TOKEN_URL'),
}

PROPAGATE_EXCEPTIONS = True


class DevConfig(Config): # pylint: disable=too-few-public-methods
"""Dev Config."""
Expand Down Expand Up @@ -368,6 +370,7 @@ def __init__(self) -> None:
'HOST': os.getenv('DATABASE_TEST_HOST', Config.DB.get('HOST')),
'PORT': os.getenv('DATABASE_TEST_PORT', Config.DB.get('PORT')),
}
IS_SINGLE_TENANT_ENVIRONMENT = False


class DockerConfig(Config): # pylint: disable=too-few-public-methods
Expand Down
47 changes: 47 additions & 0 deletions met-api/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@
import time
from random import random

import copy
import pytest
from flask_migrate import Migrate, upgrade
from sqlalchemy import event, text

from met_api import create_app, setup_jwt_manager
from met_api.auth import jwt as _jwt
from met_api.models import db as _db
from tests.utilities.factory_utils import factory_staff_user_model, set_global_tenant
from tests.utilities.factory_scenarios import TestJwtClaims, TestUserInfo


@pytest.fixture(scope='session')
Expand Down Expand Up @@ -169,3 +172,47 @@ def docker_compose_files(pytestconfig):
def auth_mock(monkeypatch):
"""Mock check_auth."""
pass


# Fixture for setting up user and claims for an admin user
@pytest.fixture
def setup_admin_user_and_claims(jwt):
staff_info = dict(TestUserInfo.user_staff_1)
user = factory_staff_user_model(user_info=staff_info)
claims = copy.deepcopy(TestJwtClaims.staff_admin_role.value)
claims['sub'] = str(user.external_id)

return user, claims


# Fixture for setting up user and claims for a reviewer
@pytest.fixture
def setup_reviewer_and_claims(jwt):
staff_info = dict(TestUserInfo.user_staff_1)
user = factory_staff_user_model(user_info=staff_info)
claims = copy.deepcopy(TestJwtClaims.reviewer_role.value)
claims['sub'] = str(user.external_id)

return user, claims


# Fixture for setting up user and claims for an team member
@pytest.fixture
def setup_team_member_and_claims(jwt):
staff_info = dict(TestUserInfo.user_staff_1)
user = factory_staff_user_model(user_info=staff_info)
claims = copy.deepcopy(TestJwtClaims.team_member_role.value)
claims['sub'] = str(user.external_id)

return user, claims


# Fixture for setting up user and claims for a user with no role
@pytest.fixture
def setup_unprivileged_user_and_claims(jwt):
staff_info = dict(TestUserInfo.user_staff_1)
user = factory_staff_user_model(user_info=staff_info)
claims = copy.deepcopy(TestJwtClaims.no_role.value)
claims['sub'] = str(user.external_id)

return user, claims
5 changes: 3 additions & 2 deletions met-api/tests/unit/api/test_comment.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,10 @@ def test_review_comment_review_note(client, jwt, session): # pylint:disable=unu
mock_mail.assert_called()


def test_get_comments_spreadsheet(mocker, client, jwt, session): # pylint:disable=unused-argument
def test_get_comments_spreadsheet(mocker, client, jwt, session,
setup_admin_user_and_claims): # pylint:disable=unused-argument
"""Assert that comments sheet can be fetched."""
claims = TestJwtClaims.staff_admin_role
user, claims = setup_admin_user_and_claims

mock_post_generate_document_response = MagicMock()
mock_post_generate_document_response.content = b'mock data'
Expand Down
66 changes: 43 additions & 23 deletions met-api/tests/unit/api/test_engagement.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,21 @@


@pytest.mark.parametrize('engagement_info', [TestEngagementInfo.engagement1])
def test_add_engagements(client, jwt, session, engagement_info): # pylint:disable=unused-argument
def test_add_engagements(client, jwt, session, engagement_info,
setup_admin_user_and_claims): # pylint:disable=unused-argument
"""Assert that an engagement can be POSTed."""
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
user, claims = setup_admin_user_and_claims
headers = factory_auth_header(jwt=jwt, claims=claims)
rv = client.post('/api/engagements/', data=json.dumps(engagement_info),
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == 200


def test_tenant_id_in_create_engagements(client, jwt, session): # pylint:disable=unused-argument
def test_tenant_id_in_create_engagements(client, jwt, session,
setup_admin_user_and_claims): # pylint:disable=unused-argument
"""Assert that an engagement can be POSTed with tenant id."""
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
user, claims = setup_admin_user_and_claims
headers = factory_auth_header(jwt=jwt, claims=claims)
tenant_short_name = current_app.config.get('DEFAULT_TENANT_SHORT_NAME')
tenant = TenantModel.find_by_short_name(tenant_short_name)
assert tenant is not None
Expand Down Expand Up @@ -83,8 +87,10 @@ def test_tenant_id_in_create_engagements(client, jwt, session): # pylint:disabl
assert response.status_code == 403

# set users tenant id to be same as engagment tenant id
staff_2 = dict(TestUserInfo.user_staff_2)
user = factory_staff_user_model(user_info=staff_2)
claims = copy.deepcopy(TestJwtClaims.staff_admin_role.value)
claims['tenant_id'] = tenant_2.id
claims['sub'] = str(user.external_id)
headers = factory_auth_header(jwt=jwt, claims=claims)
headers[TENANT_ID_HEADER] = tenant2_short_name
response = client.post('/api/engagements/',
Expand All @@ -95,19 +101,23 @@ def test_tenant_id_in_create_engagements(client, jwt, session): # pylint:disabl
assert response.json['tenant_id'] == str(tenant_2.id)


@pytest.mark.parametrize('role', [TestJwtClaims.no_role, TestJwtClaims.public_user_role])
def test_add_engagements_invalid(client, jwt, session, role): # pylint:disable=unused-argument
@pytest.mark.parametrize('engagement_info', [TestEngagementInfo.engagement1])
def test_add_engagements_invalid(client, jwt, session, engagement_info,
setup_unprivileged_user_and_claims): # pylint:disable=unused-argument
"""Assert that an engagement can not be POSTed without authorisaiton."""
headers = factory_auth_header(jwt=jwt, claims=role)
rv = client.post('/api/engagements/', data=json.dumps(TestEngagementInfo.engagement1),
user, claims = setup_unprivileged_user_and_claims
headers = factory_auth_header(jwt=jwt, claims=claims)
rv = client.post('/api/engagements/', data=json.dumps(engagement_info),
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == 401


@pytest.mark.parametrize('engagement_info', [TestEngagementInfo.engagement1])
def test_get_engagements(client, jwt, session, engagement_info): # pylint:disable=unused-argument
def test_get_engagements(client, jwt, session, engagement_info,
setup_admin_user_and_claims): # pylint:disable=unused-argument
"""Assert that an engagement can be POSTed."""
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
user, claims = setup_admin_user_and_claims
headers = factory_auth_header(jwt=jwt, claims=claims)
rv = client.post('/api/engagements/', data=json.dumps(engagement_info),
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == 200
Expand All @@ -121,16 +131,18 @@ def test_get_engagements(client, jwt, session, engagement_info): # pylint:disab


@pytest.mark.parametrize('engagement_info', [TestEngagementInfo.engagement_draft])
def test_get_engagements_reviewer(client, jwt, session, engagement_info): # pylint:disable=unused-argument
def test_get_engagements_reviewer(client, jwt, session, engagement_info,
setup_admin_user_and_claims): # pylint:disable=unused-argument
"""Assert reviewers access on an engagement."""
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
user, claims = setup_admin_user_and_claims
headers = factory_auth_header(jwt=jwt, claims=claims)
rv = client.post('/api/engagements/', data=json.dumps(engagement_info),
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == HTTPStatus.OK.value
created_eng = rv.json
eng_id = created_eng.get('id')
staff_1 = dict(TestUserInfo.user_staff_1)
user = factory_staff_user_model(user_info=staff_1)
staff_2 = dict(TestUserInfo.user_staff_1)
user = factory_staff_user_model(user_info=staff_2)
claims = copy.deepcopy(TestJwtClaims.reviewer_role.value)
claims['sub'] = str(user.external_id)
headers = factory_auth_header(jwt=jwt, claims=claims)
Expand All @@ -148,9 +160,11 @@ def test_get_engagements_reviewer(client, jwt, session, engagement_info): # pyl

@pytest.mark.parametrize('engagement_info', [TestEngagementInfo.engagement1])
def test_search_engagements_by_status(client, jwt,
session, engagement_info): # pylint:disable=unused-argument
session, engagement_info,
setup_admin_user_and_claims): # pylint:disable=unused-argument
"""Assert that an engagement can be fetched by filtering using the engagement status."""
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
user, claims = setup_admin_user_and_claims
headers = factory_auth_header(jwt=jwt, claims=claims)
rv = client.post('/api/engagements/', data=json.dumps(engagement_info),
headers=headers, content_type=ContentType.JSON.value)
assert rv.status_code == 200
Expand Down Expand Up @@ -278,9 +292,11 @@ def test_search_engagements_not_logged_in(client, session): # pylint:disable=un


@pytest.mark.parametrize('engagement_info', [TestEngagementInfo.engagement1])
def test_patch_engagement(client, jwt, session, engagement_info): # pylint:disable=unused-argument
def test_patch_engagement(client, jwt, session, engagement_info,
setup_admin_user_and_claims): # pylint:disable=unused-argument
"""Assert that an engagement can be updated."""
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
user, claims = setup_admin_user_and_claims
headers = factory_auth_header(jwt=jwt, claims=claims)
engagement = factory_engagement_model()
engagement_id = str(engagement.id)

Expand Down Expand Up @@ -349,9 +365,11 @@ def test_patch_engagement_by_member(client, jwt, session): # pylint:disable=unu
assert rv.json.get('name') == engagement_edits.get('name')


def test_patch_new_survey_block_engagement(client, jwt, session): # pylint:disable=unused-argument
def test_patch_new_survey_block_engagement(client, jwt, session,
setup_admin_user_and_claims): # pylint:disable=unused-argument
"""Assert that an engagement's survey status blocks can be updated."""
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
user, claims = setup_admin_user_and_claims
headers = factory_auth_header(jwt=jwt, claims=claims)
engagement = factory_engagement_model()
engagement_id = str(engagement.id)

Expand All @@ -375,9 +393,11 @@ def test_patch_new_survey_block_engagement(client, jwt, session): # pylint:disa
assert actual_status_blocks[0].get('survey_status') == engagement_edits.get('status_block')[0].get('survey_status')


def test_update_survey_block_engagement(client, jwt, session): # pylint:disable=unused-argument
def test_update_survey_block_engagement(client, jwt, session,
setup_admin_user_and_claims): # pylint:disable=unused-argument
"""Assert that an engagement's survey status blocks can be updated."""
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
user, claims = setup_admin_user_and_claims
headers = factory_auth_header(jwt=jwt, claims=claims)
engagement = factory_engagement_model(TestEngagementInfo.engagement2)
engagement_id = str(engagement.id)

Expand Down
48 changes: 32 additions & 16 deletions met-api/tests/unit/api/test_engagement_membership.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
memberships_url = '/api/engagements/{}/members'


def test_create_engagement_membership_team_member(mocker, client, jwt, session):
def test_create_engagement_membership_team_member(mocker, client, jwt, session,
setup_admin_user_and_claims):
"""Assert that a team member engagement membership can be created."""
user, claims = setup_admin_user_and_claims
engagement = factory_engagement_model()
staff_user = factory_staff_user_model()
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
headers = factory_auth_header(jwt=jwt, claims=claims)

mock_add_user_to_group_keycloak_response = MagicMock()
mock_add_user_to_group_keycloak_response.status_code = HTTPStatus.NO_CONTENT
Expand Down Expand Up @@ -51,11 +53,13 @@ def test_create_engagement_membership_team_member(mocker, client, jwt, session):
mock_get_users_groups_keycloak.assert_called()


def test_create_engagement_membership_reviewer(mocker, client, jwt, session):
def test_create_engagement_membership_reviewer(mocker, client, jwt, session,
setup_admin_user_and_claims):
"""Assert that a reviewer engagement membership can be created."""
user, claims = setup_admin_user_and_claims
engagement = factory_engagement_model()
staff_user = factory_staff_user_model()
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
headers = factory_auth_header(jwt=jwt, claims=claims)

mock_add_user_to_group_keycloak_response = MagicMock()
mock_add_user_to_group_keycloak_response.status_code = HTTPStatus.NO_CONTENT
Expand Down Expand Up @@ -85,11 +89,13 @@ def test_create_engagement_membership_reviewer(mocker, client, jwt, session):
mock_get_users_groups_keycloak.assert_called()


def test_create_engagement_membership_unauthorized(client, jwt, session):
def test_create_engagement_membership_unauthorized(client, jwt, session,
setup_unprivileged_user_and_claims):
"""Assert that creating an engagement membership without proper authorization fails."""
user, claims = setup_unprivileged_user_and_claims
engagement = factory_engagement_model()
staff_user = factory_staff_user_model()
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.no_role)
headers = factory_auth_header(jwt=jwt, claims=claims)
data = {'user_id': staff_user.external_id}

rv = client.post(
Expand All @@ -101,12 +107,14 @@ def test_create_engagement_membership_unauthorized(client, jwt, session):
assert rv.status_code == HTTPStatus.FORBIDDEN


def test_revoke_membership(client, jwt, session):
def test_revoke_membership(client, jwt, session,
setup_admin_user_and_claims):
"""Test that a membership can be revoked."""
user, claims = setup_admin_user_and_claims
engagement = factory_engagement_model()
staff_user = factory_staff_user_model()
membership = factory_membership_model(user_id=staff_user.id, engagement_id=engagement.id)
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
headers = factory_auth_header(jwt=jwt, claims=claims)
data = {
'action': 'revoke'
}
Expand All @@ -121,16 +129,18 @@ def test_revoke_membership(client, jwt, session):
assert rv.status_code == HTTPStatus.OK


def test_reinstate_membership(client, jwt, session):
def test_reinstate_membership(client, jwt, session,
setup_admin_user_and_claims):
"""Test that a membership can be reinstated."""
user, claims = setup_admin_user_and_claims
engagement = factory_engagement_model()
staff_user = factory_staff_user_model()
membership = factory_membership_model(
user_id=staff_user.id,
engagement_id=engagement.id,
status=MembershipStatus.REVOKED.value
)
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
headers = factory_auth_header(jwt=jwt, claims=claims)
data = {
'action': 'reinstate'
}
Expand All @@ -145,12 +155,14 @@ def test_reinstate_membership(client, jwt, session):
assert rv.status_code == HTTPStatus.OK


def test_update_membership_status_invalid_action(client, jwt, session):
def test_update_membership_status_invalid_action(client, jwt, session,
setup_admin_user_and_claims):
"""Test that an invalid action cannot be performed on a membership."""
user, claims = setup_admin_user_and_claims
engagement = factory_engagement_model()
staff_user = factory_staff_user_model()
membership = factory_membership_model(user_id=staff_user.id, engagement_id=engagement.id)
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
headers = factory_auth_header(jwt=jwt, claims=claims)
data = {
'action': 'invalid'
}
Expand All @@ -165,16 +177,18 @@ def test_update_membership_status_invalid_action(client, jwt, session):
assert rv.status_code == HTTPStatus.BAD_REQUEST


def test_revoke_already_revoked_membership(client, jwt, session):
def test_revoke_already_revoked_membership(client, jwt, session,
setup_admin_user_and_claims):
"""Test that an already revoked membership cannot be revoked again."""
user, claims = setup_admin_user_and_claims
engagement = factory_engagement_model()
staff_user = factory_staff_user_model()
membership = factory_membership_model(
user_id=staff_user.id,
engagement_id=engagement.id,
status=MembershipStatus.REVOKED.value
)
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
headers = factory_auth_header(jwt=jwt, claims=claims)
data = {
'action': 'revoke'
}
Expand All @@ -189,12 +203,14 @@ def test_revoke_already_revoked_membership(client, jwt, session):
assert rv.status_code == HTTPStatus.BAD_REQUEST


def reinstate_already_active_membership(client, jwt, session):
def reinstate_already_active_membership(client, jwt, session,
setup_admin_user_and_claims):
"""Test that an already active membership cannot be activated again."""
user, claims = setup_admin_user_and_claims
engagement = factory_engagement_model()
staff_user = factory_staff_user_model()
membership = factory_membership_model(user_id=staff_user.id, engagement_id=engagement.id)
headers = factory_auth_header(jwt=jwt, claims=TestJwtClaims.staff_admin_role)
headers = factory_auth_header(jwt=jwt, claims=claims)
data = {
'action': 'reinstate'
}
Expand Down
Loading

0 comments on commit b4df083

Please sign in to comment.