def test_list_account_requests(self): self.mocked_login() with responses.RequestsMock() as rsps: rsps.add( rsps.GET, urljoin(settings.API_URL, 'users'), json={'results': [], 'count': 0}, content_type='application/json' ) rsps.add( rsps.GET, urljoin(settings.API_URL, 'requests'), json={'results': [ { 'created': '2018-08-12T12:00:00Z', 'id': 1, 'first_name': 'John', 'last_name': 'Smith', 'username': '******', 'email': '*****@*****.**', }, { 'created': '2018-08-13T12:10:00Z', 'id': 2, 'first_name': 'Mary', 'last_name': 'Marks', 'username': '******', 'email': '*****@*****.**', }, ], 'count': 2}, content_type='application/json' ) response = self.client.get(reverse('list-users')) self.assertContains(response, 'New user requests') self.assertContains(response, 'Edit existing users') content = response.content.decode(response.charset) self.assertIn('John Smith', content) self.assertIn('Mary Marks', content) self.assertIn('12/08/2018', content) self.assertNotIn('john123', content)
def test_cannot_delete_self(self): self.mocked_login() with responses.RequestsMock() as rsps: rsps.add( rsps.DELETE, urljoin(settings.API_URL, '/users/test-user/'), json={'detail': 'You cannot disable yourself'}, status=400, content_type='application/json' ) rsps.add( rsps.GET, urljoin(settings.API_URL, '/users'), json={'results': [], 'count': 0}, status=200, content_type='application/json' ) rsps.add( rsps.GET, urljoin(settings.API_URL, 'requests'), json={'results': [], 'count': 0}, content_type='application/json' ) response = self.client.post( reverse('delete-user', kwargs={'username': '******'}), follow=True) messages = response.context['messages'] messages = [str(m) for m in messages] self.assertIn('You cannot disable yourself', messages)
def test_success(self): username = '******' # mock the response, return token expected_token = generate_tokens() expected_user_data = { 'pk': 1, 'first_name': 'My First Name', 'last_name': 'My last name', } responses.add( responses.POST, urljoin(settings.API_URL, 'oauth2/token'), body=json.dumps(expected_token), status=200, content_type='application/json' ) responses.add( responses.GET, urljoin(settings.API_URL, 'users/', username), body=json.dumps(expected_user_data), status=200, content_type='application/json' ) # authenticate, should return authentication data data = api_client.authenticate(username, 'my-password') self.assertEqual(data['pk'], expected_user_data.get('pk')) self.assertDictEqual(data['token'], expected_token) self.assertDictEqual(data['user_data'], expected_user_data)
def test_list_users(self): self.mocked_login() with responses.RequestsMock() as rsps: rsps.add( rsps.GET, urljoin(settings.API_URL, 'users'), json={'results': [ { 'first_name': 'John', 'last_name': 'Smith', 'username': '******', 'email': '*****@*****.**', 'is_active': True, 'is_locked_out': False, 'user_admin': False, }, { 'first_name': 'Mary', 'last_name': 'Marks', 'username': '******', 'email': '*****@*****.**', 'is_active': False, 'is_locked_out': False, 'user_admin': True, }, ], 'count': 2}, content_type='application/json' ) rsps.add( rsps.GET, urljoin(settings.API_URL, 'requests'), json={'results': [], 'count': 0}, content_type='application/json' ) response = self.client.get(reverse('list-users')) self.assertNotContains(response, 'New user requests') self.assertContains(response, 'Edit existing users') content = response.content.decode(response.charset) self.assertIn('john123', content) self.assertIn('mary321', content) self.assertIn('User can manage other accounts', content)
def test_success(self): username = "******" # mock the response, return token expected_token = generate_tokens() expected_user_data = {"pk": 1, "first_name": "My First Name", "last_name": "My last name"} responses.add( responses.POST, urljoin(settings.API_URL, "oauth2/token"), body=json.dumps(expected_token), status=200, content_type="application/json", ) responses.add( responses.GET, urljoin(settings.API_URL, "users/", username), body=json.dumps(expected_user_data), status=200, content_type="application/json", ) # authenticate, should return authentication data data = api_client.authenticate(username, "my-password") self.assertEqual(data["pk"], expected_user_data.get("pk")) self.assertDictEqual(data["token"], expected_token) self.assertDictEqual(data["user_data"], expected_user_data)
def test_base_api_url_allows_trailing_slash(self): actual_api_url = settings.API_URL # set API_URL and then reload the client to generate # a new REQUEST_TOKEN_URL settings.API_URL = actual_api_url + "/" reload(api_client) username = "******" # mock the response, return token expected_token = generate_tokens() expected_user_data = {"pk": 1, "first_name": "My First Name", "last_name": "My last name"} responses.add( responses.POST, urljoin(actual_api_url, "oauth2/token/"), body=json.dumps(expected_token), status=200, content_type="application/json", ) responses.add( responses.GET, urljoin(actual_api_url, "users/", username), body=json.dumps(expected_user_data), status=200, content_type="application/json", ) # authenticate, should complete without error api_client.authenticate(username, "my-password") # revert changes settings.API_URL = actual_api_url reload(api_client)
def assertAcceptRequest(self, user_admin): # noqa: N802 with responses.RequestsMock() as rsps: rsps.add( rsps.GET, urljoin(settings.API_URL, 'requests', '1'), json={ 'created': '2018-08-12T12:00:00Z', 'id': 1, 'first_name': 'A', 'last_name': 'B', 'email': '*****@*****.**', 'username': '******', 'role': 'general', 'reason': '' }, content_type='application/json' ) response = self.client.get(reverse('accept-request', kwargs={'account_request': 1})) self.assertContains(response, 'New user request') content = response.content.decode(response.charset) self.assertIn('A B', content) self.assertIn('12/08/2018', content) self.assertIn('*****@*****.**', content) self.assertIn('abc', content) self.assertNotIn('Reason', content) rsps.add( rsps.PATCH, urljoin(settings.API_URL, 'requests', '1'), content_type='application/json' ) rsps.add( rsps.GET, urljoin(settings.API_URL, 'users'), json={'results': [], 'count': 0}, content_type='application/json' ) rsps.add( rsps.GET, urljoin(settings.API_URL, 'requests'), json={'results': [], 'count': 0}, content_type='application/json' ) payload = {} if user_admin: payload['user_admin'] = 'on' response = self.client.post(reverse('accept-request', kwargs={'account_request': 1}), data=payload, follow=True) self.assertContains(response, 'New user request accepted') patch_call = rsps.calls[-3] if user_admin: self.assertEqual(patch_call.request.body, 'user_admin=True') else: self.assertEqual(patch_call.request.body, 'user_admin=False')
def test_notifications_without_cache(self): cache.clear() with responses.RequestsMock() as rsps: rsps.add( rsps.GET, urljoin(settings.API_URL, 'notifications'), json={ 'count': 1, 'results': [{ 'target': 'target', 'level': 'warning', 'headline': 'Test', 'message': 'Body', 'start': '2017-11-29T12:00:00Z', 'end': None, }] }, ) rsps.add( rsps.GET, urljoin(settings.API_URL, 'notifications'), json={ 'count': 1, 'results': [{ 'target': 'target', 'level': 'warning', 'headline': 'Test', 'message': 'Body', 'start': '2017-11-29T12:00:00Z', 'end': None, }] }, ) self.load_mocked_template( """ {% load mtp_common %} {% notification_banners request 'target' use_cache=False %} """, {'request': self.authenticated_request()}, ) response = self.load_mocked_template( """ {% load mtp_common %} {% notification_banners request 'target' use_cache=False %} """, {'request': self.authenticated_request()}, ) response_content = response.content.decode(response.charset).strip() self.assertIn('Test', response_content)
def test_edit_user(self): self.mocked_login() with responses.RequestsMock() as rsps: self._init_existing_user(rsps) self.mock_roles_list(rsps) response = self.client.get(reverse('edit-user', kwargs={'username': '******'})) content = response.content.decode(response.charset) self.assertIn('id_user_admin', content) self.assertNotIn('id_role', content) updated_user_data = { 'first_name': 'dave', 'last_name': 'smith', 'email': '*****@*****.**', 'user_admin': True, 'role': 'prison-clerk', } rsps.add( rsps.PATCH, urljoin(settings.API_URL, 'users/current_user/'), status=204, content_type='application/json' ) with silence_logger('mtp', level=logging.WARNING): self.client.post( reverse('edit-user', kwargs={'username': '******'}), data=updated_user_data ) self.assertEqual( json.loads(rsps.calls[-1].request.body.decode()), updated_user_data )
def test_new_user(self): self.mocked_login() new_user_data = { 'username': '******', 'first_name': 'new', 'last_name': 'user', 'email': '*****@*****.**', 'user_admin': False, 'role': 'prison-clerk', } with responses.RequestsMock() as rsps: rsps.add( rsps.POST, urljoin(settings.API_URL, 'users'), status=201, content_type='application/json' ) self.mock_roles_list(rsps) with silence_logger('mtp', level=logging.WARNING): self.client.post(reverse('new-user'), data=new_user_data) self.assertEqual( json.loads(rsps.calls[-1].request.body.decode()), new_user_data )
def test_cannot_change_username(self): self.mocked_login() with responses.RequestsMock() as rsps: self._init_existing_user(rsps) updated_user_data = { 'username': '******', 'first_name': 'current', 'last_name': 'user', 'email': '*****@*****.**', 'user_admin': False, 'role': 'prison-clerk', } rsps.add( rsps.PATCH, urljoin(settings.API_URL, 'users/current_user/'), status=204, content_type='application/json' ) self.mock_roles_list(rsps) with silence_logger('mtp', level=logging.WARNING): self.client.post( reverse('edit-user', kwargs={'username': '******'}), data=updated_user_data ) del updated_user_data['username'] self.assertEqual( json.loads(rsps.calls[-1].request.body.decode()), updated_user_data )
def call_command(self, housing_response, expected_location, bundle_class): credited_date = self.latest_credit.modified.date() with responses.RequestsMock() as rsps: location_response = { 'establishment': { 'code': self.latest_credit.prison.nomis_id, 'desc': self.latest_credit.prison.name }, } location_response.update(housing_response) rsps.add( responses.GET, urljoin( settings.NOMIS_API_BASE_URL, '/offenders/%s/location' % self.latest_credit.prisoner_number), json=location_response, ) call_command('create_prisoner_credit_notices', '/tmp/fake-path', self.latest_credit.prison.nomis_id, verbosity=0, date=credited_date.strftime('%Y-%m-%d')) bundle_class.assert_called_once_with(self.latest_credit.prison.name, [( self.latest_credit.prisoner_name, self.latest_credit.prisoner_number, expected_location, [self.latest_credit], [], )], self.latest_log.created.date())
def request(self, verb, path, params=None, json=None, timeout=15, retries=0, session=None): """ Makes a request call to Prison API (i.e. NOMIS). You probably want to use the `get` or the `post` methods instead. """ if not isinstance(retries, Retry): retries = AuthenticatedRetry(self, retries) response = request_retry( verb, urljoin(self.prison_api_v1_base_url, path, trailing_slash=False), retries=retries, session=session, headers=self.build_request_api_headers(), timeout=timeout, params=params, json=json, ) response.raise_for_status() if response.status_code != requests.codes.no_content: return response.json() return { 'status_code': response.status_code, }
def call_command(self, housing_response, expected_location, bundle_class): credited_date = self.latest_credit.modified.date() with responses.RequestsMock() as rsps: location_response = { 'establishment': {'code': self.latest_credit.prison.nomis_id, 'desc': self.latest_credit.prison.name}, } location_response.update(housing_response) rsps.add( responses.GET, urljoin(settings.NOMIS_API_BASE_URL, '/offenders/%s/location' % self.latest_credit.prisoner_number), json=location_response, ) call_command( 'create_prisoner_credit_notices', '/tmp/fake-path', self.latest_credit.prison.nomis_id, verbosity=0, date=credited_date.strftime('%Y-%m-%d') ) bundle_class.assert_called_once_with( self.latest_credit.prison.name, [( self.latest_credit.prisoner_name, self.latest_credit.prisoner_number, expected_location, [self.latest_credit], [], )], self.latest_log.created.date() )
def test_delete_user_permission_propagates(self): self.mocked_login() with responses.RequestsMock() as rsps: rsps.add( rsps.GET, urljoin(settings.API_URL, 'users'), json={'results': []}, status=200, content_type='application/json' ) rsps.add( rsps.GET, urljoin(settings.API_URL, 'requests'), json={'results': [], 'count': 0}, content_type='application/json' ) response = self.client.get(reverse('list-users')) self.assertTrue(response.context['can_delete'])
def test_hmpps_auth_hostname_used(self): self.assertTrue(settings.HMPPS_AUTH_BASE_URL) self.assertNotEqual(settings.HMPPS_AUTH_BASE_URL, settings.HMPPS_PRISON_API_BASE_URL) self.assertEqual( nomis.Connector().hmpps_auth_token_url, urljoin(settings.HMPPS_AUTH_BASE_URL, '/oauth/token', trailing_slash=False))
def test_reset_password(self): responses.add(responses.POST, urljoin(settings.API_URL, 'reset_password'), status=204, content_type='application/json') response = self.client.post(reverse('reset_password'), data={ 'username': '******', }, follow=False) self.assertRedirects(response, reverse('reset_password_done'))
def setUp(self): """ Sets up a request mock object with request.user.token == generated token. It also defines the {base_url}/test/ endpoint which will be used by all the test methods. """ super(GetConnectionTestCase, self).setUp() self.request = mock.MagicMock(user=mock.MagicMock(token=generate_tokens())) self.test_endpoint = urljoin(settings.API_URL, "test")
def test_base_api_url_allows_trailing_slash(self): actual_api_url = settings.API_URL # set API_URL and then reload the client to generate # a new REQUEST_TOKEN_URL settings.API_URL = actual_api_url + '/' reload(api_client) username = '******' # mock the response, return token expected_token = generate_tokens() expected_user_data = { 'pk': 1, 'first_name': 'My First Name', 'last_name': 'My last name', } responses.add( responses.POST, urljoin(actual_api_url, 'oauth2/token/'), body=json.dumps(expected_token), status=200, content_type='application/json' ) responses.add( responses.GET, urljoin(actual_api_url, 'users/', username), body=json.dumps(expected_user_data), status=200, content_type='application/json' ) # authenticate, should complete without error api_client.authenticate(username, 'my-password') # revert changes settings.API_URL = actual_api_url reload(api_client)
def test_sign_up(self): with responses.RequestsMock() as rsps: rsps.add( rsps.POST, urljoin(settings.API_URL, '/requests/'), json={}, status=201, content_type='application/json' ) response = self.client.post(reverse('sign-up'), data={ 'first_name': 'A', 'last_name': 'B', 'email': '*****@*****.**', 'username': '******', 'role': 'general', }) self.assertContains(response, 'Your request for access has been sent')
def test_can_cascade_to_fallback_notification_targets(self): with responses.RequestsMock() as rsps: rsps.add( rsps.GET, urljoin(settings.API_URL, 'notifications') + '?target__startswith=target1', match_querystring=True, json={ 'count': 0, 'results': [] }, ) rsps.add( rsps.GET, urljoin(settings.API_URL, 'notifications') + '?target__startswith=target2', match_querystring=True, json={ 'count': 1, 'results': [{ 'target': 'target2', 'level': 'warning', 'headline': 'Test', 'message': 'Body', 'start': '2017-11-29T12:00:00Z', 'end': None, }] }, ) response = self.load_mocked_template( """ {% load mtp_common %} {% notification_banners request 'target1' 'target2' %} """, {'request': self.authenticated_request()}, ) response_content = response.content.decode(response.charset).strip() self.assertIn('Test', response_content)
def _mock_successful_auth_request(self, rsps, token='my-token'): rsps.add( responses.POST, urljoin( settings.HMPPS_AUTH_BASE_URL, '/oauth/token?grant_type=client_credentials', trailing_slash=False, ), json={ 'access_token': token, 'expires_in': 3600, }, status=200, )
def test_decline_account_requests(self): self.mocked_login() with responses.RequestsMock() as rsps: rsps.add( rsps.DELETE, urljoin(settings.API_URL, 'requests', '1'), status=204, content_type='application/json' ) rsps.add( rsps.GET, urljoin(settings.API_URL, 'users'), json={'results': [], 'count': 0}, content_type='application/json' ) rsps.add( rsps.GET, urljoin(settings.API_URL, 'requests'), json={'results': [], 'count': 0}, content_type='application/json' ) response = self.client.post(reverse('decline-request', kwargs={'account_request': 1}), follow=True) self.assertContains(response, 'New user request was declined')
def setUp(self): """ Sets up a request mock object with request.user.token == generated token. It also defines the {base_url}/test/ endpoint which will be used by all the test methods. """ super(GetConnectionTestCase, self).setUp() self.request = mock.MagicMock( user=mock.MagicMock( token=generate_tokens() ) ) self.test_endpoint = urljoin(settings.API_URL, 'test')
def test_password_change(self): responses.add(responses.POST, urljoin(settings.API_URL, 'change_password'), status=204, content_type='application/json') self.login() response = self.client.post(reverse('password_change'), data={ 'old_password': '******', 'new_password': '******', 'new_password_confirmation': 'new' }, follow=False) self.assertRedirects(response, reverse('password_change_done'))
def test_unexpected_api_error_response(self): with responses.RequestsMock() as rsps: rsps.add( rsps.POST, urljoin(settings.API_URL, '/requests/'), json={'abc': '******'}, status=400, content_type='application/json' ) with silence_logger('mtp'): response = self.client.post(reverse('sign-up'), data={ 'first_name': 'A', 'last_name': 'B', 'email': '*****@*****.**', 'username': '******', 'role': 'general', }) self.assertNotContains(response, 'Your request for access has been sent') self.assertNotContains(response, '******') self.assertContains(response, 'This service is currently unavailable')
def test_reset_password_errors(self): responses.add(responses.POST, urljoin(settings.API_URL, 'reset_password'), json={'errors': { 'username': ['User not found'] }}, status=400, content_type='application/json') response = self.client.post(reverse('reset_password'), data={ 'username': '******', }, follow=True) form = response.context_data['form'] self.assertFalse(form.is_valid()) self.assertEqual(form.errors['username'], ['User not found'])
def mock_roles_list(self, rsps): rsps.add( rsps.GET, urljoin(settings.API_URL, '/roles/'), json={ 'count': 1, 'results': [{ 'name': 'prison-clerk', 'application': { 'name': 'Digital cashbook', 'client_id': 'cashbook', } }], }, status=200, content_type='application/json' )
def _init_existing_user(self, rsps, **user_data_edits): existing_user_data = { 'username': '******', 'first_name': 'current', 'last_name': 'user', 'email': '*****@*****.**', 'user_admin': False, 'roles': ['prison-clerk'], } existing_user_data.update(user_data_edits) rsps.add( rsps.GET, urljoin(settings.API_URL, '/users/current_user/'), json=existing_user_data, status=200, content_type='application/json' )
def test_api_errors_do_not_appear_on_page(self): with responses.RequestsMock() as rsps, silence_logger(): rsps.add( rsps.GET, urljoin(settings.API_URL, 'notifications'), body='error', status=500, ) response = self.load_mocked_template( """ {% load mtp_common %} {% notification_banners request 'target' %} """, {'request': self.authenticated_request()}, ) response_content = response.content.decode(response.charset).strip() self.assertEqual(response_content, '')
def test_change_password(self): responses.add(responses.POST, urljoin(settings.API_URL, 'change_password'), status=204, content_type='application/json') form = PasswordChangeForm(self.request, data={ 'old_password': '******', 'new_password': '******', 'new_password_confirmation': 'new' }) self.assertTrue(form.is_valid()) self.assertEqual( json.loads(responses.calls[0].request.body.decode('utf-8')), { 'old_password': '******', 'new_password': '******' })
def test_incorrect_password_errors(self): responses.add(responses.POST, urljoin(settings.API_URL, 'change_password'), json={'errors': { '__all__': ['Incorrect password'] }}, status=400, content_type='application/json') self.login() response = self.client.post(reverse('password_change'), data={ 'old_password': '******', 'new_password': '******', 'new_password_confirmation': 'new' }) form = response.context_data['form'] self.assertFalse(form.is_valid()) self.assertEqual(form.errors['__all__'], ['Incorrect password'])
def test_shows_has_role_page(self): with responses.RequestsMock() as rsps: error = { 'condition': 'user-exists', 'roles': [{'role': 'general', 'application': 'Application 1', 'login_url': 'http://example.com/1'}], } rsps.add( rsps.POST, urljoin(settings.API_URL, '/requests/'), json={'__mtp__': error, 'username': '******'}, status=400, content_type='application/json' ) response = self.client.post(reverse('sign-up'), data={ 'first_name': 'A', 'last_name': 'B', 'email': '*****@*****.**', 'username': '******', 'role': 'general', }) self.assertContains(response, 'You already have access to this service') self.assertContains(response, 'http://example.com/1')
def test_reset_password(self): responses.add(responses.POST, urljoin(settings.API_URL, 'reset_password'), status=204, content_type='application/json') password_change_url = '/change_password' form = ResetPasswordForm(password_change_url=password_change_url, request=None, data={'username': '******'}) self.assertTrue(form.is_valid()) self.assertEqual( json.loads(responses.calls[0].request.body.decode('utf-8')), { 'username': '******', 'create_password': { 'password_change_url': settings.SITE_URL + password_change_url, 'reset_code_param': RESET_CODE_PARAM } })
def site_url(path): return urljoin(settings.SITE_URL, path)
def api_url(path): return urljoin(settings.API_URL, path)
def govuk_url(path): return urljoin(settings.GOVUK_PAY_URL, path)