import re
import unittest
from app import create_app, db
from app.models import User, Role


class FlaskClientTestCase(unittest.TestCase):
    def setUp(self):
        self.app = create_app('testing')
        self.app_context = self.app.app_context()
        self.app_context.push()
        db.create_all()
        # Role.insert_roles()
        self.client = self.app.test_client(use_cookies=True)

    def tearDown(self):
        db.session.remove()
        db.drop_all()
        self.app_context.pop()

    def test_home_page(self):
        response = self.client.get('/')
        self.assertEqual(response.status_code, 200)
        self.assertTrue('Stranger' in response.get_data(as_text=True))

    def test_register(self):
        # register a new account
        response = self.client.post('/auth/register', data={
            'email': 'john@example.com',
            'username': 'john',
            'password': 'cat',
            'password2': 'cat'
        })
        self.assertEqual(response.status_code, 302)

    def test_login(self):
        # login with the new account
        response = self.client.post('/auth/login', data={
            'email': 'john@example.com',
            'password': 'cat'
        }, follow_redirects=True)
        self.assertEqual(response.status_code, 200)

    def test_register_false_username(self):
        # register a new account with wrong username
        response = self.client.post('/auth/register', data={
            'email': 'john@example.com',
            'username': 'john.,*Ä#ä+=?',
            'password': 'cat',
            'password2': 'cat'
        })
        self.assertEqual(response.status_code, 200)
        self.assertTrue('Usernames must have only letters, numbers, dots or underscores' in response.get_data(as_text=True))

    def test_register_false_email(self):
        # register a new account with wrong username
        response = self.client.post('/auth/register', data={
            'email': 'john@example',
            'username': 'john',
            'password': 'cat',
            'password2': 'cat'
        })
        self.assertEqual(response.status_code, 200)
        self.assertTrue('Invalid email address.' in response.get_data(as_text=True))

    def test_duplicates(self):
        # tries to register an account that has already been registered
        # test duplicate username and duplicate email
        response = self.client.post('/auth/register', data={
            'email': 'john@example.com',
            'username': 'john',
            'password': 'cat',
            'password2': 'cat'
        })
        self.assertEqual(response.status_code, 302)
        response = self.client.post('/auth/register', data={
            'email': 'john@example2.com',
            'username': 'john',
            'password': 'cat',
            'password2': 'cat'
        })
        self.assertEqual(response.status_code, 200)
        self.assertTrue('Username already in use.' in response.get_data(as_text=True))
        response = self.client.post('/auth/register', data={
            'email': 'john@example.com',
            'username': 'johnsmith',
            'password': 'cat',
            'password2': 'cat'
        })
        self.assertEqual(response.status_code, 200)
        self.assertTrue('Email already registered.' in response.get_data(as_text=True))

        def test_admin_forbidden(self):
            response = self.client.post('/auth/login', data={
                'email': 'john@example.com',
                'password': 'cat'
            }, follow_redirects=True)
            self.assertEqual(response.status_code, 200)
            response = self.client.get('/admin')
            self.assertEqual(response.status_code, 403)
