def test_new_user_accept_invite_calls_api_and_views_registration_page( client, service_one, mock_check_invite_token, mock_dont_get_user_by_email, mock_add_user_to_service, mock_get_users_by_service, mock_get_service, mocker, ): response = client.get(url_for('main.accept_invite', token='thisisnotarealtoken'), follow_redirects=True) mock_check_invite_token.assert_called_with('thisisnotarealtoken') mock_dont_get_user_by_email.assert_called_with('*****@*****.**') assert response.status_code == 200 page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') assert page.h1.string.strip() == 'Create an account' assert normalize_spaces(page.select_one('main p').text) == ( 'Your account will be created with this email address: ' '*****@*****.**') form = page.find('form') name = form.find('input', id='name') password = form.find('input', id='password') service = form.find('input', type='hidden', id='service') email = form.find('input', type='hidden', id='email_address') assert email assert email.attrs['value'] == '*****@*****.**' assert name assert password assert service assert service.attrs['value'] == service_one['id']
def test_notification_page_has_link_to_send_another_for_sms( client_request, mocker, fake_uuid, service_one, service_permissions, template_type, link_expected, ): service_one['permissions'] = service_permissions notification = create_notification(template_type=template_type) mocker.patch('app.notification_api_client.get_notification', return_value=notification) mocker.patch('app.main.views.notifications.get_page_count_for_letter', return_value=1) page = client_request.get( 'main.view_notification', service_id=SERVICE_ONE_ID, notification_id=fake_uuid, ) last_paragraph = page.select('main p')[-1] conversation_link = url_for( '.conversation', service_id=SERVICE_ONE_ID, notification_id=fake_uuid, _anchor='n{}'.format(fake_uuid), ) if link_expected: assert normalize_spaces(last_paragraph.text) == ( 'See all text messages sent to this phone number') assert last_paragraph.select_one('a')['href'] == conversation_link else: assert conversation_link not in str(page.select_one('main'))
def test_accepting_invite_removes_invite_from_session( client_request, mocker, sample_invite, mock_get_service, service_one, mock_check_invite_token, mock_get_user_by_email, mock_get_users_by_service, mock_add_user_to_service, mock_accept_invite, mock_get_service_templates, mock_get_template_statistics, mock_get_jobs, mock_get_service_statistics, mock_get_template_folders, mock_get_usage, mock_get_inbound_sms_summary, fake_uuid, user, landing_page_title, ): user = user(fake_uuid) sample_invite['email_address'] = user['email_address'] mocker.patch('app.invite_api_client.check_token', return_value=sample_invite) client_request.login(user) page = client_request.get( 'main.accept_invite', token='thisisnotarealtoken', _follow_redirects=True, ) assert normalize_spaces(page.select_one('h1').text) == landing_page_title with client_request.session_transaction() as session: assert 'invited_user' not in session
def test_should_be_able_to_view_a_template_with_links( client, mock_get_service_template, active_user_with_permissions, single_letter_contact_block, mocker, service_one, fake_uuid, permissions, links_to_be_shown, permissions_warning_to_be_shown, ): active_user_with_permissions._permissions[ service_one['id']] = permissions + ['view_activity'] client.login(active_user_with_permissions, mocker, service_one) response = client.get( url_for('.view_template', service_id=service_one['id'], template_id=fake_uuid)) assert response.status_code == 200 page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') links_in_page = page.select('.pill-separate-item') assert len(links_in_page) == len(links_to_be_shown) for index, link_to_be_shown in enumerate(links_to_be_shown): assert links_in_page[index]['href'] == url_for( link_to_be_shown, service_id=service_one['id'], template_id=fake_uuid, ) assert normalize_spaces( page.select_one('main p').text) == (permissions_warning_to_be_shown or 'To: phone number')
def test_doesnt_show_pagination_with_search_term( client_request, service_one, active_user_with_permissions, mock_get_notifications_with_previous_next, mock_get_service_statistics, mock_get_service_data_retention, mock_get_no_api_keys, mocker, ): page = client_request.post( 'main.view_notifications', service_id=service_one['id'], message_type='sms', _data={ 'to': '*****@*****.**', }, _expected_status=200, ) assert len(page.select('tbody tr')) == 50 assert not page.find('a', {'rel': 'next'}) assert not page.find('a', {'rel': 'previous'}) assert normalize_spaces(page.select_one('.table-show-more-link').text) == ( 'Only showing the first 50 messages')
def test_html_contains_links_for_failed_notifications( client_request, active_user_with_permissions, mock_get_service_statistics, mock_get_service_data_retention, mocker, ): mock_get_notifications( mocker, active_user_with_permissions, diff_template_type="sms", noti_status="technical-failure", ) response = client_request.get( "main.view_notifications", service_id=SERVICE_ONE_ID, message_type="sms", status="sending%2Cdelivered%2Cfailed", ) notifications = response.tbody.find_all("tr") for tr in notifications: link_text = tr.find("div", class_="table-field-status-error").find("a").text assert normalize_spaces(link_text) == "Technical failure"
def test_gps_can_create_own_organisations( client_request, mocker, service_one, organisation_type, organisation, expected_status, ): mocker.patch('app.organisations_client.get_service_organisation', return_value=organisation) service_one['organisation_type'] = organisation_type page = client_request.get( '.add_organisation_from_gp_service', service_id=SERVICE_ONE_ID, _expected_status=expected_status, ) if expected_status == 403: return assert page.select_one('input[type=text]')['name'] == 'name' assert normalize_spaces(page.select_one('label[for=name]').text) == ( 'What’s your practice called?')
def test_empty_inbox( logged_in_client, service_one, mock_get_service_templates_when_no_templates_exist, mock_get_jobs, mock_get_detailed_service, mock_get_template_statistics, mock_get_usage, mock_get_most_recent_inbound_sms_with_no_messages, mock_get_inbound_number_for_service, ): service_one['permissions'] = ['inbound_sms'] response = logged_in_client.get(url_for('main.inbox', service_id=SERVICE_ONE_ID)) page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') assert response.status_code == 200 assert normalize_spaces(page.select('tbody tr')) == ( 'When users text your service’s phone number (0781239871) you’ll see the messages here' ) assert not page.select('a[download]') assert not page.select('li.next-page') assert not page.select('li.previous-page')
def test_inbound_messages_shows_count_of_messages( logged_in_client, mocker, service_one, mock_get_service_templates_when_no_templates_exist, mock_get_jobs, mock_get_detailed_service, mock_get_template_statistics, mock_get_usage, inbound_summary_mock, expected_text ): service_one['permissions'] = ['inbound_sms'] inbound_summary_mock(mocker) response = logged_in_client.get(url_for('main.service_dashboard', service_id=SERVICE_ONE_ID)) page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') assert response.status_code == 200 assert normalize_spaces(page.select('.big-number-meta-wrapper')[0].text) == expected_text assert page.select('.big-number-meta-wrapper a')[0]['href'] == url_for( 'main.inbox', service_id=SERVICE_ONE_ID )
def test_jobs_page_doesnt_show_scheduled_on_page_2( client_request, service_one, active_user_with_permissions, mock_get_jobs, user, ): client_request.login(user) page = client_request.get('main.view_jobs', service_id=service_one['id'], page=2) for index, row in enumerate(( ('File Sending Delivered Failed'), ('export 1/1/2016.xls ' 'Sent today at 12:12pm 1 0 0'), ('all email addresses.xlsx ' 'Sent today at 12:12pm 1 0 0'), ('applicants.ods ' 'Sent today at 12:12pm 1 0 0'), ('thisisatest.csv ' 'Sent today at 12:12pm 1 0 0'), )): assert normalize_spaces(page.select('tr')[index].text) == row
def test_invite_org_user_errors_when_same_email_as_inviter( client_request, mocker, mock_get_organisation, sample_org_invite, ): new_org_user_data = { 'email_address': '*****@*****.**', } mock_invite_org_user = mocker.patch( 'app.org_invite_api_client.create_invite', return_value=sample_org_invite, ) page = client_request.post( '.invite_org_user', org_id=ORGANISATION_ID, _data=new_org_user_data, _follow_redirects=True ) assert mock_invite_org_user.called is False assert 'You cannot send an invitation to yourself' in normalize_spaces(page.select_one('.govuk-error-message').text)
def test_choose_account_should_show_choose_accounts_page( client_request, mock_get_orgs_and_services ): resp = client_request.get('main.choose_account') page = resp.find('div', {'id': 'content'}).main assert normalize_spaces(page.h1.text) == 'Choose service' outer_list_items = page.nav.ul.find_all('li', recursive=False) assert len(outer_list_items) == 6 # first org assert outer_list_items[0].a.text == 'org_1' assert outer_list_items[0].a['href'] == url_for('.organisation_dashboard', org_id='o1') outer_list_orgs = outer_list_items[0].ul assert ' '.join(outer_list_orgs.stripped_strings) == 'org_service_1 org_service_2 org_service_3' # second org assert outer_list_items[1].a.text == 'org_2' assert outer_list_items[1].a['href'] == url_for('.organisation_dashboard', org_id='o2') outer_list_orgs = outer_list_items[1].ul assert ' '.join(outer_list_orgs.stripped_strings) == 'org_service_4' # third org assert outer_list_items[2].a.text == 'org_3' assert outer_list_items[2].a['href'] == url_for('.organisation_dashboard', org_id='o3') assert not outer_list_items[2].ul # org 3 has no services # orphaned services assert outer_list_items[3].a.text == 'service_1' assert outer_list_items[3].a['href'] == url_for('.service_dashboard', service_id='s1') assert outer_list_items[4].a.text == 'service_2' assert outer_list_items[4].a['href'] == url_for('.service_dashboard', service_id='s2') assert outer_list_items[5].a.text == 'service_3' assert outer_list_items[5].a['href'] == url_for('.service_dashboard', service_id='s3')
def test_should_show_letter_job_with_banner_when_there_are_multiple_CSV_rows( mocker, client_request, mock_get_service_letter_template, mock_get_letter_job_in_progress, mock_get_service_data_retention, fake_uuid, ): mocker.patch( 'app.notification_api_client.get_notifications_for_service', return_value=create_notifications(template_type='letter', postage='second') ) page = client_request.get( 'main.view_job', service_id=SERVICE_ONE_ID, job_id=fake_uuid, just_sent='yes', ) assert page.select('p.bottom-gutter') == [] assert normalize_spaces(page.select('.banner-default-with-tick')[0].text) == ( 'Your letters have been sent. Printing starts today at 5:30pm.' )
def test_should_show_scheduled_job( client_request, mock_get_service_template, mock_get_scheduled_job, mock_get_service_data_retention, mock_get_notifications, fake_uuid, ): page = client_request.get( 'main.view_job', service_id=SERVICE_ONE_ID, job_id=fake_uuid, ) assert normalize_spaces(page.select('main p')[1].text) == ( 'Sending Two week reminder 2016-01-02T00:00:00.061258') assert page.select('main p a')[0]['href'] == url_for( 'main.view_template_version', service_id=SERVICE_ONE_ID, template_id='5d729fbd-239c-44ab-b498-75a985f3198f', version=1, ) assert page.select_one( 'button[type=submit]').text.strip() == 'Cancel sending'
def test_confirm_update_organisation_with_incorrect_password( logged_in_platform_admin_client, organisation_one, mock_get_organisation, mocker ): with logged_in_platform_admin_client.session_transaction() as session: session['organisation_name_change'] = 'newName' mocker.patch('app.user_api_client.verify_password', return_value=False) response = logged_in_platform_admin_client.post( url_for( '.confirm_edit_organisation_name', org_id=organisation_one['id'] ) ) assert response.status_code == 200 page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') assert normalize_spaces( page.select_one('.error-message').text ) == 'Invalid password'
def test_notification_page_shows_validation_failed_precompiled_letter( client_request, mocker, fake_uuid, ): notification = create_notification(template_type='letter', notification_status='validation-failed', is_precompiled_letter=True ) mocker.patch('app.notification_api_client.get_notification', return_value=notification) metadata = {"page_count": "1", "status": "validation-failed", "invalid_pages": "[1]", "message": "content-outside-printable-area"} mocker.patch('app.main.views.notifications.get_letter_file_data', return_value=("some letter content", metadata)) mocker.patch( 'app.main.views.notifications.get_page_count_for_letter', return_value=1, ) page = client_request.get( 'main.view_notification', service_id=SERVICE_ONE_ID, notification_id=fake_uuid, ) error_message = page.find('p', class_='notification-status-cancelled').text assert normalize_spaces(error_message) == ( 'Validation failed because content is outside the printable area on page 1.' 'Files must meet our letter specification.' ) assert not page.select('p.notification-status') assert page.select_one('main img')['src'].endswith('.png?page=1') assert not page.select('.letter-postage')
def test_conversation_reply_shows_templates( client_request, fake_uuid, mock_get_service_templates, ): page = client_request.get( 'main.conversation_reply', service_id=SERVICE_ONE_ID, notification_id=fake_uuid, ) for index, expected in enumerate([ 'sms_template_one', 'sms_template_two', ]): link = page.select('.message-name')[index] assert normalize_spaces(link.text) == expected assert link.select_one('a')['href'].startswith( url_for( 'main.conversation_reply_with_template', service_id=SERVICE_ONE_ID, notification_id=fake_uuid, template_id='', ))
def test_should_show_scheduled_job( logged_in_client, active_user_with_permissions, mock_get_service_template, mock_get_scheduled_job, mocker, mock_get_notifications, fake_uuid, ): response = logged_in_client.get( url_for('main.view_job', service_id=SERVICE_ONE_ID, job_id=fake_uuid)) assert response.status_code == 200 page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser') assert normalize_spaces(page.select('main p')[1].text) == ( 'Sending Two week reminder today at midnight') assert page.select('main p a')[0]['href'] == url_for( 'main.view_template_version', service_id=SERVICE_ONE_ID, template_id='5d729fbd-239c-44ab-b498-75a985f3198f', version=1, ) assert page.select_one( 'button[type=submit]').text.strip() == 'Cancel sending'
def test_notification_page_shows_error_message_if_precompiled_letter_cannot_be_opened( client_request, mocker, fake_uuid, ): notification = create_notification(notification_status='validation-failed', template_type='letter', is_precompiled_letter=True) mocker.patch('app.notification_api_client.get_notification', return_value=notification) mocker.patch( 'app.main.views.notifications.view_letter_notification_as_preview', side_effect=PdfReadError()) mocker.patch('app.main.views.notifications.pdf_page_count', side_effect=PdfReadError()) page = client_request.get( 'main.view_notification', service_id=SERVICE_ONE_ID, notification_id=fake_uuid, ) error_message = page.find('p', class_='notification-status-cancelled').text assert normalize_spaces(error_message) == \ "Validation failed – There’s a problem with your letter. Notify cannot read this PDF."
def test_should_show_job_without_notifications( client_request, service_one, active_user_with_permissions, mock_get_service_template, mock_get_job_in_progress, mocker, mock_get_notifications_with_no_notifications, mock_get_service_data_retention, fake_uuid, ): page = client_request.get( 'main.view_job', service_id=service_one['id'], job_id=fake_uuid, ) assert [ normalize_spaces(link.text) for link in page.select('.pill a:not(.pill-item--selected)') ] == [ '10 sending', '0 delivered', '0 failed' ] assert page.select_one('p.hint').text.strip() == 'Report is 50% complete…' assert page.select_one('tbody').text.strip() == 'No messages to show yet…'
def test_redacts_templates_that_should_be_redacted( client_request, mocker, mock_get_service_statistics, mock_get_service_data_retention, mock_get_no_api_keys, ): notifications = create_notifications( status='technical-failure', content='hello ((name))', personalisation={'name': 'Jo'}, redact_personalisation=True, ) mocker.patch('app.notification_api_client.get_notifications_for_service', return_value=notifications) page = client_request.get( 'main.view_notifications', service_id=SERVICE_ONE_ID, message_type='sms', ) assert normalize_spaces(page.select('tbody tr th')[0].text) == ( '07123456789 hello hidden' )
def test_should_show_letter_job_with_banner_after_sending_before_1730( mocker, client_request, mock_get_service_letter_template, mock_get_letter_job, mock_get_service_data_retention, fake_uuid, ): mocker.patch('app.notification_api_client.get_notifications_for_service', return_value=create_notifications(template_type='letter', postage='second')) page = client_request.get( 'main.view_job', service_id=SERVICE_ONE_ID, job_id=fake_uuid, just_sent='yes', ) assert page.select('p.bottom-gutter') == [] assert normalize_spaces( page.select('.banner-default-with-tick')[0].text) == ( 'Your letter has been sent. Printing starts today at 5:30pm.') assert not page.select_one('.govuk-back-link')
def test_add_service_has_to_choose_org_type( mocker, client_request, mock_create_service, mock_create_service_template, mock_get_services_with_no_services, api_user_active, mock_get_all_email_branding, ): mocker.patch( 'app.organisations_client.get_organisation_by_domain', return_value=None, ) page = client_request.post( 'main.add_service', _data={ 'name': 'testing the post', }, _expected_status=200, ) assert normalize_spaces(page.select_one('.govuk-error-message').text) == ( 'Error: Select the type of organisation') assert mock_create_service.called is False assert mock_create_service_template.called is False
def test_returned_letter_summary( client_request, mocker ): summary_data = [{'returned_letter_count': 30, 'reported_at': '2019-12-24'}] mock = mocker.patch("app.service_api_client.get_returned_letter_summary", return_value=summary_data) page = client_request.get("main.returned_letter_summary", service_id=SERVICE_ONE_ID) mock.assert_called_once_with(SERVICE_ONE_ID) assert page.h1.string.strip() == 'Returned letters' assert normalize_spaces( page.select_one('.table-field').text ) == ( '24 December 2019 ' '30 letters' ) assert page.select_one('.table-field a')['href'] == url_for( '.returned_letters', service_id=SERVICE_ONE_ID, reported_at='2019-12-24', )
def test_should_show_page_for_choosing_a_template( client_request, mock_get_service_templates, extra_args, expected_nav_links, expected_templates, service_one, mocker, fake_uuid, user, expected_page_title, ): mocker.patch('app.user_api_client.get_user', return_value=user(fake_uuid)) service_one['permissions'].append('letter') page = client_request.get('main.choose_template', service_id=SERVICE_ONE_ID, **extra_args) assert normalize_spaces(page.select_one('h1').text) == expected_page_title links_in_page = page.select('.pill a') assert len(links_in_page) == len(expected_nav_links) for index, expected_link in enumerate(expected_nav_links): assert links_in_page[index].text.strip() == expected_link template_links = page.select('.message-name a') assert len(template_links) == len(expected_templates) for index, expected_template in enumerate(expected_templates): assert template_links[index].text.strip() == expected_template mock_get_service_templates.assert_called_with(SERVICE_ONE_ID)
def test_show_cancel_letter_confirmation( client_request, mocker, fake_uuid, ): mock_get_notification( mocker, fake_uuid, template_type="letter", notification_status="created", ) mocker.patch("app.main.views.notifications.get_page_count_for_letter", return_value=1) page = client_request.get( "main.cancel_letter", service_id=SERVICE_ONE_ID, notification_id=fake_uuid, ) flash_message = normalize_spaces( page.find("div", class_="banner-dangerous").text) assert "Are you sure you want to cancel sending this letter?" in flash_message
def test_valid_two_factor_email_link_shows_interstitial( client_request, valid_token, mocker, extra_args, expected_encoded_next_arg, ): mock_check_code = mocker.patch('app.user_api_client.check_verify_code') encoded_token = valid_token.replace('%2E', '.') token_url = url_for( 'main.two_factor_email_interstitial', token=encoded_token, **extra_args ) # This must match the URL we put in the emails assert token_url == f'/email-auth/{encoded_token}{expected_encoded_next_arg}' client_request.logout() page = client_request.get_url(token_url) assert normalize_spaces(page.select_one('main .js-hidden').text) == ( 'Sign in ' 'Continue to dashboard' ) form = page.select_one('form') expected_form_id = 'use-email-auth' assert 'action' not in form assert form['method'] == 'post' assert form['id'] == expected_form_id assert page.select_one('main script').text.strip() == ( f'document.getElementById("{expected_form_id}").submit();' ) assert mock_check_code.called is False
def test_organisation_services_shows_live_services_and_usage_with_count_of_1( client_request, mock_get_organisation, mocker, active_user_with_permissions, fake_uuid, ): mocker.patch('app.organisations_client.get_services_and_usage', return_value={ "services": [ { 'service_id': SERVICE_ONE_ID, 'service_name': '1', 'chargeable_billable_sms': 1, 'emails_sent': 1, 'free_sms_limit': 250000, 'letter_cost': 0, 'sms_billable_units': 1, 'sms_cost': 0, 'sms_remainder': None }, ] }) client_request.login(active_user_with_permissions) page = client_request.get('.organisation_dashboard', org_id=ORGANISATION_ID) usage_rows = page.select('main .govuk-grid-column-one-third') # Totals assert normalize_spaces(usage_rows[0].text) == "Emails 1 sent" assert normalize_spaces(usage_rows[1].text) == "Text messages £0.00 spent" assert normalize_spaces(usage_rows[2].text) == "Letters £0.00 spent" assert normalize_spaces(usage_rows[3].text) == "1 email sent" assert normalize_spaces(usage_rows[4].text) == "1 free text message sent" assert normalize_spaces(usage_rows[5].text) == "£0.00 spent on letters"
def test_broadcast_dashboard( client_request, service_one, mock_get_broadcast_messages, mock_get_service_templates, ): service_one['permissions'] += ['broadcast'] page = client_request.get( '.broadcast_dashboard', service_id=SERVICE_ONE_ID, ) assert normalize_spaces(page.select('main h2')[0].text) == ('Live alerts') assert [ normalize_spaces(row.text) for row in page.select('table')[0].select('tbody tr') ] == [ 'Example template To England and Scotland Live until tomorrow at 2:20am', ] assert normalize_spaces( page.select('main h2')[1].text) == ('Waiting for approval') assert [ normalize_spaces(row.text) for row in page.select('table')[1].select('tbody tr') ] == [ 'Example template To England and Scotland Prepared by Test User', ] assert normalize_spaces( page.select('main h2')[2].text) == ('Previous alerts') assert [ normalize_spaces(row.text) for row in page.select('table')[2].select('tbody tr') ] == [ 'Example template To England and Scotland Stopped 10 February at 2:20am', 'Example template To England and Scotland Finished yesterday at 8:20pm', ]
def test_terms_page_has_correct_content(client_request): terms_page = client_request.get('main.terms') assert normalize_spaces(terms_page.select('main p')[0].text) == ( 'These terms apply to your service’s use of GOV.UK Notify. ' 'You must be the service manager to accept them.' )