2018-04-24 12:48:05 +01:00
|
|
|
import pytest
|
2019-12-10 14:01:47 +00:00
|
|
|
from flask import Flask
|
2018-04-24 12:48:05 +01:00
|
|
|
|
2019-12-10 14:01:47 +00:00
|
|
|
from app import create_app
|
2018-06-12 16:17:20 +01:00
|
|
|
from app.navigation import (
|
|
|
|
|
CaseworkNavigation,
|
|
|
|
|
HeaderNavigation,
|
|
|
|
|
MainNavigation,
|
2021-02-26 18:19:47 +00:00
|
|
|
Navigation,
|
2018-06-12 16:17:20 +01:00
|
|
|
OrgNavigation,
|
|
|
|
|
)
|
2019-12-19 16:59:07 +00:00
|
|
|
from tests.conftest import ORGANISATION_ID, SERVICE_ONE_ID, normalize_spaces
|
2018-04-24 12:48:05 +01:00
|
|
|
|
2021-02-26 18:19:47 +00:00
|
|
|
EXCLUDED_ENDPOINTS = tuple(map(Navigation.get_endpoint_with_blueprint, {
|
|
|
|
|
'accept_invite',
|
|
|
|
|
'accept_org_invite',
|
|
|
|
|
'accessibility_statement',
|
|
|
|
|
'action_blocked',
|
|
|
|
|
'add_data_retention',
|
|
|
|
|
'add_organisation',
|
|
|
|
|
'add_organisation_from_gp_service',
|
|
|
|
|
'add_organisation_from_nhs_local_service',
|
|
|
|
|
'add_service',
|
|
|
|
|
'add_service_template',
|
|
|
|
|
'api_callbacks',
|
|
|
|
|
'api_documentation',
|
|
|
|
|
'api_integration',
|
|
|
|
|
'api_keys',
|
|
|
|
|
'approve_broadcast_message',
|
|
|
|
|
'archive_service',
|
|
|
|
|
'archive_user',
|
|
|
|
|
'bat_phone',
|
|
|
|
|
'begin_tour',
|
|
|
|
|
'branding_and_customisation',
|
|
|
|
|
'branding_request',
|
|
|
|
|
'broadcast',
|
|
|
|
|
'broadcast_dashboard',
|
|
|
|
|
'broadcast_dashboard_previous',
|
2021-04-08 13:09:29 +01:00
|
|
|
'broadcast_dashboard_rejected',
|
2021-02-26 18:19:47 +00:00
|
|
|
'broadcast_dashboard_updates',
|
|
|
|
|
'broadcast_tour',
|
|
|
|
|
'callbacks',
|
|
|
|
|
'cancel_broadcast_message',
|
|
|
|
|
'cancel_invited_org_user',
|
|
|
|
|
'cancel_invited_user',
|
|
|
|
|
'cancel_job',
|
|
|
|
|
'cancel_letter',
|
|
|
|
|
'cancel_letter_job',
|
|
|
|
|
'check_and_resend_text_code',
|
|
|
|
|
'check_and_resend_verification_code',
|
|
|
|
|
'check_contact_list',
|
|
|
|
|
'check_messages',
|
|
|
|
|
'check_notification',
|
|
|
|
|
'check_tour_notification',
|
|
|
|
|
'choose_account',
|
|
|
|
|
'choose_broadcast_area',
|
|
|
|
|
'choose_broadcast_library',
|
|
|
|
|
'choose_broadcast_sub_area',
|
|
|
|
|
'choose_from_contact_list',
|
|
|
|
|
'choose_service',
|
|
|
|
|
'choose_template',
|
|
|
|
|
'choose_template_to_copy',
|
|
|
|
|
'clear_cache',
|
|
|
|
|
'confirm_edit_organisation_name',
|
|
|
|
|
'confirm_edit_user_email',
|
|
|
|
|
'confirm_edit_user_mobile_number',
|
|
|
|
|
'confirm_redact_template',
|
|
|
|
|
'contact_list',
|
|
|
|
|
'conversation',
|
|
|
|
|
'conversation_reply',
|
|
|
|
|
'conversation_reply_with_template',
|
|
|
|
|
'conversation_updates',
|
|
|
|
|
'cookies',
|
|
|
|
|
'copy_template',
|
|
|
|
|
'count_content_length',
|
|
|
|
|
'create_and_send_messages',
|
|
|
|
|
'create_api_key',
|
|
|
|
|
'create_email_branding',
|
|
|
|
|
'create_letter_branding',
|
|
|
|
|
'data_retention',
|
|
|
|
|
'delete_contact_list',
|
|
|
|
|
'delete_service_template',
|
|
|
|
|
'delete_template_folder',
|
|
|
|
|
'delivery_and_failure',
|
|
|
|
|
'delivery_status_callback',
|
|
|
|
|
'design_content',
|
|
|
|
|
'documentation',
|
|
|
|
|
'download_contact_list',
|
|
|
|
|
'download_notifications_csv',
|
|
|
|
|
'edit_and_format_messages',
|
|
|
|
|
'edit_data_retention',
|
|
|
|
|
'edit_organisation_agreement',
|
|
|
|
|
'edit_organisation_billing_details',
|
|
|
|
|
'edit_organisation_crown_status',
|
|
|
|
|
'edit_organisation_domains',
|
|
|
|
|
'edit_organisation_email_branding',
|
|
|
|
|
'edit_organisation_go_live_notes',
|
|
|
|
|
'edit_organisation_letter_branding',
|
|
|
|
|
'edit_organisation_name',
|
|
|
|
|
'edit_organisation_notes',
|
|
|
|
|
'edit_organisation_type',
|
|
|
|
|
'edit_provider',
|
|
|
|
|
'edit_service_billing_details',
|
|
|
|
|
'edit_service_notes',
|
|
|
|
|
'edit_service_template',
|
|
|
|
|
'edit_sms_provider_ratio',
|
|
|
|
|
'edit_template_postage',
|
|
|
|
|
'edit_user_email',
|
|
|
|
|
'edit_user_mobile_number',
|
|
|
|
|
'edit_user_org_permissions',
|
|
|
|
|
'edit_user_permissions',
|
|
|
|
|
'email_branding',
|
|
|
|
|
'email_not_received',
|
|
|
|
|
'email_template',
|
|
|
|
|
'error',
|
|
|
|
|
'estimate_usage',
|
|
|
|
|
'features',
|
|
|
|
|
'features_email',
|
|
|
|
|
'features_letters',
|
|
|
|
|
'features_sms',
|
|
|
|
|
'feedback',
|
|
|
|
|
'find_services_by_name',
|
|
|
|
|
'find_users_by_email',
|
|
|
|
|
'forgot_password',
|
2021-03-30 15:16:02 +01:00
|
|
|
'get_billing_report',
|
2021-02-26 18:19:47 +00:00
|
|
|
'get_example_csv',
|
|
|
|
|
'get_notifications_as_json',
|
|
|
|
|
'get_started',
|
|
|
|
|
'get_started_old',
|
|
|
|
|
'go_to_dashboard_after_tour',
|
|
|
|
|
'guest_list',
|
|
|
|
|
'guidance_index',
|
|
|
|
|
'history',
|
|
|
|
|
'how_to_pay',
|
|
|
|
|
'inbound_sms_admin',
|
|
|
|
|
'inbox',
|
|
|
|
|
'inbox_download',
|
|
|
|
|
'inbox_updates',
|
|
|
|
|
'index',
|
|
|
|
|
'information_risk_management',
|
|
|
|
|
'information_security',
|
|
|
|
|
'integration_testing',
|
|
|
|
|
'invite_org_user',
|
|
|
|
|
'invite_user',
|
|
|
|
|
'letter_branding',
|
|
|
|
|
'letter_spec',
|
|
|
|
|
'letter_specification',
|
|
|
|
|
'letter_template',
|
|
|
|
|
'link_service_to_organisation',
|
|
|
|
|
'live_services',
|
|
|
|
|
'live_services_csv',
|
|
|
|
|
'manage_org_users',
|
|
|
|
|
'manage_template_folder',
|
|
|
|
|
'manage_users',
|
|
|
|
|
'message_status',
|
|
|
|
|
'monthly',
|
|
|
|
|
'new_broadcast',
|
|
|
|
|
'new_password',
|
|
|
|
|
'no_cookie.check_messages_preview',
|
|
|
|
|
'no_cookie.check_notification_preview',
|
|
|
|
|
'no_cookie.letter_branding_preview_image',
|
|
|
|
|
'no_cookie.send_test_preview',
|
|
|
|
|
'no_cookie.view_letter_template_preview',
|
|
|
|
|
'no_cookie.view_template_version_preview',
|
|
|
|
|
'notifications_sent_by_service',
|
|
|
|
|
'old_guest_list',
|
|
|
|
|
'old_integration_testing',
|
|
|
|
|
'old_roadmap',
|
|
|
|
|
'old_service_dashboard',
|
|
|
|
|
'old_terms',
|
|
|
|
|
'old_using_notify',
|
|
|
|
|
'organisation_dashboard',
|
|
|
|
|
'organisation_preview_email_branding',
|
|
|
|
|
'organisation_preview_letter_branding',
|
|
|
|
|
'organisation_settings',
|
|
|
|
|
'organisation_trial_mode_services',
|
|
|
|
|
'organisations',
|
|
|
|
|
'performance',
|
|
|
|
|
'platform_admin',
|
|
|
|
|
'platform_admin_list_complaints',
|
|
|
|
|
'platform_admin_reports',
|
|
|
|
|
'platform_admin_returned_letters',
|
|
|
|
|
'platform_admin_splash_page',
|
|
|
|
|
'preview_broadcast_areas',
|
|
|
|
|
'preview_broadcast_message',
|
|
|
|
|
'pricing',
|
|
|
|
|
'privacy',
|
|
|
|
|
'public_agreement',
|
|
|
|
|
'public_download_agreement',
|
|
|
|
|
'received_text_messages_callback',
|
|
|
|
|
'redact_template',
|
|
|
|
|
'register',
|
|
|
|
|
'register_from_invite',
|
|
|
|
|
'register_from_org_invite',
|
|
|
|
|
'registration_continue',
|
|
|
|
|
'reject_broadcast_message',
|
|
|
|
|
'remove_broadcast_area',
|
|
|
|
|
'remove_user_from_organisation',
|
|
|
|
|
'remove_user_from_service',
|
|
|
|
|
'request_to_go_live',
|
|
|
|
|
'resend_email_link',
|
|
|
|
|
'resend_email_verification',
|
|
|
|
|
'resume_service',
|
|
|
|
|
'returned_letter_summary',
|
|
|
|
|
'returned_letters',
|
|
|
|
|
'returned_letters_report',
|
|
|
|
|
'revalidate_email_sent',
|
|
|
|
|
'revoke_api_key',
|
|
|
|
|
'roadmap',
|
|
|
|
|
'save_contact_list',
|
|
|
|
|
'security',
|
|
|
|
|
'send_files_by_email',
|
|
|
|
|
'send_files_by_email_contact_details',
|
|
|
|
|
'send_from_contact_list',
|
|
|
|
|
'send_messages',
|
|
|
|
|
'send_notification',
|
|
|
|
|
'send_one_off',
|
|
|
|
|
'send_one_off_letter_address',
|
|
|
|
|
'send_one_off_step',
|
|
|
|
|
'send_one_off_to_myself',
|
|
|
|
|
'send_uploaded_letter',
|
|
|
|
|
'service_accept_agreement',
|
|
|
|
|
'service_add_email_reply_to',
|
|
|
|
|
'service_add_letter_contact',
|
|
|
|
|
'service_add_sms_sender',
|
|
|
|
|
'service_agreement',
|
|
|
|
|
'service_confirm_agreement',
|
|
|
|
|
'service_confirm_delete_email_reply_to',
|
|
|
|
|
'service_confirm_delete_letter_contact',
|
|
|
|
|
'service_confirm_delete_sms_sender',
|
|
|
|
|
'service_dashboard',
|
|
|
|
|
'service_dashboard_updates',
|
|
|
|
|
'service_delete_email_reply_to',
|
|
|
|
|
'service_delete_letter_contact',
|
|
|
|
|
'service_delete_sms_sender',
|
|
|
|
|
'service_download_agreement',
|
|
|
|
|
'service_edit_email_reply_to',
|
|
|
|
|
'service_edit_letter_contact',
|
|
|
|
|
'service_edit_sms_sender',
|
|
|
|
|
'service_email_reply_to',
|
|
|
|
|
'service_letter_contact_details',
|
|
|
|
|
'service_make_blank_default_letter_contact',
|
|
|
|
|
'service_name_change',
|
|
|
|
|
'service_name_change_confirm',
|
|
|
|
|
'service_preview_email_branding',
|
|
|
|
|
'service_preview_letter_branding',
|
|
|
|
|
'service_set_auth_type',
|
2021-05-10 22:00:09 +01:00
|
|
|
'service_confirm_broadcast_account_type',
|
2021-05-11 11:07:30 +01:00
|
|
|
'service_set_broadcast_channel',
|
|
|
|
|
'service_set_broadcast_network',
|
2021-02-26 18:19:47 +00:00
|
|
|
'service_set_channel',
|
|
|
|
|
'service_set_email_branding',
|
|
|
|
|
'service_set_inbound_number',
|
|
|
|
|
'service_set_inbound_sms',
|
|
|
|
|
'service_set_international_letters',
|
|
|
|
|
'service_set_international_sms',
|
|
|
|
|
'service_set_letter_branding',
|
|
|
|
|
'service_set_letters',
|
|
|
|
|
'service_set_permission',
|
|
|
|
|
'service_set_reply_to_email',
|
|
|
|
|
'service_set_sms_prefix',
|
|
|
|
|
'service_settings',
|
|
|
|
|
'service_sms_senders',
|
|
|
|
|
'service_switch_count_as_live',
|
|
|
|
|
'service_switch_live',
|
|
|
|
|
'service_verify_reply_to_address',
|
|
|
|
|
'service_verify_reply_to_address_updates',
|
|
|
|
|
'services_or_dashboard',
|
|
|
|
|
'set_free_sms_allowance',
|
|
|
|
|
'set_message_limit',
|
|
|
|
|
'set_rate_limit',
|
|
|
|
|
'set_sender',
|
|
|
|
|
'set_template_sender',
|
|
|
|
|
'show_accounts_or_dashboard',
|
|
|
|
|
'sign_in',
|
|
|
|
|
'sign_out',
|
|
|
|
|
'start_job',
|
|
|
|
|
'submit_request_to_go_live',
|
|
|
|
|
'support',
|
|
|
|
|
'support_public',
|
|
|
|
|
'suspend_service',
|
|
|
|
|
'template_history',
|
|
|
|
|
'template_usage',
|
|
|
|
|
'terms',
|
|
|
|
|
'thanks',
|
|
|
|
|
'tour_step',
|
|
|
|
|
'triage',
|
|
|
|
|
'trial_mode',
|
|
|
|
|
'trial_mode_new',
|
|
|
|
|
'trial_services',
|
|
|
|
|
'two_factor',
|
|
|
|
|
'two_factor_email',
|
|
|
|
|
'two_factor_email_interstitial',
|
|
|
|
|
'two_factor_email_sent',
|
|
|
|
|
'update_email_branding',
|
|
|
|
|
'update_letter_branding',
|
|
|
|
|
'upload_a_letter',
|
|
|
|
|
'upload_contact_list',
|
|
|
|
|
'upload_letter',
|
|
|
|
|
'uploaded_letter_preview',
|
|
|
|
|
'uploaded_letters',
|
|
|
|
|
'uploads',
|
|
|
|
|
'usage',
|
|
|
|
|
'user_information',
|
|
|
|
|
'user_profile',
|
|
|
|
|
'user_profile_disable_platform_admin_view',
|
|
|
|
|
'user_profile_email',
|
|
|
|
|
'user_profile_email_authenticate',
|
|
|
|
|
'user_profile_email_confirm',
|
2021-05-14 12:40:24 +01:00
|
|
|
'user_profile_manage_security_key',
|
2021-02-26 18:19:47 +00:00
|
|
|
'user_profile_mobile_number',
|
|
|
|
|
'user_profile_mobile_number_authenticate',
|
|
|
|
|
'user_profile_mobile_number_confirm',
|
|
|
|
|
'user_profile_name',
|
|
|
|
|
'user_profile_password',
|
2021-05-07 15:00:01 +01:00
|
|
|
'user_profile_security_keys',
|
2021-02-26 18:19:47 +00:00
|
|
|
'using_notify',
|
|
|
|
|
'verify',
|
|
|
|
|
'verify_email',
|
|
|
|
|
'view_current_broadcast',
|
|
|
|
|
'view_job',
|
|
|
|
|
'view_job_csv',
|
|
|
|
|
'view_job_updates',
|
|
|
|
|
'view_jobs',
|
|
|
|
|
'view_letter_notification_as_preview',
|
|
|
|
|
'view_letter_upload_as_preview',
|
|
|
|
|
'view_notification',
|
|
|
|
|
'view_notification_updates',
|
|
|
|
|
'view_notifications',
|
|
|
|
|
'view_notifications_csv',
|
|
|
|
|
'view_previous_broadcast',
|
|
|
|
|
'view_provider',
|
|
|
|
|
'view_providers',
|
2021-04-08 13:09:29 +01:00
|
|
|
'view_rejected_broadcast',
|
2021-02-26 18:19:47 +00:00
|
|
|
'view_template',
|
|
|
|
|
'view_template_version',
|
|
|
|
|
'view_template_versions',
|
Support registering a new authenticator
This adds Yubico's FIDO2 library and two APIs for working with the
"navigator.credentials.create()" function in JavaScript. The GET
API uses the library to generate options for the "create()" function,
and the POST API decodes and verifies the resulting credential. While
the options and response are dict-like, CBOR is necessary to encode
some of the byte-level values, which can't be represented in JSON.
Much of the code here is based on the Yubico library example [1][2].
Implementation notes:
- There are definitely better ways to alert the user about failure, but
window.alert() will do for the time being. Using location.reload() is
also a bit jarring if the page scrolls, but not a major issue.
- Ideally we would use window.fetch() to do AJAX calls, but we don't
have a polyfill for this, and we use $.ajax() elsewhere [3]. We need
to do a few weird tricks [6] to stop jQuery trashing the data.
- The FIDO2 server doesn't serve web requests; it's just a "server" in
the sense of WebAuthn terminology. It lives in its own module, since it
needs to be initialised with the app / config.
- $.ajax returns a promise-like object. Although we've used ".fail()"
elsewhere [3], I couldn't find a stub object that supports it, so I've
gone for ".catch()", and used a Promise stub object in tests.
- WebAuthn only works over HTTPS, but there's an exception for "localhost"
[4]. However, the library is a bit too strict [5], so we have to disable
origin verification to avoid needing HTTPS for dev work.
[1]: https://github.com/Yubico/python-fido2/blob/c42d9628a4f33d20c4401096fa8d3fc466d5b77f/examples/server/server.py
[2]: https://github.com/Yubico/python-fido2/blob/c42d9628a4f33d20c4401096fa8d3fc466d5b77f/examples/server/static/register.html
[3]: https://github.com/alphagov/notifications-admin/blob/91453d36395b7a0cf2998dfb8a5f52cc9e96640f/app/assets/javascripts/updateContent.js#L33
[4]: https://stackoverflow.com/questions/55971593/navigator-credentials-is-null-on-local-server
[5]: https://github.com/Yubico/python-fido2/blob/c42d9628a4f33d20c4401096fa8d3fc466d5b77f/fido2/rpid.py#L69
[6]: https://stackoverflow.com/questions/12394622/does-jquery-ajax-or-load-allow-for-responsetype-arraybuffer
2021-05-07 18:10:07 +01:00
|
|
|
'webauthn_begin_register',
|
|
|
|
|
'webauthn_complete_register',
|
2021-02-26 18:19:47 +00:00
|
|
|
'who_can_use_notify',
|
|
|
|
|
'who_its_for',
|
|
|
|
|
'write_new_broadcast',
|
|
|
|
|
}))
|
|
|
|
|
|
2019-12-10 14:01:47 +00:00
|
|
|
|
|
|
|
|
def flask_app():
|
|
|
|
|
app = Flask('app')
|
|
|
|
|
create_app(app)
|
|
|
|
|
|
|
|
|
|
ctx = app.app_context()
|
|
|
|
|
ctx.push()
|
|
|
|
|
|
|
|
|
|
yield app
|
|
|
|
|
|
|
|
|
|
|
2018-04-24 12:48:05 +01:00
|
|
|
all_endpoints = [
|
2019-12-10 14:01:47 +00:00
|
|
|
rule.endpoint for rule in next(flask_app()).url_map.iter_rules()
|
2018-04-24 12:48:05 +01:00
|
|
|
]
|
|
|
|
|
|
2018-06-12 16:17:20 +01:00
|
|
|
navigation_instances = (
|
2018-04-25 11:11:37 +01:00
|
|
|
MainNavigation(),
|
|
|
|
|
HeaderNavigation(),
|
2018-04-25 13:17:47 +01:00
|
|
|
OrgNavigation(),
|
2018-06-12 16:17:20 +01:00
|
|
|
CaseworkNavigation(),
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('navigation_instance', navigation_instances)
|
2018-04-25 11:11:37 +01:00
|
|
|
def test_navigation_items_are_properly_defined(navigation_instance):
|
|
|
|
|
for endpoint in navigation_instance.endpoints_with_navigation:
|
|
|
|
|
assert (
|
|
|
|
|
endpoint in all_endpoints
|
|
|
|
|
), '{} is not a real endpoint (in {}.mapping)'.format(
|
|
|
|
|
endpoint,
|
|
|
|
|
type(navigation_instance).__name__
|
|
|
|
|
)
|
|
|
|
|
assert (
|
|
|
|
|
navigation_instance.endpoints_with_navigation.count(endpoint) == 1
|
|
|
|
|
), '{} found more than once in {}.mapping'.format(
|
|
|
|
|
endpoint,
|
|
|
|
|
type(navigation_instance).__name__
|
|
|
|
|
)
|
2018-04-24 12:48:05 +01:00
|
|
|
|
|
|
|
|
|
2021-02-26 18:19:47 +00:00
|
|
|
def test_excluded_navigation_items_are_properly_defined():
|
|
|
|
|
for endpoint in EXCLUDED_ENDPOINTS:
|
2018-04-25 11:11:37 +01:00
|
|
|
assert (
|
|
|
|
|
endpoint in all_endpoints
|
2021-02-26 18:19:47 +00:00
|
|
|
), f'{endpoint} is not a real endpoint (in EXCLUDED_ENDPOINTS)'
|
|
|
|
|
|
2018-04-25 11:11:37 +01:00
|
|
|
assert (
|
2021-02-26 18:19:47 +00:00
|
|
|
EXCLUDED_ENDPOINTS.count(endpoint) == 1
|
|
|
|
|
), f'{endpoint} found more than once in EXCLUDED_ENDPOINTS'
|
2018-04-24 12:48:05 +01:00
|
|
|
|
|
|
|
|
|
2018-06-12 16:17:20 +01:00
|
|
|
@pytest.mark.parametrize('navigation_instance', navigation_instances)
|
2018-04-25 11:11:37 +01:00
|
|
|
def test_all_endpoints_are_covered(navigation_instance):
|
2021-02-26 18:19:47 +00:00
|
|
|
covered_endpoints = (
|
|
|
|
|
navigation_instance.endpoints_with_navigation +
|
|
|
|
|
EXCLUDED_ENDPOINTS +
|
|
|
|
|
('static', 'status.show_status', 'metrics')
|
|
|
|
|
)
|
|
|
|
|
|
2018-04-24 12:48:05 +01:00
|
|
|
for endpoint in all_endpoints:
|
2021-02-26 18:19:47 +00:00
|
|
|
assert endpoint in covered_endpoints, f'{endpoint} is not listed or excluded'
|
2018-04-24 12:48:05 +01:00
|
|
|
|
|
|
|
|
|
2018-06-12 16:17:20 +01:00
|
|
|
@pytest.mark.parametrize('navigation_instance', navigation_instances)
|
2018-04-24 12:48:05 +01:00
|
|
|
@pytest.mark.xfail(raises=KeyError)
|
2018-04-25 11:11:37 +01:00
|
|
|
def test_raises_on_invalid_navigation_item(
|
|
|
|
|
client_request, navigation_instance
|
|
|
|
|
):
|
|
|
|
|
navigation_instance.is_selected('foo')
|
2018-04-24 12:48:05 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('endpoint, selected_nav_item', [
|
|
|
|
|
('main.choose_template', 'Templates'),
|
|
|
|
|
('main.manage_users', 'Team members'),
|
|
|
|
|
])
|
|
|
|
|
def test_a_page_should_nave_selected_navigation_item(
|
|
|
|
|
client_request,
|
|
|
|
|
mock_get_service_templates,
|
|
|
|
|
mock_get_users_by_service,
|
|
|
|
|
mock_get_invites_for_service,
|
2018-11-01 17:11:58 +00:00
|
|
|
mock_get_template_folders,
|
2021-04-13 13:59:51 +01:00
|
|
|
mock_get_api_keys,
|
2018-04-24 12:48:05 +01:00
|
|
|
endpoint,
|
|
|
|
|
selected_nav_item,
|
|
|
|
|
):
|
|
|
|
|
page = client_request.get(endpoint, service_id=SERVICE_ONE_ID)
|
|
|
|
|
selected_nav_items = page.select('.navigation a.selected')
|
|
|
|
|
assert len(selected_nav_items) == 1
|
|
|
|
|
assert selected_nav_items[0].text.strip() == selected_nav_item
|
2018-04-25 11:11:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('endpoint, selected_nav_item', [
|
|
|
|
|
('main.documentation', 'Documentation'),
|
|
|
|
|
('main.support', 'Support'),
|
|
|
|
|
])
|
|
|
|
|
def test_a_page_should_nave_selected_header_navigation_item(
|
|
|
|
|
client_request,
|
|
|
|
|
endpoint,
|
|
|
|
|
selected_nav_item,
|
|
|
|
|
):
|
|
|
|
|
page = client_request.get(endpoint, service_id=SERVICE_ONE_ID)
|
2019-10-22 20:01:30 +01:00
|
|
|
selected_nav_items = page.select('.govuk-header__navigation-item--active')
|
2018-04-25 11:11:37 +01:00
|
|
|
assert len(selected_nav_items) == 1
|
|
|
|
|
assert selected_nav_items[0].text.strip() == selected_nav_item
|
2018-04-25 13:17:47 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize('endpoint, selected_nav_item', [
|
2019-06-20 10:59:54 +01:00
|
|
|
('main.organisation_dashboard', 'Usage'),
|
2018-04-25 13:17:47 +01:00
|
|
|
('main.manage_org_users', 'Team members'),
|
|
|
|
|
])
|
|
|
|
|
def test_a_page_should_nave_selected_org_navigation_item(
|
|
|
|
|
client_request,
|
|
|
|
|
mock_get_organisation,
|
|
|
|
|
mock_get_users_for_organisation,
|
|
|
|
|
mock_get_invited_users_for_organisation,
|
|
|
|
|
endpoint,
|
|
|
|
|
selected_nav_item,
|
2020-02-25 17:49:55 +00:00
|
|
|
mocker
|
2018-04-25 13:17:47 +01:00
|
|
|
):
|
2020-02-25 17:49:55 +00:00
|
|
|
mocker.patch(
|
2020-02-27 15:21:08 +00:00
|
|
|
'app.organisations_client.get_services_and_usage', return_value={'services': {}}
|
2020-02-25 17:49:55 +00:00
|
|
|
)
|
2018-04-25 13:17:47 +01:00
|
|
|
page = client_request.get(endpoint, org_id=ORGANISATION_ID)
|
|
|
|
|
selected_nav_items = page.select('.navigation a.selected')
|
|
|
|
|
assert len(selected_nav_items) == 1
|
|
|
|
|
assert selected_nav_items[0].text.strip() == selected_nav_item
|
2018-06-12 16:17:20 +01:00
|
|
|
|
|
|
|
|
|
2019-11-13 15:10:16 +00:00
|
|
|
def test_navigation_urls(
|
|
|
|
|
client_request,
|
|
|
|
|
mock_get_service_templates,
|
|
|
|
|
mock_get_template_folders,
|
2021-04-13 13:59:51 +01:00
|
|
|
mock_get_api_keys,
|
2019-11-13 15:10:16 +00:00
|
|
|
):
|
|
|
|
|
page = client_request.get('main.choose_template', service_id=SERVICE_ONE_ID)
|
|
|
|
|
assert [
|
|
|
|
|
a['href'] for a in page.select('.navigation a')
|
|
|
|
|
] == [
|
|
|
|
|
'/services/{}'.format(SERVICE_ONE_ID),
|
|
|
|
|
'/services/{}/templates'.format(SERVICE_ONE_ID),
|
2020-03-12 10:37:59 +00:00
|
|
|
'/services/{}/uploads'.format(SERVICE_ONE_ID),
|
2019-11-13 15:10:16 +00:00
|
|
|
'/services/{}/users'.format(SERVICE_ONE_ID),
|
|
|
|
|
'/services/{}/usage'.format(SERVICE_ONE_ID),
|
|
|
|
|
'/services/{}/service-settings'.format(SERVICE_ONE_ID),
|
|
|
|
|
'/services/{}/api'.format(SERVICE_ONE_ID),
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
2020-07-08 09:57:32 +01:00
|
|
|
def test_navigation_for_services_with_broadcast_permission(
|
|
|
|
|
client_request,
|
|
|
|
|
service_one,
|
|
|
|
|
mock_get_service_templates,
|
|
|
|
|
mock_get_template_folders,
|
2021-04-13 13:59:51 +01:00
|
|
|
mock_get_api_keys,
|
2020-07-08 09:57:32 +01:00
|
|
|
):
|
|
|
|
|
service_one['permissions'] += ['broadcast']
|
|
|
|
|
page = client_request.get('main.choose_template', service_id=SERVICE_ONE_ID)
|
|
|
|
|
assert [
|
|
|
|
|
a['href'] for a in page.select('.navigation a')
|
|
|
|
|
] == [
|
2020-10-13 11:42:32 +01:00
|
|
|
'/services/{}/current-alerts'.format(SERVICE_ONE_ID),
|
2020-10-13 11:40:20 +01:00
|
|
|
'/services/{}/previous-alerts'.format(SERVICE_ONE_ID),
|
2021-04-08 13:09:29 +01:00
|
|
|
'/services/{}/rejected-alerts'.format(SERVICE_ONE_ID),
|
2020-07-08 09:57:32 +01:00
|
|
|
'/services/{}/templates'.format(SERVICE_ONE_ID),
|
|
|
|
|
'/services/{}/users'.format(SERVICE_ONE_ID),
|
|
|
|
|
'/services/{}/service-settings'.format(SERVICE_ONE_ID),
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
2018-06-12 16:17:20 +01:00
|
|
|
def test_caseworkers_get_caseworking_navigation(
|
|
|
|
|
client_request,
|
|
|
|
|
mocker,
|
2018-11-01 17:11:58 +00:00
|
|
|
mock_get_template_folders,
|
2018-06-12 16:17:20 +01:00
|
|
|
mock_get_service_templates,
|
2018-07-30 17:40:32 +01:00
|
|
|
mock_has_no_jobs,
|
2021-04-13 13:59:51 +01:00
|
|
|
mock_get_api_keys,
|
2019-12-19 16:59:07 +00:00
|
|
|
active_caseworking_user,
|
2018-06-12 16:17:20 +01:00
|
|
|
):
|
|
|
|
|
mocker.patch(
|
|
|
|
|
'app.user_api_client.get_user',
|
2019-12-19 16:59:07 +00:00
|
|
|
return_value=active_caseworking_user
|
2018-06-12 16:17:20 +01:00
|
|
|
)
|
|
|
|
|
page = client_request.get('main.choose_template', service_id=SERVICE_ONE_ID)
|
2019-10-22 20:01:30 +01:00
|
|
|
assert normalize_spaces(page.select_one('header + .govuk-width-container nav').text) == (
|
2020-03-16 12:08:38 +00:00
|
|
|
'Templates Sent messages Uploads Team members'
|
2018-06-12 16:17:20 +01:00
|
|
|
)
|
2018-07-30 17:40:32 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_caseworkers_see_jobs_nav_if_jobs_exist(
|
|
|
|
|
client_request,
|
|
|
|
|
mocker,
|
|
|
|
|
mock_get_service_templates,
|
2018-11-01 17:11:58 +00:00
|
|
|
mock_get_template_folders,
|
2018-07-30 17:40:32 +01:00
|
|
|
mock_has_jobs,
|
2019-12-19 16:59:07 +00:00
|
|
|
active_caseworking_user,
|
2021-04-13 13:59:51 +01:00
|
|
|
mock_get_api_keys,
|
2018-07-30 17:40:32 +01:00
|
|
|
):
|
|
|
|
|
mocker.patch(
|
|
|
|
|
'app.user_api_client.get_user',
|
2019-12-19 16:59:07 +00:00
|
|
|
return_value=active_caseworking_user
|
2018-07-30 17:40:32 +01:00
|
|
|
)
|
|
|
|
|
page = client_request.get('main.choose_template', service_id=SERVICE_ONE_ID)
|
2019-10-22 20:01:30 +01:00
|
|
|
assert normalize_spaces(page.select_one('header + .govuk-width-container nav').text) == (
|
2019-10-09 10:52:33 +01:00
|
|
|
'Templates Sent messages Uploads Team members'
|
2018-07-30 17:40:32 +01:00
|
|
|
)
|