Example #1
0
 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)
Example #2
0
    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)
Example #4
0
 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)
Example #7
0
    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)
Example #9
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
            )
Example #10
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
            )
Example #11
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
            )
Example #12
0
 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()
     )
Example #15
0
 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))
Example #17
0
    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)
Example #20
0
 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,
     )
Example #23
0
 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')
Example #25
0
    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'))
Example #26
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')
Example #27
0
    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'])
Example #28
0
 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'
     )
Example #29
0
 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, '')
Example #31
0
    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': '******'
            })
Example #32
0
    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'])
Example #33
0
 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')
Example #34
0
    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)