Exemple #1
0
    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.'})
Exemple #2
0
    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."
        })
Exemple #3
0
    def test_author_registration_with_existing_username(self) -> None:
        """
        Makes a request to /api/authors/create/ to create a user but
        expects failure because we'll provide a username that already
        exists in the database by picking an Author randomly from db.
        """

        # Create a fake test Author
        author: Author = create_author()

        # Construct POST request with taken username
        response: Response = self.client.post(
            BASE_URL + '/create/', {
                'password': '******',
                'bio': fake.text(120),
                'email': fake.email(),
                'username': author.username,
                'first_name': fake.first_name(),
            })

        data: typing.Dict[typing.Any, typing.Any] = u.get_json(response)

        self.assertEqual(response.status_code, status.HTTP_409_CONFLICT)
        self.assertEqual(
            data, {'detail': f"User '{author.username}' already exists."})
Exemple #4
0
    def test_invalid_authentication(self):
        """
        Similar to test_valid_authenticate except this tests for invalid
        credentials and incomplete data. Easy.
        """

        # Test for incomplete data.
        for field in ('username', 'password'):
            response: Response = self.client.post(
                BASE_URL + '/authenticate/',
                data={
                    field: random.choice(self.authors).
                    username  # Random value because it doesn't really matter
                })
            data = u.get_json(response)

            self.assertEqual(response.status_code,
                             status.HTTP_422_UNPROCESSABLE_ENTITY)
            self.assertEqual(
                data, {
                    'detail':
                    f"Field '{'password' if field.startswith('u') else 'username'}' not provided."
                })

        # Test for invalid password
        for author in self.authors + [self.super_author]:
            response = self.client.post(
                BASE_URL + '/authenticate/',
                data={
                    'username': author.username,
                    'password': '******'  # invalid password
                })
            data = u.get_json(response)

            self.assertEqual(response.status_code,
                             status.HTTP_401_UNAUTHORIZED)
            self.assertEqual(data, {'detail': 'Invalid credentials.'})
Exemple #5
0
    def test_verification_with_invalid_token(self) -> None:
        """
        Makes a valid request to an invalid URL containing the secret_key that
        does not belong to any existing Author. This should result in nothing
        but an error response with status code 404.
        """

        uuids: typing.List[str] = []
        for i in range(2, 5):
            uuids.append(str(uuid.uuid5(uuid.uuid1(1), f'abcd123456{i}')))

        for temp_uuid in uuids:
            response: Response = self.client.get(
                f'/api/authors/verify/{temp_uuid}/')
            data = u.get_json(response)
            self.assertEqual(response.status_code, 404)
            self.assertEqual(data, {'detail': 'Not found.'})
Exemple #6
0
    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)
Exemple #7
0
    def test_valid_authentication(self):
        """
        Makes a valid POST request to /api/authors/authenticate/ by provided
        a valid username & password combo and compares authtoken provided to
        the one in the database.
        """

        for author in self.authors + [self.super_author]:
            response: Response = self.client.post(
                BASE_URL + '/authenticate/',
                data={
                    'username': author.username,
                    'password':
                    '******'  # Might be a better way to store random passwords.
                })
            data = u.get_json(response)

            self.assertEqual(response.status_code, status.HTTP_200_OK)
            self.assertEqual(data, {'token': author.get_key()})
Exemple #8
0
    def make_test(self, model_type: str, model_serializer, url_name: str):
        """
        A custom generic test maker to not duplicate the same code over
        and over - it takes a model_type that is a string of model types.
        It could be "articles" or "topics" so that a getattr call can
        get the data members from some string formatting as the variables
        are named following a certain syntax. Then it makes a GET request
        to the url_name that was provided with the apt parameters (in this
        case, the username). Then it's simply a matter of asserting cases.
        """

        for author_id in [1, 2]:
            username = getattr(self, f'author_{author_id}').username

            instances = getattr(self, f'{model_type}_by_author_{author_id}')
            instances_data = model_serializer(instances, many=True).data

            response = self.client.get(
                reverse(url_name, kwargs={'username': username}))
            data = u.get_json(response)

            self.assertEqual(response.status_code, status.HTTP_200_OK)
            self.assertEqual(data['count'], len(instances_data))
Exemple #9
0
    def test_author_registration_with_invalid_data(self) -> None:
        """
        Makes invalid requests to /api/authors/create/ by sending incomplete
        or poorly formatted data - such as having a space in a username or not
        including a required param in the POST body. Takes care of two error
        responses in one test case.
        """

        # First check without any parameters. It should return with an
        # error message for the username field since that's what the view
        # tried to check for first - before anything else.
        response: Response = self.client.post(BASE_URL + '/create/')
        data: typing.Dict[typing.Any, typing.Any] = u.get_json(response)

        self.assertEqual(response.status_code,
                         status.HTTP_422_UNPROCESSABLE_ENTITY)
        self.assertEqual(data, {'detail': "Field 'username' not provided."})

        # Now check with an invalid username - one having a space and a
        # dollar sign. We dont' even need to send any more data (other than email)
        # since the view immediately returns an invalid username (or email) error
        # if they (email and username) aren't valid.
        response = self.client.post(BASE_URL + '/create/', {
            'username': '******',
            'email': '*****@*****.**'
        })
        data = u.get_json(response)

        self.assertEqual(response.status_code,
                         status.HTTP_422_UNPROCESSABLE_ENTITY)
        self.assertEqual(
            data, {
                'detail':
                'Requires 150 characters or fewer. Letters, digits and @/./+/-/_ only.'
            })

        post_data = {
            'bio': fake.text(120),
            'email': fake.email(),
            'password': '******',
            'username': fake.user_name(),
            'first_name': fake.first_name(),
        }

        # Now check with two missing fields - password and bio.
        for missing_field in ['bio', 'password']:

            # Make a local for loop specific copy
            # to delete required missing field.
            d = post_data.copy()
            del d[missing_field]

            response = self.client.post(BASE_URL + '/create/', d)
            data = u.get_json(response)

            # It should raise a 'bio' field error since that's entered into the data
            # dictionary that's passed as params to the create() Author method first.
            self.assertEqual(response.status_code,
                             status.HTTP_422_UNPROCESSABLE_ENTITY)
            self.assertEqual(
                data, {'detail': f"Field '{missing_field}' not provided."})