def test_get_user_phone_number_raises_if_both_api_requests_fail(mocker):
    mock_get_inbound_sms = mocker.patch(
        'app.main.views.conversation.service_api_client.get_inbound_sms_by_id',
        side_effect=HTTPError(response=Mock(status_code=404)),
    )
    mock_get_notification = mocker.patch(
        'app.main.views.conversation.notification_api_client.get_notification',
        side_effect=HTTPError(response=Mock(status_code=404)),
    )
    with pytest.raises(HTTPError):
        get_user_number('service', 'notification')
    mock_get_inbound_sms.assert_called_once_with('service', 'notification')
    mock_get_notification.assert_called_once_with('service', 'notification')
예제 #2
0
def test_update_organisation_domains_when_domain_already_exists(
    mocker,
    client_request,
    fake_uuid,
    organisation_one,
    mock_get_organisation,
):
    user = create_platform_admin_user()
    client_request.login(user)

    mocker.patch('app.organisations_client.update_organisation',
                 side_effect=HTTPError(response=Mock(
                     status_code=400,
                     json={
                         'result': 'error',
                         'message': 'Domain already exists'
                     }),
                                       message="Domain already exists"))

    response = client_request.post(
        'main.edit_organisation_domains',
        org_id=ORGANISATION_ID,
        _data={'domains': [
            'example.gov.uk',
        ]},
        _expected_status=200,
    )

    assert response.find("div", class_="banner-dangerous").text.strip(
    ) == "This domain is already in use"
def test_should_show_delete_template_page_with_never_used_block(app_,
                                                                api_user_active,
                                                                mock_login,
                                                                mock_get_service,
                                                                mock_get_service_template,
                                                                mock_get_user,
                                                                mock_get_user_by_email,
                                                                mock_has_permissions,
                                                                fake_uuid,
                                                                mocker):
    with app_.test_request_context():
        with app_.test_client() as client:
            mocker.patch(
                'app.template_statistics_client.get_template_statistics_for_template',
                side_effect=HTTPError(response=Mock(status_code=404), message="Default message")
            )

            client.login(api_user_active)
            service_id = fake_uuid
            template_id = fake_uuid
            response = client.get(url_for(
                '.delete_service_template',
                service_id=service_id,
                template_id=template_id))

            content = response.get_data(as_text=True)
            assert response.status_code == 200
            assert 'Two week reminder has never been used. Are you sure you want to delete it?' in content
            assert 'Are you sure' in content
            assert 'Two week reminder' in content
            assert 'Your vehicle tax is about to expire' in content
            mock_get_service_template.assert_called_with(service_id, template_id)
예제 #4
0
def test_new_user_accept_invite_with_malformed_token(
    admin_endpoint,
    api_endpoint,
    client,
    service_one,
    mocker,
):
    mocker.patch(api_endpoint, side_effect=HTTPError(
        response=Mock(
            status_code=400,
            json={
                'result': 'error',
                'message': {
                    'invitation': {
                        'Something’s wrong with this link. Make sure you’ve copied the whole thing.'
                    }
                }
            }
        ),
        message={'invitation': 'Something’s wrong with this link. Make sure you’ve copied the whole thing.'}
    ))

    response = client.get(url_for(admin_endpoint, token='thisisnotarealtoken'), follow_redirects=True)

    assert response.status_code == 200
    page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')

    assert normalize_spaces(
        page.select_one('.banner-dangerous').text
    ) == 'Something’s wrong with this link. Make sure you’ve copied the whole thing.'
예제 #5
0
def test_confirm_update_organisation_with_name_already_in_use(
        platform_admin_client, organisation_one, mock_get_organisation,
        mock_verify_password, mocker):
    with platform_admin_client.session_transaction() as session:
        session['organisation_name_change'] = 'newName'

    mocker.patch('app.organisations_client.update_organisation_name',
                 side_effect=HTTPError(
                     response=Mock(status_code=400,
                                   json={
                                       'result':
                                       'error',
                                       'message':
                                       'Organisation name already exists'
                                   }),
                     message="Organisation name already exists"))

    response = platform_admin_client.post(
        url_for('.confirm_edit_organisation_name',
                org_id=organisation_one['id']))

    assert response.status_code == 302
    assert response.location == url_for('main.edit_organisation_name',
                                        org_id=organisation_one['id'],
                                        _external=True)
def test_show_custom_error_message(
    client_request,
    service_one,
    mock_get_service_templates,
    mock_get_template_folders,
    mock_move_to_template_folder,
    mock_create_template_folder,
    data,
    error_msg,
):
    mock_get_template_folders.return_value = [
        _folder("folder_one", PARENT_FOLDER_ID, None),
        _folder("folder_two", FOLDER_TWO_ID, None),
    ]
    mock_move_to_template_folder.side_effect = HTTPError(message="Some api error msg")

    page = client_request.post(
        "main.choose_template",
        service_id=SERVICE_ONE_ID,
        _data=data,
        _expected_status=200,
        _expected_redirect=None,
    )

    assert page.select_one("div.banner-dangerous").text.strip() == error_msg
def test_update_letter_branding_shows_database_errors_on_name_field(
    mocker,
    logged_in_platform_admin_client,
    mock_get_letter_branding_by_id,
    fake_uuid,
):
    mocker.patch('app.main.views.letter_branding.get_png_file_from_svg')
    mocker.patch(
        'app.main.views.letter_branding.letter_branding_client.update_letter_branding',
        side_effect=HTTPError(response=Mock(status_code=400,
                                            json={
                                                'result': 'error',
                                                'message': {
                                                    'name':
                                                    {'name already in use'}
                                                }
                                            }),
                              message={'name': ['name already in use']}))

    response = logged_in_platform_admin_client.post(url_for(
        '.update_letter_branding', branding_id='abc'),
                                                    data={
                                                        'name':
                                                        'my brand',
                                                        'operation':
                                                        'branding-details'
                                                    })

    page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
    error_message = page.find('span', class_='error-message').text.strip()

    assert page.find('h1').text == 'Update letter branding'
    assert error_message == 'name already in use'
def test_view_conversation_updates(
    logged_in_client,
    mocker,
    fake_uuid,
    mock_get_inbound_sms_by_id_with_no_messages,
    mock_get_notification,
):

    mocker.patch(
        'app.main.views.conversation.service_api_client.get_inbound_sms_by_id',
        side_effect=HTTPError(response=Mock(status_code=404)),
    )
    mock_get_partials = mocker.patch(
        'app.main.views.conversation.get_conversation_partials',
        return_value={'messages': 'foo'})

    response = logged_in_client.get(
        url_for(
            'main.conversation_updates',
            service_id=SERVICE_ONE_ID,
            notification_id=fake_uuid,
        ))

    assert response.status_code == 200
    assert json.loads(response.get_data(as_text=True)) == {'messages': 'foo'}

    mock_get_partials.assert_called_once_with(SERVICE_ONE_ID, '07123 456789')
예제 #9
0
def test_accept_invite_redirects_if_api_raises_an_error_that_they_are_already_part_of_the_service(
        client, mocker, api_user_active, sample_invite, mock_accept_invite,
        mock_get_service, mock_get_users_by_service):
    sample_invite['email_address'] = api_user_active['email_address']

    # This mock needs to return a user with a different ID to the invited user so that
    # `existing_user in Users(invited_user.service)` returns False and the right code path is tested
    mocker.patch('app.user_api_client.get_user_by_email',
                 return_value=create_api_user_active(with_unique_id=True))
    mocker.patch('app.invite_api_client.check_token',
                 return_value=sample_invite)

    mocker.patch(
        'app.user_api_client.add_user_to_service',
        side_effect=HTTPError(
            response=Mock(
                status_code=400,
                json={
                    "result": "error",
                    "message": {
                        f"User id: {api_user_active['id']} already part of service id: {SERVICE_ONE_ID}"
                    }
                },
            ),
            message=
            f"User id: {api_user_active['id']} already part of service id: {SERVICE_ONE_ID}"
        ))

    response = client.get(url_for('main.accept_invite',
                                  token='thisisnotarealtoken'),
                          follow_redirects=False)
    assert response.location == url_for('main.service_dashboard',
                                        service_id=SERVICE_ONE_ID,
                                        _external=True)
def test_archive_user_shows_error_message_if_user_cannot_be_archived(
    platform_admin_client,
    api_user_active,
    mocker,
    mock_get_non_empty_organisations_and_services_for_user,
):
    mocker.patch(
        'app.user_api_client.post',
        side_effect=HTTPError(
            response=mocker.Mock(
                status_code=400,
                json={'result': 'error',
                      'message': 'User can’t be removed from a service - check all services have another '
                      'team member with manage_settings'}
            ),
            message='User can’t be removed from a service - check all services have another team member '
            'with manage_settings'
        )
    )

    response = platform_admin_client.post(
        url_for('main.archive_user', user_id=api_user_active['id']),
        follow_redirects=True
    )

    page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')

    assert normalize_spaces(page.find('h1').text) == 'Platform admin user'
    assert normalize_spaces(
        page.select_one('.banner-dangerous').text
    ) == 'User can’t be removed from a service - check all services have another team member with manage_settings'
예제 #11
0
def test_confirm_update_organisation_with_name_already_in_use(
    platform_admin_client,
    organisation_one,
    mock_get_organisation,
    mock_verify_password,
    mocker,
):
    with platform_admin_client.session_transaction() as session:
        session["organisation_name_change"] = "newName"

    mocker.patch(
        "app.organisations_client.update_organisation_name",
        side_effect=HTTPError(
            response=Mock(
                status_code=400,
                json={
                    "result": "error",
                    "message": "Organisation name already exists"
                },
            ),
            message="Organisation name already exists",
        ),
    )

    response = platform_admin_client.post(
        url_for(".confirm_edit_organisation_name",
                org_id=organisation_one["id"]))

    assert response.status_code == 302
    assert response.location == url_for("main.edit_organisation_name",
                                        org_id=organisation_one["id"],
                                        _external=True)
예제 #12
0
def test_logo_does_not_get_persisted_if_updating_email_branding_client_throws_an_error(
        logged_in_platform_admin_client, mock_create_email_branding, mocker,
        fake_uuid):
    with logged_in_platform_admin_client.session_transaction() as session:
        user_id = session["user_id"]

    temp_filename = EMAIL_LOGO_LOCATION_STRUCTURE.format(
        temp=TEMP_TAG.format(user_id=user_id),
        unique_id=fake_uuid,
        filename='test.png')

    mocked_persist_logo = mocker.patch(
        'app.main.views.email_branding.persist_logo')
    mocked_delete_email_temp_files_by = mocker.patch(
        'app.main.views.email_branding.delete_email_temp_files_created_by')
    mocker.patch(
        'app.main.views.email_branding.email_branding_client.create_email_branding',
        side_effect=HTTPError())

    logged_in_platform_admin_client.post(url_for('.create_email_branding',
                                                 logo=temp_filename),
                                         content_type='multipart/form-data')

    assert not mocked_persist_logo.called
    assert not mocked_delete_email_temp_files_by.called
예제 #13
0
def test_activate_user_redirects_to_service_dashboard_if_user_already_belongs_to_service(
    mocker,
    client,
    service_one,
    sample_invite,
    api_user_active,
    mock_login,
):
    mocker.patch(
        'app.user_api_client.add_user_to_service',
        side_effect=HTTPError(
            response=Mock(
                status_code=400,
                json={
                    "result": "error",
                    "message": {
                        f"User id: {api_user_active['id']} already part of service id: {service_one['id']}"
                    }
                },
            ),
            message=
            f"User id: {api_user_active['id']} already part of service id: {service_one['id']}"
        ))

    # Can't use `with client.session_transaction()...` here since activate_session is not a view function
    flask_session['invited_user'] = sample_invite

    response = activate_user(api_user_active['id'])

    assert response.location == url_for('main.service_dashboard',
                                        service_id=service_one['id'])

    flask_session.pop('invited_user')
예제 #14
0
 def _update(
     service_id,
     **kwargs
 ):
     json_mock = Mock(return_value={'message': {'name': ["Duplicate service name '{}'".format(kwargs.get('name'))]}})
     resp_mock = Mock(status_code=400, json=json_mock)
     http_error = HTTPError(response=resp_mock, message="Default message")
     raise http_error
예제 #15
0
 def _create(**_kwargs):
     json_mock = mocker.Mock(
         return_value={'message': {
             'name': ["Duplicate service name"]
         }})
     resp_mock = mocker.Mock(status_code=400, json=json_mock)
     http_error = HTTPError(response=resp_mock, message="Default message")
     raise http_error
예제 #16
0
 def _update(id_, name, type_, content, service, subject=None):
     json_mock = Mock(return_value={
         'message': {'content': ["Content has a character count greater than the limit of 459"]},
         'result': 'error'
     })
     resp_mock = Mock(status_code=400, json=json_mock)
     http_error = HTTPError(
         response=resp_mock,
         message={'content': ["Content has a character count greater than the limit of 459"]})
     raise http_error
def test_notifications_api_error(view, service_id, document_id, client, mocker,
                                 sample_service):
    mocker.patch('app.service_api_client.get_service',
                 return_value={'data': sample_service})
    mocker.patch('app.service_api_client.get_service',
                 side_effect=HTTPError(response=Mock(status_code=404)))
    response = client.get(
        url_for(view, service_id=uuid4(), document_id=uuid4(), key='1234'))

    assert response.status_code == 404
예제 #18
0
def test_load_service_before_request_handles_404(client_request, mocker):
    exc = HTTPError(Response(status=404), 'Not found')
    get_service = mocker.patch('app.service_api_client.get_service',
                               side_effect=exc)

    client_request.get('main.service_dashboard',
                       service_id='00000000-0000-0000-0000-000000000000',
                       _expected_status=404)

    get_service.assert_called_once_with('00000000-0000-0000-0000-000000000000')
def test_get_user_phone_number_when_only_outbound_exists(mocker):
    mock_get_inbound_sms = mocker.patch(
        'app.main.views.conversation.service_api_client.get_inbound_sms_by_id',
        side_effect=HTTPError(response=Mock(status_code=404)),
    )
    mock_get_notification = mocker.patch(
        'app.main.views.conversation.notification_api_client.get_notification',
        return_value={'to': '15550000000'})
    assert get_user_number('service', 'notification') == '+1 555-000-0000'
    mock_get_inbound_sms.assert_called_once_with('service', 'notification')
    mock_get_notification.assert_called_once_with('service', 'notification')
def test_load_service_before_request_handles_404(client_request, mocker):
    exc = HTTPError(Response(status=404), "Not found")
    get_service = mocker.patch("app.service_api_client.get_service",
                               side_effect=exc)

    client_request.get(
        "main.service_dashboard",
        service_id="00000000-0000-0000-0000-000000000000",
        _expected_status=404,
    )

    get_service.assert_called_once_with("00000000-0000-0000-0000-000000000000")
def notify_example_http_error():
    """Return a mock object with attributes of Notify `HTTPError`."""
    response = mock.Mock()
    response.status_code = 400
    response.json.side_effect = AttributeError
    message = [
        {u'message': u'email_address Not a valid email address', u'error': u'ValidationError'},
        {u'message': u'template_id is not a valid UUID', u'error': u'ValidationError'},
        # notify do actually use non-ascii characters in their error messages
        {u'message': u'Won\u2019t send unless you give us \u00a3\u00a3\u00a3', u'error': u'ValidationError'},
    ]
    return HTTPError(response, message)
예제 #22
0
    def request(self, method, url, data=None, params=None):

        logger.debug("API request {} {}".format(method, url))

        payload = json.dumps(data)

        api_token = create_jwt_token(
            self.api_key,
            self.service_id
        )

        headers = {
            "Content-type": "application/json",
            "Authorization": "Bearer {}".format(api_token),
            "User-agent": "NOTIFY-API-PYTHON-CLIENT/{}".format(__version__),
        }

        url = urlparse.urljoin(self.base_url, url)

        start_time = monotonic()
        try:
            response = requests.request(
                method,
                url,
                headers=headers,
                data=payload,
                params=params
            )
            response.raise_for_status()
        except requests.RequestException as e:
            api_error = HTTPError.create(e)
            logger.error(
                "API {} request on {} failed with {} '{}'".format(
                    method,
                    url,
                    api_error.status_code,
                    api_error.message
                )
            )
            raise api_error
        finally:
            elapsed_time = monotonic() - start_time
            logger.debug("API {} request on {} finished in {}".format(method, url, elapsed_time))

        try:
            if response.status_code == 204:
                return
            return response.json()
        except ValueError:
            raise InvalidResponse(
                response,
                message="No JSON response object could be decoded"
            )
def test_validate_security_key_api_error(client_request,
                                         api_nongov_user_active, mocker):
    mock_login = mocker.patch("app.models.user.User.login")
    mock_validate = mocker.patch(
        "app.user_api_client.validate_security_keys",
        side_effect=HTTPError(response=Mock(status_code=500)),
    )

    client_request.post(("main.user_profile_validate_security_keys"),
                        _data="fake",
                        _expected_status=500)

    assert mock_validate.called
    assert mock_login.called is False
def test_should_redirect_to_password_reset_sent_for_missing_email(
        app_, api_user_active, mocker):
    with app_.test_request_context():

        mocker.patch('app.user_api_client.send_reset_password_url',
                     side_effect=HTTPError(Response(status=404), 'Not found'))
        response = app_.test_client().post(
            url_for('.forgot_password'),
            data={'email_address': api_user_active.email_address})
        assert response.status_code == 200
        assert 'Click the link in the email to reset your password.' \
               in response.get_data(as_text=True)
        app.user_api_client.send_reset_password_url.assert_called_once_with(
            api_user_active.email_address)
def test_get_user_phone_number_when_only_inbound_exists(mocker):

    mock_get_inbound_sms = mocker.patch(
        'app.main.views.conversation.service_api_client.get_inbound_sms_by_id',
        return_value={
            'user_number': '4407900900123',
            'notify_number': '07900000002'
        })
    mock_get_notification = mocker.patch(
        'app.main.views.conversation.notification_api_client.get_notification',
        side_effect=HTTPError(response=Mock(status_code=404)),
    )
    assert get_user_number('service', 'notification') == '07900 900123'
    mock_get_inbound_sms.assert_called_once_with('service', 'notification')
    assert mock_get_notification.called is False
예제 #26
0
 def _perform_request(self, method, url, kwargs):
     start_time = monotonic()
     try:
         response = requests.request(method, url, **kwargs)
         response.raise_for_status()
         return response
     except requests.RequestException as e:
         api_error = HTTPError.create(e)
         logger.error("API {} request on {} failed with {} '{}'".format(
             method, url, api_error.status_code, api_error.message))
         raise api_error
     finally:
         elapsed_time = monotonic() - start_time
         logger.debug("API {} request on {} finished in {}".format(
             method, url, elapsed_time))
def test_should_redirect_to_password_reset_sent_for_missing_email(
    client,
    api_user_active,
    mocker,
):

    mocker.patch(
        "app.user_api_client.send_reset_password_url",
        side_effect=HTTPError(Response(status=404), "Not found"),
    )
    response = client.post(
        url_for(".forgot_password"),
        data={"email_address": api_user_active["email_address"]},
    )
    assert response.status_code == 200
    assert "Click the link in the email to reset your password." in response.get_data(
        as_text=True)
    app.user_api_client.send_reset_password_url.assert_called_once_with(
        api_user_active["email_address"])
def test_create_letter_branding_shows_database_errors_on_name_fields(
    mocker,
    platform_admin_client,
    fake_uuid,
):
    with platform_admin_client.session_transaction() as session:
        user_id = session["user_id"]

    mocker.patch("app.main.views.letter_branding.get_png_file_from_svg")
    mocker.patch(
        "app.main.views.letter_branding.letter_branding_client.create_letter_branding",
        side_effect=HTTPError(
            response=Mock(
                status_code=400,
                json={
                    "result": "error",
                    "message": {
                        "name": {"name already in use"}
                    }
                },
            ),
            message={"name": ["name already in use"]},
        ),
    )

    temp_logo = LETTER_TEMP_LOGO_LOCATION.format(user_id=user_id,
                                                 unique_id=fake_uuid,
                                                 filename="test.svg")

    response = platform_admin_client.post(
        url_for(".create_letter_branding", logo=temp_logo),
        data={
            "name": "my brand",
            "operation": "branding-details"
        },
    )

    page = BeautifulSoup(response.data.decode("utf-8"), "html.parser")
    error_message = page.find("span", class_="error-message").text.strip()

    assert page.find("h1").text == "Add letter branding"
    assert error_message == "name already in use"
예제 #29
0
def test_should_show_delete_template_page_with_never_used_block(
    client_request,
    mock_get_service_template,
    fake_uuid,
    mocker,
):
    mocker.patch(
        'app.template_statistics_client.get_template_statistics_for_template',
        side_effect=HTTPError(response=Mock(status_code=404),
                              message="Default message"))
    page = client_request.get(
        '.delete_service_template',
        service_id=SERVICE_ONE_ID,
        template_id=fake_uuid,
        _test_page_title=False,
    )
    assert page.h1.text == 'Are you sure you want to delete Two week reminder?'
    assert not page.select('.banner-dangerous p')
    assert normalize_spaces(page.select('.sms-message-wrapper')[0].text) == (
        'service one: Template <em>content</em> with & entity')
    mock_get_service_template.assert_called_with(SERVICE_ONE_ID, fake_uuid)
예제 #30
0
    def request(self, method, url, data=None, params=None):

        logger.debug("API request {} {}".format(method, url))

        api_token = create_jwt_token(self.api_key, self.service_id)

        kwargs = {
            "headers": self.generate_headers(api_token),
        }

        if data is not None:
            kwargs.update(data=json.dumps(data))

        if params is not None:
            kwargs.update(params=params)

        url = urllib.parse.urljoin(str(self.base_url), str(url))

        start_time = monotonic()
        try:
            response = requests.request(method, url, **kwargs)
            response.raise_for_status()
        except requests.RequestException as e:
            api_error = HTTPError.create(e)
            logger.error("API {} request on {} failed with {} '{}'".format(
                method, url, api_error.status_code, api_error.message))
            raise api_error
        finally:
            elapsed_time = monotonic() - start_time
            logger.debug("API {} request on {} finished in {}".format(
                method, url, elapsed_time))

        try:
            if response.status_code == 204:
                return
            return response.json()
        except ValueError:
            raise InvalidResponse(
                response, message="No JSON response object could be decoded")
def test_create_letter_branding_shows_database_errors_on_name_fields(
    mocker,
    logged_in_platform_admin_client,
    fake_uuid,
):
    with logged_in_platform_admin_client.session_transaction() as session:
        user_id = session["user_id"]

    mocker.patch('app.main.views.letter_branding.get_png_file_from_svg')
    mocker.patch(
        'app.main.views.letter_branding.letter_branding_client.create_letter_branding',
        side_effect=HTTPError(response=Mock(status_code=400,
                                            json={
                                                'result': 'error',
                                                'message': {
                                                    'name':
                                                    {'name already in use'}
                                                }
                                            }),
                              message={'name': ['name already in use']}))

    temp_logo = LETTER_TEMP_LOGO_LOCATION.format(user_id=user_id,
                                                 unique_id=fake_uuid,
                                                 filename='test.svg')

    response = logged_in_platform_admin_client.post(url_for(
        '.create_letter_branding', logo=temp_logo),
                                                    data={
                                                        'name':
                                                        'my brand',
                                                        'operation':
                                                        'branding-details'
                                                    })

    page = BeautifulSoup(response.data.decode('utf-8'), 'html.parser')
    error_message = page.find('span', class_='error-message').text.strip()

    assert page.find('h1').text == 'Add letter branding'
    assert error_message == 'name already in use'