From 29c2e0018368e6d90ac648923634bde9f0a7d4f6 Mon Sep 17 00:00:00 2001 From: VineetBala-AOT <90332175+VineetBala-AOT@users.noreply.github.com> Date: Tue, 26 Mar 2024 16:09:38 -0700 Subject: [PATCH] Removing content fron engagement table (#2426) --- ...160dd120_remove_content_from_engagement.py | 30 ++++++++++ .../constants/engagement_content_type.py | 10 +++- met-api/src/met_api/models/engagement.py | 4 -- .../models/engagement_summary_content.py | 8 +++ met-api/src/met_api/resources/__init__.py | 6 +- .../met_api/resources/engagement_content.py | 6 +- .../resources/engagement_custom_content.py | 2 +- .../resources/engagement_summary_content.py | 2 +- met-api/src/met_api/schemas/engagement.py | 2 - .../services/engagement_content_service.py | 23 +++++++- .../met_api/services/engagement_service.py | 44 ++++++++++++++- .../engagement_translation_service.py | 13 +++-- met-api/tests/unit/api/test_engagement.py | 3 - .../tests/unit/api/test_engagement_content.py | 44 +++++++-------- .../api/test_engagement_custom_content.py | 42 +++++++++++--- .../api/test_engagement_summary_content.py | 16 +++--- .../unit/api/test_engagement_translation.py | 55 +++++++++++-------- .../tests/unit/services/test_engagement.py | 11 ++-- met-api/tests/utilities/factory_scenarios.py | 3 - met-api/tests/utilities/factory_utils.py | 2 - 20 files changed, 226 insertions(+), 100 deletions(-) create mode 100644 met-api/migrations/versions/734f160dd120_remove_content_from_engagement.py diff --git a/met-api/migrations/versions/734f160dd120_remove_content_from_engagement.py b/met-api/migrations/versions/734f160dd120_remove_content_from_engagement.py new file mode 100644 index 000000000..6904678ff --- /dev/null +++ b/met-api/migrations/versions/734f160dd120_remove_content_from_engagement.py @@ -0,0 +1,30 @@ +"""remove_content_from_engagement + +Revision ID: 734f160dd120 +Revises: f3842579261c +Create Date: 2024-03-20 21:01:24.327334 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.dialects import postgresql + +# revision identifiers, used by Alembic. +revision = '734f160dd120' +down_revision = 'f3842579261c' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('engagement', 'content') + op.drop_column('engagement', 'rich_content') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('engagement', sa.Column('rich_content', postgresql.JSON(astext_type=sa.Text()), autoincrement=False, nullable=True)) + op.add_column('engagement', sa.Column('content', sa.TEXT(), autoincrement=False, nullable=True)) + # ### end Alembic commands ### diff --git a/met-api/src/met_api/constants/engagement_content_type.py b/met-api/src/met_api/constants/engagement_content_type.py index d3515103a..82f89a9f7 100644 --- a/met-api/src/met_api/constants/engagement_content_type.py +++ b/met-api/src/met_api/constants/engagement_content_type.py @@ -15,7 +15,7 @@ Each value in this corresponds to a specific section or content element. """ -from enum import IntEnum +from enum import Enum, IntEnum class EngagementContentType(IntEnum): @@ -23,3 +23,11 @@ class EngagementContentType(IntEnum): Summary = 1 Custom = 2 + + +class EngagementContentDefaultValues(Enum): + """Default enum of engagement content type.""" + + Title = 'Summary' + Icon = 'faRectangleList' + Type = 'Summary' diff --git a/met-api/src/met_api/models/engagement.py b/met-api/src/met_api/models/engagement.py index 766a02597..c67e05f3b 100644 --- a/met-api/src/met_api/models/engagement.py +++ b/met-api/src/met_api/models/engagement.py @@ -41,8 +41,6 @@ class Engagement(BaseModel): status = db.relationship('EngagementStatus', backref='engagement') published_date = db.Column(db.DateTime, nullable=True) scheduled_date = db.Column(db.DateTime, nullable=True) - content = db.Column(db.Text, unique=False, nullable=False) - rich_content = db.Column(JSON, unique=False, nullable=False) banner_filename = db.Column(db.String(), unique=False, nullable=True) surveys = db.relationship('Survey', backref='engagement', cascade='all, delete') status_block = db.relationship('EngagementStatusBlock', backref='engagement') @@ -123,8 +121,6 @@ def update_engagement(cls, engagement: EngagementSchema) -> Engagement: updated_date=datetime.utcnow(), updated_by=engagement.get('updated_by', None), banner_filename=engagement.get('banner_filename', None), - content=engagement.get('content', None), - rich_content=engagement.get('rich_content', None), is_internal=engagement.get('is_internal', record.is_internal), consent_message=engagement.get('consent_message', record.consent_message), ) diff --git a/met-api/src/met_api/models/engagement_summary_content.py b/met-api/src/met_api/models/engagement_summary_content.py index b7dd2367c..2eb52270f 100644 --- a/met-api/src/met_api/models/engagement_summary_content.py +++ b/met-api/src/met_api/models/engagement_summary_content.py @@ -30,6 +30,14 @@ def get_summary_content(cls, content_id) -> list[EngagementSummary]: .all() return summary_content + @classmethod + def get_summary_content_by_engagement_id(cls, engagement_id) -> list[EngagementSummary]: + """Get engagement summary content by engagement id.""" + summary_content = db.session.query(EngagementSummary) \ + .filter(EngagementSummary.engagement_id == engagement_id) \ + .first() + return summary_content + @classmethod def update_summary_content(cls, content_id, summary_content_data: dict) -> EngagementSummary: """Update engagement summary content.""" diff --git a/met-api/src/met_api/resources/__init__.py b/met-api/src/met_api/resources/__init__.py index 0bcaad1bc..7cab76bee 100644 --- a/met-api/src/met_api/resources/__init__.py +++ b/met-api/src/met_api/resources/__init__.py @@ -87,9 +87,9 @@ API.add_namespace(SUBSCRIPTION_API) API.add_namespace(COMMENT_API) API.add_namespace(EMAIL_VERIFICATION_API) -API.add_namespace(ENGAGEMENT_CONTENT_API) -API.add_namespace(ENGAGEMENT_CUSTOM_CONTENT_API, path='/engagement_content//custom') -API.add_namespace(ENGAGEMENT_SUMMARY_CONTENT_API, path='/engagement_content//summary') +API.add_namespace(ENGAGEMENT_CONTENT_API, path='/engagement//content') +API.add_namespace(ENGAGEMENT_CUSTOM_CONTENT_API, path='/content//custom') +API.add_namespace(ENGAGEMENT_SUMMARY_CONTENT_API, path='/content//summary') API.add_namespace(FEEDBACK_API) API.add_namespace(WIDGET_API) API.add_namespace(CONTACT_API) diff --git a/met-api/src/met_api/resources/engagement_content.py b/met-api/src/met_api/resources/engagement_content.py index 9734a97ab..8ca5f5a1c 100644 --- a/met-api/src/met_api/resources/engagement_content.py +++ b/met-api/src/met_api/resources/engagement_content.py @@ -34,7 +34,7 @@ @cors_preflight('GET, POST, OPTIONS') -@API.route('/engagement/') +@API.route('') class EngagementContent(Resource): """Resource for managing a engagement content.""" @@ -69,7 +69,7 @@ def post(engagement_id): @cors_preflight('PATCH') -@API.route('/engagement//sort_index') +@API.route('/sort_index') class EngagementContentSort(Resource): """Resource for managing engagement contents sort order with engagements.""" @@ -88,7 +88,7 @@ def patch(engagement_id): @cors_preflight('GET, DELETE, PATCH') -@API.route('//engagements/') +@API.route('/') class EngagementContentEdit(Resource): """Resource for managing engagement contents with engagements.""" diff --git a/met-api/src/met_api/resources/engagement_custom_content.py b/met-api/src/met_api/resources/engagement_custom_content.py index 600bcbff6..5a33ff44b 100644 --- a/met-api/src/met_api/resources/engagement_custom_content.py +++ b/met-api/src/met_api/resources/engagement_custom_content.py @@ -33,7 +33,7 @@ @cors_preflight('GET, POST, PATCH, OPTIONS') @API.route('') -class Map(Resource): +class CustomContent(Resource): """Resource for managing engagement custom content.""" @staticmethod diff --git a/met-api/src/met_api/resources/engagement_summary_content.py b/met-api/src/met_api/resources/engagement_summary_content.py index cda1a7724..d2e504a0d 100644 --- a/met-api/src/met_api/resources/engagement_summary_content.py +++ b/met-api/src/met_api/resources/engagement_summary_content.py @@ -33,7 +33,7 @@ @cors_preflight('GET, POST, PATCH, OPTIONS') @API.route('') -class Map(Resource): +class SummaryContent(Resource): """Resource for managing engagement summary content.""" @staticmethod diff --git a/met-api/src/met_api/schemas/engagement.py b/met-api/src/met_api/schemas/engagement.py index 9ef4db9b0..94938874a 100644 --- a/met-api/src/met_api/schemas/engagement.py +++ b/met-api/src/met_api/schemas/engagement.py @@ -38,8 +38,6 @@ class Meta: # pylint: disable=too-few-public-methods updated_date = fields.Str(data_key='updated_date') published_date = fields.Str(data_key='published_date') scheduled_date = fields.Str(data_key='scheduled_date') - content = fields.Str(data_key='content') - rich_content = fields.Str(data_key='rich_content') banner_filename = fields.Str(data_key='banner_filename') engagement_status = fields.Nested(EngagementStatusSchema) surveys = fields.List(fields.Nested(EngagementSurveySchema)) diff --git a/met-api/src/met_api/services/engagement_content_service.py b/met-api/src/met_api/services/engagement_content_service.py index fe89b4cc2..51e21ab44 100644 --- a/met-api/src/met_api/services/engagement_content_service.py +++ b/met-api/src/met_api/services/engagement_content_service.py @@ -1,11 +1,13 @@ """Service for engagement content management.""" from http import HTTPStatus +from flask import current_app from met_api.constants.engagement_content_type import EngagementContentType from met_api.constants.membership_type import MembershipType from met_api.exceptions.business_exception import BusinessException from met_api.models.engagement_content import EngagementContent as EngagementContentModel from met_api.schemas.engagement_content import EngagementContentSchema +from met_api.services.engagement_custom_content_service import EngagementCustomContentService from met_api.services import authorization from met_api.utils.roles import Role @@ -36,10 +38,29 @@ def create_engagement_content(engagement_content_data, engagement_id): sort_index = EngagementContentService._find_higest_sort_index(engagement_id) engagement_content_data['sort_index'] = sort_index + 1 + created_content = EngagementContentService._create_content(engagement_id, engagement_content_data) created_content.commit() + + if engagement_content_data.get('content_type') == EngagementContentType.Custom.name: + EngagementContentService.create_default_custom_content(engagement_id, created_content.id) + return EngagementContentSchema().dump(created_content) + @staticmethod + def create_default_custom_content(eng_id: int, eng_content_id: int): + """Create default engagement custom content.""" + default_summary_content = { + 'engagement_id': eng_id + } + try: + EngagementCustomContentService.create_custom_content(eng_content_id, default_summary_content) + except Exception as exc: # noqa: B902 + current_app.logger.error('Failed to create default engagement summary content', exc) + raise BusinessException( + error='Failed to create default engagement summary content.', + status_code=HTTPStatus.INTERNAL_SERVER_ERROR) from exc + @staticmethod def _find_higest_sort_index(engagement_id): # find the highest sort order of the engagement content @@ -58,7 +79,7 @@ def _create_content(engagement_id, engagement_content_data: dict): engagement_content_model.icon_name = engagement_content_data.get('icon_name') engagement_content_model.content_type = EngagementContentType[engagement_content_data.get('content_type')] engagement_content_model.sort_index = engagement_content_data.get('sort_index') - engagement_content_model.is_internal = engagement_content_data.get('is_internal') + engagement_content_model.is_internal = engagement_content_data.get('is_internal', False) engagement_content_model.flush() return engagement_content_model diff --git a/met-api/src/met_api/services/engagement_service.py b/met-api/src/met_api/services/engagement_service.py index 0432f1028..725b8752f 100644 --- a/met-api/src/met_api/services/engagement_service.py +++ b/met-api/src/met_api/services/engagement_service.py @@ -4,6 +4,7 @@ from flask import current_app +from met_api.constants.engagement_content_type import EngagementContentDefaultValues from met_api.constants.engagement_status import Status from met_api.constants.membership_type import MembershipType from met_api.exceptions.business_exception import BusinessException @@ -17,8 +18,9 @@ from met_api.services import authorization from met_api.services.engagement_settings_service import EngagementSettingsService from met_api.services.engagement_slug_service import EngagementSlugService +from met_api.services.engagement_content_service import EngagementContentService +from met_api.services.engagement_summary_content_service import EngagementSummaryContentService from met_api.services.object_storage_service import ObjectStorageService - from met_api.services.project_service import ProjectService from met_api.utils import email_util, notification from met_api.utils.enums import SourceAction, SourceType @@ -157,6 +159,9 @@ def create_engagement(request_json: dict): EngagementService.validate_fields(request_json) eng_model = EngagementService._create_engagement_model(request_json) + eng_content = EngagementService.create_default_engagement_content(eng_model.id) + EngagementService.create_default_summary_content(eng_model.id, eng_content['id'], request_json) + if request_json.get('status_block'): EngagementService._create_eng_status_block(eng_model.id, request_json) eng_model.commit() @@ -182,14 +187,47 @@ def _create_engagement_model(engagement_data: dict) -> EngagementModel: published_date=None, scheduled_date=None, banner_filename=engagement_data.get('banner_filename', None), - content=engagement_data.get('content', None), - rich_content=engagement_data.get('rich_content', None), is_internal=engagement_data.get('is_internal', False), consent_message=engagement_data.get('consent_message', None) ) new_engagement.save() return new_engagement + @staticmethod + def create_default_engagement_content(eng_id): + """Create default engagement content for the given engagement ID.""" + default_engagement_content = { + 'title': EngagementContentDefaultValues.Title.value, + 'icon_name': EngagementContentDefaultValues.Icon.value, + 'content_type': EngagementContentDefaultValues.Type.value, + 'engagement_id': eng_id + } + try: + eng_content = EngagementContentService.create_engagement_content(default_engagement_content, eng_id) + except Exception as exc: # noqa: B902 + current_app.logger.error('Failed to create default engagement content', exc) + raise BusinessException( + error='Failed to create default engagement content.', + status_code=HTTPStatus.INTERNAL_SERVER_ERROR) from exc + + return eng_content + + @staticmethod + def create_default_summary_content(eng_id: int, eng_content_id: int, content_data: dict): + """Create default summary content for the engagement ID, mandatory for each engagement.""" + default_summary_content = { + 'engagement_id': eng_id, + 'content': content_data.get('content', None), + 'rich_content': content_data.get('rich_content', None) + } + try: + EngagementSummaryContentService.create_summary_content(eng_content_id, default_summary_content) + except Exception as exc: # noqa: B902 + current_app.logger.error('Failed to create default engagement summary content', exc) + raise BusinessException( + error='Failed to create default engagement summary content.', + status_code=HTTPStatus.INTERNAL_SERVER_ERROR) from exc + @staticmethod def _create_eng_status_block(eng_id, engagement_data: dict): """Save engagement.""" diff --git a/met-api/src/met_api/services/engagement_translation_service.py b/met-api/src/met_api/services/engagement_translation_service.py index a7f6f79d6..bff3e56dd 100644 --- a/met-api/src/met_api/services/engagement_translation_service.py +++ b/met-api/src/met_api/services/engagement_translation_service.py @@ -8,6 +8,7 @@ from met_api.models.engagement import Engagement as EngagementModel from met_api.models.engagement_slug import EngagementSlug as EngagementSlugModel from met_api.models.engagement_status_block import EngagementStatusBlock as EngagementStatusBlockModel +from met_api.models.engagement_summary_content import EngagementSummary as EngagementSummaryModel from met_api.models.engagement_translation import EngagementTranslation as EngagementTranslationModel from met_api.models.language import Language as LanguageModel from met_api.schemas.engagement_translation import EngagementTranslationSchema @@ -41,6 +42,8 @@ def create_engagement_translation(translation_data, pre_populate=True): """Create engagement translation.""" try: engagement = EngagementModel.find_by_id(translation_data['engagement_id']) + summary_content = EngagementSummaryModel.get_summary_content_by_engagement_id( + translation_data['engagement_id']) if not engagement: raise ValueError('Engagement to translate was not found') @@ -56,7 +59,9 @@ def create_engagement_translation(translation_data, pre_populate=True): if pre_populate: # prepopulate translation with base language data - EngagementTranslationService._get_default_language_values(engagement, translation_data) + EngagementTranslationService._get_default_language_values(engagement, + summary_content, + translation_data) created_engagement_translation = EngagementTranslationModel.create_engagement_translation( translation_data) @@ -117,14 +122,14 @@ def _verify_engagement_translation(engagement_translation_id): return engagement_translation @staticmethod - def _get_default_language_values(engagement, translation_data): + def _get_default_language_values(engagement, summary_content, translation_data): """Populate the default values.""" engagement_id = engagement.id translation_data['name'] = engagement.name translation_data['description'] = engagement.description translation_data['rich_description'] = engagement.rich_description - translation_data['content'] = engagement.content - translation_data['rich_content'] = engagement.rich_content + translation_data['content'] = summary_content.content + translation_data['rich_content'] = summary_content.rich_content translation_data['consent_message'] = engagement.consent_message engagement_slug = EngagementSlugModel.find_by_engagement_id(engagement_id) diff --git a/met-api/tests/unit/api/test_engagement.py b/met-api/tests/unit/api/test_engagement.py index 7b56d6f35..d4da1601e 100644 --- a/met-api/tests/unit/api/test_engagement.py +++ b/met-api/tests/unit/api/test_engagement.py @@ -351,7 +351,6 @@ def test_patch_engagement(client, jwt, session, engagement_info, side_effect, ex 'start_date': fake.date(), 'end_date': fake.date(), 'description': fake.text(), - 'content': fake.text(), 'created_date': fake.date(), } @@ -367,7 +366,6 @@ def test_patch_engagement(client, jwt, session, engagement_info, side_effect, ex assert engagement_edits.get('start_date') in rv.json.get('start_date') assert engagement_edits.get('end_date') in rv.json.get('end_date') assert rv.json.get('description') == engagement_edits.get('description') - assert rv.json.get('content') == engagement_edits.get('content') assert engagement_edits.get('created_date') in rv.json.get('created_date') with patch.object(EngagementService, 'edit_engagement', side_effect=side_effect): @@ -392,7 +390,6 @@ def test_patch_engagement_by_member(client, jwt, session): # pylint:disable=unu 'start_date': fake.date(), 'end_date': fake.date(), 'description': fake.text(), - 'content': fake.text(), 'created_date': fake.date(), } diff --git a/met-api/tests/unit/api/test_engagement_content.py b/met-api/tests/unit/api/test_engagement_content.py index 9a7cf33b0..92d8c53fc 100644 --- a/met-api/tests/unit/api/test_engagement_content.py +++ b/met-api/tests/unit/api/test_engagement_content.py @@ -42,26 +42,26 @@ def test_create_engagement_content(client, jwt, session, engagement_content_info engagement_content_info['engagement_id'] = engagement.id user, claims = setup_admin_user_and_claims headers = factory_auth_header(jwt=jwt, claims=claims) - rv = client.post('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.post(f'/api/engagement/{engagement.id}/content', data=json.dumps(engagement_content_info), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 200 - rv = client.get('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.get(f'/api/engagement/{engagement.id}/content', headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 200 assert rv.json[0].get('sort_index') == 1 with patch.object(EngagementContentService, 'create_engagement_content', side_effect=ValueError('Test error')): - rv = client.post('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.post(f'/api/engagement/{engagement.id}/content', data=json.dumps(engagement_content_info), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR with patch.object(EngagementContentService, 'create_engagement_content', side_effect=ValidationError('Test error')): - rv = client.post('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.post(f'/api/engagement/{engagement.id}/content', data=json.dumps(engagement_content_info), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR @@ -75,18 +75,18 @@ def test_get_engagement_content(client, jwt, session, engagement_content_info, engagement_content_info['engagement_id'] = engagement.id user, claims = setup_admin_user_and_claims headers = factory_auth_header(jwt=jwt, claims=claims) - rv = client.post('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.post(f'/api/engagement/{engagement.id}/content', data=json.dumps(engagement_content_info), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 200 - rv = client.get('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.get(f'/api/engagement/{engagement.id}/content', headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 200 assert rv.json[0].get('sort_index') == 1 with patch.object(EngagementContentService, 'get_contents_by_engagement_id', side_effect=ValueError('Test error')): - rv = client.get('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.get(f'/api/engagement/{engagement.id}/content', headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR @@ -99,7 +99,7 @@ def test_create_engagement_content_sort(client, jwt, session, engagement_content_info_1['engagement_id'] = engagement.id user, claims = setup_admin_user_and_claims headers = factory_auth_header(jwt=jwt, claims=claims) - rv = client.post('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.post(f'/api/engagement/{engagement.id}/content', data=json.dumps(engagement_content_info_1), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 200 @@ -107,12 +107,12 @@ def test_create_engagement_content_sort(client, jwt, session, engagement_content_info_2 = TestEngagementContentInfo.content2 engagement_content_info_2['engagement_id'] = engagement.id headers = factory_auth_header(jwt=jwt, claims=claims) - rv = client.post('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.post(f'/api/engagement/{engagement.id}/content', data=json.dumps(engagement_content_info_2), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 200 - rv = client.get('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.get(f'/api/engagement/{engagement.id}/content', headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 200 assert len(rv.json) == 2, 'Two Contents Should exist.' @@ -134,12 +134,12 @@ def test_create_engagement_content_sort(client, jwt, session, } ] - rv = client.patch(f'/api/engagement_content/engagement/{engagement.id}/sort_index', + rv = client.patch(f'/api/engagement/{engagement.id}/content/sort_index', data=json.dumps(reorder_dict), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 204 - rv = client.get('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.get(f'/api/engagement/{engagement.id}/content', headers=headers, content_type=ContentType.JSON.value) engagement_contents = rv.json summary_content = _find_engagement_content(engagement_contents, EngagementContentType.Summary.name) @@ -162,7 +162,7 @@ def test_create_engagement_content_sort_invalid(client, jwt, session, engagement_content_info_1['engagement_id'] = engagement.id user, claims = setup_admin_user_and_claims headers = factory_auth_header(jwt=jwt, claims=claims) - rv = client.post('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.post(f'/api/engagement/{engagement.id}/content', data=json.dumps(engagement_content_info_1), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 200 @@ -176,7 +176,7 @@ def test_create_engagement_content_sort_invalid(client, jwt, session, 'sort_index': 1 } ] - rv = client.patch(f'/api/engagement_content/engagement/{engagement.id}/sort_index', + rv = client.patch(f'/api/engagement/{engagement.id}/content/sort_index', data=json.dumps(reorder_dict), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.BAD_REQUEST @@ -190,19 +190,19 @@ def test_delete_engagement_content(client, jwt, session, engagement_content_info_1['engagement_id'] = engagement.id user, claims = setup_admin_user_and_claims headers = factory_auth_header(jwt=jwt, claims=claims) - rv = client.post('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.post(f'/api/engagement/{engagement.id}/content', data=json.dumps(engagement_content_info_1), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 200 response_json = rv.json created_content_id = response_json.get('id') - rv = client.delete(f'/api/engagement_content/{created_content_id}/engagements/' + str(engagement.id), + rv = client.delete(f'/api/engagement/{engagement.id}/content/{created_content_id}', headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.OK - rv = client.post('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.post(f'/api/engagement/{engagement.id}/content', data=json.dumps(engagement_content_info_1), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 200 @@ -211,7 +211,7 @@ def test_delete_engagement_content(client, jwt, session, with patch.object(EngagementContentService, 'delete_engagement_content', side_effect=ValueError('Test error')): - rv = client.delete(f'/api/engagement_content/{created_content_id}/engagements/' + str(engagement.id), + rv = client.delete(f'/api/engagement/{engagement.id}/content/{created_content_id}', headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR @@ -224,7 +224,7 @@ def test_patch_engagement_content(client, jwt, session, engagement_content_info_1['engagement_id'] = engagement.id user, claims = setup_admin_user_and_claims headers = factory_auth_header(jwt=jwt, claims=claims) - rv = client.post('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.post(f'/api/engagement/{engagement.id}/content', data=json.dumps(engagement_content_info_1), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 200 @@ -234,7 +234,7 @@ def test_patch_engagement_content(client, jwt, session, data = { 'title': fake.text(max_nb_chars=10), } - rv = client.patch(f'/api/engagement_content/{created_content_id}/engagements/' + str(engagement.id), + rv = client.patch(f'/api/engagement/{engagement.id}/content/{created_content_id}', data=json.dumps(data), headers=headers, content_type=ContentType.JSON.value) @@ -243,14 +243,14 @@ def test_patch_engagement_content(client, jwt, session, with patch.object(EngagementContentService, 'update_engagement_content', side_effect=ValueError('Test error')): - rv = client.patch(f'/api/engagement_content/{created_content_id}/engagements/' + str(engagement.id), + rv = client.patch(f'/api/engagement/{engagement.id}/content/{created_content_id}', data=json.dumps(data), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR with patch.object(EngagementContentService, 'update_engagement_content', side_effect=ValidationError('Test error')): - rv = client.patch(f'/api/engagement_content/{created_content_id}/engagements/' + str(engagement.id), + rv = client.patch(f'/api/engagement/{engagement.id}/content/{created_content_id}', data=json.dumps(data), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR diff --git a/met-api/tests/unit/api/test_engagement_custom_content.py b/met-api/tests/unit/api/test_engagement_custom_content.py index d274cf97b..cf750d71c 100644 --- a/met-api/tests/unit/api/test_engagement_custom_content.py +++ b/met-api/tests/unit/api/test_engagement_custom_content.py @@ -33,6 +33,30 @@ fake = Faker() +@pytest.mark.parametrize('engagement_content_info', [TestEngagementContentInfo.content2]) +def test_default_engagement_custom_content_is_created(client, jwt, session, engagement_content_info, + setup_admin_user_and_claims): # pylint:disable=unused-argument + """Assert that a engagement custom content can be POSTed.""" + engagement = factory_engagement_model() + engagement_content_info['engagement_id'] = engagement.id + user, claims = setup_admin_user_and_claims + headers = factory_auth_header(jwt=jwt, claims=claims) + rv = client.post(f'/api/engagement/{engagement.id}/content', + data=json.dumps(engagement_content_info), + headers=headers, content_type=ContentType.JSON.value) + assert rv.status_code == 200 + response_json = rv.json + created_content_id = response_json.get('id') + + rv = client.get( + f'/api/content/{created_content_id}/custom', + headers=headers, + content_type=ContentType.JSON.value + ) + assert rv.status_code == HTTPStatus.OK.value + assert rv.json[0].get('custom_text_content') is None + + @pytest.mark.parametrize('engagement_content_info', [TestEngagementContentInfo.content2]) def test_engagement_custom_content(client, jwt, session, engagement_content_info, setup_admin_user_and_claims): # pylint:disable=unused-argument @@ -41,7 +65,7 @@ def test_engagement_custom_content(client, jwt, session, engagement_content_info engagement_content_info['engagement_id'] = engagement.id user, claims = setup_admin_user_and_claims headers = factory_auth_header(jwt=jwt, claims=claims) - rv = client.post('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.post(f'/api/engagement/{engagement.id}/content', data=json.dumps(engagement_content_info), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 200 @@ -56,7 +80,7 @@ def test_engagement_custom_content(client, jwt, session, engagement_content_info } rv = client.post( - f'/api/engagement_content/{created_content_id}/custom', + f'/api/content/{created_content_id}/custom', data=json.dumps(data), headers=headers, content_type=ContentType.JSON.value @@ -66,7 +90,7 @@ def test_engagement_custom_content(client, jwt, session, engagement_content_info with patch.object(EngagementCustomContentService, 'create_custom_content', side_effect=BusinessException('Test error', status_code=HTTPStatus.BAD_REQUEST)): rv = client.post( - f'/api/engagement_content/{created_content_id}/custom', + f'/api/content/{created_content_id}/custom', data=json.dumps(data), headers=headers, content_type=ContentType.JSON.value @@ -74,17 +98,17 @@ def test_engagement_custom_content(client, jwt, session, engagement_content_info assert rv.status_code == HTTPStatus.BAD_REQUEST rv = client.get( - f'/api/engagement_content/{created_content_id}/custom', + f'/api/content/{created_content_id}/custom', headers=headers, content_type=ContentType.JSON.value ) assert rv.status_code == HTTPStatus.OK.value - assert rv.json[0].get('custom_text_content') == data.get('custom_text_content') + assert rv.json[1].get('custom_text_content') == data.get('custom_text_content') with patch.object(EngagementCustomContentService, 'get_custom_content', side_effect=BusinessException('Test error', status_code=HTTPStatus.BAD_REQUEST)): rv = client.get( - f'/api/engagement_content/{created_content_id}/custom', + f'/api/content/{created_content_id}/custom', headers=headers, content_type=ContentType.JSON.value ) @@ -95,7 +119,7 @@ def test_engagement_custom_content(client, jwt, session, engagement_content_info } rv = client.patch( - f'/api/engagement_content/{created_content_id}/custom', + f'/api/content/{created_content_id}/custom', data=json.dumps(data_edits), headers=headers, content_type=ContentType.JSON.value @@ -103,7 +127,7 @@ def test_engagement_custom_content(client, jwt, session, engagement_content_info assert rv.status_code == HTTPStatus.OK rv = client.get( - f'/api/engagement_content/{created_content_id}/custom', + f'/api/content/{created_content_id}/custom', headers=headers, content_type=ContentType.JSON.value ) @@ -113,7 +137,7 @@ def test_engagement_custom_content(client, jwt, session, engagement_content_info with patch.object(EngagementCustomContentService, 'update_custom_content', side_effect=BusinessException('Test error', status_code=HTTPStatus.BAD_REQUEST)): rv = client.patch( - f'/api/engagement_content/{created_content_id}/custom', + f'/api/content/{created_content_id}/custom', data=json.dumps(data_edits), headers=headers, content_type=ContentType.JSON.value diff --git a/met-api/tests/unit/api/test_engagement_summary_content.py b/met-api/tests/unit/api/test_engagement_summary_content.py index 506982064..e9d61915e 100644 --- a/met-api/tests/unit/api/test_engagement_summary_content.py +++ b/met-api/tests/unit/api/test_engagement_summary_content.py @@ -41,7 +41,7 @@ def test_engagement_summary_content(client, jwt, session, engagement_content_inf engagement_content_info['engagement_id'] = engagement.id user, claims = setup_admin_user_and_claims headers = factory_auth_header(jwt=jwt, claims=claims) - rv = client.post('/api/engagement_content/engagement/' + str(engagement.id), + rv = client.post(f'/api/engagement/{engagement.id}/content', data=json.dumps(engagement_content_info), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == 200 @@ -56,7 +56,7 @@ def test_engagement_summary_content(client, jwt, session, engagement_content_inf } rv = client.post( - f'/api/engagement_content/{created_content_id}/summary', + f'/api/content/{created_content_id}/summary', data=json.dumps(data), headers=headers, content_type=ContentType.JSON.value @@ -66,7 +66,7 @@ def test_engagement_summary_content(client, jwt, session, engagement_content_inf with patch.object(EngagementSummaryContentService, 'create_summary_content', side_effect=BusinessException('Test error', status_code=HTTPStatus.BAD_REQUEST)): rv = client.post( - f'/api/engagement_content/{created_content_id}/summary', + f'/api/content/{created_content_id}/summary', data=json.dumps(data), headers=headers, content_type=ContentType.JSON.value @@ -74,7 +74,7 @@ def test_engagement_summary_content(client, jwt, session, engagement_content_inf assert rv.status_code == HTTPStatus.BAD_REQUEST rv = client.get( - f'/api/engagement_content/{created_content_id}/summary', + f'/api/content/{created_content_id}/summary', headers=headers, content_type=ContentType.JSON.value ) @@ -84,7 +84,7 @@ def test_engagement_summary_content(client, jwt, session, engagement_content_inf with patch.object(EngagementSummaryContentService, 'get_summary_content', side_effect=BusinessException('Test error', status_code=HTTPStatus.BAD_REQUEST)): rv = client.get( - f'/api/engagement_content/{created_content_id}/summary', + f'/api/content/{created_content_id}/summary', headers=headers, content_type=ContentType.JSON.value ) @@ -95,7 +95,7 @@ def test_engagement_summary_content(client, jwt, session, engagement_content_inf } rv = client.patch( - f'/api/engagement_content/{created_content_id}/summary', + f'/api/content/{created_content_id}/summary', data=json.dumps(data_edits), headers=headers, content_type=ContentType.JSON.value @@ -103,7 +103,7 @@ def test_engagement_summary_content(client, jwt, session, engagement_content_inf assert rv.status_code == HTTPStatus.OK rv = client.get( - f'/api/engagement_content/{created_content_id}/summary', + f'/api/content/{created_content_id}/summary', headers=headers, content_type=ContentType.JSON.value ) @@ -113,7 +113,7 @@ def test_engagement_summary_content(client, jwt, session, engagement_content_inf with patch.object(EngagementSummaryContentService, 'update_summary_content', side_effect=BusinessException('Test error', status_code=HTTPStatus.BAD_REQUEST)): rv = client.patch( - f'/api/engagement_content/{created_content_id}/summary', + f'/api/content/{created_content_id}/summary', data=json.dumps(data_edits), headers=headers, content_type=ContentType.JSON.value diff --git a/met-api/tests/unit/api/test_engagement_translation.py b/met-api/tests/unit/api/test_engagement_translation.py index ff1cf2c8a..c0eca545b 100644 --- a/met-api/tests/unit/api/test_engagement_translation.py +++ b/met-api/tests/unit/api/test_engagement_translation.py @@ -27,7 +27,7 @@ from met_api.exceptions.business_exception import BusinessException from met_api.services.engagement_translation_service import EngagementTranslationService from met_api.utils.enums import ContentType -from tests.utilities.factory_scenarios import TestEngagementTranslationInfo +from tests.utilities.factory_scenarios import TestEngagementInfo, TestEngagementTranslationInfo from tests.utilities.factory_utils import ( factory_auth_header, factory_engagement_model, factory_engagement_translation_model, factory_language_model) @@ -36,84 +36,93 @@ @pytest.mark.parametrize('engagement_translation_info', [TestEngagementTranslationInfo.engagementtranslation1]) -def test_create_engagement_translation(client, jwt, session, engagement_translation_info, +@pytest.mark.parametrize('engagement_info', [TestEngagementInfo.engagement1]) +def test_create_engagement_translation(client, jwt, session, engagement_translation_info, engagement_info, setup_admin_user_and_claims): # pylint:disable=unused-argument """Assert that a engagement translation can be POSTed.""" - engagement = factory_engagement_model() - language = factory_language_model({'name': 'French', 'code': 'FR', 'right_to_left': False}) - engagement_translation_info['engagement_id'] = engagement.id - engagement_translation_info['language_id'] = language.id 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 + engagement_id = rv.json.get('id') + language = factory_language_model({'name': 'French', 'code': 'FR', 'right_to_left': False}) + engagement_translation_info['engagement_id'] = engagement_id + engagement_translation_info['language_id'] = language.id - rv = client.post(f'/api/engagement/{engagement.id}/translations/', + rv = client.post(f'/api/engagement/{engagement_id}/translations/', data=json.dumps(engagement_translation_info), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.OK - rv = client.get(f'/api/engagement/{engagement.id}/translations/language/{language.id}', + rv = client.get(f'/api/engagement/{engagement_id}/translations/language/{language.id}', headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.OK - assert rv.json[0].get('engagement_id') == engagement.id + assert rv.json[0].get('engagement_id') == engagement_id with patch.object(EngagementTranslationService, 'create_engagement_translation', side_effect=ValueError('Test error')): - rv = client.post(f'/api/engagement/{engagement.id}/translations/', + rv = client.post(f'/api/engagement/{engagement_id}/translations/', data=json.dumps(engagement_translation_info), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR with patch.object(EngagementTranslationService, 'create_engagement_translation', side_effect=KeyError('Test error')): - rv = client.post(f'/api/engagement/{engagement.id}/translations/', + rv = client.post(f'/api/engagement/{engagement_id}/translations/', data=json.dumps(engagement_translation_info), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR with patch.object(EngagementTranslationService, 'create_engagement_translation', side_effect=ValidationError('Test error')): - rv = client.post(f'/api/engagement/{engagement.id}/translations/', + rv = client.post(f'/api/engagement/{engagement_id}/translations/', data=json.dumps(engagement_translation_info), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.BAD_REQUEST with patch.object(EngagementTranslationService, 'create_engagement_translation', side_effect=BusinessException('Test error', status_code=HTTPStatus.CONFLICT)): - rv = client.post(f'/api/engagement/{engagement.id}/translations/', + rv = client.post(f'/api/engagement/{engagement_id}/translations/', data=json.dumps(engagement_translation_info), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.CONFLICT @pytest.mark.parametrize('engagement_translation_info', [TestEngagementTranslationInfo.engagementtranslation1]) -def test_get_engagement_translation(client, jwt, session, engagement_translation_info, +@pytest.mark.parametrize('engagement_info', [TestEngagementInfo.engagement1]) +def test_get_engagement_translation(client, jwt, session, engagement_translation_info, engagement_info, setup_admin_user_and_claims): # pylint:disable=unused-argument """Assert that a engagement translation can be fetched.""" - engagement = factory_engagement_model() - language = factory_language_model({'name': 'French', 'code': 'FR', 'right_to_left': False}) - engagement_translation_info['engagement_id'] = engagement.id - engagement_translation_info['language_id'] = language.id user, claims = setup_admin_user_and_claims headers = factory_auth_header(jwt=jwt, claims=claims) - rv = client.post(f'/api/engagement/{engagement.id}/translations/', + rv = client.post('/api/engagements/', data=json.dumps(engagement_info), + headers=headers, content_type=ContentType.JSON.value) + assert rv.status_code == 200 + engagement_id = rv.json.get('id') + language = factory_language_model({'name': 'French', 'code': 'FR', 'right_to_left': False}) + engagement_translation_info['engagement_id'] = engagement_id + engagement_translation_info['language_id'] = language.id + + rv = client.post(f'/api/engagement/{engagement_id}/translations/', data=json.dumps(engagement_translation_info), headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.OK - rv = client.get(f'/api/engagement/{engagement.id}/translations/language/{language.id}', + rv = client.get(f'/api/engagement/{engagement_id}/translations/language/{language.id}', headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.OK - assert rv.json[0].get('engagement_id') == engagement.id + assert rv.json[0].get('engagement_id') == engagement_id with patch.object(EngagementTranslationService, 'get_translation_by_engagement_and_language', side_effect=ValueError('Test error')): - rv = client.get(f'/api/engagement/{engagement.id}/translations/language/{language.id}', + rv = client.get(f'/api/engagement/{engagement_id}/translations/language/{language.id}', headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR with patch.object(EngagementTranslationService, 'get_translation_by_engagement_and_language', side_effect=KeyError('Test error')): - rv = client.get(f'/api/engagement/{engagement.id}/translations/language/{language.id}', + rv = client.get(f'/api/engagement/{engagement_id}/translations/language/{language.id}', headers=headers, content_type=ContentType.JSON.value) assert rv.status_code == HTTPStatus.INTERNAL_SERVER_ERROR diff --git a/met-api/tests/unit/services/test_engagement.py b/met-api/tests/unit/services/test_engagement.py index e5e97c37e..08982d601 100644 --- a/met-api/tests/unit/services/test_engagement.py +++ b/met-api/tests/unit/services/test_engagement.py @@ -30,11 +30,11 @@ def test_create_engagement(session, monkeypatch): # pylint:disable=unused-argument """Assert that an Org can be created.""" + patch_token_info(TestJwtClaims.staff_admin_role, monkeypatch) + factory_staff_user_model(external_id=TestJwtClaims.staff_admin_role['sub']) engagement_data = TestEngagementInfo.engagement1 saved_engagament = EngagementService().create_engagement(engagement_data) # fetch the engagement with id and assert - patch_token_info(TestJwtClaims.staff_admin_role, monkeypatch) - factory_staff_user_model(external_id=TestJwtClaims.staff_admin_role['sub']) fetched_engagement = EngagementService().get_engagement(saved_engagament.id) assert fetched_engagement.get('id') == saved_engagament.id assert fetched_engagement.get('name') == engagement_data.get('name') @@ -45,10 +45,10 @@ def test_create_engagement(session, monkeypatch): # pylint:disable=unused-argum def test_create_engagement_with_survey_block(session, monkeypatch): # pylint:disable=unused-argument """Assert that an Org can be created.""" - engagement_data = TestEngagementInfo.engagement2 - saved_engagament = EngagementService().create_engagement(engagement_data) patch_token_info(TestJwtClaims.staff_admin_role, monkeypatch) factory_staff_user_model(external_id=TestJwtClaims.staff_admin_role['sub']) + engagement_data = TestEngagementInfo.engagement2 + saved_engagament = EngagementService().create_engagement(engagement_data) # fetch the engagement with id and assert fetched_engagement = EngagementService().get_engagement(saved_engagament.id) assert fetched_engagement.get('id') == saved_engagament.id @@ -68,7 +68,6 @@ def test_patch_engagement(session, monkeypatch): # pylint:disable=unused-argume 'start_date': saved_engagament_record.start_date, 'end_date': saved_engagament_record.end_date, 'description': saved_engagament_record.description, - 'content': saved_engagament_record.content, 'created_date': saved_engagament_record.created_date, 'status_id': saved_engagament_record.status_id, } @@ -79,7 +78,6 @@ def test_patch_engagement(session, monkeypatch): # pylint:disable=unused-argume 'start_date': fake.date(), 'end_date': fake.date(), 'description': fake.text(), - 'content': fake.text(), 'created_date': fake.date(), } @@ -91,5 +89,4 @@ def test_patch_engagement(session, monkeypatch): # pylint:disable=unused-argume assert updated_engagement_record.start_date.strftime(date_format) == engagement_edits.get('start_date') assert updated_engagement_record.end_date.strftime(date_format) == engagement_edits.get('end_date') assert updated_engagement_record.description == engagement_edits.get('description') - assert updated_engagement_record.content == engagement_edits.get('content') assert updated_engagement_record.created_date.strftime(date_format) == engagement_edits.get('created_date') diff --git a/met-api/tests/utilities/factory_scenarios.py b/met-api/tests/utilities/factory_scenarios.py index 37508402f..c6dc350bc 100644 --- a/met-api/tests/utilities/factory_scenarios.py +++ b/met-api/tests/utilities/factory_scenarios.py @@ -245,9 +245,6 @@ class TestEngagementInfo(dict, Enum): 'description': 'My Test Engagement Description', 'rich_description': '"{\"blocks\":[{\"key\":\"2ku94\",\"text\":\"Rich Description Sample\",\"type\":\"unstyled\",\ \"depth\":0,\"inlineStyleRanges\":[],\"entityRanges\":[],\"data\":{}}],\"entityMap\":{}}"', - 'content': 'Content Sample', - 'rich_content': '"{\"blocks\":[{\"key\":\"fclgj\",\"text\":\"Rich Content Sample\",\"type\":\"unstyled\",\"depth\":0,\ - \"inlineStyleRanges\":[],\"entityRanges\":[],\"data\":{}}],\"entityMap\":{}}"' } diff --git a/met-api/tests/utilities/factory_utils.py b/met-api/tests/utilities/factory_utils.py index 522dd6f22..1481dde6f 100644 --- a/met-api/tests/utilities/factory_utils.py +++ b/met-api/tests/utilities/factory_utils.py @@ -162,8 +162,6 @@ def factory_engagement_model(eng_info: dict = TestEngagementInfo.engagement1, na name=name if name else fake.name(), description=eng_info.get('description'), rich_description=eng_info.get('rich_description'), - content=eng_info.get('content'), - rich_content=eng_info.get('rich_content'), created_by=eng_info.get('created_by'), updated_by=eng_info.get('updated_by'), status_id=status if status else eng_info.get('status'),