text: # -*- coding: utf-8 -*-
  import mocker
  
  import unittest
  import transaction
  
  from pyramid import testing
  from stalker import (db, User, Status, StatusList, Repository, Project, Task,\
                      Group)
  from stalker.db.session import DBSession
  from stalker_pyramid.views import time_log
  
  
  class TimeLogViewTestCase(unittest.TestCase):
      """tests the time log view
      """
  
      def setUp(self):
          """setup the test
          """
          self.config = testing.setUp()
          db.setup({'sqlalchemy.url': 'sqlite:///:memory:'})
          db.init()
  
          DBSession.remove()
          # test users
          self.user1 = User(
              name='Test User 1',
              login='tuser1',
              email='tuser1@test.com',
              password='secret'
          )
          DBSession.add(self.user1)
  
          # create a couple of tasks
          self.status_new = Status(name='New', code='NEW')
          self.status_rts = Status(name='Ready To Start', code='RTS')
          self.status_wip = Status(name='Work In Progress', code='WIP')
          self.status_prev = Status(name='Pending Review', code='PREV')
          self.status_hrev = Status(name='Has Revisions', code='HREV')
          self.status_cmpl = Status(name='Complete', code='CMPL')
  
          self.project_status_list = StatusList(
              name='Project Statuses',
              target_entity_type='Project',
              statuses=[self.status_new, self.status_wip, self.status_cmpl]
          )
          DBSession.add(self.project_status_list)
  
          self.task_status_list = StatusList(
              name='Task Statuses',
              target_entity_type='Task',
              statuses=[self.status_new, self.status_rts, self.status_wip,
                        self.status_prev, self.status_hrev, self.status_cmpl]
          )
          DBSession.add(self.task_status_list)
  
          # repo
          self.repo = Repository(
              name='Test Repository'
          )
          DBSession.add(self.repo)
  
          # proj1
          self.proj1 = Project(
              name='Test Project',
              code='TProj1',
              status_list=self.project_status_list,
              repository=self.repo,
              lead=self.user1
          )
          DBSession.add(self.proj1)
  
          # tasks
          self.task1 = Task(
              name='Test Task 1',
              project=self.proj1,
              status_list=self.task_status_list,
              status=self.status_new,
              resources=[self.user1],
              schedule_timing=5,
              schedule_unit='d',
              schedule_model='effort'
          )
          DBSession.add(self.task1)
          transaction.commit()
  
      def tearDown(self):
          DBSession.remove()
          testing.tearDown()
  
      def test_creating_a_time_log_for_a_task_with_status_new(self):
          """testing if an error response will be returned when trying to create
          time log for a task with status "new"
          """
          request = testing.DummyRequest()
          self.task1 = Task.query.filter(Task.name == self.task1.name).first()
          request.params['task_id'] = self.task1.id
          request.params['resource_id'] = self.task1.resources[0].id
          request.params['start'] = "Fri, 01 Nov 2013 08:00:00 GMT"
          request.params['end'] = "Fri, 01 Nov 2013 17:00:00 GMT"
  
          self.assertEqual(self.task1.status, self.status_new)
          response = time_log.create_time_log(request)
          self.assertEqual(response.status_int, 500)
          self.assertEqual(
              response.body,
              'It is only possible to create time log for a task '
              'with status "RTS", "WIP", "PREV" or "HREV"'
          )
          self.assertEqual(self.task1.status, self.status_new)
  
      def test_creating_a_time_log_for_a_task_with_status_rts(self):
          """testing if the status of the time log will be set to WIP if the
          status of that task is rts
          """
          request = testing.DummyRequest()
          self.task1 = Task.query.filter(Task.name == self.task1.name).first()
          request.params['task_id'] = self.task1.id
          request.params['resource_id'] = self.task1.resources[0].id
          request.params['start'] = "Fri, 01 Nov 2013 08:00:00 GMT"
          request.params['end'] = "Fri, 01 Nov 2013 17:00:00 GMT"
  
          self.task1.status = self.status_rts
          self.assertEqual(self.task1.status, self.status_rts)
          time_log.create_time_log(request)
          self.assertEqual(self.task1.status, self.status_wip)
  
      def test_creating_a_time_log_for_a_task_with_status_pending_review(self):
          """testing if an response with status code 200 will be returned when
          a time log for a task with status "pending review" has been created
          """
          request = testing.DummyRequest()
          self.task1 = Task.query.filter(Task.name == self.task1.name).first()
          self.task1.status = self.status_prev
  
          request.params['task_id'] = self.task1.id
          request.params['resource_id'] = self.task1.resources[0].id
          request.params['start'] = "Fri, 01 Nov 2013 08:00:00 GMT"
          request.params['end'] = "Fri, 01 Nov 2013 17:00:00 GMT"
  
          response = time_log.create_time_log(request)
          self.assertEqual(response.status_code, 200)
  
      def test_creating_a_time_log_for_a_task_with_status_completed(self):
          """testing if an error response will be returned when trying to create
          time log for a completed task
          """
          request = testing.DummyRequest()
          self.task1 = Task.query.filter(Task.name == self.task1.name).first()
          self.task1.status = self.status_cmpl
  
          request.params['task_id'] = self.task1.id
          request.params['resource_id'] = self.task1.resources[0].id
          request.params['start'] = "Fri, 01 Nov 2013 08:00:00 GMT"
          request.params['end'] = "Fri, 01 Nov 2013 17:00:00 GMT"
  
          response = time_log.create_time_log(request)
          self.assertEqual(response.status_code, 500)
  
      def test_creating_a_time_log_for_a_task_with_status_has_revision(self):
          """testing if the task status will be converted to wip when a time log
          is eneter for a task with status "has revision"
          """
          request = testing.DummyRequest()
          self.task1 = Task.query.filter(Task.name == self.task1.name).first()
          self.task1.status = self.status_hrev
  
          request.params['task_id'] = self.task1.id
          request.params['resource_id'] = self.task1.resources[0].id
          request.params['start'] = "Fri, 01 Nov 2013 08:00:00 GMT"
          request.params['end'] = "Fri, 01 Nov 2013 17:00:00 GMT"
  
          response = time_log.create_time_log(request)
          self.assertEqual(response.status_code, 200)
  
          self.assertEqual(
              self.task1.status,
              self.status_wip
          )
  
      def test_creating_a_time_log_for_a_task_whose_dependending_tasks_already_has_time_logs(self):
          """testing if a HTTPServer error will be raised when a time log tried
          to be for a task whose depending tasks already has time logs created
          (This test should be in Stalker)
          """
          # create a new task
          task2 = Task(
              name='Test Task 2',
              project=self.proj1,
              depends=[self.task1],
              resources=[self.user1],
              schedule_timing=4,
              schedule_unit= 'd',
              schedule_model='effort',
              status_list=self.task_status_list
          )
          DBSession.add(task2)
          DBSession.flush()
          transaction.commit()
  
          # set the status of task1 to complete
          self.task1.status = self.status_cmpl
          # artificially update task2 status to rts
          task2.status = self.status_rts
          DBSession.flush()
          transaction.commit()
  
          # and now create time logs for task2
          request = testing.DummyRequest()
          request.params['task_id'] = task2.id
          request.params['resource_id'] = self.user1.id
          request.params['start'] = "Fri, 01 Nov 2013 08:00:00 GMT"
          request.params['end'] = "Fri, 01 Nov 2013 17:00:00 GMT"
          response = time_log.create_time_log(request)
          self.assertEqual(response.status_int, 200)
          DBSession.add(task2)
          DBSession.flush()
          transaction.commit()
  
          # now because task2 is depending on to the task1
          # and task2 has now started, entering any new time logs to task1
          # is forbidden
          request = testing.DummyRequest()
          request.params['task_id'] = self.task1.id
          request.params['resource_id'] = self.user1.id
          request.params['start'] = "Fri, 02 Nov 2013 08:00:00 GMT"
          request.params['end'] = "Fri, 02 Nov 2013 17:00:00 GMT"
  
          response = time_log.create_time_log(request)
          self.assertEqual(
              response.status_int, 500
          )
  
      def test_creating_a_time_log_for_a_task_whose_dependent_tasks_has_not_finished_yet(self):
          """testing if a HTTPServer error will be raised when a time log tried
          to be created for a Task whose dependent tasks has not finished yet
          """
          # create a new task
          task2 = Task(
              name='Test Task 2',
              project=self.proj1,
              depends=[self.task1],
              resources=[self.user1],
              schedule_timing=4,
              schedule_unit='d',
              schedule_model='effort',
              status_list=self.task_status_list
          )
          DBSession.add(task2)
          DBSession.flush()
          transaction.commit()
  
          # now because task2 is depending on to the task1
          # and task1 is not finished yet (where the status is not
          # set to Complete, we should expect an HTTPServerError()
          # to be raised
          request = testing.DummyRequest()
          request.params['task_id'] = task2.id
          request.params['resource_id'] = self.user1.id
          request.params['start'] = "Fri, 01 Nov 2013 08:00:00 GMT"
          request.params['end'] = "Fri, 01 Nov 2013 17:00:00 GMT"
  
          response = time_log.create_time_log(request)
          self.assertEqual(
              response.status_int, 500
          )
  
      def test_creating_a_time_log_for_a_leaf_task_will_set_its_parents_status_to_wip(self):
          """testing if the status of the parent task will turn to wip if time
          log is entered to a child task
          """
          # TODO: This is also testing some functionality from view.task, slit it
          # create two new task
          task0 = Task(
              name='Test Task 0',
              project=self.proj1,
              status_list=self.task_status_list
          )
          task1 = Task(
              name='Test Task 1',
              parent=task0,
              status_list=self.task_status_list
          )
          task2 = Task(
              name='Test Task 2',
              parent=task1,
              resources=[self.user1],
              status_list=self.task_status_list,
              status=self.status_rts
          )
          task3 = Task(
              name='Test Task 3',
              parent=task1,
              resources=[self.user1],
              status_list=self.task_status_list,
              status=self.status_rts
          )
          task4 = Task(
              name='Test Task 4',
              parent=task0,
              resources=[self.user1],
              status_list=self.task_status_list,
              status=self.status_rts
          )
          DBSession.add_all([task0, task1, task2, task3, task4])
          DBSession.commit()
          DBSession.flush()
          transaction.commit()
  
          self.assertEqual(task0.status, self.status_new)
          self.assertEqual(task1.status, self.status_new)
          self.assertEqual(task2.status, self.status_rts)
          self.assertEqual(task3.status, self.status_rts)
          self.assertEqual(task4.status, self.status_rts)
  
          # now add a time log for task3 through create_time_log view
          request = testing.DummyRequest()
  
          # patch get_logged_in_user
          admins = Group.query.filter(Group.name == 'admins').first()
          self.user1.groups.append(admins)
          m = mocker.Mocker()
          obj = m.replace("stalker_pyramid.views.auth.get_logged_in_user")
          obj(request)
          m.result(self.user1)
          m.count(1, 1000000000)
          m.replay()
          request.route_url = lambda x, id=1: 'view_user'
  
          request.params['task_id'] = task3.id
          request.params['resource_id'] = self.user1.id
          request.params['start'] = "Fri, 19 Nov 2013 08:00:00 GMT"
          request.params['end'] = "Fri, 19 Nov 2013 17:00:00 GMT"
          response = time_log.create_time_log(request)
          self.assertEqual(response.status_int, 200)
  
          # now expect to have the status of task1 to be wip
          self.assertEqual(task3.status, self.status_wip)
          self.assertEqual(task2.status, self.status_rts)
          self.assertEqual(task1.status, self.status_wip)
          self.assertEqual(task0.status, self.status_wip)
          self.assertEqual(task4.status, self.status_rts)
  
          request.params['task_id'] = task2.id
          request.params['resource_id'] = self.user1.id
          request.params['start'] = "Fri, 18 Nov 2013 08:00:00 GMT"
          request.params['end'] = "Fri, 18 Nov 2013 17:00:00 GMT"
          response = time_log.create_time_log(request)
          self.assertEqual(response.status_int, 200)
  
          # now expect to have the status of task1 to be wip
          self.assertEqual(task3.status, self.status_wip)
          self.assertEqual(task2.status, self.status_wip)
          self.assertEqual(task1.status, self.status_wip)
          self.assertEqual(task0.status, self.status_wip)
          self.assertEqual(task4.status, self.status_rts)
  
          # now request a review and approve the task2 and task3 and expect the
          # task1 status is complete
          from stalker_pyramid.views.task import request_review, review_task
          #request = testing.DummyRequest()
          request.matchdict['id'] = task2.id
          request.params['send_email'] = 0
          request.route_url = lambda x, id: 'localhost:6453/tasks/23/view'
          request.route_path = lambda x, id: '/tasks/23/view'
  
          response = request_review(request)
          self.assertEqual(response.status_int, 200)
  
          #request = testing.DummyRequest()
          request.matchdict['id'] = task3.id
          request.params['send_email'] = 0
          response = request_review(request)
          print(response.body)
          self.assertEqual(response.status_int, 200)
  
          self.assertEqual(task3.status, self.status_prev)
          self.assertEqual(task2.status, self.status_prev)
          self.assertEqual(task1.status, self.status_wip)
          self.assertEqual(task0.status, self.status_wip)
          self.assertEqual(task4.status, self.status_rts)
  
          # approve the task2
          request.matchdict['id'] = task2.id
          request.params['review'] = 'Approve'
          response = review_task(request)
          self.assertEqual(response.status_int, 200)
  
          # and except task1 is still wip
          self.assertEqual(task3.status, self.status_prev)
          self.assertEqual(task2.status, self.status_cmpl)
          self.assertEqual(task1.status, self.status_wip)
          self.assertEqual(task0.status, self.status_wip)
          self.assertEqual(task4.status, self.status_rts)
  
          # approve the task3
          request.matchdict['id'] = task3.id
          request.params['review'] = 'Approve'
          response = review_task(request)
          self.assertEqual(response.status_int, 200)
  
          # now check the statuses
          self.assertEqual(task3.status, self.status_cmpl)
          self.assertEqual(task2.status, self.status_cmpl)
          self.assertEqual(task1.status, self.status_cmpl)
          self.assertEqual(task0.status, self.status_wip)
          self.assertEqual(task4.status, self.status_rts)
  
      def test_deleting_time_log_for_a_task_with_status_complete(self):
          """testing if it is not allowed to delete a time log of a task with
          status completed
          """
          # TODO: This is also testing some functionality from view.task, slit it
          # create two new task
          task0 = Task(
              name='Test Task 0',
              project=self.proj1,
              status_list=self.task_status_list
          )
          task1 = Task(
              name='Test Task 1',
              parent=task0,
              status_list=self.task_status_list,
              resources=[self.user1]
          )
          task1.status = self.status_wip
          DBSession.add_all([task0, task1])
          DBSession.commit()
          DBSession.flush()
          transaction.commit()
  
          self.assertEqual(task0.status, self.status_new)
          self.assertEqual(task1.status, self.status_wip)
  
          # now add a time log for task3 through create_time_log view
          request = testing.DummyRequest()
  
          # patch get_logged_in_user
          admins = Group.query.filter(Group.name == 'admins').first()
          self.user1.groups.append(admins)
          m = mocker.Mocker()
          obj = m.replace("stalker_pyramid.views.auth.get_logged_in_user")
          obj(request)
          m.result(self.user1)
          m.count(1, 1000000000)
          m.replay()
          request.route_url = lambda x, id=1: 'view_user'
  
          request.params['task_id'] = task1.id
          request.params['resource_id'] = self.user1.id
          request.params['start'] = "Fri, 19 Nov 2013 08:00:00 GMT"
          request.params['end'] = "Fri, 19 Nov 2013 17:00:00 GMT"
          response = time_log.create_time_log(request)
          self.assertEqual(response.status_int, 200)
  
          # set it to complete
          task1.status = self.status_cmpl
  
          # now try to remove it
          request.matchdict['id'] = task1.time_logs[0].id
          response = time_log.delete_time_log(request)
          self.assertEqual(response.status_int, 500)
          self.assertEqual(
              response.body,
              'Error: You can not delete a TimeLog of a Task with status CMPL'
          )
  
  