# project/test.py


import os
import unittest

from views import app, db
from _config import basedir
from models import User

TEST_DB = 'test.db'




class AllTests(unittest.TestCase):

    ############################
    #### setup and teardown ####
    ############################

    # executed prior to each test
    def setUp(self):
        app.config['TESTING'] = True
        app.config['WTF_CSRF_ENABLED'] = False
        app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, TEST_DB)
        self.app = app.test_client()
        db.create_all()

    # executed after each test
    def tearDown(self):
        db.session.remove()
        db.drop_all()

    #################################
    ######## helper methods  ########
    #################################

    # login helper method
    def login(self, name, password):
        return self.app.post('/', data=dict(name=name, password=password), follow_redirects=True)

    # register helper method
    def register(self, name, email, password, confirm):
        return self.app.post(
            'register/',
            data=dict(name=name, email=email, password=password, confirm=confirm),
            follow_redirects=True
        )

    # logout helper method
    def logout(self):
        return self.app.get('logout/', follow_redirects=True)


    # create user helper method
    def create_user(self, name, email, password):
        new_user = User(name=name, email=email, password=password)
        db.session.add(new_user)
        db.session.commit()


    # create task helper method
    def create_task(self):
        return self.app.post('add/', data=dict(
            name ='Go to the bank',
            due_date = '02/05/2014',
            priority = '1',
            posted_date = '02/04/2014',
            status = '1'
        ), follow_redirects=True)


    ###################################
    ############# test  ###############
    ###################################
    # each test should start with 'test'
    def test_user_setup(self):
        new_user = User("david", "david@meltwater.org", "davidopoku")
        db.session.add(new_user)
        db.session.commit()
        test = db.session.query(User).all()
        for t in test:
            t.name
        assert t.name == "david"


    # form is present on login page
    def test_form_is_present_on_login(self):
        response = self.app.get('/')
        self.assertEqual(response.status_code, 200)
        self.assertIn(b'Please sign in to access your task list', response.data)


    # unregistered users cannot login
    def test_users_cannot_login_unless_registered(self):
        response = self.login('foo', 'bar')
        self.assertIn(b'Invalid username or password.', response.data)


    # registered users can login (form validation)
    def test_users_can_login(self):
        self.register('David', 'david@adoore.org', 'python', 'python')
        response = self.login('David', 'python')
        self.assertIn('Welcome to FlaskTaskr', response.data)


    # show error for invalid form data
    def test_invalid_form_data(self):
        self.register('David', 'david@meltwater.org', 'python', 'python')
        response = self.login('alert("alert box!");', 'foo')
        self.assertIn(b'Invalid username or password.', response.data)


    # form is present on register page
    def test_form_is_present_on_register_page(self):
        response = self.app.get('register/')
        self.assertEqual(response.status_code, 200)
        self.assertIn(b'Please register to access the task list.', response.data)


    # users can register (form validation)
    def test_user_registration_error(self):
        self.app.get('register/', follow_redirects=True)
        self.register('DavidOpoku', 'david@meltwater.org', 'python', 'python')
        self.app.get('register/', follow_redirects=True)
        response = self.register(
            'DavidOpoku', 'david@meltwater.org', 'python', 'python')
        self.assertIn(b'That username and/or email already exist.', response.data)


    # logged in user can logout
    def test_logged_in_users_can_logout(self):
        self.register('Ranger', 'ranger@adoorelabs.com', 'python101', 'python101')
        self.login('Ranger', 'python101')
        response = self.logout()
        self.assertIn(b'Goodbye!', response.data)


    # users not logged in cannot logout
    def test_not_logged_in_cannot_logout(self):
        response = self.logout()
        self.assertNotIn(b'Goodbye!', response.data)


    # logged in users can access tasks page
    def test_logged_in_users_can_access_tasks_page(self):
        self.register(
            'Ranger', 'ranger@adoorelabs.com', 'python101', 'python101'
        )
        self.login('Ranger', 'python101')
        response = self.app.get('tasks/')
        self.assertEqual(response.status_code, 200)
        self.assertIn('Add a new task:', response.data)


    # test that users not logged in cannot access tasks page
    def test_not_logged_in_users_cannot_access_tasks_page(self):
        response = self.app.get('tasks/', follow_redirects=True)
        self.assertIn(b'You need to login first.', response.data)


    # test that user can add tasks
    def test_users_can_add_tasks(self):
        self.create_user('Ranger', 'ranger@adoorelabs.com', 'python')
        self.login('Ranger', 'python')
        self.app.get('tasks/', follow_redirects=True)
        response = self.create_task()
        self.assertIn(
            b'New entry was successfully posted. Thanks.', response.data
        )


    # test that users cannot add tasks when there is an error
    def test_users_cannot_add_tasks_when_error(self):
        self.create_user('Ranger', 'ranger@adoorelabs.com', 'python')
        self.login('Ranger', 'python')
        self.app.get('tasks/', follow_redirects=True)
        response = self.app.post('add/', data=dict(
            name = 'Go to the bank',
            due_date ='',
            priority='1',
            posted_date='02/05/2014',
            status='1',
        ), follow_redirects=True)
        self.assertIn(b'This field is required.', response.data)


    # test that users can complete tasks
    def test_users_can_complete_tasks(self):
        self.create_user('Ranger', 'ranger@adoorelabs.com', 'python')
        self.login('Ranger', 'python')
        self.app.get('tasks/', follow_redirects=True)
        self.create_task()
        response = self.app.get("complete/1", follow_redirects=True)
        self.assertIn(b'The task is complete. Nice.', response.data)


    # test that users can delete tasks
    def test_users_can_delete_tasks(self):
        self.create_user('Ranger', 'ranger@adoorelabs.com', 'python')
        self.login('Ranger', 'python')
        self.app.get('tasks/', follow_redirects=True)
        self.create_task()
        response = self.app.get("delete/1/", follow_redirects=True)
        self.assertIn(b'The task was deleted.', response.data)


    # test that users cannot complete tasks that are not created by them
    def test_users_cannot_complete_tasks_that_are_not_created_by_them(self):
        self.create_user('Ranger', 'ranger@adoorelabs.com', 'python')
        self.login('Ranger', 'python')
        self.app.get('tasks/', follow_redirects=True)
        self.create_task()
        self.logout()
        self.create_user('Davisclex', 'davisclex@adoorelabs.com', 'python101')
        self.login('Davisclex', 'python101')
        self.app.get('tasks/', follow_redirects=True)
        response = self.app.get("complete/1/", follow_redirects=True)
        self.assertNotIn(
            b'The task is complete. Nice.', response.data
        )

if __name__ == "__main__":
    unittest.main()
