from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse

from oauthlib.oauth2 import (InvalidClientIdError, MissingClientIdError,
                             InvalidRedirectURIError, MismatchingRedirectURIError)

from rest_framework import status
from rest_framework.test import APITestCase

from oauth_api.models import get_application_model


Application = get_application_model()
User = get_user_model()


class BaseTest(APITestCase):
    def setUp(self):
        self.test_user = User.objects.create_user('test_user', 'test_user@example.com', '1234')
        self.dev_user = User.objects.create_user('dev_user', 'dev_user@example.com', '1234')
        self.application = Application(
            name='Test Application',
            redirect_uris='http://localhost http://example.com',
            user=self.dev_user,
            client_type=Application.CLIENT_CONFIDENTIAL,
            authorization_grant_type=Application.GRANT_AUTHORIZATION_CODE,
        )
        self.application.save()


class TestAuthorizationCode(BaseTest):
    def test_invalid_client(self):
        self.client.login(username='test_user', password='1234')

        query_string = {
            'client_id': 'invalid',
            'response_type': 'code',
        }
        response = self.client.get(reverse('oauth_api:authorize'), data=query_string)

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

        self.assertIn('error', response.context)
        error = response.context['error']

        self.assertTrue(isinstance(error, InvalidClientIdError))

    def test_missing_client(self):
        self.client.login(username='test_user', password='1234')

        query_string = {
            'response_type': 'code',
        }
        response = self.client.get(reverse('oauth_api:authorize'), data=query_string)

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

        self.assertIn('error', response.context)
        error = response.context['error']

        self.assertTrue(isinstance(error, MissingClientIdError))

    def test_valid_client(self):
        self.client.login(username='test_user', password='1234')

        query_string = {
            'client_id': self.application.client_id,
            'response_type': 'code',
            'state': 'random_state_string',
            'scope': 'read write',
            'redirect_uri': 'http://localhost',
        }
        response = self.client.get(reverse('oauth_api:authorize'), data=query_string)

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

        self.assertIn('form', response.context)
        form = response.context['form']

        self.assertEqual(form['redirect_uri'].value(), 'http://localhost')
        self.assertEqual(form['state'].value(), 'random_state_string')
        self.assertEqual(form['scopes'].value(), 'read write')
        self.assertEqual(form['client_id'].value(), self.application.client_id)

    def test_invalid_response_type(self):
        self.client.login(username='test_user', password='1234')

        query_string = {
            'client_id': self.application.client_id,
            'response_type': 'invalid',
        }
        response = self.client.get(reverse('oauth_api:authorize'), data=query_string)

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

    def test_missing_response_type(self):
        self.client.login(username='test_user', password='1234')

        query_string = {
            'client_id': self.application.client_id,
        }
        response = self.client.get(reverse('oauth_api:authorize'), data=query_string)

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

    def test_forbidden_redirect_uri(self):
        self.client.login(username='test_user', password='1234')

        query_string = {
            'client_id': self.application.client_id,
            'response_type': 'code',
            'redirect_uri': 'http://invalid.local.host',
        }
        response = self.client.get(reverse('oauth_api:authorize'), data=query_string)

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

        self.assertIn('error', response.context)
        error = response.context['error']

        self.assertTrue(isinstance(error, MismatchingRedirectURIError))

    def test_invalid_redirect_uri(self):
        self.client.login(username='test_user', password='1234')

        query_string = {
            'client_id': self.application.client_id,
            'response_type': 'code',
            'redirect_uri': 'invalid',
        }
        response = self.client.get(reverse('oauth_api:authorize'), data=query_string)

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

        self.assertIn('error', response.context)
        error = response.context['error']

        self.assertTrue(isinstance(error, InvalidRedirectURIError))

@@ -1094,32 +1094,100 @@
 d_client(self):%0A
+        %22%22%22%0A        Test for invalid client information%0A        %22%22%22%0A
         self.cli
@@ -1227,32 +1227,32 @@
 assword='1234')%0A
-
 %0A        query_s
@@ -1693,32 +1693,100 @@
 g_client(self):%0A
+        %22%22%22%0A        Test for missing client information%0A        %22%22%22%0A
         self.cli
@@ -2254,32 +2254,98 @@
 d_client(self):%0A
+        %22%22%22%0A        Test for valid client information%0A        %22%22%22%0A
         self.cli
@@ -3214,32 +3214,95 @@
 nse_type(self):%0A
+        %22%22%22%0A        Test for invalid response_type%0A        %22%22%22%0A
         self.cli
@@ -3671,32 +3671,95 @@
 nse_type(self):%0A
+        %22%22%22%0A        Test for missing response_type%0A        %22%22%22%0A
         self.cli
@@ -4089,32 +4089,134 @@
 rect_uri(self):%0A
+        %22%22%22%0A        Test for forbidden redirect_uri (Not defined in list of allowed URIs)%0A        %22%22%22%0A
         self.cli
@@ -4768,32 +4768,32 @@
 rectURIError))%0A%0A
-
     def test_inv
@@ -4809,32 +4809,102 @@
 rect_uri(self):%0A
+        %22%22%22%0A        Test for malformed redirect_uri value%0A        %22%22%22%0A
         self.cli

Test docstrings added