def test_author_list_equality_with_invalid_authentication(self) -> None: """ Similar to the previous test except the request sent to /api/authors/ is invalid with improper permissions - once with an Author with no permissions and once with no authentication headers at all. """ # Let's check for a request with no authorization response: Response = self.client.get(self.url) data = u.get_json(response) self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED) self.assertEqual( data, {'detail': 'Authentication credentials were not provided.'}) # Now lets check with an Author without permissions. # Select the underprivileged author randomly. author: Author = random.choice(self.authors) self.client.credentials( HTTP_AUTHORIZATION=u.auth_header(author.get_key())) response: Response = self.client.get(self.url) data: typing.Dict[typing.Any, typing.Any] = u.get_json(response) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertEqual( data, {'detail': 'You do not have permission to perform this action.'})
def test_valid_update_request(self): bio = fake.text(120) username = fake.user_name() first_name = fake.first_name() # Changes different fields in a loop. data: typing.Dict[str, str] = { 'bio': bio, 'username': username, 'first_name': first_name, } for field, value in data.items(): # Update the authorization header for every field because the # because with every update, a new authtoken is generated for # the user and the previous one is rendered invalid. The self. # author instance is refreshed from database at end of this loop # because then it's also updated and .save() has been called. self.client.credentials( HTTP_AUTHORIZATION=u.auth_header(self.author.get_key())) # Make actual response and get back JSON data. Hopefully, # no errors are raised since the AuthorUpdateAPIView doesn't # implement a lot of sanity checks or exception handling. response: Response = self.client.patch(BASE_URL + '/update/', data={field: value}) # Refresh author instance. self.author.refresh_from_db() self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(getattr(self.author, field), value)
def test_invalid_update_request_with_taken_username(self): """ Tests to update an Author instance with a username that has already been taken - in this case, the username of the second author constructed only for this test case inside of the setUpTestData because it will be deleted once the test case finishes running automatically by Django. This should raise a 409 error with same error message as AuthorCreateAPIView. tl;dr - this makes an authenticated request to update mentix02's Author instance but with a username that already belongs to another user (the cls.temporary_author) - that returns an error and this test cases verifies. """ self.client.credentials( HTTP_AUTHORIZATION=u.auth_header(self.author.get_key())) response: Response = self.client.patch( BASE_URL + '/update/', data={'username': self.temporary_author.username}) data = u.get_json(response) self.assertEqual(response.status_code, status.HTTP_409_CONFLICT, msg=data) self.assertEqual(data, { 'detail': f"User '{self.temporary_author.username}' already exists." })
def test_valid_permission_topic_deletion(self): """ Last test to run in this APITestCase - makes valid delete requests /api/topics/delete/<slug:slug>/ and compares status code and check for existence inside of database. """ for index, author in self.authors: self.client.credentials(HTTP_AUTHORIZATION=auth_header(author.get_key())) topics_by_author = getattr(self, f'author_{index}_topics') for topic in topics_by_author: topic_slug = topic.slug response: Response = self.client.delete(reverse('topic:delete', kwargs={ 'slug': topic_slug })) # No need to get data since a 204 response doesn't return anything. self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) # Now check for data. with self.assertRaises(ObjectDoesNotExist): Topic.objects.get(slug__iexact=topic_slug)
def test_authenticated_topic_creation_with_incomplete_data(self): """ Makes a properly authenticated request to /api/topics/create/ but with invalid (read: incomplete) data that should result in error. """ self.client.credentials(HTTP_AUTHORIZATION=auth_header(self.author.get_key())) for field in self.data.keys(): # Make a copy of the data so that # the original isn't changed because # every iteration will remove one # field - going through all. temp_data = self.data.copy() del temp_data[field] response: Response = self.client.post(reverse('topic:create'), data=temp_data) response_data = u.get_json(response) self.assertEqual(response.status_code, status.HTTP_422_UNPROCESSABLE_ENTITY) # Special case for thumbnail_url field since the # view (and Topic model) either expects a FILE # upload or an image url. For testing purposes, # we only work with placeholder image urls. if field == 'thumbnail_url': self.assertEqual(response_data, { 'detail': 'Either provide a url for a thumbnail or an image upload.' }) else: self.assertEqual(response_data, { 'detail': f"Field '{field}' not provided." })
def test_author_list_equality_with_valid_authentication(self) -> None: """ Makes a valid (authenticated) request to /api/authors/ to compare list results with AuthorListSerializer serialized queryset data. Should return with a status code 200. Request is authenticated with authtoken for the super_author account inside of the Header. """ # Set the Authorization header to the appropriate # format as the rest_framework expects using utils. self.client.credentials( HTTP_AUTHORIZATION=u.auth_header(self.super_author.get_key())) response = self.client.get(self.url) data = u.get_json(response) self.assertEqual(data, self.serialized_data, msg=data) self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_authenticated_topic_creation(self): """ Makes a valid request to /api/topics/create/ with proper auth creds and valid (read: complete) POST data. """ # Authenticate via header token self.client.credentials(HTTP_AUTHORIZATION=auth_header(self.author.get_key())) response: Response = self.client.post(reverse('topic:create'), data=self.data) data = u.get_json(response) self.assertEqual(response.status_code, status.HTTP_201_CREATED) # Assert response with serialized last entry in Topic table self.assertEqual(data, TopicDetailSerializer( Topic.objects.last() ).data)
def test_invalid_permission_topic_deletion(self): """ Make valid authorized delete requests to /api/topics/delete/<slug:slug>/ to raise a Forbidden error with apt response. """ for index, author in self.authors: # Authenticate delete request with current author self.client.credentials(HTTP_AUTHORIZATION=auth_header(author.get_key())) topics_not_by_author = self.topics.difference(getattr(self, f'author_{index}_topics')) for topic in topics_not_by_author: response: Response = self.client.delete(reverse('topic:delete', kwargs={ 'slug': topic.slug })) data = u.get_json(response) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) self.assertEqual(data, {'detail': 'Deletion is not authorized.'})