Exemple #1
0
    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 test_cannot_update_disbursement_for_different_prison(self):
        user = self.prison_clerks[0]

        disbursement = Disbursement.objects.create(
            amount=1000,
            prisoner_number='A1234BC',
            prison=Prison.objects.get(pk='INP'),
            method=DISBURSEMENT_METHOD.BANK_TRANSFER,
            recipient_first_name='Sam',
            recipient_last_name='Hall'
        )

        with silence_logger('django.request'):
            response = self.client.patch(
                reverse('disbursement-detail', args=[disbursement.pk]),
                data={'amount': 2000}, format='json',
                HTTP_AUTHORIZATION=self.get_http_authorization_for_user(user)
            )

        self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)

        updated = Disbursement.objects.get(pk=disbursement.pk)
        self.assertEqual(updated.amount, 1000)

        self.assertEqual(Log.objects.all().count(), 0)
Exemple #3
0
    def test_nomis_response_with_unexpected_account_values(self, mocked_nomis):
        mocked_nomis.get_account_balances.return_value = {'cash': 1000, 'spends': 550, 'savings': None}

        with silence_logger():
            response = self.make_api_call(self.prisoner_location_public, self.send_money_user)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertIn(b'malformed', response.content)
Exemple #4
0
    def test_nomis_error_propagates(self, mocked_nomis):
        mocked_nomis.get_account_balances.side_effect = requests.HTTPError('403 Client Error: FORBIDDEN')

        with silence_logger():
            response = self.make_api_call(self.prisoner_location_public, self.send_money_user)
        self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
        self.assertIn(b'Cannot lookup NOMIS balances', response.content)
Exemple #5
0
    def test_location_file_upload(self, mock_api_client):
        self.login()
        self.setup_mock_get_authenticated_api_session(mock_api_client)

        file_data, expected_data = generate_testable_location_data()
        expected_calls = [expected_data]

        with responses.RequestsMock() as rsps, silence_logger(
                level=logging.WARNING):
            mock_prison_response(rsps)
            rsps.add(rsps.POST,
                     api_url('/prisoner_locations/actions/delete_inactive/'))
            rsps.add(rsps.POST, api_url('/prisoner_locations/'))
            rsps.add(rsps.POST,
                     api_url('/prisoner_locations/actions/delete_old/'))
            response = self.client.post(
                reverse('location_file_upload'),
                {'location_file': get_csv_data_as_file(file_data)})

            for call in rsps.calls:
                if call.request.url == api_url('/prisoner_locations/'):
                    self.assertEqual(json.loads(call.request.body.decode()),
                                     expected_calls.pop())

        if expected_calls:
            self.fail('Not all location data was uploaded')

        self.assertRedirects(response, reverse('location_file_upload'))
Exemple #6
0
    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
            )
Exemple #7
0
    def test_confirm_disbursement_resets_on_failure(self):
        self.login(credentials={
            'username': '******',
            'password': '******'
        })

        disbursement = SAMPLE_DISBURSEMENTS[4]
        self.pending_detail(disbursement=disbursement)
        responses.add(responses.POST,
                      api_url('/disbursements/actions/preconfirm/'),
                      status=200)
        responses.add(
            responses.POST,
            nomis_url(
                '/prison/{nomis_id}/offenders/{prisoner_number}/transactions/'.
                format(nomis_id=disbursement['prison'],
                       prisoner_number=disbursement['prisoner_number'])),
            status=500)
        responses.add(responses.POST,
                      api_url('/disbursements/actions/reset/'),
                      status=200)

        with silence_logger():
            response = self.client.post(self.url(disbursement['id']),
                                        data={'confirmation': 'yes'},
                                        follow=True)
        self.assertOnPage(response, 'disbursements:pending_detail')
        self.assertContains(response,
                            'Payment not confirmed due to technical error')
Exemple #8
0
    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_doesnt_retry_more_than_once_after_401_response(self):
        """
        Test that if a request returns 401, the logic invalidates the cached token
        and retries again to make sure it wasn't because of the cached token
        but it doesn't invalidate the token again if the subsequent call is still in error.
        """
        django_cache.cache.set(
            nomis.Connector.TOKEN_CACHE_KEY,
            'invalid-token',
        )

        path = '/some/path'
        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.GET,
                build_prison_api_v1_url(path),
                status=401,
            )
            self._mock_successful_auth_request(rsps, token='my-token')
            rsps.add(
                responses.GET,
                build_prison_api_v1_url(path),
                status=401,
            )

            with silence_logger('mtp'):
                with self.assertRaises(HTTPError):
                    nomis.connector.get(path, retries=0)
            self.assertEqual(len(rsps.calls), 3)

        self.assertEqual(
            django_cache.cache.get(nomis.Connector.TOKEN_CACHE_KEY),
            'my-token',
        )
Exemple #10
0
    def _generate_test_disbursements_file(self, receipt_date=None):
        if receipt_date is None:
            receipt_date = date(2016, 9, 13)

        test_private_estate_batches = get_private_estate_batches()
        test_disbursements = get_test_disbursements(20)

        mock_list_prisons()
        mock_bank_holidays()
        responses.add(responses.POST,
                      api_url('/transactions/reconcile/'),
                      status=200)
        responses.add(responses.GET,
                      api_url('/private-estate-batches/'),
                      json=test_private_estate_batches)
        responses.add(responses.GET,
                      api_url('/disbursements/'),
                      json=test_disbursements,
                      status=200)
        responses.add(responses.POST,
                      api_url('/disbursements/actions/send/'),
                      status=200)

        with silence_logger(name='mtp', level=logging.WARNING):
            exceldata = disbursements.generate_disbursements_journal(
                self.get_api_session(), receipt_date)

        return exceldata, test_private_estate_batches, test_disbursements
    def test_retries_after_401_response(self):
        """
        Test that if a request returns 401, the logic invalidates the cached token
        and retries again to make sure it wasn't because of the cached token.
        This happens even when the caller passes in retries == 0.
        """
        django_cache.cache.set(
            nomis.Connector.TOKEN_CACHE_KEY,
            'invalid-token',
        )

        path = '/some/path'
        with responses.RequestsMock() as rsps:
            rsps.add(
                responses.GET,
                build_prison_api_v1_url(path),
                status=401,
            )
            self._mock_successful_auth_request(rsps, token='my-token')
            rsps.add(
                responses.GET,
                build_prison_api_v1_url(path),
                json={},
                status=200,
            )

            with silence_logger('mtp'):
                nomis.connector.get(path, retries=0)

        self.assertEqual(
            django_cache.cache.get(nomis.Connector.TOKEN_CACHE_KEY),
            'my-token',
        )
 def test_missing_csrf_cookie(self):
     with silence_logger('django.request', level=logging.ERROR):
         response = self.client.post(self.login_url, data={
             'username': '******',
             'password': '******',
         })
     self.assertInvalidCsrfResponse(response)
 def test_invalid_csrf_token(self):
     self.client.get(self.login_url)
     with silence_logger('django.request', level=logging.ERROR):
         response = self.client.post(self.login_url, data={
             'username': '******',
             'password': '******',
             'csrfmiddlewaretoken': 'invalid',
         })
     self.assertInvalidCsrfResponse(response)
Exemple #14
0
    def test_invalid_date_params(self):
        with responses.RequestsMock(), silence_logger(name='django.request'):
            response = self.client.get(
                reverse_lazy('performance_data_csv') + '?from=invalid')
            self.assertEqual(response.status_code, HTTPStatus.BAD_REQUEST)
            self.assertIn(
                'Date "invalid" could not be parsed - use YYYY-MM-DD format',
                response.json()['errors'])
            self.assertEqual(0, get_max_age(response))

        with responses.RequestsMock(), silence_logger(name='django.request'):
            response = self.client.get(
                reverse_lazy('performance_data_csv') +
                '?from=2021-01-01&to=invalid')
            self.assertEqual(response.status_code, HTTPStatus.BAD_REQUEST)
            self.assertIn(
                'Date "invalid" could not be parsed - use YYYY-MM-DD format',
                response.json()['errors'])
            self.assertEqual(0, get_max_age(response))
Exemple #15
0
 def test_editing_self_hides_roles_and_admin_status(self):
     self.mocked_login(username='******')
     with responses.RequestsMock() as rsps:
         self._init_existing_user(rsps, username='******')
         with silence_logger('mtp', level=logging.WARNING):
             response = self.client.get(reverse('edit-user', kwargs={'username': '******'}))
     self.assertNotContains(response, 'Digital cashbook', msg_prefix=response.content.decode(response.charset))
     content = response.content.decode(response.charset)
     self.assertNotIn('id_user_admin', content)
     self.assertNotIn('id_role', content)
    def test_no_transactions_raises_error(self, mock_api_client):
        conn = mock_api_client.get_connection()
        conn.prisons.get.return_value = TEST_PRISONS_RESPONSE
        conn.credits.get.return_value = NO_TRANSACTIONS
        conn.transactions.get.return_value = NO_TRANSACTIONS

        with self.assertRaises(EmptyFileError), mock.patch('bank_admin.utils.requests') as mock_requests, \
                silence_logger(name='mtp', level=logging.WARNING):
            mock_requests.get().status_code = 200
            mock_requests.get().json.return_value = TEST_HOLIDAYS
            _, exceldata = adi.generate_adi_journal(self.get_request(), date(2016, 9, 13))
Exemple #17
0
    def test_no_transactions_raises_error(self):
        mock_list_prisons()
        mock_bank_holidays()
        responses.add(responses.GET,
                      api_url('/disbursements/'),
                      json=NO_TRANSACTIONS)

        with self.assertRaises(EmptyFileError), silence_logger(
                name='mtp', level=logging.WARNING):
            disbursements.generate_disbursements_journal(
                self.get_api_session(), date(2016, 9, 13))
Exemple #18
0
 def test_form_lists_roles(self, mocked_template):
     self.mocked_login()
     with responses.RequestsMock() as rsps:
         mocked_template.return_value = '{{ form }}'
         self.mock_roles_list(rsps)
         with silence_logger('mtp', level=logging.WARNING):
             response = self.client.get(reverse('new-user'))
     self.assertContains(response, 'prison-clerk')
     self.assertSequenceEqual(
         response.context['form']['role'].field.choices,
         [('prison-clerk', 'Digital cashbook')]
     )
Exemple #19
0
    def test_api_response_error(self):
        with responses.RequestsMock() as rsps, silence_logger():
            rsps.add(
                rsps.GET,
                f'{settings.API_URL}/requests/?username=my-username&role__name=security',
                status=500,
            )
            response = self.client.post(
                reverse('sign-up'),
                data=self.account_request_valid_payload,
            )

        self.assertContains(response, 'This service is currently unavailable')
Exemple #20
0
 def test_command_deleted_when_flag_set(self):
     command = ScheduledCommand(
         name='load_test_data',
         arg_string='--number-of-prisoners 60 --number-of-transactions 70',
         cron_entry='* * * * *',
         next_execution=timezone.now(),
         delete_after_next=True
     )
     command.save()
     run_commands = run_scheduled_commands.Command()
     with captured_stdout(), silence_logger():
         run_commands.handle()
     self.assertEqual(ScheduledCommand.objects.all().count(), 0)
    def test_new_user(self, mock_api_client):
        new_user_data = {
            "username": "******",
            "first_name": "new",
            "last_name": "user",
            "email": "*****@*****.**",
            "user_admin": False,
        }
        self.mocked_login()
        with silence_logger("mtp", level=logging.WARNING):
            self.client.post(reverse("new-user"), data=new_user_data)

        mock_api_client.get_connection().users().post.assert_called_with(new_user_data)
Exemple #22
0
 def test_handles_invalid_strings(self):
     """
     Test that if the values are invalid, they are not converted.
     """
     objs = [{
         'started_at': '2019-13-01',
         'received_at': 'invalid',
     }]
     with silence_logger():
         converted_objects = convert_date_fields(objs)
     self.assertEqual(converted_objects[0], {
         'started_at': '2019-13-01',
         'received_at': 'invalid',
     })
Exemple #23
0
    def _generate_test_adi_journal(
        self,
        receipt_date=None,
        user=None,
        credits=20,
        refundable_transactions=5,
        rejected_transactions=2,
    ):
        if receipt_date is None:
            receipt_date = date(2016, 9, 13)
        start_date = quote_plus(str(set_worldpay_cutoff(receipt_date)))
        end_date = quote_plus(
            str(set_worldpay_cutoff(receipt_date + timedelta(days=1))))

        credits = get_test_credits(credits)
        refundable_transactions = get_test_transactions(
            PaymentType.refund, refundable_transactions)
        rejected_transactions = get_test_transactions(PaymentType.reject,
                                                      rejected_transactions)

        responses.add(responses.POST,
                      api_url('/transactions/reconcile/'),
                      status=200)
        mock_list_prisons()
        responses.add(responses.GET, api_url('/credits/'), json=credits)
        responses.add(responses.GET,
                      api_url('/transactions/?offset=0&limit=500'
                              '&received_at__lt={end_date}'
                              '&received_at__gte={start_date}'
                              '&status=refundable'.format(
                                  start_date=start_date, end_date=end_date)),
                      json=refundable_transactions,
                      match_querystring=True)
        responses.add(responses.GET,
                      api_url('/transactions/?offset=0&limit=500'
                              '&received_at__lt={end_date}'
                              '&received_at__gte={start_date}'
                              '&status=unidentified'.format(
                                  start_date=start_date, end_date=end_date)),
                      json=rejected_transactions,
                      match_querystring=True)
        mock_bank_holidays()

        with silence_logger(name='mtp', level=logging.WARNING):
            exceldata = adi.generate_adi_journal(self.get_api_session(),
                                                 receipt_date,
                                                 user=user)

        return exceldata, (credits, refundable_transactions,
                           rejected_transactions)
    def _patch_refunded_with_invalid_status(self, valid_data_list, status):
        url = self._get_url()
        user = self._get_authorised_user()

        invalid_transactions = Transaction.objects.filter(
            Transaction.STATUS_LOOKUP[status])
        invalid_data_list = (
            [{'id': t.id, 'refunded': True} for t in invalid_transactions]
        )

        with silence_logger():
            return self.client.patch(
                url, data=valid_data_list + invalid_data_list, format='json',
                HTTP_AUTHORIZATION=self.get_http_authorization_for_user(user)
            )
    def test_edit_user(self, mock_view_api_client, mock_form_api_client):
        self._init_existing_user(mock_view_api_client, mock_form_api_client)

        updated_user_data = {
            "first_name": "dave",
            "last_name": "smith",
            "email": "*****@*****.**",
            "user_admin": True,
        }
        self.mocked_login()
        with silence_logger("mtp", level=logging.WARNING):
            self.client.post(reverse("edit-user", args={"username": "******"}), data=updated_user_data)

        conn = mock_form_api_client.get_connection()
        conn.users().patch.assert_called_with(updated_user_data)
    def test_create_disbursement_service_unavailable(self):
        self.login()
        self.choose_sending_method(method=SENDING_METHOD.BANK_TRANSFER)
        self.enter_prisoner_details()
        self.enter_amount()
        self.enter_recipient_details()
        self.enter_recipient_postcode()
        self.enter_recipient_address()
        self.enter_recipient_bank_account()
        self.enter_remittance_description(remittance='no')
        with silence_logger():
            response = self.client.post(reverse('disbursements:created'), follow=True)

        self.assertOnPage(response, 'disbursements:handover')
        self.assertContains(response, HandoverView.error_messages['connection'])
    def test_turning_off_csrf_failure_override(self, mocked_csrf_failure):
        from mtp_common.auth.csrf import default_csrf_behaviour
        from mtp_common.auth.views import login

        default_csrf_behaviour(login)
        mocked_csrf_failure.return_value = HttpResponseForbidden(b'Django CSRF response')
        with silence_logger('django.request', level=logging.ERROR):
            response = self.client.post(self.login_url, data={
                'username': '******',
                'password': '******',
            })
        self.assertTrue(mocked_csrf_failure.called)
        self.assertEqual(response.status_code, 403)
        self.assertEqual(response.content, b'Django CSRF response')
        login.no_moj_csrf = False
Exemple #28
0
 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_location_file_upload(self, mock_api_client):
        self.login()

        conn = mock_api_client.get_authenticated_connection().prisoner_locations
        conn.post.return_value = 200

        file_data, expected_data = generate_testable_location_data()

        with silence_logger(name='mtp', level=logging.WARNING):
            response = self.client.post(
                reverse('location_file_upload'),
                {'location_file': get_csv_data_as_file(file_data)}
            )

        conn.post.assert_called_with(expected_data)
        self.assertRedirects(response, reverse('location_file_upload'))
 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 _patch_refunded_with_invalid_status(self, valid_data_list, status):
        url = self._get_url()
        user = self._get_authorised_user()

        invalid_transactions = Transaction.objects.filter(
            Transaction.STATUS_LOOKUP[status])
        invalid_data_list = ([{
            'id': t.id,
            'refunded': True
        } for t in invalid_transactions])

        with silence_logger():
            return self.client.patch(
                url,
                data=valid_data_list + invalid_data_list,
                format='json',
                HTTP_AUTHORIZATION=self.get_http_authorization_for_user(user))
 def test_locale_switches_based_on_browser_language(self):
     languages = (
         ('*', 'en-gb'),
         ('en', 'en-gb'),
         ('en-gb', 'en-gb'),
         ('en-GB, en, *', 'en-gb'),
         ('cy', 'cy'),
         ('cy, en-GB, en, *', 'cy'),
         ('en, cy, *', 'en-gb'),
         ('es', 'en-gb'),
     )
     with silence_logger(name='django.request', level=logging.ERROR):
         for accept_language, expected_slug in languages:
             response = self.client.get('/', HTTP_ACCEPT_LANGUAGE=accept_language)
             self.assertRedirects(response, '/%s/' % expected_slug, fetch_redirect_response=False)
             response = self.client.get('/login/', HTTP_ACCEPT_LANGUAGE=accept_language)
             self.assertRedirects(response, '/%s/login/' % expected_slug, fetch_redirect_response=True)
Exemple #33
0
    def test_create_disbursement_service_unavailable(self):
        self.login()
        self.choose_sending_method(method=SENDING_METHOD.BANK_TRANSFER)
        self.enter_prisoner_details()
        self.enter_amount()
        self.enter_recipient_details()
        self.enter_recipient_postcode()
        self.enter_recipient_address()
        self.enter_recipient_bank_account()
        self.enter_remittance_description(remittance='no')
        with silence_logger():
            response = self.client.post(reverse('disbursements:created'),
                                        follow=True)

        self.assertOnPage(response, 'disbursements:handover')
        self.assertContains(response,
                            HandoverView.error_messages['connection'])
 def test_locale_switches_based_on_browser_language(self):
     languages = (
         ('*', 'en-gb'),
         ('en', 'en-gb'),
         ('en-gb', 'en-gb'),
         ('en-GB, en, *', 'en-gb'),
         ('cy', 'cy'),
         ('cy, en-GB, en, *', 'cy'),
         ('en, cy, *', 'en-gb'),
         ('es', 'en-gb'),
     )
     with silence_logger(name='django.request', level=logging.ERROR):
         for accept_language, expected_slug in languages:
             response = self.client.get('/', HTTP_ACCEPT_LANGUAGE=accept_language)
             self.assertRedirects(response, '/%s/' % expected_slug, fetch_redirect_response=False)
             response = self.client.get('/login/', HTTP_ACCEPT_LANGUAGE=accept_language)
             self.assertRedirects(response, '/%s/login/' % expected_slug, fetch_redirect_response=True)
Exemple #35
0
    def test_dont_send_email(self, mock_send_email):
        """
        Test that the method only sends any email if the govuk payment status is 'capturable'
        and the MTP payment didn't have the email field set
        """
        client = PaymentClient()

        payment = {
            'uuid': 'some-id',
        }

        statuses = [
            status for status in GovUkPaymentStatus
            if status != GovUkPaymentStatus.capturable
        ]

        with responses.RequestsMock() as rsps, silence_logger():
            mock_auth(rsps)

            # API call related to updating the email address on the payment record
            rsps.add(
                rsps.PATCH,
                api_url(f'/payments/{payment["uuid"]}/'),
                json={
                    'email': '*****@*****.**',
                },
                status=200,
            )

            for status in statuses:
                govuk_payment = {
                    'payment_id': 'payment-id',
                    'state': {
                        'status': status.name,

                        # for status == 'errors'
                        'code': 'code',
                        'message': 'message',
                    },
                    'email': '*****@*****.**',
                }
                actual_status = client.complete_payment_if_necessary(
                    payment, govuk_payment)

                self.assertEqual(actual_status, status)
                mock_send_email.assert_not_called()
Exemple #36
0
 def test_form_invalid_response(self):
     """
     Test that errors are rendered when mandatory field is missing (email)
     """
     with responses.RequestsMock() as rsps, silence_logger():
         self.mock_prison_list(rsps)
         response = self.client.post(reverse('sign-up'),
                                     data={
                                         'first_name': 'My First Name',
                                         'last_name': 'My Last Name',
                                         'username': '******',
                                         'role': 'prison-clerk',
                                         'prison': 'INP',
                                         'reason': 'because'
                                     },
                                     follow=True)
     self.assertContains(response, 'Email')
     self.assertContains(response, 'This field is required')
Exemple #37
0
    def test_no_transactions_raises_error(self):
        responses.add(responses.POST,
                      api_url('/transactions/reconcile/'),
                      status=200)
        mock_list_prisons()
        responses.add(responses.GET,
                      api_url('/credits/'),
                      json=NO_TRANSACTIONS)
        responses.add(responses.GET,
                      api_url('/transactions/'),
                      json=NO_TRANSACTIONS)
        responses.add(responses.GET,
                      api_url('/transactions/'),
                      json=NO_TRANSACTIONS)
        mock_bank_holidays()

        with self.assertRaises(EmptyFileError), silence_logger(
                name='mtp', level=logging.WARNING):
            adi.generate_adi_journal(self.get_api_session(), date(2016, 9, 13))
Exemple #38
0
    def test_location_file_batch_upload(self, mock_api_client):
        self.setup_mock_get_authenticated_api_session(mock_api_client)

        file_data, expected_data = generate_testable_location_data(length=50)
        expected_calls = [
            expected_data[40:50],
            expected_data[30:40],
            expected_data[20:30],
            expected_data[10:20],
            expected_data[0:10]
        ]

        request = self.make_request(get_csv_data_as_file(file_data))

        with responses.RequestsMock() as rsps, silence_logger(level=logging.WARNING):
            mock_prison_response(rsps)
            form = LocationFileUploadForm(request.POST, request.FILES, request=request)
            self.assertTrue(form.is_valid())

            rsps.add(
                rsps.POST,
                api_url('/prisoner_locations/actions/delete_inactive/')
            )
            rsps.add(
                rsps.POST,
                api_url('/prisoner_locations/')
            )
            rsps.add(
                rsps.POST,
                api_url('/prisoner_locations/actions/delete_old/')
            )
            form.update_locations()

            for call in rsps.calls:
                if call.request.url == api_url('/prisoner_locations/'):
                    self.assertEqual(
                        json.loads(call.request.body.decode()),
                        expected_calls.pop()
                    )

        if expected_calls:
            self.fail('Not all location data was uploaded')
Exemple #39
0
 def test_error_response(self):
     with responses.RequestsMock() as rsps, silence_logger():
         self.mock_prison_list(rsps)
         rsps.add(
             rsps.GET,
             api_url(
                 '/requests/?username=my-username&role__name=prison-clerk'),
             json={'count': 0},
             status=400)
         response = self.client.post(reverse('sign-up'),
                                     data={
                                         'first_name': 'My First Name',
                                         'last_name': 'My Last Name',
                                         'email': '*****@*****.**',
                                         'username': '******',
                                         'role': 'prison-clerk',
                                         'prison': 'INP',
                                         'reason': 'because'
                                     },
                                     follow=True)
     self.assertContains(response, 'This service is currently unavailable')
Exemple #40
0
    def test_command_running(self):
        command = ScheduledCommand(
            name='load_test_data',
            arg_string='--number-of-prisoners 60 --number-of-transactions 70',
            cron_entry='* * * * *',
            next_execution=timezone.now()
        )
        command.save()
        run_commands = run_scheduled_commands.Command()
        with captured_stdout() as stdout, silence_logger():
            run_commands.handle()

        stdout = stdout.getvalue()
        self.assertIn('Making test users', stdout)
        self.assertIn('random credits', stdout)

        from prison.models import PrisonerLocation
        self.assertEqual(PrisonerLocation.objects.count(), 60)

        from transaction.models import Transaction
        self.assertEqual(Transaction.objects.count(), 70)
    def _generate_test_adi_journal(self, mock_api_client, receipt_date=None):
        credits = get_test_credits(20)
        refundable_transactions = get_test_transactions(PaymentType.refund, 5)
        rejected_transactions = get_test_transactions(PaymentType.reject, 2)

        conn = mock_api_client.get_connection()
        conn.prisons.get.return_value = TEST_PRISONS_RESPONSE
        conn.credits.get.return_value = credits
        conn.transactions.get.side_effect = [
            refundable_transactions,
            rejected_transactions
        ]

        if receipt_date is None:
            receipt_date = date(2016, 9, 13)
        with mock.patch('bank_admin.utils.requests') as mock_requests, \
                silence_logger(name='mtp', level=logging.WARNING):
            mock_requests.get().status_code = 200
            mock_requests.get().json.return_value = TEST_HOLIDAYS
            filename, exceldata = adi.generate_adi_journal(self.get_request(),
                                                           receipt_date)

        return filename, exceldata, (credits, refundable_transactions, rejected_transactions)
    def assertAccessiblyOnlyBySuperuser(self, url, sentinel):  # noqa: N802
        response = self.client.get(url)
        self.assertNotContains(response, sentinel, status_code=http_status.HTTP_302_FOUND)

        user_details = dict(username='******', password='******')
        user = User.objects.create_user(**user_details)

        self.client.login(**user_details)
        response = self.client.get(url)
        self.assertNotContains(response, sentinel, status_code=http_status.HTTP_302_FOUND)

        user.is_staff = True
        user.save()
        self.client.login(**user_details)
        with silence_logger('django.request'):
            response = self.client.get(url)
        self.assertNotContains(response, sentinel, status_code=http_status.HTTP_403_FORBIDDEN)

        user.is_superuser = True
        user.save()
        self.client.login(**user_details)
        response = self.client.get(url)
        self.assertContains(response, sentinel)
    def test_data_management_command_runs(self):
        from core.management.commands.load_test_data import Command

        self.make_superuser(log_into_client=True)
        with mock.patch.object(Command, 'handle') as method:
            method.return_value = ''
            with silence_logger():
                response = self.client.post(self.url, data={
                    'scenario': 'random',
                    'number_of_transactions': '50',
                    'number_of_disbursements': '50',
                    'number_of_payments': '50',
                    'number_of_prisoners': '50',
                    'days_of_history': '7',
                })
            self.assertEqual(response.status_code, 200)
            self.assertEqual(method.call_count, 1)
            expected_options_subset = {
                'protect_superusers': True,
                'protect_usernames': ['transaction-uploader'],
                'protect_credits': False,
                'no_color': True,
                'credits': 'random',
                'prisons': ['sample'],
                'number_of_transactions': 50,
                'number_of_payments': 50,
                'number_of_prisoners': 50,
                'days_of_history': 7
            }
            options = method.call_args[1]
            options_subset = {
                k: v
                for k, v in options.items()
                if k in expected_options_subset.keys()
            }
            self.assertDictEqual(options_subset, expected_options_subset)
 def load_test_data(self):
     with silence_logger(name='mtp', level=logging.WARNING):
         super().load_test_data(command=b'load_nomis_test_data')
 def load_test_data(self):
     with silence_logger(name='mtp', level=logging.WARNING):
         super().load_test_data()
    def test_new_credits_submit_with_uncreditable(self):
        with responses.RequestsMock() as rsps:
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(CREDIT_1, CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # create batch
            rsps.add(
                rsps.POST,
                api_url('/credits/batches/'),
                status=201,
            )
            # credit credits to NOMIS and API
            rsps.add(
                rsps.POST,
                nomis_url('/prison/BXI/offenders/A1234BC/transactions/'),
                status=400,
            )
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/setmanual/'),
                status=204,
            )
            rsps.add(
                rsps.POST,
                nomis_url('/prison/BXI/offenders/A1234GG/transactions/'),
                json={'id': '6244780-1'},
                status=200,
            )
            rsps.add(
                rsps.POST,
                api_url('/credits/actions/credit/'),
                status=204,
            )
            # REDIRECT after success
            # get active batches
            rsps.add(
                rsps.GET,
                api_url('/credits/batches/'),
                json=wrap_response_data(PROCESSING_BATCH),
                status=200,
            )
            # get incomplete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=pending&pk=1&pk=2'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get complete credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=credited&pk=1&pk=2'),
                json=wrap_response_data(CREDIT_2),
                status=200,
                match_querystring=True,
            )
            # delete completed batch
            rsps.add(
                rsps.DELETE,
                api_url('/credits/batches/%s/' % PROCESSING_BATCH['id']),
                status=200,
            )
            # get new credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?ordering=-received_at&offset=0&limit=100&status=credit_pending&resolution=pending'),
                json=wrap_response_data(),
                status=200,
                match_querystring=True,
            )
            # get manual credits
            rsps.add(
                rsps.GET,
                api_url('/credits/?resolution=manual&status=credit_pending&offset=0&limit=100&ordering=-received_at'),
                json=wrap_response_data(CREDIT_1),
                status=200,
                match_querystring=True,
            )
            rsps.add(
                rsps.GET,
                nomis_url('/offenders/A1234BC/location/'),
                json={
                    'establishment': {
                        'code': 'LEI',
                        'desc': 'LEEDS (HMP)'
                    }
                },
                status=200,
            )

            self.login()
            with silence_logger(name='mtp', level=logging.CRITICAL):
                response = self.client.post(
                    self.url,
                    data={'credits': [1, 2], 'submit_new': None},
                    follow=True
                )
            self.assertEqual(response.status_code, 200)
            self.assertContains(response, '1 credit sent to NOMIS')
            self.assertContains(response, '1 credit needs your manual input in NOMIS')
            self.assertEqual(len(mail.outbox), 1)