From ec1aa293d0e70ff1da08bcd7085162c52251c4bb Mon Sep 17 00:00:00 2001 From: Jumana B Date: Wed, 2 Oct 2024 10:36:28 -0400 Subject: [PATCH] start removal of FF_TEMPLATE_CATEGORY (#1960) * start removal of FF_TEMPLATE_CATEGORY * remove FF * test(templates): update test to work without `FF_TEMPLATE_CATEGORY` * chore(test_templates): rename variable --------- Co-authored-by: Andrew Leith --- app/config.py | 3 - app/main/forms.py | 40 --- app/main/views/api_keys.py | 69 ++-- app/main/views/templates.py | 133 +++----- app/templates/views/edit-email-template.html | 10 +- app/templates/views/edit-sms-template.html | 12 +- .../views/templates/_template_list.html | 4 - app/templates/views/templates/choose.html | 16 +- tests/app/main/views/test_template_folders.py | 15 +- tests/app/main/views/test_templates.py | 304 ++++++++---------- .../e2e/admin/template/create-template.cy.js | 71 ---- 11 files changed, 224 insertions(+), 453 deletions(-) diff --git a/app/config.py b/app/config.py index 9bb4137355..3b0f3d92c5 100644 --- a/app/config.py +++ b/app/config.py @@ -80,7 +80,6 @@ class Config(object): # FEATURE FLAGS FF_NEW_BRANDING = env.bool("FF_NEW_BRANDING", False) FF_SALESFORCE_CONTACT = env.bool("FF_SALESFORCE_CONTACT", True) - FF_TEMPLATE_CATEGORY = env.bool("FF_TEMPLATE_CATEGORY", False) FF_TOU = env.bool("FF_TOU", False) FREE_YEARLY_EMAIL_LIMIT = env.int("FREE_YEARLY_EMAIL_LIMIT", 10_000_000) @@ -222,7 +221,6 @@ class Test(Development): FF_ABTEST_SERVICE_ID = "" FF_NEW_BRANDING = True FF_TOU = True - FF_TEMPLATE_CATEGORY = True class ProductionFF(Config): @@ -256,7 +254,6 @@ class ProductionFF(Config): FF_ABTEST_SERVICE_ID = "" FF_NEW_BRANDING = True FF_TOU = False - FF_TEMPLATE_CATEGORY = False class Production(Config): diff --git a/app/main/forms.py b/app/main/forms.py index 809a1f3b67..5446032d1f 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -797,46 +797,6 @@ class BaseTemplateForm(StripWhitespaceForm): ) -# TODO: Remove this class when FF_TEMPLATE_CATEGORY is removed -class SMSTemplateForm(BaseTemplateForm): - def validate_template_content(self, field): - OnlySMSCharacters()(None, field) - - template_content = TextAreaField( - _l("Text message"), - validators=[ - DataRequired(message=_l("This cannot be empty")), - NoCommasInPlaceHolders(), - ], - ) - - -# TODO: Remove this class when FF_TEMPLATE_CATEGORY is removed -class EmailTemplateForm(BaseTemplateForm): - subject = TextAreaField(_l("Subject line of the email"), validators=[DataRequired(message=_l("This cannot be empty"))]) - - template_content = TextAreaField( - _l("Email message"), - validators=[ - DataRequired(message=_l("This cannot be empty")), - NoCommasInPlaceHolders(), - ], - ) - - -# TODO: Remove this class when FF_TEMPLATE_CATEGORY is removed -class LetterTemplateForm(EmailTemplateForm): - subject = TextAreaField("Main heading", validators=[DataRequired(message="This cannot be empty")]) - - template_content = TextAreaField( - "Body", - validators=[ - DataRequired(message="This cannot be empty"), - NoCommasInPlaceHolders(), - ], - ) - - class RequiredIf(InputRequired): # a validator which makes a field required if # another field is set and has a truthy value diff --git a/app/main/views/api_keys.py b/app/main/views/api_keys.py index a86a6722e3..8b5100d578 100644 --- a/app/main/views/api_keys.py +++ b/app/main/views/api_keys.py @@ -28,13 +28,11 @@ @main.route("/services//api") @user_has_permissions("manage_api_keys") def api_integration(service_id): - callbacks_link = ".api_callbacks" if current_service.has_permission( - "inbound_sms") else ".delivery_status_callback" + callbacks_link = ".api_callbacks" if current_service.has_permission("inbound_sms") else ".delivery_status_callback" return render_template( "views/api/index.html", callbacks_link=callbacks_link, - api_notifications=notification_api_client.get_api_notifications_for_service( - service_id), + api_notifications=notification_api_client.get_api_notifications_for_service(service_id), ) @@ -89,8 +87,7 @@ def create_api_key(service_id): disabled_options, option_hints = [], {} if current_service.trial_mode: disabled_options = [KEY_TYPE_NORMAL] - option_hints[KEY_TYPE_NORMAL] = Markup( - _l("Not available because your service is in trial mode.")) + option_hints[KEY_TYPE_NORMAL] = Markup(_l("Not available because your service is in trial mode.")) if current_service.has_permission("letter"): option_hints[KEY_TYPE_TEAM] = "" if form.validate_on_submit(): @@ -122,8 +119,7 @@ def revoke_api_key(service_id, key_id): if request.method == "GET": flash( [ - "{} ‘{}’?".format( - _l("Are you sure you want to revoke"), key_name), + "{} ‘{}’?".format(_l("Are you sure you want to revoke"), key_name), _l("You will not be able to use this API key to connect to GC Notify"), ], "revoke this API key", @@ -141,11 +137,9 @@ def get_apis(): callback_api = None inbound_api = None if current_service.service_callback_api: - callback_api = service_api_client.get_service_callback_api( - current_service.id, current_service.service_callback_api[0]) + callback_api = service_api_client.get_service_callback_api(current_service.id, current_service.service_callback_api[0]) if current_service.inbound_api: - inbound_api = service_api_client.get_service_inbound_api( - current_service.id, current_service.inbound_api[0]) + inbound_api = service_api_client.get_service_inbound_api(current_service.id, current_service.inbound_api[0]) return (callback_api, inbound_api) @@ -167,8 +161,7 @@ def api_callbacks(service_id): return render_template( "views/api/callbacks.html", - received_text_messages_callback=received_text_messages_callback[ - "url"] if received_text_messages_callback else None, + received_text_messages_callback=received_text_messages_callback["url"] if received_text_messages_callback else None, delivery_status_callback=delivery_status_callback["url"] if delivery_status_callback else None, ) @@ -182,8 +175,7 @@ def get_delivery_status_callback_details(): @user_has_permissions("manage_api_keys") def delete_delivery_status_callback(service_id): delivery_status_callback = get_delivery_status_callback_details() - back_link = ".api_callbacks" if current_service.has_permission( - "inbound_sms") else ".api_integration" + back_link = ".api_callbacks" if current_service.has_permission("inbound_sms") else ".api_integration" url_hint_txt = "Must start with https://" if request.method == "POST": @@ -193,23 +185,19 @@ def delete_delivery_status_callback(service_id): delivery_status_callback["id"], ) - flash(_l("Your Callback configuration has been deleted."), - "default_with_tick") + flash(_l("Your Callback configuration has been deleted."), "default_with_tick") return redirect(url_for(back_link, service_id=service_id)) - flash(["{}".format( - _l("Are you sure you want to delete this callback configuration?"))], "delete") + flash(["{}".format(_l("Are you sure you want to delete this callback configuration?"))], "delete") form = ServiceDeliveryStatusCallbackForm( - url=delivery_status_callback.get( - "url") if delivery_status_callback else "", + url=delivery_status_callback.get("url") if delivery_status_callback else "", bearer_token=dummy_bearer_token if delivery_status_callback else "", ) return render_template( "views/api/callbacks/delivery-status-callback.html", - back_link=".api_callbacks" if current_service.has_permission( - "inbound_sms") else ".delivery_status_callback", + back_link=".api_callbacks" if current_service.has_permission("inbound_sms") else ".delivery_status_callback", hint_text=url_hint_txt, is_deleting=True, form=form, @@ -223,13 +211,11 @@ def delete_delivery_status_callback(service_id): @user_has_permissions("manage_api_keys") def delivery_status_callback(service_id): delivery_status_callback = get_delivery_status_callback_details() - back_link = ".api_callbacks" if current_service.has_permission( - "inbound_sms") else ".api_integration" + back_link = ".api_callbacks" if current_service.has_permission("inbound_sms") else ".api_integration" url_hint_txt = _l("Must start with https://") form = ServiceDeliveryStatusCallbackForm( - url=delivery_status_callback.get( - "url") if delivery_status_callback else "", + url=delivery_status_callback.get("url") if delivery_status_callback else "", bearer_token=dummy_bearer_token if delivery_status_callback else "", ) @@ -244,8 +230,7 @@ def delivery_status_callback(service_id): service_api_client.update_service_callback_api( service_id, url=form.url.data, - bearer_token=check_token_against_dummy_bearer( - form.bearer_token.data), + bearer_token=check_token_against_dummy_bearer(form.bearer_token.data), user_id=current_user.id, callback_api_id=delivery_status_callback.get("id"), ) @@ -352,13 +337,11 @@ def get_received_text_messages_callback(): def received_text_messages_callback(service_id): if not current_service.has_permission("inbound_sms"): return redirect(url_for(".api_integration", service_id=service_id)) - back_link = ".api_callbacks" if current_service.has_permission( - "inbound_sms") else ".api_integration" + back_link = ".api_callbacks" if current_service.has_permission("inbound_sms") else ".api_integration" received_text_messages_callback = get_received_text_messages_callback() form = ServiceReceiveMessagesCallbackForm( - url=received_text_messages_callback.get( - "url") if received_text_messages_callback else "", + url=received_text_messages_callback.get("url") if received_text_messages_callback else "", bearer_token=dummy_bearer_token if received_text_messages_callback else "", ) url_hint_txt = _l("Must start with https://") @@ -373,8 +356,7 @@ def received_text_messages_callback(service_id): service_api_client.update_service_inbound_api( service_id, url=form.url.data, - bearer_token=check_token_against_dummy_bearer( - form.bearer_token.data), + bearer_token=check_token_against_dummy_bearer(form.bearer_token.data), user_id=current_user.id, inbound_api_id=received_text_messages_callback.get("id"), ) @@ -469,8 +451,7 @@ def received_text_messages_callback(service_id): @user_has_permissions("manage_api_keys") def delete_received_text_messages_callback(service_id): received_text_messages_callback = get_received_text_messages_callback() - back_link = ".api_callbacks" if current_service.has_permission( - "inbound_sms") else ".api_integration" + back_link = ".api_callbacks" if current_service.has_permission("inbound_sms") else ".api_integration" url_hint_txt = "Must start with https://" if request.method == "POST": @@ -480,23 +461,19 @@ def delete_received_text_messages_callback(service_id): received_text_messages_callback["id"], ) - flash(_l("Your Callback configuration has been deleted."), - "default_with_tick") + flash(_l("Your Callback configuration has been deleted."), "default_with_tick") return redirect(url_for(back_link, service_id=service_id)) - flash(["{}".format( - _l("Are you sure you want to delete this callback configuration?"))], "delete") + flash(["{}".format(_l("Are you sure you want to delete this callback configuration?"))], "delete") form = ServiceReceiveMessagesCallbackForm( - url=received_text_messages_callback.get( - "url") if delivery_status_callback else "", + url=received_text_messages_callback.get("url") if delivery_status_callback else "", bearer_token=dummy_bearer_token if received_text_messages_callback else "", ) return render_template( "views/api/callbacks/delivery-status-callback.html", - back_link=".api_callbacks" if current_service.has_permission( - "inbound_sms") else ".delivery_status_callback", + back_link=".api_callbacks" if current_service.has_permission("inbound_sms") else ".delivery_status_callback", hint_text=url_hint_txt, is_deleting=True, form=form, diff --git a/app/main/views/templates.py b/app/main/views/templates.py index 415d974dc0..78cd2e1b29 100644 --- a/app/main/views/templates.py +++ b/app/main/views/templates.py @@ -39,14 +39,11 @@ AddEmailRecipientsForm, AddSMSRecipientsForm, CreateTemplateForm, - EmailTemplateForm, # remove when FF_TEMPLATE_CATEGORY is removed EmailTemplateFormWithCategory, - LetterTemplateForm, LetterTemplateFormWithCategory, LetterTemplatePostageForm, SearchByNameForm, SetTemplateSenderForm, - SMSTemplateForm, # remove when FF_TEMPLATE_CATEGORY is removed SMSTemplateFormWithCategory, TemplateAndFoldersSelectionForm, TemplateCategoryForm, @@ -54,7 +51,6 @@ ) from app.main.views.send import get_example_csv_rows, get_sender_details from app.models.enum.template_categories import DefaultTemplateCategories -from app.models.enum.template_process_types import TemplateProcessTypes from app.models.service import Service from app.models.template_list import ( TEMPLATE_TYPES_NO_LETTER, @@ -70,13 +66,6 @@ user_is_platform_admin, ) -# TODO: Remove `form_objects` when FF_TEMPLATE_CATEGORY IS REMOVED -form_objects = { - "email": EmailTemplateForm, - "sms": SMSTemplateForm, - "letter": LetterTemplateForm, -} - # Todo: Remove this once the process_types in the backend are updated to use low/med/high category_mapping = { "bulk": "Bulk", @@ -190,7 +179,7 @@ def preview_template(service_id, template_id=None): service_id, template["subject"], None if template["process_type"] == TC_PRIORITY_VALUE else template["process_type"], - template["template_category_id"] if current_app.config["FF_TEMPLATE_CATEGORY"] else None, + template["template_category_id"], ) else: new_template = service_api_client.create_service_template( @@ -201,7 +190,7 @@ def preview_template(service_id, template_id=None): template["subject"], None if template["process_type"] == TC_PRIORITY_VALUE else template["process_type"], template["folder"], - template["template_category_id"] if current_app.config["FF_TEMPLATE_CATEGORY"] else None, + template["template_category_id"], ) template_id = new_template["data"]["id"] @@ -600,12 +589,7 @@ def copy_template(service_id, template_id): template["template_content"] = template["content"] template["name"] = _get_template_copy_name(template, current_service.all_templates) - if current_app.config["FF_TEMPLATE_CATEGORY"]: # TODO: remove when FF_TEMPLATE_CATEGORY removed - form, other_category, template_category_hints = _get_categories_and_prepare_form(template, template["template_type"]) - else: # TODO: remove when FF_TEMPLATE_CATEGORY removed - other_category = None - template_category_hints = None - form = form_objects[template["template_type"]](**template) # TODO: remove when FF_TEMPLATE_CATEGORY removed + form, other_category, template_category_hints = _get_categories_and_prepare_form(template, template["template_type"]) return render_template( f"views/edit-{template['template_type']}-template.html", form=form, @@ -766,22 +750,11 @@ def add_service_template(service_id, template_type, template_folder_id=None): # template = get_preview_data(service_id) - if current_app.config["FF_TEMPLATE_CATEGORY"]: # TODO: remove when FF_TEMPLATE_CATEGORY removed - form, other_category, template_category_hints = _get_categories_and_prepare_form(template, template_type) - else: # TODO: remove when FF_TEMPLATE_CATEGORY removed - if template.get("process_type") is None: - template["process_type"] = TemplateProcessTypes.BULK.value - other_category = None - template_category_hints = None - form = form_objects[template_type](**template) # TODO: remove when FF_TEMPLATE_CATEGORY removed + form, other_category, template_category_hints = _get_categories_and_prepare_form(template, template_type) if form.validate_on_submit(): - if current_app.config["FF_TEMPLATE_CATEGORY"]: # TODO: remove when FF_TEMPLATE_CATEGORY removed - if form.process_type.data != TC_PRIORITY_VALUE: - abort_403_if_not_admin_user() - else: # TODO: remove when FF_TEMPLATE_CATEGORY removed - if form.process_type.data != TemplateProcessTypes.BULK.value: # TODO: remove when FF_TEMPLATE_CATEGORY removed - abort_403_if_not_admin_user() # TODO: remove when FF_TEMPLATE_CATEGORY removed + if form.process_type.data != TC_PRIORITY_VALUE: + abort_403_if_not_admin_user() subject = form.subject.data if hasattr(form, "subject") else None if request.form.get("button_pressed") == "preview": preview_template_data = { @@ -793,7 +766,7 @@ def add_service_template(service_id, template_type, template_folder_id=None): # "id": None, "process_type": form.process_type.data, "folder": template_folder_id, - "template_category_id": form.template_category_id.data if current_app.config["FF_TEMPLATE_CATEGORY"] else None, + "template_category_id": form.template_category_id.data, } set_preview_data(preview_template_data, service_id) return redirect( @@ -811,29 +784,27 @@ def add_service_template(service_id, template_type, template_folder_id=None): # subject, None if form.process_type.data == TC_PRIORITY_VALUE else form.process_type.data, template_folder_id, - form.template_category_id.data if current_app.config["FF_TEMPLATE_CATEGORY"] else None, + form.template_category_id.data, ) # Send the information in form's template_category_other field to Freshdesk - # This code path is a little complex - We do not want to raise an error if the request to Freshdesk fails, only if template creation fails - if current_app.config["FF_TEMPLATE_CATEGORY"]: - if form.template_category_other.data: - is_english = get_current_locale(current_app) == "en" - try: - current_user.send_new_template_category_request( - current_user.id, - current_service.id, - form.template_category_other.data if is_english else None, - form.template_category_other.data if not is_english else None, - new_template["data"]["id"], - ) - except HTTPError as e: - current_app.logger.error( - f"Failed to send new template category request to Freshdesk: {e} for template {new_template['data']['id']}, data is {form.template_category_other.data}" - ) - except AttributeError as e: - current_app.logger.error( - f"Failed to send new template category request to Freshdesk: {e} for template {new_template['data']['id']}, data is {form.template_category_other.data}" - ) + if form.template_category_other.data: + is_english = get_current_locale(current_app) == "en" + try: + current_user.send_new_template_category_request( + current_user.id, + current_service.id, + form.template_category_other.data if is_english else None, + form.template_category_other.data if not is_english else None, + new_template["data"]["id"], + ) + except HTTPError as e: + current_app.logger.error( + f"Failed to send new template category request to Freshdesk: {e} for template {new_template['data']['id']}, data is {form.template_category_other.data}" + ) + except AttributeError as e: + current_app.logger.error( + f"Failed to send new template category request to Freshdesk: {e} for template {new_template['data']['id']}, data is {form.template_category_other.data}" + ) except HTTPError as e: if ( e.status_code == 400 @@ -918,7 +889,7 @@ def _get_categories_and_prepare_form(template, template_type): @main.route("/services//templates//edit", methods=["GET", "POST"]) @user_has_permissions("manage_templates") -def edit_service_template(service_id, template_id): # noqa: C901 TODO: remove this comment when FF_TEMPLATE_CATEGORY removed +def edit_service_template(service_id, template_id): template = current_service.get_template_with_user_permission_or_403(template_id, current_user) new_template_data = get_preview_data(service_id, template_id) @@ -929,17 +900,9 @@ def edit_service_template(service_id, template_id): # noqa: C901 TODO: remove t template["template_content"] = template["content"] if template.get("process_type_column") is None: - if current_app.config["FF_TEMPLATE_CATEGORY"]: # TODO: remove when FF_TEMPLATE_CATEGORY removed - template["process_type"] = TC_PRIORITY_VALUE - else: # TODO: remove when FF_TEMPLATE_CATEGORY removed - template["process_type"] = TemplateProcessTypes.BULK.value # TODO: remove when FF_TEMPLATE_CATEGORY removed - - if current_app.config["FF_TEMPLATE_CATEGORY"]: # TODO: remove when FF_TEMPLATE_CATEGORY removed - form, other_category, template_category_hints = _get_categories_and_prepare_form(template, template["template_type"]) - else: # TODO: remove when FF_TEMPLATE_CATEGORY removed - other_category = None # TODO: remove when FF_TEMPLATE_CATEGORY removed - template_category_hints = None # TODO: remove when FF_TEMPLATE_CATEGORY removed - form = form_objects[template["template_type"]](**template) # TODO: remove when FF_TEMPLATE_CATEGORY removed + template["process_type"] = TC_PRIORITY_VALUE + + form, other_category, template_category_hints = _get_categories_and_prepare_form(template, template["template_type"]) if form.validate_on_submit(): if form.process_type.data != template["process_type"]: @@ -956,7 +919,7 @@ def edit_service_template(service_id, template_id): # noqa: C901 TODO: remove t "process_type": form.process_type.data, "reply_to_text": template["reply_to_text"], "folder": template["folder"], - "template_category_id": form.template_category_id.data if current_app.config["FF_TEMPLATE_CATEGORY"] else None, + "template_category_id": form.template_category_id.data, } set_preview_data(new_template_data, service_id, template_id) @@ -995,25 +958,24 @@ def edit_service_template(service_id, template_id): # noqa: C901 TODO: remove t service_id, subject, None if form.process_type.data == TC_PRIORITY_VALUE else form.process_type.data, - form.template_category_id.data if current_app.config["FF_TEMPLATE_CATEGORY"] else None, + form.template_category_id.data, ) # Send the information in form's template_category_other field to Freshdesk # This code path is a little complex - We do not want to raise an error if the request to Freshdesk fails, only if template creation fails - if current_app.config["FF_TEMPLATE_CATEGORY"]: - if form.template_category_other.data: - is_english = get_current_locale(current_app) == "en" - try: - current_user.send_new_template_category_request( - current_user.id, - current_service.id, - form.template_category_other.data if is_english else None, - form.template_category_other.data if not is_english else None, - template_id, - ) - except HTTPError as e: - current_app.logger.error( - f"Failed to send new template category request to Freshdesk: {e} for template {template_id}, data is {form.template_category_other.data}" - ) + if form.template_category_other.data: + is_english = get_current_locale(current_app) == "en" + try: + current_user.send_new_template_category_request( + current_user.id, + current_service.id, + form.template_category_other.data if is_english else None, + form.template_category_other.data if not is_english else None, + template_id, + ) + except HTTPError as e: + current_app.logger.error( + f"Failed to send new template category request to Freshdesk: {e} for template {template_id}, data is {form.template_category_other.data}" + ) flash(_("'{}' template saved").format(form.name.data), "default_with_tick") return redirect( url_for( @@ -1233,7 +1195,8 @@ def get_template_sender_form_dict(service_id, template): context["no_senders"] = True context["value_and_label"] = [(sender["id"], Markup(nl2br(sender[sender_format]))) for sender in service_senders] - context["value_and_label"].insert(0, ("", "Blank")) # Add blank option to start of list + # Add blank option to start of list + context["value_and_label"].insert(0, ("", "Blank")) context["current_choice"] = template["service_letter_contact"] if template["service_letter_contact"] else "" return context diff --git a/app/templates/views/edit-email-template.html b/app/templates/views/edit-email-template.html index ef97201654..795a7906a6 100644 --- a/app/templates/views/edit-email-template.html +++ b/app/templates/views/edit-email-template.html @@ -53,12 +53,10 @@ {{ textbox(form.template_content, highlight_tags=True, width='w-full', rows=8, testid="template-content" ) }} - {% if config["FF_TEMPLATE_CATEGORY"] %} -

{{ _('Template category') }}

- {% call template_category(form.template_category_id, true if template_category_mode == 'expand' else false) %} - {{ select(form.template_category_id, hint=_('Template categories help improve delivery of your messages'), option_hints=template_category_hints, option_conditionals=other_category, testid="template-categories", use_aria_labelledby=false) }} - {% endcall %} - {% endif %} +

{{ _('Template category') }}

+ {% call template_category(form.template_category_id, true if template_category_mode == 'expand' else false) %} + {{ select(form.template_category_id, hint=_('Template categories help improve delivery of your messages'), option_hints=template_category_hints, option_conditionals=other_category, testid="template-categories", use_aria_labelledby=false) }} + {% endcall %} {% if current_user.platform_admin %} {{ radios(form.process_type, hint=_('This is only manageable by platform admins'), use_aria_labelledby=false) }} diff --git a/app/templates/views/edit-sms-template.html b/app/templates/views/edit-sms-template.html index 5cc647cbe2..1c92aed70f 100644 --- a/app/templates/views/edit-sms-template.html +++ b/app/templates/views/edit-sms-template.html @@ -39,13 +39,11 @@
{{ textbox(form.template_content, highlight_tags=True, width='w-full', rows=5, hint=_('Maximum 612 characters. Some messages may be too long due to custom content.'), testid="template-content") }} - {% if config["FF_TEMPLATE_CATEGORY"] %} -

{{ _('Template category') }}

- {% call template_category(form.template_category_id, true if template_category_mode == 'expand' else false) %} - {{ select(form.template_category_id, hint=_('Template categories help improve delivery of your messages'), option_hints=template_category_hints, option_conditionals=other_category, testid="template-categories", use_aria_labelledby=false) }} - {% endcall %} - {% endif %} - +

{{ _('Template category') }}

+ {% call template_category(form.template_category_id, true if template_category_mode == 'expand' else false) %} + {{ select(form.template_category_id, hint=_('Template categories help improve delivery of your messages'), option_hints=template_category_hints, option_conditionals=other_category, testid="template-categories", use_aria_labelledby=false) }} + {% endcall %} + {% if current_user.platform_admin %} {{ radios(form.process_type, hint=_('This is only manageable by platform admins'), use_aria_labelledby=false) }} {% endif %} diff --git a/app/templates/views/templates/_template_list.html b/app/templates/views/templates/_template_list.html index 1f8ea6d19e..e9eee5e55b 100644 --- a/app/templates/views/templates/_template_list.html +++ b/app/templates/views/templates/_template_list.html @@ -64,7 +64,6 @@ {# Compose hint + "template" IF it has a type. ELSE just print the hint #} {{ _("{} template").format(_(item.hint)) | capitalize if item.type else _(item.hint) }} - {% if config["FF_TEMPLATE_CATEGORY"] %} {% if not item.template_category.hidden %} {{ item.template_category[template_category_name_col] }} @@ -72,16 +71,13 @@ {{ _('Other') }} {% endif %} - {% endif %}
{% endfor %} - {% if config["FF_TEMPLATE_CATEGORY"] %} {% if template_list_length > 0 %}
{{ empty_list(_('No matching templates'), _('Change your filters or search for more templates'), 'emptyBirdHole') }}
{% endif %} - {% endif %} {% if display_checkboxes %} diff --git a/app/templates/views/templates/choose.html b/app/templates/views/templates/choose.html index ee040c3f2e..abc2393676 100644 --- a/app/templates/views/templates/choose.html +++ b/app/templates/views/templates/choose.html @@ -77,16 +77,12 @@

{% endif %} {% if show_template_nav %}
- {% if config["FF_TEMPLATE_CATEGORY"] %} - {{ - template_filter(".template-list-item", template_types, template_categories, - "data-notification-type", - "data-template-category" - ) - }} - {% else %} - {{ pill(template_nav_items, current_value=template_type, show_count=False, label=_("Filter by template type")) }} - {% endif %} + {{ + template_filter(".template-list-item", template_types, template_categories, + "data-notification-type", + "data-template-category" + ) + }}
{% endif %} diff --git a/tests/app/main/views/test_template_folders.py b/tests/app/main/views/test_template_folders.py index 727d642e0a..ae89d74502 100644 --- a/tests/app/main/views/test_template_folders.py +++ b/tests/app/main/views/test_template_folders.py @@ -5,7 +5,6 @@ from notifications_python_client.errors import HTTPError from app.main.forms import TC_PRIORITY_VALUE -from app.models.enum.template_process_types import TemplateProcessTypes from app.models.service import Service from app.models.user import User from tests import TESTING_TEMPLATE_CATEGORY, sample_uuid @@ -314,12 +313,8 @@ def test_should_show_templates_folder_page( assert normalize_spaces(page.select_one("title").text) == expected_title_tag assert normalize_spaces(page.select_one("h1").text) == expected_page_title - if app_.config["FF_TEMPLATE_CATEGORY"]: - expected_nav_links = ["All", "Email", "Text message", "All"] - links_in_page = page.select('nav[data-testid="filter-content"] a') - else: - expected_nav_links = ["All", "Email", "Text message", "Letter"] - links_in_page = page.select(".pill a") + expected_nav_links = ["All", "Email", "Text message", "All"] + links_in_page = page.select('nav[data-testid="filter-content"] a') assert len(links_in_page) == len(expected_nav_links) @@ -386,7 +381,7 @@ def test_can_create_email_template_with_parent_folder( "template_type": "email", "template_category_id": TESTING_TEMPLATE_CATEGORY, "service": SERVICE_ONE_ID, - "process_type": TC_PRIORITY_VALUE if app_.config["FF_TEMPLATE_CATEGORY"] else TemplateProcessTypes.BULK.value, + "process_type": TC_PRIORITY_VALUE, "parent_folder_id": PARENT_FOLDER_ID, } client_request.post( @@ -403,9 +398,9 @@ def test_can_create_email_template_with_parent_folder( data["template_content"], SERVICE_ONE_ID, data["subject"], - None if app_.config["FF_TEMPLATE_CATEGORY"] else data["process_type"], + None, data["parent_folder_id"], - data["template_category_id"] if app_.config["FF_TEMPLATE_CATEGORY"] else None, + data["template_category_id"], ) diff --git a/tests/app/main/views/test_templates.py b/tests/app/main/views/test_templates.py index 99f790483c..cbd36c275d 100644 --- a/tests/app/main/views/test_templates.py +++ b/tests/app/main/views/test_templates.py @@ -49,7 +49,6 @@ fake_uuid, mock_get_service_template_with_process_type, normalize_spaces, - set_config, ) DEFAULT_PROCESS_TYPE = TemplateProcessTypes.BULK.value @@ -118,29 +117,28 @@ def test_create_email_template_cat_other_to_freshdesk( fake_uuid, app_, ): - with set_config(app_, "FF_TEMPLATE_CATEGORY", True): - client_request.post( - ".add_service_template", - service_id=SERVICE_ONE_ID, - template_type="email", - _data={ - "name": "new name", - "subject": "Food incoming!", - "template_content": "here's a burrito 🌯", - "template_type": "email", - "template_category_id": TESTING_TEMPLATE_CATEGORY, - "service": SERVICE_ONE_ID, - "process_type": None if app_.config["FF_TEMPLATE_CATEGORY"] else DEFAULT_PROCESS_TYPE, - "button_pressed": "save", - "template_category_other": "hello", - }, - _follow_redirects=True, - ) - assert mock_create_service_template.called is True - assert mock_send_other_category_to_freshdesk.called is True - mock_send_other_category_to_freshdesk.assert_called_once_with( - active_user_with_permissions["id"], SERVICE_ONE_ID, "hello", None, fake_uuid - ) + client_request.post( + ".add_service_template", + service_id=SERVICE_ONE_ID, + template_type="email", + _data={ + "name": "new name", + "subject": "Food incoming!", + "template_content": "here's a burrito 🌯", + "template_type": "email", + "template_category_id": TESTING_TEMPLATE_CATEGORY, + "service": SERVICE_ONE_ID, + "process_type": None, + "button_pressed": "save", + "template_category_other": "hello", + }, + _follow_redirects=True, + ) + assert mock_create_service_template.called is True + assert mock_send_other_category_to_freshdesk.called is True + mock_send_other_category_to_freshdesk.assert_called_once_with( + active_user_with_permissions["id"], SERVICE_ONE_ID, "hello", None, fake_uuid + ) def test_edit_email_template_cat_other_to_freshdesk( self, @@ -153,42 +151,41 @@ def test_edit_email_template_cat_other_to_freshdesk( fake_uuid, app_, ): - with set_config(app_, "FF_TEMPLATE_CATEGORY", True): - mock_get_service_template_with_process_type(mocker, "bulk", None) - name = "new name" - content = "template content with & entity" - client_request.post( - ".edit_service_template", - service_id=SERVICE_ONE_ID, - template_id=fake_uuid, - _data={ - "id": fake_uuid, - "name": name, - "template_content": content, - "template_type": "sms", - "template_category_id": DEFAULT_TEMPLATE_CATEGORY_LOW if app_.config["FF_TEMPLATE_CATEGORY"] else None, - "service": SERVICE_ONE_ID, - "template_category_other": "hello", - "reply_to_text": "reply@go.com", - "process_type": None if app_.config["FF_TEMPLATE_CATEGORY"] else DEFAULT_PROCESS_TYPE, - }, - _follow_redirects=True, - ) + mock_get_service_template_with_process_type(mocker, "bulk", None) + name = "new name" + content = "template content with & entity" + client_request.post( + ".edit_service_template", + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + _data={ + "id": fake_uuid, + "name": name, + "template_content": content, + "template_type": "sms", + "template_category_id": DEFAULT_TEMPLATE_CATEGORY_LOW, + "service": SERVICE_ONE_ID, + "template_category_other": "hello", + "reply_to_text": "reply@go.com", + "process_type": None, + }, + _follow_redirects=True, + ) - mock_update_service_template.assert_called_with( - fake_uuid, - name, - "sms", - content, - SERVICE_ONE_ID, - None, - None if app_.config["FF_TEMPLATE_CATEGORY"] else DEFAULT_PROCESS_TYPE, - DEFAULT_TEMPLATE_CATEGORY_LOW if app_.config["FF_TEMPLATE_CATEGORY"] else None, - ) - assert mock_send_other_category_to_freshdesk.called is True - mock_send_other_category_to_freshdesk.assert_called_once_with( - active_user_with_permissions["id"], SERVICE_ONE_ID, "hello", None, fake_uuid - ) + mock_update_service_template.assert_called_with( + fake_uuid, + name, + "sms", + content, + SERVICE_ONE_ID, + None, + None, + DEFAULT_TEMPLATE_CATEGORY_LOW, + ) + assert mock_send_other_category_to_freshdesk.called is True + mock_send_other_category_to_freshdesk.assert_called_once_with( + active_user_with_permissions["id"], SERVICE_ONE_ID, "hello", None, fake_uuid + ) def test_should_show_empty_page_when_no_templates( @@ -302,12 +299,8 @@ def test_should_show_page_for_choosing_a_template( page = client_request.get("main.choose_template", service_id=service_one["id"], **extra_args) - if app_.config["FF_TEMPLATE_CATEGORY"]: - expected_nav_links = ["All", "Email", "Text message", "All", "Other"] - links_in_page = page.select('nav[data-testid="filter-content"] a') - else: - expected_nav_links = ["All", "Email", "Text message", "Letter"] - links_in_page = page.select(".pill a") + expected_nav_links = ["All", "Email", "Text message", "All", "Other"] + links_in_page = page.select('nav[data-testid="filter-content"] a') assert normalize_spaces(page.select_one("h1").text) == expected_page_title @@ -1344,8 +1337,6 @@ def test_should_redirect_to_one_off_if_template_type_is_letter( ) -# parametrize with FF enabled and disabled -@pytest.mark.parametrize("ff_enabled", [True, False]) def test_should_redirect_when_saving_a_template( client_request, mock_get_template_categories, @@ -1353,42 +1344,40 @@ def test_should_redirect_when_saving_a_template( fake_uuid, app_, mocker, - ff_enabled, ): - with set_config(app_, "FF_TEMPLATE_CATEGORY", ff_enabled): - mock_get_service_template_with_process_type(mocker, DEFAULT_PROCESS_TYPE, None) - name = "new name" - content = "template content with & entity" + mock_get_service_template_with_process_type(mocker, DEFAULT_PROCESS_TYPE, None) + name = "new name" + content = "template content with & entity" - page = client_request.post( - ".edit_service_template", - service_id=SERVICE_ONE_ID, - template_id=fake_uuid, - _data={ - "id": fake_uuid, - "name": name, - "template_content": content, - "template_type": "sms", - "template_category_id": DEFAULT_TEMPLATE_CATEGORY_LOW if ff_enabled else None, - "service": SERVICE_ONE_ID, - "process_type": None if ff_enabled else DEFAULT_PROCESS_TYPE, - }, - _follow_redirects=True, - ) + page = client_request.post( + ".edit_service_template", + service_id=SERVICE_ONE_ID, + template_id=fake_uuid, + _data={ + "id": fake_uuid, + "name": name, + "template_content": content, + "template_type": "sms", + "template_category_id": DEFAULT_TEMPLATE_CATEGORY_LOW, + "service": SERVICE_ONE_ID, + "process_type": None, + }, + _follow_redirects=True, + ) - flash_banner = page.select_one(".banner-default-with-tick").string.strip() - assert flash_banner == f"'{name}' template saved" - # self, id_, name, type_, content, service_id, subject=None, process_type=None, template_category_id=None - mock_update_service_template.assert_called_with( - fake_uuid, - name, - "sms", - content, - SERVICE_ONE_ID, - None, - None if ff_enabled else DEFAULT_PROCESS_TYPE, - DEFAULT_TEMPLATE_CATEGORY_LOW if ff_enabled else None, - ) + flash_banner = page.select_one(".banner-default-with-tick").string.strip() + assert flash_banner == f"'{name}' template saved" + # self, id_, name, type_, content, service_id, subject=None, process_type=None, template_category_id=None + mock_update_service_template.assert_called_with( + fake_uuid, + name, + "sms", + content, + SERVICE_ONE_ID, + None, + None, + DEFAULT_TEMPLATE_CATEGORY_LOW, + ) @pytest.mark.parametrize("process_type", [TemplateProcessTypes.NORMAL.value, TemplateProcessTypes.PRIORITY.value]) @@ -1426,7 +1415,7 @@ def test_should_edit_content_when_process_type_is_set_not_platform_admin( SERVICE_ONE_ID, None, process_type, - TESTING_TEMPLATE_CATEGORY if app_.config["FF_TEMPLATE_CATEGORY"] else None, + TESTING_TEMPLATE_CATEGORY, ) @@ -1653,8 +1642,8 @@ def test_should_not_update_if_template_name_too_long( "name": "new name", "template_content": "template content!!", "template_type": template_type, - "template_category_id": DEFAULT_TEMPLATE_CATEGORY_LOW if app_.config["FF_TEMPLATE_CATEGORY"] else None, - "process_type": TC_PRIORITY_VALUE if app_.config["FF_TEMPLATE_CATEGORY"] else DEFAULT_PROCESS_TYPE, + "template_category_id": DEFAULT_TEMPLATE_CATEGORY_LOW, + "process_type": TC_PRIORITY_VALUE, } if template_type == "email": template_data.update({"subject": "subject"}) @@ -1679,7 +1668,7 @@ def test_should_not_create_if_template_name_too_long( "template_type": template_type, "template_category_id": TESTING_TEMPLATE_CATEGORY, "service": SERVICE_ONE_ID, - "process_type": None if app_.config["FF_TEMPLATE_CATEGORY"] else DEFAULT_PROCESS_TYPE, + "process_type": None, } if template_type == "email": template_data.update({"subject": "subject"}) @@ -1712,7 +1701,7 @@ def test_should_not_create_too_big_template( "template_type": "sms", "template_category_id": TESTING_TEMPLATE_CATEGORY, "service": SERVICE_ONE_ID, - "process_type": None if app_.config["FF_TEMPLATE_CATEGORY"] else DEFAULT_PROCESS_TYPE, + "process_type": None, }, _expected_status=200, ) @@ -1734,7 +1723,7 @@ def test_should_not_update_too_big_template( "service": SERVICE_ONE_ID, "template_type": "sms", "template_category_id": DEFAULT_TEMPLATE_CATEGORY_LOW, - "process_type": TC_PRIORITY_VALUE if app_.config["FF_TEMPLATE_CATEGORY"] else DEFAULT_PROCESS_TYPE, + "process_type": TC_PRIORITY_VALUE, }, _expected_status=200, ) @@ -1783,7 +1772,7 @@ def test_should_redirect_when_saving_a_template_email( SERVICE_ONE_ID, subject, DEFAULT_PROCESS_TYPE, - DEFAULT_TEMPLATE_CATEGORY_LOW if app_.config["FF_TEMPLATE_CATEGORY"] else None, + DEFAULT_TEMPLATE_CATEGORY_LOW, ) @@ -1975,7 +1964,7 @@ def test_preview_should_update_and_redirect_on_save(client_request, mock_update_ "template_type": "email", "process_type": DEFAULT_PROCESS_TYPE, "id": fake_uuid, - "template_category_id": DEFAULT_TEMPLATE_CATEGORY_LOW if app_.config["FF_TEMPLATE_CATEGORY"] else None, + "template_category_id": DEFAULT_TEMPLATE_CATEGORY_LOW, } mocker.patch( "app.main.views.templates.get_preview_data", @@ -2004,7 +1993,7 @@ def test_preview_should_update_and_redirect_on_save(client_request, mock_update_ SERVICE_ONE_ID, "test subject", DEFAULT_PROCESS_TYPE, - DEFAULT_TEMPLATE_CATEGORY_LOW if app_.config["FF_TEMPLATE_CATEGORY"] else None, + DEFAULT_TEMPLATE_CATEGORY_LOW, ) @@ -2016,7 +2005,7 @@ def test_preview_should_create_and_redirect_on_save(client_request, mock_create_ "template_type": "email", "process_type": DEFAULT_PROCESS_TYPE, "folder": None, - "template_category_id": DEFAULT_TEMPLATE_CATEGORY_LOW if app_.config["FF_TEMPLATE_CATEGORY"] else None, + "template_category_id": DEFAULT_TEMPLATE_CATEGORY_LOW, } mocker.patch( "app.main.views.templates.get_preview_data", @@ -2044,7 +2033,7 @@ def test_preview_should_create_and_redirect_on_save(client_request, mock_create_ "test subject", DEFAULT_PROCESS_TYPE, None, - DEFAULT_TEMPLATE_CATEGORY_LOW if app_.config["FF_TEMPLATE_CATEGORY"] else None, + DEFAULT_TEMPLATE_CATEGORY_LOW, ) @@ -2356,7 +2345,7 @@ def test_can_create_email_template_with_emoji( "template_type": "email", "template_category_id": TESTING_TEMPLATE_CATEGORY, "service": SERVICE_ONE_ID, - "process_type": None if app_.config["FF_TEMPLATE_CATEGORY"] else DEFAULT_PROCESS_TYPE, + "process_type": None, "button_pressed": "save", }, _follow_redirects=True, @@ -2371,12 +2360,12 @@ def test_can_create_email_template_with_emoji( @pytest.mark.parametrize( - "PRIORITY_FF_ON, PRIORITY_FF_OFF, expect_success", - [ # TODO: Remove `PRIORITY_FF_OFF`, rename `PRIORITY_FF_ON` to simply `priority` - (TC_PRIORITY_VALUE, TemplateProcessTypes.BULK.value, True), - (TemplateProcessTypes.BULK.value, TC_PRIORITY_VALUE, False), - (TemplateProcessTypes.NORMAL.value, TemplateProcessTypes.NORMAL.value, False), - (TemplateProcessTypes.PRIORITY.value, TemplateProcessTypes.PRIORITY.value, False), + "PRIORITY, IS_ADMIN", + [ + (TC_PRIORITY_VALUE, False), + (TemplateProcessTypes.BULK.value, True), + (TemplateProcessTypes.NORMAL.value, True), + (TemplateProcessTypes.PRIORITY.value, True), ], ) def test_create_template_with_process_types( @@ -2387,60 +2376,33 @@ def test_create_template_with_process_types( mock_get_template_categories, app_, mocker, - PRIORITY_FF_ON, - PRIORITY_FF_OFF, - expect_success, + platform_admin_user, + PRIORITY, + IS_ADMIN, ): - with set_config(app_, "FF_TEMPLATE_CATEGORY", False): # TODO: Remove this block when FF_TEMPLATE_CATEGORY is removed - # mock /workspaces/notification-admin/app/main/views/templates.py/abort_403_if_not_admin_user - raise_403 = mocker.patch("app.main.views.templates.abort_403_if_not_admin_user", return_value=None) - - page = client_request.post( - ".add_service_template", - service_id=SERVICE_ONE_ID, - template_type="email", - _data={ - "name": "new name", - "subject": "Food incoming!", - "template_content": "here's a burrito 🌯", - "template_type": "email", - "template_category_id": TESTING_TEMPLATE_CATEGORY, - "service": SERVICE_ONE_ID, - "process_type": PRIORITY_FF_OFF, - "button_pressed": "save", - }, - _follow_redirects=True, - ) - - if expect_success: - assert mock_create_service_template.called + if IS_ADMIN: + client_request.login(platform_admin_user) - flash_banner = page.select_one(".banner-default-with-tick").string.strip() - assert flash_banner == "'new name' template saved" - else: - assert raise_403.called - - with set_config(app_, "FF_TEMPLATE_CATEGORY", True): - page = client_request.post( - ".add_service_template", - service_id=SERVICE_ONE_ID, - template_type="email", - _data={ - "name": "new name", - "subject": "Food incoming!", - "template_content": "here's a burrito 🌯", - "template_type": "email", - "template_category_id": TESTING_TEMPLATE_CATEGORY, - "service": SERVICE_ONE_ID, - "process_type": PRIORITY_FF_ON, - "button_pressed": "save", - }, - _follow_redirects=True, - ) - assert mock_create_service_template.called is True + page = client_request.post( + ".add_service_template", + service_id=SERVICE_ONE_ID, + template_type="email", + _data={ + "name": "new name", + "subject": "Food incoming!", + "template_content": "here's a burrito 🌯", + "template_type": "email", + "template_category_id": TESTING_TEMPLATE_CATEGORY, + "service": SERVICE_ONE_ID, + "process_type": PRIORITY, + "button_pressed": "save", + }, + _follow_redirects=True, + ) + assert mock_create_service_template.called is True - flash_banner = page.select_one(".banner-default-with-tick").string.strip() - assert flash_banner == "'new name' template saved" + flash_banner = page.select_one(".banner-default-with-tick").string.strip() + assert flash_banner == "'new name' template saved" def test_should_not_create_sms_template_with_emoji( @@ -2456,7 +2418,7 @@ def test_should_not_create_sms_template_with_emoji( "template_type": "sms", "template_category_id": DEFAULT_TEMPLATE_CATEGORY_LOW, "service": SERVICE_ONE_ID, - "process_type": None if app_.config["FF_TEMPLATE_CATEGORY"] else DEFAULT_PROCESS_TYPE, + "process_type": None, }, _expected_status=200, ) @@ -2504,7 +2466,7 @@ def test_should_create_sms_template_without_downgrading_unicode_characters( "template_content": msg, "template_type": "sms", "service": SERVICE_ONE_ID, - "process_type": None if app_.config["FF_TEMPLATE_CATEGORY"] else DEFAULT_PROCESS_TYPE, + "process_type": None, "template_category_id": TESTING_TEMPLATE_CATEGORY, }, expected_status=302, diff --git a/tests_cypress/cypress/e2e/admin/template/create-template.cy.js b/tests_cypress/cypress/e2e/admin/template/create-template.cy.js index 8dd7e54c82..4e75c291aa 100644 --- a/tests_cypress/cypress/e2e/admin/template/create-template.cy.js +++ b/tests_cypress/cypress/e2e/admin/template/create-template.cy.js @@ -5,77 +5,6 @@ import { TemplatesPage } from "../../../Notify/Admin/Pages/all"; import { Admin } from "../../../Notify/NotifyAPI"; describe("Create Template", () => { - context.skip("FF_TEMPLATE_CATEGORY - OFF", () => { - it("Process type defaults to bulk if non-admin", () => { - cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD")); - cy.visit(`/services/${config.Services.Cypress}/templates`); - - TemplatesPage.CreateTemplate(); - TemplatesPage.SelectTemplateType("email"); - TemplatesPage.Continue(); - TemplatesPage.FillTemplateForm( - "Test Template", - "Test Subject", - "Test Content", - ); - - TemplatesPage.SaveTemplate(); - - cy.url().then((url) => { - let templateId = url.split("/templates/")[1]; - Admin.GetTemplate({ - templateId: templateId, - serviceId: config.Services.Cypress, - }).then((response) => { - let template = response.body.data; - expect(template.process_type_column).to.be.equal("bulk"); - expect(template.template_category_id).to.be.a("null"); - expect(template.process_type).to.be.equal("bulk"); - Admin.DeleteTemplate({ - templateId: templateId, - serviceId: config.Services.Cypress, - }); - }); - }); - }); - - it.skip("Process type defaults to bulk if admin", () => { - cy.login( - Cypress.env("NOTIFY_ADMIN_USER"), - Cypress.env("NOTIFY_PASSWORD"), - ); - cy.visit(`/services/${config.Services.Cypress}/templates`); - - TemplatesPage.CreateTemplate(); - TemplatesPage.SelectTemplateType("email"); - TemplatesPage.Continue(); - TemplatesPage.FillTemplateForm( - "Test Template", - "Test Subject", - "Test Content", - ); - - TemplatesPage.SaveTemplate(); - - cy.url().then((url) => { - let templateId = url.split("/templates/")[1]; - Admin.GetTemplate({ - templateId: templateId, - serviceId: config.Services.Cypress, - }).then((response) => { - let template = response.body.data; - expect(template.process_type_column).to.be.equal("bulk"); - expect(template.template_category_id).to.be.a("null"); - expect(template.process_type).to.be.equal("bulk"); - Admin.DeleteTemplate({ - templateId: templateId, - serviceId: config.Services.Cypress, - }); - }); - }); - }); - }); - context("FF_TEMPLATE_CATEGORY - ON", () => { it("Process type should be null and the category process type should be used if non-admin", () => { cy.login(Cypress.env("NOTIFY_USER"), Cypress.env("NOTIFY_PASSWORD"));