from django.contrib.sessions.middleware import SessionMiddleware
from django.test import TestCase, RequestFactory
from graphene.test import Client
from api.schema import schema
from core.factories import UserFactory
from django.contrib.auth import authenticate


class PasswordUpdate(TestCase):
    def setUp(self):
        self.user = UserFactory(username='aschi')

        request = RequestFactory().get('/')
        request.user = self.user

        # adding session
        middleware = SessionMiddleware()
        middleware.process_request(request)
        request.session.save()
        self.client = Client(schema=schema, context_value=request)

    def make_request(self, new_password, old_password='test'):

        mutation = '''
        mutation UpdatePassword($input: UpdatePasswordInput!) {
            updatePassword(input: $input) {
              success
              errors {
                field
                errors {
                    code
                }
              }
            }
        }
        '''

        return self.client.execute(mutation, variables={
            'input': {
                'passwordInput': {
                    'oldPassword': old_password,
                    'newPassword': new_password
                }
            }
        })

    def test_update_password(self):

        new_password = 'Abcd123!'
        result = self.make_request(new_password)

        self.assertTrue(result.get('data').get('updatePassword').get('success'))

        user = authenticate(username=self.user.username, password=new_password)
        self.assertIsNotNone(user)

    def test_update_fails_with_short_password(self):

        new_password = 'Ab!d123'

        result = self.make_request(new_password)

        self.assertFalse(result.get('data').get('updatePassword').get('success'))
        self.assertEquals(result.get('data').get('updatePassword').get('errors')[0], {
            'field': 'new_password',
            'errors': [
                {'code': 'min_length'}
            ]
        })

    def test_update_fails_with_no_special_character(self):

        new_password = 'Abcd1239'
        result = self.make_request(new_password)

        self.assertFalse(result.get('data').get('updatePassword').get('success'))
        self.assertEquals(result.get('data').get('updatePassword').get('errors')[0], {
            'field': 'new_password',
            'errors': [
                {'code': 'invalid'}
            ]
        })

    def test_update_fails_with_no_digit(self):

        new_password = 'Abcd!asddfg'
        result = self.make_request(new_password)

        self.assertFalse(result.get('data').get('updatePassword').get('success'))
        self.assertEquals(result.get('data').get('updatePassword').get('errors')[0], {
            'field': 'new_password',
            'errors': [
                {'code': 'invalid'}
            ]
        })

    def test_update_fails_with_no_lowercase_char(self):

        new_password = '45ABDC!AWSWS'
        result = self.make_request(new_password)

        self.assertFalse(result.get('data').get('updatePassword').get('success'))
        self.assertEquals(result.get('data').get('updatePassword').get('errors')[0], {
            'field': 'new_password',
            'errors': [
                {'code': 'invalid'}
            ]
        })

    def test_update_fails_with_no_uppercase_char(self):

        new_password = '45aswed!aswdef'
        result = self.make_request(new_password)

        self.assertFalse(result.get('data').get('updatePassword').get('success'))
        self.assertEquals(result.get('data').get('updatePassword').get('errors')[0], {
            'field': 'new_password',
            'errors': [
                {'code': 'invalid'}
            ]
        })

    def test_update_fails_with_wrong_old_password(self):

        new_password = 'Abcd123!'
        result = self.make_request(new_password, 'testttt')

        self.assertFalse(result.get('data').get('updatePassword').get('success'))
        self.assertEquals(result.get('data').get('updatePassword').get('errors')[0], {
            'field': 'old_password',
            'errors': [
                {'code': 'invalid'}
            ]
        })
