def test_api_partners_update_with_members_exists(self): self.assertFalse(Activity.objects.exists()) response = self.forced_auth_req( 'get', reverse('partners_api:partner-detail', args=[self.partner.pk]), user=self.unicef_staff, ) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(len(response.data["staff_members"]), 1) self.assertEqual(response.data["staff_members"][0]["first_name"], "Mace") staff_members = [{ "title": "Some title", "first_name": "John", "last_name": "Doe", "email": response.data["staff_members"][0]["email"], "active": True, }] data = { "name": self.partner.name + ' Updated', "partner_type": self.partner.partner_type, "vendor_number": self.partner.vendor_number, "staff_members": staff_members, } response = self.forced_auth_req( 'patch', reverse('partners_api:partner-detail', args=[self.partner.pk]), user=self.unicef_staff, data=data, ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual( response.data, { "staff_members": { "email": [ ErrorDetail(string="Email address in use already.", code="invalid") ] } }, )
def test_teacher(admin_client, admin_user): """Create Teacher.""" # Create without middle name should fail. response = admin_client.post( '/teacher/', { 'first_name': TEST_FIRST_NAME, 'last_name': TEST_LAST_NAME, }, ) assert response.status_code == status.HTTP_400_BAD_REQUEST assert response.data == { 'middle_name': [ErrorDetail(string='This field is required.', code='required')], 'status_code': 400, } # Create should be successful. response = admin_client.post( '/teacher/', { 'first_name': TEST_FIRST_NAME, 'last_name': TEST_LAST_NAME, 'middle_name': TEST_MIDDLE_NAME, }, ) assert response.status_code == status.HTTP_201_CREATED # Update should be successful. teacher = Teacher.objects.get(id=response.data['id']) response = admin_client.patch( f'/teacher/{teacher.pk}/', json.dumps({ 'middle_name': f'{TEST_FIRST_NAME}', }), content_type='application/json', ) assert response.status_code == status.HTTP_200_OK assert response.data['middle_name'] == f'{TEST_FIRST_NAME}' # Delete should be successful. response = admin_client.delete(f'/teacher/{teacher.pk}/', ) assert response.status_code == status.HTTP_204_NO_CONTENT
def test_end_date_analysis_greater_than_lead_published_on(self): """ Test for a lead published date after the analysis end_date """ user = self.create_user() project = self.create_project() project.add_member(user) now = timezone.now() lead = self.create_lead(project=project, published_on=now + relativedelta(days=6)) entry = self.create_entry(project=project, lead=lead) analysis = self.create(Analysis, project=project, title='Test Analysis', end_date=now + relativedelta(days=4)) url = f'/api/v1/projects/{project.id}/analysis/{analysis.id}/pillars/' data = { 'main_statement': 'Some main statement', 'information_gap': 'Some information gap', 'assignee': user.id, 'title': 'Some title', 'analytical_statements': [ { "statement": "coffee", "order": 1, "client_id": "1", "analytical_entries": [ { "order": 1, "client_id": "1", "entry": entry.id, }, ] } ] } self.authenticate(user) response = self.client.post(url, data) self.assert_400(response) self.assertEqual( response.data['errors']['analytical_statements'][0]['analytical_entries'][0]['entry'][0], ErrorDetail( string=( f'Entry {entry.id} lead published_on cannot be greater than analysis end_date {analysis.end_date.date()}' ), code='invalid', ), )
def challenge_valid(self, response: PasswordChallengeResponse) -> HttpResponse: """Authenticate against django's authentication backend""" if PLAN_CONTEXT_PENDING_USER not in self.executor.plan.context: return self.executor.stage_invalid() # Get the pending user's username, which is used as # an Identifier by most authentication backends pending_user: User = self.executor.plan.context[ PLAN_CONTEXT_PENDING_USER] auth_kwargs = { "password": response.validated_data.get("password", None), "username": pending_user.username, } try: user = authenticate(self.request, self.executor.current_stage.backends, **auth_kwargs) except PermissionDenied: del auth_kwargs["password"] # User was found, but permission was denied (i.e. user is not active) LOGGER.debug("Denied access", **auth_kwargs) return self.executor.stage_invalid() except ValidationError as exc: del auth_kwargs["password"] # User was found, authentication succeeded, but another signal raised an error # (most likely LDAP) LOGGER.debug("Validation error from signal", exc=exc, **auth_kwargs) return self.executor.stage_invalid() else: if not user: # No user was found -> invalid credentials LOGGER.debug("Invalid credentials") # Manually inject error into form response._errors.setdefault("password", []) response._errors["password"].append( ErrorDetail(_("Invalid password"), "invalid")) return self.challenge_invalid(response) # User instance returned from authenticate() has .backend property set self.executor.plan.context[PLAN_CONTEXT_PENDING_USER] = user self.executor.plan.context[ PLAN_CONTEXT_AUTHENTICATION_BACKEND] = user.backend return self.executor.stage_ok()
def test_incomplete_rain_date_time_error(self): """ Testing if a Rain is not created whit incomplete date_time in request.data . """ date_time = random_datetime_10_days_left_and_now() self.request_data.update({"date_time": date_time.strftime("%Y-%m-%d")}) assert Field.objects.count() == 1 assert Rain.objects.count() == 0 response = self._post_data(data=self.request_data) assert Rain.objects.count() == 0 data = response.data assert data.get("date_time")[0] == ErrorDetail( string= "Datetime has wrong format. Use one of these formats instead: " "YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].", code="invalid", ) assert response.status_code == status.HTTP_400_BAD_REQUEST
def test_user_not_found(self): """ Ensure that if a valid token is generated, but the user gets destroyed in the process, the appropriate error message is displayed. """ body = { 'username': '******', 'password': '******', } response = self.client.post(self.url_path, body, format='json') self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) values = { NON_FIELD_ERRORS_KEY: [ ErrorDetail( 'The credentials used to login were invalid.', 'invalid') ] } self.assertDictValues(response.data, values)
def test_allow_empty_false(self, partial): """ If allow_empty is False, empty lists should fail validation regardless of the value of partial on the parent serializer. """ class ChildSerializer(serializers.Serializer): id = serializers.IntegerField() class ParentSerializer(serializers.Serializer): ids = ChildSerializer(many=True, allow_empty=False) serializer = ParentSerializer(data={'ids': []}, partial=partial) assert not serializer.is_valid() assert serializer.errors == { 'ids': { 'non_field_errors': [ ErrorDetail(string='This list may not be empty.', code='empty')], } }
def test_search_with_frm__invalid_exceed_max_number(self, mock_essearch): url = reverse("complaint_search:search") params = {"frm": 10000001} mock_essearch.return_value = "OK" response = self.client.get(url, params) self.assertEqual(status.HTTP_400_BAD_REQUEST, response.status_code) mock_essearch.assert_not_called() self.assertDictEqual( { "frm": [ ErrorDetail( string= "Ensure this value is less than or equal to 10000.", code="max_value", ) ] }, response.data, )
def test_password_blank(self): initial_user_count = User.objects.count() initial_team_count = Team.objects.count() request_data = { 'username': '******', 'password': '', 'password_confirmation': 'barbarbar' } response = self.client.post(self.endpoint, request_data) self.assertEqual(response.status_code, 400) self.assertEqual( response.data, { 'password': [ ErrorDetail(string='Password cannot be empty.', code='blank') ] }) self.assertEqual(User.objects.count(), initial_user_count) self.assertEqual(Team.objects.count(), initial_team_count)
def test_deserialize_invalid_sub_missing_required_field_in_related_model(self): """Job done with a custom validate() method in the Subscriber serializer""" sub = { "address_number_and_street": "1, rue de la Paix", "address_zipcode": "75001", "iban": "FR7630056009271234567890182", "user": { "email": "*****@*****.**", "last_name": "Doe", "password": "******" } } serializer = erp_serializers.SubscriberSerializer(data=sub) with self.assertRaises(ValidationError) as e: serializer.is_valid(raise_exception=True) self.assertEqual( serializer.errors['non_field_errors'], [ErrorDetail(string='The user first_name is missing', code='invalid')] )
def test_owner_must_have_org_access(self): serializer = ReleaseWithVersionSerializer( data={ "version": self.version, "owner": self.create_user().username, "ref": self.ref, "url": self.url, "dateReleased": self.dateReleased, "commits": self.commits, }, context={"organization": self.organization}, ) assert not serializer.is_valid() assert serializer.errors == { "owner": [ ErrorDetail("User does not have access to this organization", "invalid") ] }
def test_api_partners_update_invalid_basis_for_type_of_assessment(self): data = { "type_of_assessment": PartnerOrganization.HIGH_RISK_ASSUMED, "basis_for_risk_rating": "NOT NULL VALUE", } response = self.forced_auth_req('patch', reverse('partners_api:partner-detail', args=[self.partner.pk]), user=self.unicef_staff, data=data) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) error = [ ErrorDetail( string= 'The basis for risk rating has to be blank if Type is Low or High', code='invalid') ] self.assertEqual(response.data, {"basis_for_risk_rating": error})
def test_validation_fail_non_government(self): """Ensure update happens if no id value provided""" current_year = datetime.date.today().year cso_partner = PartnerFactory( partner_type=PartnerType.CIVIL_SOCIETY_ORGANIZATION, cso_type="International", hidden=False, vendor_number="XYZ", short_name="City Hunter", ) PartnerPlannedVisitsFactory( partner=cso_partner, year=current_year, programmatic_q1=1, programmatic_q2=2, programmatic_q3=3, programmatic_q4=4, ) planned_visits = [{ "programmatic_q1": 4, "programmatic_q2": 3, "programmatic_q3": 2, "programmatic_q4": 1, }] data = { "name": cso_partner.name + ' Updated', "partner_type": cso_partner.partner_type, "vendor_number": cso_partner.vendor_number, "planned_visits": planned_visits, } response = self.forced_auth_req( 'patch', reverse('partners_api:partner-detail', args=[cso_partner.pk]), user=self.unicef_staff, data=data, ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual( response.data["planned_visits"]["partner"], ErrorDetail( string='Planned Visit can be set only for Government partners', code='invalid'))
def test_get_order_by_order_id(self): """ Test that GET orders/<int:pk>/ returns a single order of given id """ # hit the API endpoint response = self.client.get( reverse("orders-single", kwargs={"pk": self.valid_id})) # fetch the data from db expected = Orders.objects.get(pk=self.valid_id) serialized = OrderSerializer(expected) self.assertEqual(response.data, serialized.data) self.assertEqual(response.status_code, status.HTTP_200_OK) # test with an order that does not exist response = self.client.get( reverse("orders-single", kwargs={"pk": self.invalid_id})) self.assertEqual( response.data, {"detail": ErrorDetail(string='Not found.', code='not_found')}) self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
def test_blacklisted_token(self): """ Ensure that we get an unsuccessful response from a request containing a blacklisted token. """ body = { 'username': '******', 'password': '******', 'refresh': self.user.refresh } self.client.post(self.url_path, body, format='json') response = self.client.post(self.url_path, body, format='json') self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) values = { NON_FIELD_ERRORS_KEY: [ErrorDetail('Token is blacklisted.', 'invalid')] } self.assertDictValues(response.data, values)
def test_deserialize_invalid_librarian_missing_required_field_in_related_model(self): librarian = { "is_manager": False, "user": { "email": "*****@*****.**", "first_name": "Lin", "password": "******", } } serializer = erp_serializers.LibrarianSerializer(data=librarian) with self.assertRaises(ValidationError): serializer.is_valid(raise_exception=True) self.assertEqual( serializer.errors, # DRF gives the name of the field concerned by the error, # only when the field is part of the Model and is auto-detected by DRF {'non_field_errors': [ErrorDetail(string='The user last_name is missing', code='invalid')]} )
def test_board_name_empty(self): initial_boards_count = Board.objects.count() initial_columns_count = Column.objects.count() response = self.client.post(self.endpoint, { 'team_id': self.team.id, 'name': '' }, HTTP_AUTH_USER=self.admin['username'], HTTP_AUTH_TOKEN=self.admin['token']) self.assertEqual(response.status_code, 400) self.assertEqual( response.data, { 'name': [ ErrorDetail(string='Board name cannot be blank.', code='blank') ] }) self.assertEqual(Board.objects.count(), initial_boards_count) self.assertEqual(Column.objects.count(), initial_columns_count)
def test_all_invalid_date(self): data = { "interviewers": [7, 6], "candidate": 1, "name": "Interview with Emmanuel", "start_time": "2019-08-08B08:00:00", } available_slots_serializer = InterviewScheduleSerializer(data=data) self.assertFalse(available_slots_serializer.is_valid()) self.assertDictEqual( available_slots_serializer.errors, { 'start_time': [ ErrorDetail( string='Datetime has wrong format. ' 'Use one of these formats instead: ' 'YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].', code='invalid') ] })
def test_post_user_exists_fail(self): success_fail = 'fail' data_post = self.registered_user.copy() data_post['password'] = data_post['password'] + '_another' action = self.base_action_test_case(data_post) client, response = action.post(client=None) # action.data_expected['post'][success_fail] = { # 'username': ['A user with that username already exists.'] # } action.data_expected['post'][success_fail] = { 'username': [ErrorDetail(string='A user with that username already exists.', code='unique')] } action.base_test_post(response=response, success_fail=success_fail, assert_message='views') count_users_expected = 1 count_users = User.objects.count() self.assertEquals(count_users, count_users_expected)
def test_task_id_empty(self): request_data = list(map( lambda t: {'title': t['title'], 'order': t['order']}, self.task_data )) response = self.client.patch(f'{self.endpoint}{self.column.id}', request_data, format='json', HTTP_AUTH_USER=self.admin['username'], HTTP_AUTH_TOKEN=self.admin['token']) self.assertEqual(response.status_code, 400) self.assertEqual(response.data, { 'task.id': ErrorDetail(string='Task ID cannot be empty.', code='blank') }) new_tasks = Task.objects.filter(column_id=self.column.id) for i in range(0, 5): task = new_tasks.get(title=str(i)) self.assertEqual(task.order, int(task.title))
def test_invalid_password(self): """ Ensure that we are denied access with an invalid password. """ body = { 'username': '******', 'password': '******', } response = self.client.post(self.url_path, body, format='json') self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) values = { NON_FIELD_ERRORS_KEY: [ ErrorDetail( 'The credentials used to login were invalid.', 'invalid') ] } self.assertDictValues(response.data, values)
def get_error_details(data, default_code=None): if isinstance(data, list): ret = [get_error_details(item, default_code) for item in data] if isinstance(data, ReturnList): return ReturnList(ret, serializer=data.serializer) return ret elif isinstance(data, dict): ret = { key: get_error_details(value, default_code) for key, value in data.items() } if isinstance(data, ReturnDict): return ReturnDict(ret, serializer=data.serializer) return ret text = force_str(data) code = getattr(data, 'code', default_code) return ErrorDetail(text, code)
def test_put_400(self): coll = OrganizationCollectionFactory(mnemonic='coll1', name='Collection') user = UserProfileFactory(organizations=[coll.organization]) self.assertEqual(coll.versions.count(), 1) response = self.client.put(coll.uri, dict(name=''), HTTP_AUTHORIZATION='Token ' + user.get_token(), format='json') self.assertEqual(response.status_code, 400) self.assertEqual( response.data, dict(name=[ ErrorDetail(string='This field may not be blank.', code='blank') ]))
def test_validate_valid_checks_and_link(self): serializer = InvoiceRequiredChecksSerializer( data={ 'valid_checks': False, 'valid_checks_link': 'https://google.com' }) self.assertFalse(serializer.is_valid()) error_message = { 'valid_checks': [ErrorDetail(string='Checkbox is not checked', code='invalid')] } self.assertEqual(serializer.errors, error_message) serializer = InvoiceRequiredChecksSerializer( data={ 'valid_checks': True, 'valid_checks_link': 'https://google.com' }) self.assertTrue(serializer.is_valid())
def test_rate_with_too_small_rating_create(self): request = factory.post(self.url, { "car_id": self.car_id, "rating": 0 }, format="json") response = self.view(request) response.render() self.assertEqual( response.data, { "rating": [ ErrorDetail( string= "Ensure this value is greater than or equal to 1.", code="min_value") ] }) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
def test_blank_input(self): """ Ensure that the proper error messages are sent on blank input. """ body = { 'username': '', 'email': '', 'password': '', } response = self.client.post(self.url_path, body, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) values = {} for key in {'username', 'email', 'password'}: values = { **values, key: [ErrorDetail('This field may not be blank.', 'blank')] } self.assertDictValues(response.data, values)
def test_password_too_short(self): """ Ensure that a user cannot create an account if the supplied password is at least eight characters. """ body = { 'username': '******', 'email': '*****@*****.**', 'password': '******', } response = self.client.post(self.url_path, body, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) values = { 'password': [ ErrorDetail('Ensure this field has at least 8 characters.', 'min_length') ] } self.assertDictValues(response.data, values)
def test_password_too_common(self): """ Ensure that a user cannot create an account if the supplied password is too common. """ body = { 'username': '******', 'email': '*****@*****.**', 'password': '******', } response = self.client.post(self.url_path, body, format='json') self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) values = { NON_FIELD_ERRORS_KEY: [ ErrorDetail('This password is too common.', 'password_too_common') ] } self.assertDictValues(response.data, values)
def post(self, request, *args, **kwargs): self.request = request if request.user.is_anonymous: form_data = request.data.get('form_data', {}) self.serializer = self.get_serializer(data=form_data) if self.serializer.is_valid(): self.login() return self.get_response() exc = ValidationError({self.form_name: self.serializer.errors}) else: message = ErrorDetail("Please log out before signing in again.") exc = ValidationError({ self.form_name: { api_settings.NON_FIELD_ERRORS_KEY: [message] } }) response = self.handle_exception(exc) self.response = self.finalize_response(request, response, *args, **kwargs) return self.response
def test_method_title_405(self): """ Ensure non-GET returns 405 """ methods = [ (self.client.delete, 'DELETE'), (self.client.post, 'POST'), (self.client.put, 'PUT'), ] for method, methodStr in methods: response = method(self.api_title_url) self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED) self.assertEqual( response.data, { 'detail': ErrorDetail( string='Method \"' + methodStr + '\" not allowed.', code='method_not_allowed') })