Exemple #1
0
    def setUp(self):
        """Set up."""
        super(TestWfNotifsGenerator, self).setUp()
        self.api = Api()
        self.wf_generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()
        Notification.query.delete()

        with freeze_time("2015-05-01 14:29:00"):
            wf_slug = "wf1"
            with factories.single_commit():
                wf = wf_factories.WorkflowFactory(slug=wf_slug,
                                                  is_verification_needed=True)
                task_group = wf_factories.TaskGroupFactory(workflow=wf)
                wf_factories.TaskGroupTaskFactory(task_group=task_group,
                                                  title='task1',
                                                  start_date=datetime.now(),
                                                  end_date=datetime.now() +
                                                  timedelta(7))
            data = workflow_api.get_cycle_post_dict(wf)
            self.api.post(all_models.Cycle, data)
            wf = all_models.Workflow.query.filter_by(slug=wf_slug).one()
            self.cycle = all_models.Cycle.query.filter_by(
                workflow_id=wf.id).one()
            self.ctask = all_models.CycleTaskGroupObjectTask.query.filter_by(
                cycle_id=self.cycle.id).first()
Exemple #2
0
    def setUp(self):
        TestCase.setUp(self)
        self.api = Api()
        self.generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        self.weekly_wf = {
            "title":
            "weekly thingy",
            "description":
            "start this many a time",
            "frequency":
            "weekly",
            "task_groups": [
                {
                    "title":
                    "weekly task group",
                    "task_group_tasks": [{
                        "title": "weekly task 1",
                        "relative_end_day": 1,
                        "relative_end_month": None,
                        "relative_start_day": 5,
                        "relative_start_month": None,
                    }, {
                        "title": "weekly task 1",
                        "relative_end_day": 1,
                        "relative_end_month": None,
                        "relative_start_day": 1,
                        "relative_start_month": None,
                    }]
                },
            ]
        }
    def setUp(self):
        super(TestWorkflowCycleStatePropagation, self).setUp()
        self.api = Api()
        self.generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        self.weekly_wf = {
            "title":
            "weekly thingy",
            "description":
            "start this many a time",
            "unit":
            "week",
            "repeat_every":
            1,
            "is_verification_needed":
            True,
            "task_groups": [
                {
                    "title":
                    "weekly task group",
                    "task_group_tasks": [{
                        "title": "weekly task 1",
                        "start_date": dtm.date(2016, 6, 10),
                        "end_date": dtm.date(2016, 6, 13),
                    }, {
                        "title": "weekly task 1",
                        "start_date": dtm.date(2016, 6, 10),
                        "end_date": dtm.date(2016, 6, 13),
                    }]
                },
            ]
        }
Exemple #4
0
    def setUp(self):
        super(TestOneTimeWorkflowNotification, self).setUp()
        self.api = Api()
        self.wf_generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        self.random_objects = self.object_generator.generate_random_objects()
        self.random_people = [
            self.object_generator.generate_person(user_role="Administrator")[1]
            for _ in range(5)
        ]
        self.create_test_cases()

        self.create_users()

        db.session.query(Notification).delete()

        def init_decorator(init):
            def new_init(self, *args, **kwargs):
                init(self, *args, **kwargs)
                if hasattr(self, "created_at"):
                    self.created_at = datetime.now()

            return new_init

        Notification.__init__ = init_decorator(Notification.__init__)
Exemple #5
0
    def setUp(self):
        TestCase.setUp(self)
        self.api = Api()
        self.generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        self.random_objects = self.object_generator.generate_random_objects()
        self.create_test_cases()
    def setUp(self):
        super(TestBasicWorkflowActions, self).setUp()
        self.api = Api()
        self.generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        self.random_objects = self.object_generator.generate_random_objects()
        self.create_test_cases()
    def setUp(self):
        """Set up."""
        super(TestNotificationsHistory, self).setUp()
        self.wf_generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()
        _, self.user = self.object_generator.generate_person(
            user_role="Administrator")

        self._create_test_cases()
Exemple #8
0
    def setUp(self):
        TestCase.setUp(self)
        self.api = Api()
        self.generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        _, self.assignee = self.object_generator.generate_person(
            user_role="Administrator")

        self.create_test_cases()
Exemple #9
0
    def setUp(self):
        super(TestRecurringCycleNotifications, self).setUp()
        self.api = Api()
        self.generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        _, self.assignee = self.object_generator.generate_person(
            user_role="Administrator")

        self.create_test_cases()
  def setUp(self):
    super(TestRecurringWorkflowRevisions, self).setUp()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.random_objects = self.object_generator.generate_random_objects()
    _, self.person_1 = self.object_generator.generate_person(
        user_role="Administrator")
    _, self.person_2 = self.object_generator.generate_person(
        user_role="Administrator")
    self._create_test_cases()
    def setUp(self):
        TestCase.setUp(self)
        self.wf_generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        self.random_objects = self.object_generator.generate_random_objects()
        _, self.person_1 = self.object_generator.generate_person(
            user_role="Administrator")
        _, self.person_2 = self.object_generator.generate_person(
            user_role="Administrator")
        self._create_test_cases()
Exemple #12
0
  def setUp(self):
    super(TestRecurringWorkflowRevisions, self).setUp()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.random_objects = self.object_generator.generate_random_objects()
    _, self.person_1 = self.object_generator.generate_person(
        user_role="Administrator")
    _, self.person_2 = self.object_generator.generate_person(
        user_role="Administrator")

    def person_dict(person_id):
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }
    self.monthly_workflow = {
        "title": "test monthly wf notifications",
        "notify_on_change": True,
        "description": "some test workflow",
        "owners": [person_dict(self.person_2.id)],
        "unit": "month",
        "repeat_every": 1,
        "task_groups": [{
            "title": "one time task group",
            "contact": person_dict(self.person_1.id),
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "contact": person_dict(self.person_1.id),
            }, {
                "title": "task 2",
                "description": "some task",
                "contact": person_dict(self.person_1.id),
            }],
            "task_group_objects": self.random_objects[:2]
        }, {
            "title": "another one time task group",
            "contact": person_dict(self.person_1.id),
            "task_group_tasks": [{
                "title": "task 1 in tg 2",
                "description": "some task",
                "contact": person_dict(self.person_1.id),
            }, {
                "title": "task 2 in tg 2",
                "description": "some task",
                "contact": person_dict(self.person_2.id),
            }],
            "task_group_objects": []
        }]
    }
Exemple #13
0
    def setUp(self):
        super(TestTaskOverdueNotificationsUsingAPI, self).setUp()
        self.api = Api()
        self.wf_generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()
        all_models.Notification.query.delete()

        self._fix_notification_init()

        self.random_objects = self.object_generator.generate_random_objects(2)
        self.user = self.create_user_with_role(role="Administrator")
        self.secondary_assignee = self.create_user_with_role(role="Reader")
        self._create_test_cases()
  def setUp(self):
    super(TestTaskOverdueNotificationsUsingAPI, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    models.Notification.query.delete()

    self._fix_notification_init()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")
    self._create_test_cases()
Exemple #15
0
  def setUp(self):
    TestCase.setUp(self)
    self.generator = ObjectGenerator()
    self.client.get("/login")

    self.create_custom_attributes()
    filename = "comprehensive_sheet1.csv"
    self.import_file(filename)

    gen = WorkflowsGenerator()
    wfs = all_models.Workflow.eager_query().filter_by(status='Draft').all()
    for workflow in wfs:
      _, cycle = gen.generate_cycle(workflow)
      self.assertIsNotNone(cycle)
Exemple #16
0
  def setUp(self):
    super(TestComprehensiveSheets, self).setUp()
    self.client.get("/login")
    self.generator = ObjectGenerator()

    self.create_custom_attributes()
    # TODO: use here such a CSV that doesn't have errors or warnings
    self.import_file("comprehensive_sheet1.csv", safe=False)

    gen = WorkflowsGenerator()
    wfs = all_models.Workflow.eager_query().filter_by(status='Draft').all()
    for workflow in wfs:
      _, cycle = gen.generate_cycle(workflow)
      self.assertIsNotNone(cycle)
    def setUp(self):
        super(TestComprehensiveSheets, self).setUp()
        self.client.get("/login")
        self.generator = ObjectGenerator()

        self.create_custom_attributes()
        # TODO: use here such a CSV that doesn't have errors or warnings
        self.import_file("comprehensive_sheet1.csv", safe=False)

        gen = WorkflowsGenerator()
        wfs = all_models.Workflow.eager_query().filter_by(status='Draft').all()
        for workflow in wfs:
            _, cycle = gen.generate_cycle(workflow)
            self.assertIsNotNone(cycle)
    def setUp(self):
        super(TestWorkflowAclPropagation, self).setUp()
        self.generator = WorkflowsGenerator()
        with factories.single_commit():
            self.people_ids = [
                factories.PersonFactory(
                    name="user {}".format(i),
                    email="user{}@example.com".format(i),
                ).id for i in range(10)
            ]

        acr = all_models.AccessControlRole
        self.acr_name_map = dict(
            db.session.query(
                acr.name,
                acr.id,
            ).filter(acr.object_type == all_models.Workflow.__name__, ))

        self.weekly_wf = {
            "title":
            "weekly thingy",
            "description":
            "start this many a time",
            "access_control_list": [{
                "ac_role_id": self.acr_name_map["Admin"],
                "person": {
                    "type": "Person",
                    "id": self.people_ids[i]
                },
            } for i in range(5)],
            "unit":
            "week",
            "repeat_every":
            1,
            "task_groups": [
                {
                    "title":
                    "weekly task group",
                    "task_group_tasks": [{
                        "title":
                        "weekly task {}".format(i),
                        "start_date":
                        datetime.date(2016, 6, 10),
                        "end_date":
                        datetime.date(2016, 6, 13),
                    } for i in range(3)]
                },
            ]
        }
  def setUp(self):
    self.client.get("/login")
    self.generator = ObjectGenerator()
    if TestComprehensiveSheets.first_run:
      TestComprehensiveSheets.first_run = False
      super(TestComprehensiveSheets, self).setUp()

      self.create_custom_attributes()
      self.import_file("comprehensive_sheet1.csv")

      gen = WorkflowsGenerator()
      wfs = all_models.Workflow.eager_query().filter_by(status='Draft').all()
      for workflow in wfs:
        _, cycle = gen.generate_cycle(workflow)
        self.assertIsNotNone(cycle)
 def setUp(self):
     super(TestCycleTaskImportUpdate, self).setUp()
     self.wf_generator = WorkflowsGenerator()
     self.object_generator = ObjectGenerator()
     self.random_objects = self.object_generator.generate_random_objects(2)
     self.person_1 = ggrc_factories.PersonFactory()
     self.ftime_active = "2016-07-01"
     self.ftime_historical = "2014-05-01"
     self._create_test_cases_data()
     # It is needed because cycle-tasks are generated automatically with
     # 'slug' based on auto_increment 'id' field.
     # At start of each test we suppose that created cycle-task's 'slug'
     # lie in range from 1 to 10.
     db.session.execute('ALTER TABLE cycle_task_group_object_tasks '
                        'AUTO_INCREMENT = 1')
Exemple #21
0
    def setUp(self):
        super(TestWorkflowCycleStatePropagation, self).setUp()
        self.api = Api()
        self.generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        self.weekly_wf = {
            "title": "weekly thingy",
            "description": "start this many a time",
            "unit": "week",
            "repeat_every": 1,
            "task_groups": [{
                "title": "weekly task group",
            }]
        }
  def setUp(self):
    self.client.get("/login")
    self.generator = ObjectGenerator()
    if TestComprehensiveSheets.first_run:
      TestComprehensiveSheets.first_run = False
      super(TestComprehensiveSheets, self).setUp()

      self.create_custom_attributes()
      self.import_file("comprehensive_sheet1.csv")

      gen = WorkflowsGenerator()
      wfs = all_models.Workflow.eager_query().filter_by(status='Draft').all()
      for workflow in wfs:
        _, cycle = gen.generate_cycle(workflow)
        self.assertIsNotNone(cycle)
  def activate(self):
    """ activate workflows just once after the class has been initialized

    This should be in setUpClass method, but we can't access the server
    context from there."""
    gen = WorkflowsGenerator()

    # generate cycle for the only one time wf
    wf1 = Workflow.query.filter_by(status="Draft", slug="wf-1").first()
    if wf1:
      gen.generate_cycle(wf1)

    workflows = Workflow.query.filter_by(status="Draft").all()
    for wf in workflows:
      gen.activate_workflow(wf)
  def setUp(self):
    super(TestWorkflowCycleStatePropagantion, self).setUp()
    self.api = Api()
    self.generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.weekly_wf = {
        "title": "weekly thingy",
        "description": "start this many a time",
        "frequency": "weekly",
        "task_groups": [{
            "title": "weekly task group",
            "task_group_tasks": [{
                "title": "weekly task 1",
                "relative_end_day": 1,
                "relative_end_month": None,
                "relative_start_day": 5,
                "relative_start_month": None,
            }, {
                "title": "weekly task 1",
                "relative_end_day": 1,
                "relative_end_month": None,
                "relative_start_day": 1,
                "relative_start_month": None,
            }
            ]},
        ]
    }
Exemple #25
0
  def setUp(self):
    """Set up."""
    super(TestWfNotifsGenerator, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    Notification.query.delete()

    with freeze_time("2015-05-01 14:29:00"):
      wf_slug = "wf1"
      with factories.single_commit():
        wf = wf_factories.WorkflowFactory(slug=wf_slug)
        task_group = wf_factories.TaskGroupFactory(workflow=wf)
        wf_factories.TaskGroupTaskFactory(
            task_group=task_group,
            title='task1',
            start_date=datetime.now(),
            end_date=datetime.now() + timedelta(7)
        )
      data = workflow_api.get_cycle_post_dict(wf)
      self.api.post(all_models.Cycle, data)
      wf = all_models.Workflow.query.filter_by(slug=wf_slug).one()
      self.cycle = all_models.Cycle.query.filter_by(workflow_id=wf.id).one()
      self.ctask = all_models.CycleTaskGroupObjectTask.query.filter_by(
          cycle_id=self.cycle.id).first()
Exemple #26
0
    def setUp(self):
        super(WorkflowTestCase, self).setUp()
        self.api = Api()
        self.generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        self.random_objects = self.object_generator.generate_random_objects()
    def setUp(self):  # noqa
        TestCase.setUp(self)
        self.api = Api()
        self.generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        self.random_objects = self.object_generator.generate_random_objects()
        self.create_backlog_workflow()
Exemple #28
0
  def setUp(self):
    # old-style class
    TestCase.setUp(self)
    self.api = Api()
    self.generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.random_objects = self.object_generator.generate_random_objects()
  def setUp(self):  # noqa
    super(TestBacklogWorkflow, self).setUp()
    self.api = Api()
    self.generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.random_objects = self.object_generator.generate_random_objects()
    self.create_backlog_workflow()
  def setUp(self):
    super(TestBasicWorkflowActions, self).setUp()
    self.api = Api()
    self.generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.random_objects = self.object_generator.generate_random_objects()
    self.create_test_cases()
Exemple #31
0
  def activate(self):
    """ activate workflows just once after the class has been initialized

    This should be in setUpClass method, but we can't access the server
    context from there."""
    gen = WorkflowsGenerator()

    # generate cycle for the only one time wf
    wf1 = Workflow.query.filter_by(status="Draft", slug="wf-1").first()
    if wf1:
      gen.generate_cycle(wf1)

    # Only workflows with at least one task group could be activated
    workflows = db.session.query(Workflow).join(TaskGroup).filter(
        Workflow.id == TaskGroup.workflow_id,
        Workflow.status == 'Draft').all()
    for workflow in workflows:
      gen.activate_workflow(workflow)
Exemple #32
0
  def setUp(self):
    """Set up."""
    super(TestNotificationsHistory, self).setUp()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")

    self._create_test_cases()
  def setUp(self):
    super(TestRecurringCycleNotifications, self).setUp()
    self.api = Api()
    self.generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    _, self.assignee = self.object_generator.generate_person(
        user_role="Administrator")

    self.create_test_cases()
Exemple #34
0
    def setUp(self):
        TestCase.setUp(self)
        self.api = Api()
        self.wf_generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()

        self.random_objects = self.object_generator.generate_random_objects()
        self.random_people = self.object_generator.generate_random_people(
            user_role="Administrator")
        self.create_test_cases()

        def init_decorator(init):
            def new_init(self, *args, **kwargs):
                init(self, *args, **kwargs)
                if hasattr(self, "created_at"):
                    self.created_at = datetime.now()

            return new_init

        Notification.__init__ = init_decorator(Notification.__init__)
Exemple #35
0
  def setUp(self):
    super(TestOneTimeWfEndDateChange, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    Notification.query.delete()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")
    self.create_test_cases()

    def init_decorator(init):
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = datetime.now()
      return new_init

    Notification.__init__ = init_decorator(Notification.__init__)
  def setUp(self):
    super(TestMonthlyWorkflowNotification, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.random_objects = self.object_generator.generate_random_objects()
    _, self.person_1 = self.object_generator.generate_person(
        user_role="Administrator")
    _, self.person_2 = self.object_generator.generate_person(
        user_role="Administrator")
    self.create_test_cases()

    def init_decorator(init):
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = dt.datetime.now()
      return new_init

    Notification.__init__ = init_decorator(Notification.__init__)
Exemple #37
0
    def setUp(self):
        super(TestCycleTaskStatusChange, self).setUp()
        self.api = Api()
        self.wf_generator = WorkflowsGenerator()
        self.object_generator = ObjectGenerator()
        all_models.Notification.query.delete()
        self.random_objects = self.object_generator.generate_random_objects(2)
        self.user = self.create_user_with_role(role="Administrator")
        self.secondary_assignee = self.create_user_with_role(role="Reader")
        self.create_test_cases()

        def init_decorator(init):
            def new_init(self, *args, **kwargs):
                init(self, *args, **kwargs)
                if hasattr(self, "created_at"):
                    self.created_at = datetime.now()

            return new_init

        all_models.Notification.__init__ = init_decorator(
            all_models.Notification.__init__)
  def setUp(self):
    super(TestTaskOverdueNotificationsUsingAPI, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    models.Notification.query.delete()

    self._fix_notification_init()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")
    self._create_test_cases()
 def setUp(self):
   super(TestCycleTaskImportUpdate, self).setUp()
   self.wf_generator = WorkflowsGenerator()
   self.object_generator = ObjectGenerator()
   self.random_objects = self.object_generator.generate_random_objects(2)
   _, self.person_1 = self.object_generator.generate_person(
       user_role="Administrator")
   self.ftime_active = "2016-07-01"
   self.ftime_historical = "2014-05-01"
   self._create_test_cases_data()
   # It is needed because cycle-tasks are generated automatically with
   # 'slug' based on auto_increment 'id' field.
   # At start of each test we suppose that created cycle-task's 'slug'
   # lie in range from 1 to 10.
   db.session.execute('ALTER TABLE cycle_task_group_object_tasks '
                      'AUTO_INCREMENT = 1')
Exemple #40
0
  def setUp(self):
    super(TestWorkflowAclPropagation, self).setUp()
    self.generator = WorkflowsGenerator()
    with factories.single_commit():
      self.people_ids = [
          factories.PersonFactory(
              name="user {}".format(i),
              email="user{}@example.com".format(i),
          ).id
          for i in range(10)
      ]

    acr = all_models.AccessControlRole
    self.acr_name_map = dict(db.session.query(
        acr.name,
        acr.id,
    ).filter(
        acr.object_type == all_models.Workflow.__name__,
    ))

    self.weekly_wf = {
        "title": "weekly thingy",
        "description": "start this many a time",
        "access_control_list": [
            {
                "ac_role_id": self.acr_name_map["Admin"],
                "person": {"type": "Person", "id": self.people_ids[i]},
            }
            for i in range(5)
        ],
        "unit": "week",
        "repeat_every": 1,
        "task_groups": [{
            "title": "weekly task group",
            "task_group_tasks": [
                {
                    "title": "weekly task {}".format(i),
                    "start_date": datetime.date(2016, 6, 10),
                    "end_date": datetime.date(2016, 6, 13),
                }
                for i in range(3)
            ]},
        ]
    }
  def setUp(self):
    super(TestNotificationsForDeletedObjects, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    Notification.query.delete()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")
    self.create_test_cases()

    def init_decorator(init):
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = datetime.now()
      return new_init

    Notification.__init__ = init_decorator(Notification.__init__)
Exemple #42
0
  def setUp(self):
    super(TestOneTimeWorkflowNotification, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.random_objects = self.object_generator.generate_random_objects()
    self.random_people = self.object_generator.generate_random_people(
        user_role="Administrator"
    )
    self.create_test_cases()

    def init_decorator(init):
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = datetime.now()
      return new_init

    Notification.__init__ = init_decorator(Notification.__init__)
Exemple #43
0
    def activate(self):
        """ activate workflows just once after the class has been initialized

    This should be in setUpClass method, but we can't access the server
    context from there."""
        gen = WorkflowsGenerator()

        # generate cycle for the only one time wf
        wf1 = Workflow.query.filter_by(status="Draft", slug="wf-1").first()
        if wf1:
            gen.generate_cycle(wf1)

        workflows = Workflow.query.filter_by(status="Draft").all()
        for wf in workflows:
            gen.activate_workflow(wf)
    def activate(self):
        """ activate workflows just once after the class has been initialized

    This should be in setUpClass method, but we can't access the server
    context from there."""
        gen = WorkflowsGenerator()

        # generate cycle for the only one time wf
        wf1 = Workflow.query.filter_by(status="Draft", slug="wf-1").first()
        if wf1:
            gen.generate_cycle(wf1)

        # Only workflows with at least one task group could be activated
        workflows = db.session.query(Workflow).join(TaskGroup).filter(
            Workflow.id == TaskGroup.workflow_id,
            Workflow.status == 'Draft').all()
        for workflow in workflows:
            gen.activate_workflow(workflow)
  def setUp(self):
    super(TestWorkflowCycleStatePropagation, self).setUp()
    self.api = Api()
    self.generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.weekly_wf = {
        "title": "weekly thingy",
        "description": "start this many a time",
        "unit": "week",
        "repeat_every": 1,
        "task_groups": [{
            "title": "weekly task group",
            "task_group_tasks": [{
                "title": "weekly task 1",
                "start_date": dtm.date(2016, 6, 10),
                "end_date": dtm.date(2016, 6, 13),
            }, {
                "title": "weekly task 1",
                "start_date": dtm.date(2016, 6, 10),
                "end_date": dtm.date(2016, 6, 13),
            }]},
        ]
    }
class TestOneTimeWfEndDateChange(TestCase):

  """ This class contains simple one time workflow tests that are not
  in the gsheet test grid
  """

  def setUp(self):
    super(TestOneTimeWfEndDateChange, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    Notification.query.delete()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")
    self.create_test_cases()

    def init_decorator(init):
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = datetime.now()
      return new_init

    Notification.__init__ = init_decorator(Notification.__init__)

  @patch("ggrc.notifications.common.send_email")
  def test_no_date_change(self, mock_mail):
    def get_person(person_id):
      return db.session.query(Person).filter(Person.id == person_id).one()

    with freeze_time("2015-04-10 03:21:34"):
      _, workflow = self.wf_generator.generate_workflow(
          self.one_time_workflow_1)

      _, cycle = self.wf_generator.generate_cycle(workflow)
      self.wf_generator.activate_workflow(workflow)

    with freeze_time("2015-04-11 03:21:34"):
      user = get_person(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn("cycle_started", notif_data[user.email])

    with freeze_time("2015-05-02 03:21:34"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("cycle_started", notif_data[user.email])
      self.assertNotIn("due_in", notif_data[user.email])
      self.assertNotIn("due_today", notif_data[user.email])

    with freeze_time("2015-05-02 03:21:34"):
      common.send_daily_digest_notifications()
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

      # one email to owner and one to assigne
      self.assertEqual(mock_mail.call_count, 2)

    with freeze_time("2015-05-04 03:21:34"):  # one day before due date
      _, notif_data = common.get_daily_notifications()
      user = get_person(self.user.id)
      self.assertIn("due_in", notif_data[user.email])
      self.assertEqual(len(notif_data[user.email]["due_in"]), 2)

    with freeze_time("2015-05-04 03:21:34"):  # one day before due date
      common.send_daily_digest_notifications()
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

      # one email to owner and one to assigne
      self.assertEqual(mock_mail.call_count, 3)

    with freeze_time("2015-05-05 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertIn("due_today", notif_data[user.email])
      self.assertEqual(len(notif_data[user.email]["due_today"]), 2)

  @patch("ggrc.notifications.common.send_email")
  def test_move_end_date_to_future(self, mock_mail):
    """
    test moving the end date to the future, befor due_in and due_today
    notifications have been sent
    """
    def get_person(person_id):
      return db.session.query(Person).filter(Person.id == person_id).one()

    with freeze_time("2015-04-10 03:21:34"):
      _, workflow = self.wf_generator.generate_workflow(
          self.one_time_workflow_1)

      _, cycle = self.wf_generator.generate_cycle(workflow)
      self.wf_generator.activate_workflow(workflow)

    with freeze_time("2015-04-11 03:21:34"):
      user = get_person(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn("cycle_started", notif_data[user.email])

    with freeze_time("2015-05-02 03:21:34"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("cycle_started", notif_data[user.email])
      self.assertNotIn("due_in", notif_data[user.email])
      self.assertNotIn("due_today", notif_data[user.email])

    with freeze_time("2015-05-02 03:21:34"):
      common.send_daily_digest_notifications()
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

      # one email to owner and one to assigne
      self.assertEqual(mock_mail.call_count, 2)

    with freeze_time("2015-05-03 03:21:34"):
      cycle = Cycle.query.get(cycle.id)
      task1 = CycleTaskGroupObjectTask.query.get(
          cycle.cycle_task_group_object_tasks[0].id)
      task2 = CycleTaskGroupObjectTask.query.get(
          cycle.cycle_task_group_object_tasks[1].id)

      self.wf_generator.modify_object(
          task1, data={"end_date": date(2015, 5, 15)})
      self.wf_generator.modify_object(
          task2, data={"end_date": date(2015, 5, 15)})

    with freeze_time("2015-05-04 03:21:34"):  # one day befor due date
      _, notif_data = common.get_daily_notifications()
      user = get_person(self.user.id)
      self.assertEqual(notif_data, {})

    with freeze_time("2015-05-05 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

    with freeze_time("2015-05-14 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("due_in", notif_data[user.email])
      self.assertEqual(len(notif_data[user.email]["due_in"]),
                       len(self.random_objects))

    with freeze_time("2015-05-15 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)

      # yesterdays mail has not been sent
      self.assertIn("due_in", notif_data[user.email])

      self.assertIn("due_today", notif_data[user.email])
      self.assertEqual(len(notif_data[user.email]["due_today"]),
                       len(self.random_objects))

  @patch("ggrc.notifications.common.send_email")
  def test_move_end_date_to_past(self, mock_mail):
    def get_person(person_id):
      return db.session.query(Person).filter(Person.id == person_id).one()

    with freeze_time("2015-04-10 03:21:34"):
      _, workflow = self.wf_generator.generate_workflow(
          self.one_time_workflow_1)

      _, cycle = self.wf_generator.generate_cycle(workflow)
      self.wf_generator.activate_workflow(workflow)

    with freeze_time("2015-05-02 03:21:34"):
      common.send_daily_digest_notifications()
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

      # one email to owner and one to assigne
      self.assertEqual(mock_mail.call_count, 2)

    with freeze_time("2015-05-03 03:21:34"):
      cycle = Cycle.query.get(cycle.id)
      task1 = CycleTaskGroupObjectTask.query.get(
          cycle.cycle_task_group_object_tasks[0].id)
      task2 = CycleTaskGroupObjectTask.query.get(
          cycle.cycle_task_group_object_tasks[1].id)

      self.wf_generator.modify_object(
          task1, data={"end_date": date(2015, 5, 1)})
      self.wf_generator.modify_object(
          task2, data={"end_date": date(2015, 5, 1)})

    with freeze_time("2015-05-03 03:21:34"):  # one day befor due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

    with freeze_time("2015-05-04 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

    with freeze_time("2015-05-05 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

  @patch("ggrc.notifications.common.send_email")
  def test_move_end_date_to_today(self, mock_mail):
    def get_person(person_id):
      return db.session.query(Person).filter(Person.id == person_id).one()

    with freeze_time("2015-04-10 03:21:34"):
      _, workflow = self.wf_generator.generate_workflow(
          self.one_time_workflow_1)

      _, cycle = self.wf_generator.generate_cycle(workflow)
      self.wf_generator.activate_workflow(workflow)

    with freeze_time("2015-05-02 03:21:34"):
      common.send_daily_digest_notifications()
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

      # one email to owner and one to assigne
      self.assertEqual(mock_mail.call_count, 2)

    with freeze_time("2015-05-03 03:21:34"):
      cycle = Cycle.query.get(cycle.id)
      task1 = CycleTaskGroupObjectTask.query.get(
          cycle.cycle_task_group_object_tasks[0].id)
      task2 = CycleTaskGroupObjectTask.query.get(
          cycle.cycle_task_group_object_tasks[1].id)

      self.wf_generator.modify_object(
          task1, data={"end_date": date(2015, 5, 3)})
      self.wf_generator.modify_object(
          task2, data={"end_date": date(2015, 5, 4)})

    with freeze_time("2015-05-03 03:21:34"):  # one day befor due date
      user = get_person(self.user.id)
      _, notif_data = common.get_daily_notifications()

      self.assertNotEquals(notif_data, {})
      self.assertIn(user.email, notif_data)
      self.assertIn("due_today", notif_data[user.email])
      self.assertIn("due_in", notif_data[user.email])
      self.assertEqual(len(notif_data[user.email]["due_today"]), 1)

      common.send_daily_digest_notifications()

    with freeze_time("2015-05-04 03:21:34"):  # due date
      user = get_person(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("due_today", notif_data[user.email])
      self.assertNotIn("due_in", notif_data[user.email])
      common.send_daily_digest_notifications()

    with freeze_time("2015-05-05 03:21:34"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(notif_data, {})

  def create_test_cases(self):
    def person_dict(person_id):
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }

    self.one_time_workflow_1 = {
        "title": "one time test workflow",
        "notify_on_change": True,
        "description": "some test workflow",
        "owners": [person_dict(self.user.id)],
        "task_groups": [{
            "title": "one time task group",
            "contact": person_dict(self.user.id),
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "contact": person_dict(self.user.id),
                "start_date": date(2015, 5, 1),  # friday
                "end_date": date(2015, 5, 5),
            }, {
                "title": "task 2",
                "description": "some task 2",
                "contact": person_dict(self.user.id),
                "start_date": date(2015, 5, 1),  # friday
                "end_date": date(2015, 5, 5),
            }],
            "task_group_objects": self.random_objects
        }]
    }
Exemple #47
0
class TestOneTimeWorkflowNotification(TestCase):

  """ This class contains simple one time workflow tests that are not
  in the gsheet test grid
  """

  def setUp(self):
    super(TestOneTimeWorkflowNotification, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.random_objects = self.object_generator.generate_random_objects()
    self.random_people = self.object_generator.generate_random_people(
        user_role="Administrator"
    )
    self.create_test_cases()

    def init_decorator(init):
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = datetime.now()
      return new_init

    Notification.__init__ = init_decorator(Notification.__init__)

  def test_one_time_wf_activate(self):
    def get_person(person_id):
      return db.session.query(Person).filter(Person.id == person_id).one()
    with freeze_time("2015-04-10"):
      _, wf = self.wf_generator.generate_workflow(self.one_time_workflow_1)

      _, cycle = self.wf_generator.generate_cycle(wf)
      self.wf_generator.activate_workflow(wf)

      person_2 = get_person(self.random_people[2].id)

    with freeze_time("2015-04-11"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(person_2.email, notif_data)
      self.assertIn("cycle_started", notif_data[person_2.email])
      self.assertIn(cycle.id, notif_data[person_2.email]["cycle_started"])
      self.assertIn("my_tasks",
                    notif_data[person_2.email]["cycle_data"][cycle.id])

      person_1 = get_person(self.random_people[0].id)

    with freeze_time("2015-05-03"):  # two days befor due date
      _, notif_data = common.get_daily_notifications()
      self.assertIn(person_1.email, notif_data)
      self.assertNotIn("due_in", notif_data[person_1.email])
      self.assertNotIn("due_today", notif_data[person_1.email])

    with freeze_time("2015-05-04"):  # one day befor due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(len(notif_data[person_1.email]["due_in"]), 1)

    with freeze_time("2015-05-05"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(len(notif_data[person_1.email]["due_today"]), 1)

  @patch("ggrc.notifications.common.send_email")
  def test_one_time_wf_activate_single_person(self, mock_mail):

    with freeze_time("2015-04-10"):
      user = "******"
      _, wf = self.wf_generator.generate_workflow(
          self.one_time_workflow_single_person)

      _, cycle = self.wf_generator.generate_cycle(wf)
      self.wf_generator.activate_workflow(wf)

    with freeze_time("2015-04-11"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn("cycle_started", notif_data[user])
      self.assertIn(cycle.id, notif_data[user]["cycle_started"])
      self.assertIn("my_tasks", notif_data[user]["cycle_data"][cycle.id])
      self.assertIn("cycle_tasks", notif_data[user]["cycle_data"][cycle.id])
      self.assertIn(
          "my_task_groups", notif_data[user]["cycle_data"][cycle.id])
      self.assertIn("cycle_url", notif_data[user]["cycle_started"][cycle.id])

      cycle = Cycle.query.get(cycle.id)
      cycle_data = notif_data[user]["cycle_data"][cycle.id]
      for task in cycle.cycle_task_group_object_tasks:
        self.assertIn(task.id, cycle_data["my_tasks"])
        self.assertIn(task.id, cycle_data["cycle_tasks"])
        self.assertIn("title", cycle_data["my_tasks"][task.id])
        self.assertIn("title", cycle_data["cycle_tasks"][task.id])
        self.assertIn("cycle_task_url", cycle_data["cycle_tasks"][task.id])

    with freeze_time("2015-05-03"):  # two days before due date
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user, notif_data)
      self.assertNotIn("due_in", notif_data[user])
      self.assertNotIn("due_today", notif_data[user])

    with freeze_time("2015-05-04"):  # one day before due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(len(notif_data[user]["due_in"]), 2)

    with freeze_time("2015-05-05"):  # due date
      _, notif_data = common.get_daily_notifications()
      self.assertEqual(len(notif_data[user]["due_today"]), 2)

      common.send_daily_digest_notifications()
      self.assertEqual(mock_mail.call_count, 1)

  def create_test_cases(self):
    def person_dict(person_id):
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }

    role_id = all_models.AccessControlRole.query.filter(
        all_models.AccessControlRole.name == "Task Assignees",
        all_models.AccessControlRole.object_type == "TaskGroupTask",
    ).one().id
    self.one_time_workflow_1 = {
        "title": "one time test workflow",
        "description": "some test workflow",
        "notify_on_change": True,
        # admin will be current user with id == 1
        "task_groups": [{
            "title": "one time task group",
            "contact": person_dict(self.random_people[2].id),
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.random_people[0].id)
                ],
                "start_date": date(2015, 5, 1),  # friday
                "end_date": date(2015, 5, 5),
            }, {
                "title": "task 2",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.random_people[1].id)
                ],
                "start_date": date(2015, 5, 4),
                "end_date": date(2015, 5, 7),
            }],
            "task_group_objects": self.random_objects[:2]
        }, {
            "title": "another one time task group",
            "contact": person_dict(self.random_people[2].id),
            "task_group_tasks": [{
                "title": "task 1 in tg 2",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.random_people[0].id)
                ],
                "start_date": date(2015, 5, 8),  # friday
                "end_date": date(2015, 5, 12),
            }, {
                "title": "task 2 in tg 2",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.random_people[2].id)
                ],
                "start_date": date(2015, 5, 1),  # friday
                "end_date": date(2015, 5, 5),
            }],
            "task_group_objects": []
        }]
    }

    user = Person.query.filter(Person.email == "*****@*****.**").one().id

    self.one_time_workflow_single_person = {
        "title": "one time test workflow",
        "notify_on_change": True,
        "description": "some test workflow",
        # admin will be current user with id == 1
        "task_groups": [{
            "title": "one time task group",
            "contact": person_dict(user),
            "task_group_tasks": [{
                "title": u"task 1 \u2062 WITH AN UMBRELLA ELLA ELLA. \u2062",
                "description": "some task. ",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user)
                ],
                "start_date": date(2015, 5, 1),  # friday
                "end_date": date(2015, 5, 5),
            }, {
                "title": "task 2",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user)
                ],
                "start_date": date(2015, 5, 4),
                "end_date": date(2015, 5, 7),
            }],
            "task_group_objects": self.random_objects[:2]
        }, {
            "title": "another one time task group",
            "contact": person_dict(user),
            "task_group_tasks": [{
                "title": u"task 1 \u2062 WITH AN UMBRELLA ELLA ELLA. \u2062",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user)
                ],
                "start_date": date(2015, 5, 8),  # friday
                "end_date": date(2015, 5, 12),
            }, {
                "title": "task 2 in tg 2",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user)
                ],
                "start_date": date(2015, 5, 1),  # friday
                "end_date": date(2015, 5, 5),
            }],
            "task_group_objects": []
        }]
    }
class TestRecurringCycleNotifications(TestCase):

  def setUp(self):
    super(TestRecurringCycleNotifications, self).setUp()
    self.api = Api()
    self.generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    _, self.assignee = self.object_generator.generate_person(
        user_role="Administrator")

    self.create_test_cases()

  def tearDown(self):
    pass

  def test_cycle_starts_in_less_than_X_days(self):

    with freeze_time("2015-02-01"):
      _, wf = self.generator.generate_workflow(self.quarterly_wf_1)
      response, wf = self.generator.activate_workflow(wf)

      self.assert200(response)

      assignee = Person.query.get(self.assignee.id)

    with freeze_time("2015-01-01"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(assignee.email, notif_data)

    with freeze_time("2015-01-29"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(assignee.email, notif_data)

    with freeze_time("2015-02-01"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(assignee.email, notif_data)

  # TODO: this should mock google email api.
  @patch("ggrc.notifications.common.send_email")
  def test_marking_sent_notifications(self, mail_mock):
    mail_mock.return_value = True

    with freeze_time("2015-02-01"):
      _, wf = self.generator.generate_workflow(self.quarterly_wf_1)
      response, wf = self.generator.activate_workflow(wf)

      self.assert200(response)

      assignee = Person.query.get(self.assignee.id)

    with freeze_time("2015-01-01"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(assignee.email, notif_data)

    with freeze_time("2015-01-29"):
      common.send_daily_digest_notifications()
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(assignee.email, notif_data)

    with freeze_time("2015-02-01"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(assignee.email, notif_data)

  def create_test_cases(self):
    def person_dict(person_id):
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }

    self.quarterly_wf_1 = {
        "title": "quarterly wf 1",
        "description": "",
        # admin will be current user with id == 1
        "unit": "month",
        "repeat_every": 3,
        "notify_on_change": True,
        "task_groups": [{
            "title": "tg_1",
            "contact": person_dict(self.assignee.id),
            "task_group_tasks": [{
                "contact": person_dict(self.assignee.id),
                "description": factories.random_str(100),
            },
            ],
        },
        ]
    }

    self.all_workflows = [
        self.quarterly_wf_1,
    ]
class TestBasicWorkflowActions(TestCase):
  """
  Tests for basic workflow actions
  """
  def setUp(self):
    super(TestBasicWorkflowActions, self).setUp()
    self.api = Api()
    self.generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.random_objects = self.object_generator.generate_random_objects()
    self.create_test_cases()

  def tearDown(self):
    pass

  def test_create_workflows(self):
    _, wflow = self.generator.generate_workflow(self.one_time_workflow_1)
    self.assertIsInstance(wflow, Workflow)

    task_groups = db.session.query(TaskGroup)\
        .filter(TaskGroup.workflow_id == wflow.id).all()

    self.assertEqual(len(task_groups),
                     len(self.one_time_workflow_1["task_groups"]))

  def test_workflows(self):
    for workflow in self.all_workflows:
      _, wflow = self.generator.generate_workflow(workflow)
      self.assertIsInstance(wflow, Workflow)

      task_groups = db.session.query(TaskGroup)\
          .filter(TaskGroup.workflow_id == wflow.id).all()

      self.assertEqual(len(task_groups),
                       len(workflow["task_groups"]))

  def test_activate_wf(self):
    for workflow in self.all_workflows:
      _, wflow = self.generator.generate_workflow(workflow)
      response, wflow = self.generator.activate_workflow(wflow)

      self.assert200(response)

  def test_one_time_workflow_edits(self):
    _, wflow = self.generator.generate_workflow(self.one_time_workflow_1)

    wf_dict = {"title": "modified one time wf"}
    self.generator.modify_workflow(wflow, data=wf_dict)

    modified_wf = db.session.query(Workflow).filter(
        Workflow.id == wflow.id).one()
    self.assertEqual(wf_dict["title"], modified_wf.title)

  def test_one_time_wf_activate(self):
    _, wflow = self.generator.generate_workflow(self.one_time_workflow_1)
    self.generator.generate_cycle(wflow)
    self.generator.activate_workflow(wflow)

    tasks = [len(tg.get("task_group_tasks", []))
             for tg in self.one_time_workflow_1["task_groups"]]

    cycle_tasks = db.session.query(CycleTaskGroupObjectTask).join(
        Cycle).join(Workflow).filter(Workflow.id == wflow.id).all()
    active_wf = db.session.query(Workflow).filter(
        Workflow.id == wflow.id).one()

    self.assertEqual(sum(tasks), len(cycle_tasks))
    self.assertEqual(active_wf.status, "Active")

  def test_one_time_wf_state_transition_dates(self):
    _, wflow = self.generator.generate_workflow(self.one_time_workflow_1)
    self.generator.generate_cycle(wflow)
    self.generator.activate_workflow(wflow)

    cycle_tasks = db.session.query(CycleTaskGroupObjectTask).join(
        Cycle).join(Workflow).filter(Workflow.id == wflow.id).all()
    with freeze_time("2015-6-9 13:00:00"):
      today = dtm.datetime.now()
      transitions = [
          ("InProgress", None, None),
          ("Finished", today, None),
          ("Declined", None, None),
          ("Finished", today, None),
          ("Verified", today, today),
          ("Finished", today, None),
      ]
      # Iterate over possible transitions and check if dates got set correctly
      for (status, expected_finished, expected_verified) in transitions:
        cycle_task = cycle_tasks[0]
        _, task = self.generator.modify_object(cycle_task, {"status": status})
        self.assertEqual(task.finished_date, expected_finished)
        self.assertEqual(task.verified_date, expected_verified)

  def test_delete_calls(self):
    _, workflow = self.generator.generate_workflow()
    self.generator.generate_task_group(workflow)
    _, task_group = self.generator.generate_task_group(workflow)
    task_groups = db.session.query(TaskGroup).filter(
        TaskGroup.workflow_id == workflow.id).all()
    self.assertEqual(len(task_groups), 2)

    response = self.generator.api.delete(task_group)
    self.assert200(response)

    task_groups = db.session.query(TaskGroup).filter(
        TaskGroup.workflow_id == workflow.id).all()
    self.assertEqual(len(task_groups), 1)

  def create_test_cases(self):

    self.quarterly_wf_1 = {
        "title": "quarterly wf 1",
        "description": "",
        "unit": "month",
        "repeat_every": 3,
        "task_groups": [{
            "title": "tg_1",
            "task_group_tasks": [{
                "description": factories.random_str(100),
            }, {
                "description": factories.random_str(100),
            }, {
                "description": factories.random_str(100),
            },
            ],
        },
        ]
    }

    self.weekly_wf_1 = {
        "title": "weekly thingy",
        "description": "start this many a time",
        "unit": "week",
        "repeat_every": 1,
        "task_groups": [{
            "title": "tg_2",
            "task_group_tasks": [{
                "description": factories.random_str(100),
            }, {
                "title": "monday task",
            }, {
                "title": "weekend task",
            },
            ],
            "task_group_objects": self.random_objects
        },
        ]
    }

    self.one_time_workflow_1 = {
        "title": "one time wf test",
        "description": "some test workflow",
        "task_groups": [{
            "title": "tg_1",
            "task_group_tasks": [{}, {}, {}]
        }, {
            "title": "tg_2",
            "task_group_tasks": [{
                "description": factories.random_str(100)
            }, {}
            ],
            "task_group_objects": self.random_objects[:2]
        }, {
            "title": "tg_3",
            "task_group_tasks": [{
                "title": "simple task 1",
                "description": factories.random_str(100)
            }, {
                "title": factories.random_str(),
                "description": factories.random_str(100)
            }, {
                "title": factories.random_str(),
                "description": factories.random_str(100)
            }
            ],
            "task_group_objects": self.random_objects
        }
        ]
    }
    self.one_time_workflow_2 = {
        "title": "test_wf_title",
        "description": "some test workflow",
        "task_groups": [
            {
                "title": "tg_1",
                "task_group_tasks": [{}, {}, {}]
            },
            {
                "title": "tg_2",
                "task_group_tasks": [{
                    "description": factories.random_str(100)
                }, {}],
                "task_group_objects": self.random_objects[:2]
            },
            {
                "title": "tg_3",
                "task_group_tasks": [{
                    "title": "simple task 1",
                    "description": factories.random_str(100)
                }, {
                    "title": factories.random_str(),
                    "description": factories.random_str(100)
                }, {
                    "title": factories.random_str(),
                    "description": factories.random_str(100)
                }],
                "task_group_objects": []
            }
        ]
    }

    self.monthly_workflow_1 = {
        "title": "monthly test wf",
        "description": "start this many a time",
        "unit": "month",
        "repeat_every": 1,
        "task_groups": [
            {
                "title": "tg_2",
                "task_group_tasks": [{
                    "description": factories.random_str(100),
                }, {
                    "title": "monday task",
                }, {
                    "title": "weekend task",
                }],
                "task_group_objects": self.random_objects
            },
        ]
    }
    self.all_workflows = [
        self.one_time_workflow_1,
        self.one_time_workflow_2,
        self.weekly_wf_1,
        self.monthly_workflow_1,
        self.quarterly_wf_1,
    ]
class TestWorkflowsCycleGeneration(TestCase):
  """
  Tests for Cycle generation logic
  """
  def setUp(self):
    super(TestWorkflowsCycleGeneration, self).setUp()
    self.api = Api()
    self.generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

  def tearDown(self):
    pass

  @ddt.data(
      True, False
  )
  def test_recurring_without_tgts_skip(self, has_tg):
    """Test that Active Workflow without TGTs is skipped on cron job"""
    with freeze_time(dtm.date(2017, 9, 25)):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=1,
                                                unit=Workflow.MONTH_UNIT)
        workflow_id = workflow.id
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=dtm.date(2017, 9, 26),
            end_date=dtm.date(2017, 9, 26) + dtm.timedelta(days=4))
      self.generator.activate_workflow(workflow)
      active_wf = db.session.query(Workflow).filter(
          Workflow.id == workflow_id).one()
      self.assertEqual(active_wf.next_cycle_start_date, dtm.date(2017, 9, 26))
      self.assertEqual(active_wf.recurrences, True)
      self.assertEqual(len(active_wf.cycles), 0)
      TaskGroupTask.query.delete()
      if not has_tg:
        TaskGroup.query.delete()
      db.session.commit()

    with freeze_time(dtm.date(2017, 10, 25)):
      start_recurring_cycles()
      active_wf = db.session.query(Workflow).filter(
          Workflow.id == workflow_id).one()
      self.assertEqual(active_wf.next_cycle_start_date, dtm.date(2017, 9, 26))
      self.assertEqual(active_wf.recurrences, True)
      self.assertEqual(len(active_wf.cycles), 0)

  @ddt.data(
      # (expected, setup_date),
      (dtm.date(2017, 2, 28), dtm.date(2017, 2, 28)),
      (dtm.date(2017, 3, 3), dtm.date(2017, 3, 3)),
      (dtm.date(2017, 8, 4), dtm.date(2017, 8, 5)),
      (dtm.date(2017, 7, 21), dtm.date(2017, 7, 22)),
  )
  @ddt.unpack
  def test_one_time_wf_start_date_shifting(self, expected, setup_date):
    """Test case for correct cycle task start_ dates for one_time wf"""
    with factories.single_commit():
      workflow = wf_factories.WorkflowFactory()
      group = wf_factories.TaskGroupFactory(workflow=workflow)
      wf_factories.TaskGroupTaskFactory(
          task_group=group,
          start_date=setup_date,
          end_date=setup_date + dtm.timedelta(days=4))
    self.generator.generate_cycle(workflow)
    self.generator.activate_workflow(workflow)
    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    self.assertEqual(1,
                     len(active_wf.cycles[0].cycle_task_group_object_tasks))
    cycle_task = active_wf.cycles[0].cycle_task_group_object_tasks[0]
    adj_start_date = cycle_task.start_date
    self.assertEqual(expected, adj_start_date)

  @ddt.data(
      # (expected, end_date),
      (dtm.date(2017, 2, 28), dtm.date(2017, 2, 28)),
      (dtm.date(2017, 3, 3), dtm.date(2017, 3, 3)),
      (dtm.date(2017, 8, 4), dtm.date(2017, 8, 5)),
      (dtm.date(2017, 7, 21), dtm.date(2017, 7, 22)),
  )
  @ddt.unpack
  def test_one_time_wf_end_date_shifting(self, expected, setup_date):
    """Test case for correct cycle task end_ dates for one_time wf"""
    with factories.single_commit():
      workflow = wf_factories.WorkflowFactory()
      group = wf_factories.TaskGroupFactory(workflow=workflow)
      wf_factories.TaskGroupTaskFactory(
          task_group=group,
          start_date=setup_date - dtm.timedelta(days=4),
          end_date=setup_date)
    self.generator.generate_cycle(workflow)
    self.generator.activate_workflow(workflow)
    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    self.assertEqual(1,
                     len(active_wf.cycles[0].cycle_task_group_object_tasks))
    cycle_task = active_wf.cycles[0].cycle_task_group_object_tasks[0]
    adj_end_date = cycle_task.end_date
    self.assertEqual(expected, adj_end_date)

  # pylint: disable=too-many-arguments
  @ddt.data(
      # (expected, setup_date, freeze_date, repeat_every, unit),
      (dtm.date(2017, 3, 31), dtm.date(2017, 2, 28), dtm.date(2017, 4, 1), 1,
       Workflow.MONTH_UNIT),
      (dtm.date(2016, 3, 28), dtm.date(2016, 2, 28), dtm.date(2016, 4, 1), 1,
       Workflow.MONTH_UNIT),
      (dtm.date(2017, 2, 28), dtm.date(2017, 1, 31), dtm.date(2017, 3, 31), 1,
       Workflow.MONTH_UNIT),
      (dtm.date(2017, 3, 17), dtm.date(2017, 3, 10), dtm.date(2017, 3, 24), 1,
       Workflow.WEEK_UNIT),
      (dtm.date(2017, 2, 28), dtm.date(2016, 2, 29), dtm.date(2017, 3, 29), 12,
       Workflow.MONTH_UNIT),
      (dtm.date(2017, 4, 28), dtm.date(2017, 1, 31), dtm.date(2017, 5, 31), 3,
       Workflow.MONTH_UNIT),
  )
  @ddt.unpack
  def test_recurring_wf_start_date_shifting(self, expected, setup_date,
                                            freeze_date, repeat_every, unit):
    """Test case for correct next cycle task start_date for recurring wf"""
    with freeze_time(freeze_date):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=repeat_every,
                                                unit=unit)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_date,
            end_date=setup_date + dtm.timedelta(days=4))
      self.generator.activate_workflow(workflow)

    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    cycle_task = active_wf.cycles[1].cycle_task_group_object_tasks[0]
    adj_start_date = cycle_task.start_date
    self.assertEqual(expected, adj_start_date)

  @ddt.data(
      # today is dtm.date(2017, 8, 15), task repeat every
      # (setup_start_date, update_start_date, expected_date),
      (dtm.date(2017, 1, 15), dtm.date(2017, 1, 1), dtm.date(2017, 9, 1)),
      (dtm.date(2017, 1, 15), dtm.date(2017, 1, 5), dtm.date(2017, 9, 5)),
      # new cycle starts on weekend that's why it moves to friday
      (dtm.date(2017, 1, 15), dtm.date(2017, 1, 10), dtm.date(2017, 9, 8)),
      (dtm.date(2017, 1, 15), dtm.date(2017, 8, 15), dtm.date(2017, 9, 15)),
      # new cycle starts on weekend that's why it moves to friday
      (dtm.date(2017, 1, 15), dtm.date(2017, 1, 20), dtm.date(2017, 8, 18)),
      (dtm.date(2017, 1, 15), dtm.date(2017, 1, 25), dtm.date(2017, 8, 25)),
      (dtm.date(2017, 8, 16), dtm.date(2017, 8, 14), dtm.date(2017, 9, 14)),
      (dtm.date(2017, 8, 16), dtm.date(2017, 8, 18), dtm.date(2017, 8, 18)),
      (dtm.date(2017, 8, 14), dtm.date(2017, 8, 18), dtm.date(2017, 8, 18)),
  )
  @ddt.unpack
  def test_recalculate_date(self,
                            setup_start_date,
                            update_start_date,
                            expected_date):
    """Recalculate next cycle start date"""
    with freeze_time(dtm.date(2017, 8, 15)):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=1,
                                                status=Workflow.DRAFT,
                                                unit=Workflow.MONTH_UNIT)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        task_id = wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_start_date,
            end_date=setup_start_date + dtm.timedelta(days=4)).id
      self.generator.activate_workflow(workflow)
      self.api.put(TaskGroupTask.query.get(task_id),
                   {"start_date": update_start_date,
                    "end_date": update_start_date + dtm.timedelta(4)})
    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    self.assertEqual(expected_date, active_wf.next_cycle_start_date)

  def test_recalculate_date_not_started(self):
    """Changing start_date on notstarted workflow will
       not affect next_cycle_start_date"""
    setup_start_date = dtm.date(2017, 1, 15)
    update_start_date = dtm.date(2017, 1, 1)
    with freeze_time(dtm.date(2017, 8, 15)):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=1,
                                                status=Workflow.DRAFT,
                                                unit=Workflow.MONTH_UNIT)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        task_id = wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_start_date,
            end_date=setup_start_date + dtm.timedelta(days=4)).id
        workflow_id = workflow.id
    self.api.put(TaskGroupTask.query.get(task_id),
                 {"start_date": update_start_date,
                  "end_date": update_start_date + dtm.timedelta(4)})
    self.assertIsNone(Workflow.query.get(workflow_id).next_cycle_start_date)

  @ddt.data(
      # (setup_date, freeze_date, repeat_every, unit),
      (dtm.date(2017, 2, 28), dtm.date(2017, 4, 28), 1, Workflow.MONTH_UNIT),
      (dtm.date(2017, 3, 10), dtm.date(2017, 3, 24), 1, Workflow.WEEK_UNIT),
  )
  @ddt.unpack
  def test_recurring_wf_start_date_and_cycles(self, setup_date, freeze_date,
                                              repeat_every, unit):
    """Test case for correct cycle start date and number of cycles"""
    with freeze_time(freeze_date):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=repeat_every,
                                                unit=unit)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_date,
            end_date=setup_date + dtm.timedelta(days=4))
      self.generator.activate_workflow(workflow)

    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    # freeze_date is chosen so that we expect 3 cycles to be generated:
    self.assertEqual(len(active_wf.cycles), 3)
    cycle_task = active_wf.cycles[0].cycle_task_group_object_tasks[0]
    adj_start_date = cycle_task.start_date
    self.assertEqual(setup_date, adj_start_date)

  @ddt.data(
      # (setup_date, freeze_date, repeat_every, unit,
      #  exp_start_date, exp_end_date),
      (dtm.date(2017, 2, 28), dtm.date(2017, 4, 28), 1, Workflow.MONTH_UNIT,
       dtm.date(2017, 2, 27), dtm.date(2017, 3, 3)),
      (dtm.date(2017, 3, 10), dtm.date(2017, 3, 24), 1, Workflow.WEEK_UNIT,
       dtm.date(2017, 3, 9), dtm.date(2017, 3, 14)),
  )
  @ddt.unpack
  def test_recurring_wf_start_end_cycle_dates(self,
                                              setup_date,
                                              freeze_date,
                                              repeat_every,
                                              unit,
                                              exp_start_date,
                                              exp_end_date):
    """Test case for correct cycle start and end dates"""
    with freeze_time(freeze_date):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=repeat_every,
                                                unit=unit)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_date,
            end_date=setup_date + dtm.timedelta(days=4))
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_date - dtm.timedelta(days=1),
            end_date=setup_date + dtm.timedelta(days=3))
      self.generator.activate_workflow(workflow)

    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    # freeze_date is chosen so that we expect 3 cycles to be generated:
    self.assertEqual(len(active_wf.cycles), 3)
    cycle = active_wf.cycles[0]
    self.assertEqual(cycle.start_date, exp_start_date)
    self.assertEqual(cycle.end_date, exp_end_date)

  @ddt.data(
      # (setup_date, freeze_date, repeat_every, unit),
      (dtm.date(2017, 4, 28), dtm.date(2017, 2, 28), 1, Workflow.MONTH_UNIT),
      (dtm.date(2017, 3, 5), dtm.date(2017, 3, 3), 1, Workflow.DAY_UNIT),
      (dtm.date(2017, 3, 24), dtm.date(2017, 3, 10), 1, Workflow.WEEK_UNIT),
  )
  @ddt.unpack
  def test_recurring_wf_future_start_date(self, setup_date, freeze_date,
                                          repeat_every, unit):
    """Test case for 0 number of cycles for future setup date"""
    with freeze_time(freeze_date):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=repeat_every,
                                                unit=unit)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_date,
            end_date=setup_date + dtm.timedelta(days=4))
      self.generator.activate_workflow(workflow)

    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    # no cycles should be generated:
    self.assertEqual(len(active_wf.cycles), 0)

  @ddt.data(
      # (expected_date, expected_num, setup_date,
      #  freeze_date, repeat_every),
      # should not exclude Jul 4
      (dtm.date(2017, 1, 2), 2, dtm.date(2016, 12, 30),
       dtm.date(2017, 1, 2), 1),
      (dtm.date(2017, 1, 4), 2, dtm.date(2016, 12, 30),
       dtm.date(2017, 1, 8), 3),
      (dtm.date(2017, 7, 7), 5, dtm.date(2017, 7, 3),
       dtm.date(2017, 7, 8), 1),
      (dtm.date(2017, 7, 11), 3, dtm.date(2017, 7, 3),
       dtm.date(2017, 7, 12), 3),
      (dtm.date(2017, 7, 10), 2, dtm.date(2017, 7, 3),
       dtm.date(2017, 7, 11), 5),
      (dtm.date(2017, 7, 12), 2, dtm.date(2017, 7, 3),
       dtm.date(2017, 7, 20), 7),
      (dtm.date(2017, 7, 13), 2, dtm.date(2017, 6, 1),
       dtm.date(2017, 7, 31), 30),
  )
  @ddt.unpack
  def test_recurring_daily_workflow_dates(self,
                                          expected_date,
                                          expected_num,
                                          setup_date,
                                          freeze_date,
                                          repeat_every):
    """
    Test for correct weekdays for daily based workflows
    When calculating the dates for daily workflows - only week working days
    are taken into account. So neither start date nor end date can fall on
    a weekend. But can fall on holiday.
    Params:
    expected - last generated cycle start date
    """
    with freeze_time(freeze_date):
      with factories.single_commit():
        workflow = wf_factories.WorkflowFactory(repeat_every=repeat_every,
                                                unit=Workflow.DAY_UNIT)
        group = wf_factories.TaskGroupFactory(workflow=workflow)
        wf_factories.TaskGroupTaskFactory(
            task_group=group,
            start_date=setup_date,
            end_date=setup_date + dtm.timedelta(days=repeat_every))
      self.generator.activate_workflow(workflow)

    active_wf = db.session.query(Workflow).filter(
        Workflow.status == 'Active').one()
    self.assertEqual(len(active_wf.cycles), expected_num)
    last_cycle_task = active_wf.cycles[-1].cycle_task_group_object_tasks[0]
    self.assertEqual(expected_date, last_cycle_task.start_date)
Exemple #51
0
 def setUp(self):
   super(TestPersonResource, self).setUp()
   self.client.get("/login")
   self.api = Api()
   self.generator = WorkflowsGenerator()
Exemple #52
0
class TestPersonResource(TestCase, WithQueryApi):
  """Tests for special people api endpoints."""

  def setUp(self):
    super(TestPersonResource, self).setUp()
    self.client.get("/login")
    self.api = Api()
    self.generator = WorkflowsGenerator()

  @staticmethod
  def _create_users_names_rbac(users):
    """Create name and Creator role for users, created vid PersonFactory"""
    if not users:
      return
    roles = {r.name: r for r in all_models.Role.query.all()}
    for user in users:
      user.name = user.email.split("@")[0]
      rbac_factories.UserRoleFactory(role=roles["Creator"], person=user)

  def assert_profile_get_successful(self, response, expected_datetime):
    """Verify assertions for successful GET profile method"""
    self.assert200(response)
    response_datetime = date_parser.parse(response.json["last_seen_whats_new"])
    self.assertEqual(expected_datetime, response_datetime)

  @freeze_time("2018-05-20 12:23:17")
  def test_profile_get_successful(self):
    """Test person_profile GET method successfully achieves correct data"""
    with factories.single_commit():
      user = factories.PersonFactory()
      self._create_users_names_rbac([user])
    self.api.set_user(person=user)

    response = self.api.client.get("/api/people/{}/profile".format(user.id))
    self.assert_profile_get_successful(response, default_date())

  def test_profile_get_no_profile(self):
    """Test person_profile GET method achieves data with missing profile"""
    with factories.single_commit():
      user = factories.PersonFactory()
      self._create_users_names_rbac([user])
    self.api.set_user(person=user)

    profiles_table = PersonProfile.__table__
    db_request = profiles_table.delete().where(
        profiles_table.c.person_id == user.id)
    db.engine.execute(db_request)
    with freeze_time("2018-05-28 23:30:10"):
      response = self.api.client.get("/api/people/{}/profile".format(user.id))
      self.assert_profile_get_successful(response, default_date())

  def test_profile_get_failed(self):
    """Test person_profiles GET method fails

    Now only logged user can request his profile
    """
    with factories.single_commit():
      valid_user = factories.PersonFactory()
      self._create_users_names_rbac([valid_user])

    response = self.client.get(
        "/api/people/{}/profile".format(valid_user.id))
    # logged with default user during setUp
    self.assert403(response)
    response = self.api.client.get(
        "/api/people/{}/profile".format(valid_user.id))
    # not authorized user
    self.assert403(response)

  def assert_profile_put_successful(self,
                                    response,
                                    correct_response,
                                    user,
                                    new_date):
    """Verify assertions for successful PUT profile method"""
    self.assert200(response)
    self.assertEqual(response.json, correct_response)
    profile = PersonProfile.query.filter_by(person_id=user.id).first()
    self.assertEqual(profile.last_seen_whats_new, date_parser.parse(new_date))

  def test_profile_put_successful(self):
    """Test person_profile PUT method for setting data and correct response"""
    with factories.single_commit():
      user = factories.PersonFactory()
      self._create_users_names_rbac([user])
    self.api.set_user(person=user)

    new_date = "2018-05-20 16:38:17"
    data = {"last_seen_whats_new": new_date}
    correct_response = {"Person": {"id": user.id, "profile": data}}
    response = self.api.client.put("/api/people/{}/profile".format(user.id),
                                   content_type='application/json',
                                   data=json.dumps(data),
                                   headers=[('X-Requested-By', 'Tests')])
    self.assert_profile_put_successful(response,
                                       correct_response,
                                       user,
                                       new_date)

  def test_profile_put_no_profile(self):
    """Test person_profile PUT method for setting data for missing profile"""
    with factories.single_commit():
      user = factories.PersonFactory()
      self._create_users_names_rbac([user])
    self.api.set_user(person=user)

    new_date = "2018-05-20 22:05:17"
    data = {"last_seen_whats_new": new_date}
    correct_response = {"Person": {"id": user.id, "profile": data}}
    profiles_table = PersonProfile.__table__
    db_request = profiles_table.delete().where(
        profiles_table.c.person_id == user.id)
    db.engine.execute(db_request)
    response = self.api.client.put("/api/people/{}/profile".format(user.id),
                                   content_type='application/json',
                                   data=json.dumps(data),
                                   headers=[('X-Requested-By', 'Tests')])
    self.assert_profile_put_successful(response,
                                       correct_response,
                                       user,
                                       new_date)

  def test_profile_put_unauthorized(self):
    """Test person_profiles PUT method fails for unauthorized user"""
    with factories.single_commit():
      user = factories.PersonFactory()
      self._create_users_names_rbac([user])

    new_date = "2018-05-20 22:05:17"
    data = {"last_seen_whats_new": new_date}
    response = self.client.put("/api/people/{}/profile".format(user.id),
                               content_type='application/json',
                               data=json.dumps(data),
                               headers=[('X-Requested-By', 'Tests')])
    # logged with default user during setUp
    self.assert403(response)
    response = self.api.client.put("/api/people/{}/profile".format(user.id),
                                   content_type='application/json',
                                   data=json.dumps(data),
                                   headers=[('X-Requested-By', 'Tests')])
    # not authorized user
    self.assert403(response)

  @ddt.data({"last_seen_whats_new": "NOT A 123 DAT456A"},
            {"other_key": "2018-05-20 22:05:17", "one_more_key": 42})
  def test_profile_put_corrupted_data(self, data):
    """Test person_profiles PUT method fails via incorrect request data

    If request doesn't have "last_seen_whats_new" key or date is incorrect,
      response is code 400 "Bad Request"
    """
    with factories.single_commit():
      user = factories.PersonFactory()
      self._create_users_names_rbac([user])
    self.api.set_user(person=user)

    response = self.api.client.put("/api/people/{}/profile".format(user.id),
                                   content_type='application/json',
                                   data=json.dumps(data),
                                   headers=[('X-Requested-By', 'Tests')])
    # missed key in request
    self.assert400(response)

  def test_task_count_empty(self):
    """Test query count without any workflows and tasks."""
    user = all_models.Person.query.first()
    response = self.client.get("/api/people/{}/task_count".format(user.id))
    self.assertEqual(
        response.json,
        {"open_task_count": 0, "has_overdue": False}
    )

  @ddt.data(
      (True, [
          ("task 1", "Finished", 3, True, 3),
          ("task 1", "Verified", 2, True, 3),
          ("task 2", "Declined", 2, True, 3),
          ("task 2", "Verified", 1, False, 3),
          ("task 2", "Finished", 2, True, 3),
          ("task 3", "Verified", 1, True, 3),
          ("task 2", "Verified", 0, False, 3),
      ]),
      (False, [
          ("task 1", "Finished", 2, True, 3),
          ("task 2", "In Progress", 2, True, 3),
          ("task 2", "Finished", 1, False, 3),
          ("task 3", "Finished", 0, False, 3),
      ]),
  )
  @ddt.unpack
  def test_task_count(self, is_verification_needed, transitions):
    """Test person task counts.

    This tests checks for correct task counts
     - with inactive workflows and
     - with overdue tasks
     - without overdue tasks
     - with finished overdue tasks

    The four checks are done in a single test due to complex differences
    between tests that make ddt cumbersome and the single test also improves
    integration test performance due to slow workflow setup stage.
    """
    # pylint: disable=too-many-locals

    user = all_models.Person.query.first()
    dummy_user = factories.PersonFactory()
    user_id = user.id
    role_id = all_models.AccessControlRole.query.filter(
        all_models.AccessControlRole.name == "Task Assignees",
        all_models.AccessControlRole.object_type == "TaskGroupTask",
    ).one().id
    secondary_role_id = all_models.AccessControlRole.query.filter(
        all_models.AccessControlRole.name == "Task Secondary Assignees",
        all_models.AccessControlRole.object_type == "TaskGroupTask",
    ).one().id

    one_time_workflow = {
        "title": "Person resource test workflow",
        "notify_on_change": True,
        "description": "some test workflow",
        "owners": [create_stub(user)],
        "is_verification_needed": is_verification_needed,
        "task_groups": [{
            "title": "one time task group",
            "contact": create_stub(user),
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user.id),
                    acl_helper.get_acl_json(secondary_role_id, user.id)
                ],
                "start_date": date(2017, 5, 5),
                "end_date": date(2017, 8, 15),
            }, {
                "title": "task 2",
                "description": "some task 3",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user.id),
                    acl_helper.get_acl_json(secondary_role_id, user.id),
                    acl_helper.get_acl_json(secondary_role_id, dummy_user.id)
                ],
                "start_date": date(2017, 5, 5),
                "end_date": date(2017, 9, 16),
            }, {
                "title": "task 3",
                "description": "some task 4",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user.id),
                    acl_helper.get_acl_json(role_id, dummy_user.id)
                ],
                "start_date": date(2017, 6, 5),
                "end_date": date(2017, 10, 16),
            }, {
                "title": "dummy task 4",  # task should not counted
                "description": "some task 4",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, dummy_user.id)],
                "start_date": date(2017, 6, 5),
                "end_date": date(2017, 11, 17),
            }, {
                "title": "dummy task 5",  # task should not counted
                "description": "some task 4",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, dummy_user.id)],
                "start_date": date(2017, 6, 5),
                "end_date": date(2017, 11, 18),
            }],
            "task_group_objects": []
        }]
    }

    inactive_workflow = {
        "title": "Activated workflow with archived cycles",
        "notify_on_change": True,
        "description": "Extra test workflow",
        "owners": [create_stub(user)],
        "task_groups": [{
            "title": "Extra task group",
            "contact": create_stub(user),
            "task_group_tasks": [{
                "title": "not counted existing task",
                "description": "",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user.id)],
                "start_date": date(2017, 5, 5),
                "end_date": date(2017, 8, 15),
            }],
            "task_group_objects": []
        }]
    }

    with freeze_time("2017-10-16 05:09:10"):
      self.client.get("/login")
      # Activate normal one time workflow
      _, workflow = self.generator.generate_workflow(one_time_workflow)
      _, cycle = self.generator.generate_cycle(workflow)
      tasks = {t.title: t for t in cycle.cycle_task_group_object_tasks}
      _, workflow = self.generator.activate_workflow(workflow)

      # Activate and close the inactive workflow
      _, workflow = self.generator.generate_workflow(inactive_workflow)
      _, cycle = self.generator.generate_cycle(workflow)
      _, workflow = self.generator.activate_workflow(workflow)
      self.generator.modify_object(cycle, data={"is_current": False})

    with freeze_time("2017-7-16 07:09:10"):
      self.client.get("/login")
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 3, "has_overdue": False}
      )

    with freeze_time("2017-10-16 08:09:10"):  # same day as task 3 end date
      self.client.get("/login")
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 3, "has_overdue": True}
      )

      for task, status, count, overdue, my_work_count in transitions:
        self.generator.modify_object(tasks[task], data={"status": status})
        task_count_response = \
            self.client.get("/api/people/{}/task_count".format(user_id))
        my_work_count_response = \
            self.client.get("/api/people/{}/my_work_count".format(user_id))

        self.assertEqual(
            task_count_response.json,
            {"open_task_count": count, "has_overdue": overdue}
        )

        self.assertEqual(
            my_work_count_response.json["CycleTaskGroupObjectTask"],
            my_work_count
        )

  def test_task_count_multiple_wfs(self):
    """Test task count with both verified and non verified workflows.

    This checks task counts with 4 tasks
        2017, 8, 15  - verification needed
        2017, 11, 18  - verification needed
        2017, 8, 15  - No verification needed
        2017, 11, 18  - No verification needed
    """

    user = all_models.Person.query.first()
    user_id = user.id
    role_id = all_models.AccessControlRole.query.filter(
        all_models.AccessControlRole.name == "Task Assignees",
        all_models.AccessControlRole.object_type == "TaskGroupTask",
    ).one().id
    workflow_template = {
        "title": "verified workflow",
        "owners": [create_stub(user)],
        "is_verification_needed": True,
        "task_groups": [{
            "title": "one time task group",
            "contact": create_stub(user),
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user.id)],
                "start_date": date(2017, 5, 5),
                "end_date": date(2017, 8, 15),
            }, {
                "title": "dummy task 5",
                "description": "some task 4",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, user.id)],
                "start_date": date(2017, 6, 5),
                "end_date": date(2017, 11, 18),
            }],
            "task_group_objects": []
        }]
    }

    with freeze_time("2017-10-16 05:09:10"):
      self.client.get("/login")
      verified_workflow = workflow_template.copy()
      verified_workflow["is_verification_needed"] = True
      _, workflow = self.generator.generate_workflow(verified_workflow)
      _, cycle = self.generator.generate_cycle(workflow)
      verified_tasks = {
          task.title: task
          for task in cycle.cycle_task_group_object_tasks
      }
      _, workflow = self.generator.activate_workflow(workflow)

      non_verified_workflow = workflow_template.copy()
      non_verified_workflow["is_verification_needed"] = False
      _, workflow = self.generator.generate_workflow(non_verified_workflow)
      _, cycle = self.generator.generate_cycle(workflow)
      non_verified_tasks = {
          task.title: task
          for task in cycle.cycle_task_group_object_tasks
      }
      _, workflow = self.generator.activate_workflow(workflow)

    with freeze_time("2017-7-16 07:09:10"):
      self.client.get("/login")
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 4, "has_overdue": False}
      )

    with freeze_time("2017-10-16 08:09:10"):
      self.client.get("/login")
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 4, "has_overdue": True}
      )

      # transition 1, task that needs verification goes to finished state. This
      # transition should not change anything
      self.generator.modify_object(
          verified_tasks["task 1"],
          data={"status": "Finished"}
      )
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 4, "has_overdue": True}
      )

      # transition 2, task that needs verification goes to verified state. This
      # transition should reduce task count.
      self.generator.modify_object(
          verified_tasks["task 1"],
          data={"status": "Verified"}
      )
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 3, "has_overdue": True}
      )

      # transition 3, task that does not need verification goes into Finished
      # state. This transition should reduce task count and remove all overdue
      # tasks
      self.generator.modify_object(
          non_verified_tasks["task 1"],
          data={"status": "Finished"}
      )
      response = self.client.get("/api/people/{}/task_count".format(user_id))
      self.assertEqual(
          response.json,
          {"open_task_count": 2, "has_overdue": False}
      )

  @ddt.data(("Creator", 403),
            ("Reader", 403),
            ("Editor", 200),
            ("Administrator", 200))
  @ddt.unpack
  def test_person_editing(self, role_name, status):
    """{0} should receive {1} status code on edit Person."""
    role = all_models.Role.query.filter(
        all_models.Role.name == role_name
    ).one()
    with factories.single_commit():
      client_user = factories.PersonFactory()
      rbac_factories.UserRoleFactory(role=role, person=client_user)
    self.api.set_user(client_user)
    self.client.get("/login")
    base_email = "*****@*****.**"
    person = factories.PersonFactory(email=base_email)
    person_id = person.id
    new_email = "new_{}".format(base_email)
    resp = self.api.put(person, {"email": new_email})
    self.assertEqual(status, resp.status_code)
    person = all_models.Person.query.get(person_id)
    if status == 200:
      self.assertEqual(new_email, person.email)
    else:
      self.assertEqual(base_email, person.email)
Exemple #53
0
class TestEnableAndDisableNotifications(TestCase):

  """ This class contains simple one time workflow tests that are not
  in the gsheet test grid
  """

  def setUp(self):
    super(TestEnableAndDisableNotifications, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    models.Notification.query.delete()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")
    self.create_test_cases()

    def init_decorator(init):
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = datetime.now()
      return new_init

    models.Notification.__init__ = init_decorator(models.Notification.__init__)

  @patch("ggrc.notifications.common.send_email")
  def test_default_notifications_settings(self, mock_mail):

    with freeze_time("2015-02-01 13:39:20"):
      _, wf = self.wf_generator.generate_workflow(self.quarterly_wf)
      response, wf = self.wf_generator.activate_workflow(wf)

      self.assert200(response)

      user = models.Person.query.get(self.user.id)

    with freeze_time("2015-01-01 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(user.email, notif_data)

    with freeze_time("2015-01-29 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)

  @patch("ggrc.notifications.common.send_email")
  def test_disabled_notifications(self, mock_mail):

    with freeze_time("2015-02-01 13:39:20"):
      _, wf = self.wf_generator.generate_workflow(self.quarterly_wf)
      response, wf = self.wf_generator.activate_workflow(wf)

      self.assert200(response)

      self.object_generator.generate_notification_setting(
          self.user.id, "Email_Digest", False)

      user = models.Person.query.get(self.user.id)

    with freeze_time("2015-01-01 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(user.email, notif_data)

    with freeze_time("2015-01-29 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(user.email, notif_data)

  @patch("ggrc.notifications.common.send_email")
  def test_enabled_notifications(self, mock_mail):

    with freeze_time("2015-02-01 13:39:20"):
      _, wf = self.wf_generator.generate_workflow(self.quarterly_wf)
      response, wf = self.wf_generator.activate_workflow(wf)
      self.assert200(response)

    with freeze_time("2015-01-29 13:39:20"):
      user = models.Person.query.get(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)

      self.object_generator.generate_notification_setting(
          self.user.id, "Email_Digest", True)

      user = models.Person.query.get(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)

  @patch("ggrc.notifications.common.send_email")
  def test_forced_notifications(self, mock_mail):

    with freeze_time("2015-02-01 13:39:20"):
      _, wf = self.wf_generator.generate_workflow(self.quarterly_wf_forced)
      response, wf = self.wf_generator.activate_workflow(wf)

      self.assert200(response)

      user = models.Person.query.get(self.user.id)

    with freeze_time("2015-01-29 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)

      self.object_generator.generate_notification_setting(
          self.user.id, "Email_Digest", True)

      user = models.Person.query.get(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)

  @patch("ggrc.notifications.common.send_email")
  def test_force_one_wf_notifications(self, mock_mail):

    with freeze_time("2015-02-01 13:39:20"):
      _, wf_forced = self.wf_generator.generate_workflow(
          self.quarterly_wf_forced)
      response, wf_forced = self.wf_generator.activate_workflow(wf_forced)
      _, wf = self.wf_generator.generate_workflow(self.quarterly_wf)
      response, wf = self.wf_generator.activate_workflow(wf)

      self.assert200(response)

      user = models.Person.query.get(self.user.id)

    with freeze_time("2015-01-29 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("cycle_starts_in", notif_data[user.email])
      self.assertIn(wf_forced.id, notif_data[user.email]["cycle_starts_in"])
      self.assertIn(wf.id, notif_data[user.email]["cycle_starts_in"])

      self.object_generator.generate_notification_setting(
          self.user.id, "Email_Digest", False)

      user = models.Person.query.get(self.user.id)
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("cycle_starts_in", notif_data[user.email])
      self.assertIn(wf_forced.id, notif_data[user.email]["cycle_starts_in"])
      self.assertNotIn(wf.id, notif_data[user.email]["cycle_starts_in"])

  def create_test_cases(self):
    def person_dict(person_id):
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }

    self.quarterly_wf_forced = {
        "title": "quarterly wf forced notifications",
        "notify_on_change": True,
        "description": "",
        # admin will be current user with id == 1
        "unit": "month",
        "repeat_every": 3,
        "task_groups": [{
            "title": "tg_1",
            "contact": person_dict(self.user.id),
            "task_group_tasks": [{
                "contact": person_dict(self.user.id),
                "description": factories.random_str(100),
            },
            ],
        },
        ]
    }

    self.quarterly_wf = {
        "title": "quarterly wf 1",
        "description": "",
        # admin will be current user with id == 1
        "unit": "month",
        "repeat_every": 3,
        "task_groups": [{
            "title": "tg_1",
            "contact": person_dict(self.user.id),
            "task_group_tasks": [{
                "contact": person_dict(self.user.id),
                "description": factories.random_str(100),
            },
            ],
        },
        ]
    }
class TestTaskDueNotifications(TestCase):
  """Test suite for task due soon/today notifications."""

  # pylint: disable=invalid-name

  def _fix_notification_init(self):
    """Fix Notification object init function.

    This is a fix needed for correct created_at field when using freezgun. By
    default the created_at field is left empty and filed by database, which
    uses system time and not the fake date set by freezugun plugin. This fix
    makes sure that object created in freeze_time block has all dates set with
    the correct date and time.
    """
    def init_decorator(init):
      """"Adjust the value of the object's created_at attribute to now."""
      @functools.wraps(init)
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = datetime.now()
      return new_init

    models.Notification.__init__ = init_decorator(models.Notification.__init__)

  def setUp(self):
    super(TestTaskDueNotifications, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    models.Notification.query.delete()

    self._fix_notification_init()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")

    role_id = models.all_models.AccessControlRole.query.filter(
        models.all_models.AccessControlRole.name == "Task Assignees",
        models.all_models.AccessControlRole.object_type == "TaskGroupTask",
    ).one().id

    self.one_time_workflow = {
        "title": "one time test workflow",
        "notify_on_change": True,
        "description": "some test workflow",
        "is_verification_needed": False,
        # admin will be current user with id == 1
        "task_groups": [{
            "title": "one time task group",
            "contact": {
                "href": "/api/people/{}".format(self.user.id),
                "id": self.user.id,
                "type": "Person",
            },
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 5, 15),
                "end_date": date(2017, 6, 11),
            }, {
                "title": "task 2",
                "description": "some task 2",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 5, 8),
                "end_date": date(2017, 6, 12),
            }, {
                "title": "task 3",
                "description": "some task 3",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 5, 31),
                "end_date": date(2017, 6, 13),
            }, {
                "title": "task 4",
                "description": "some task 4",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 6, 2),
                "end_date": date(2017, 6, 14),
            }, {
                "title": "task 5",
                "description": "some task 5",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 6, 8),
                "end_date": date(2017, 6, 15),
            }],
            "task_group_objects": self.random_objects
        }]
    }

  @ddt.unpack
  @ddt.data(
      ("2017-06-12 12:12:12", ["task 1"], ["task 2"], ["task 3"]),
      ("2017-06-13 13:13:13", ["task 1", "task 2"], ["task 3"], ["task 4"]),
  )
  @patch("ggrc.notifications.common.send_email")
  def test_creating_obsolete_notifications(
      self, fake_now, expected_overdue, expected_due_today, expected_due_in, _
  ):
    """Notifications already obsolete on creation date should not be created.
    """
    with freeze_time("2017-06-12 09:39:32"):
      tmp = self.one_time_workflow.copy()
      _, workflow = self.wf_generator.generate_workflow(tmp)
      self.wf_generator.generate_cycle(workflow)
      response, workflow = self.wf_generator.activate_workflow(workflow)
      self.assert200(response)

    user = models.Person.query.get(self.user.id)

    with freeze_time(fake_now):
      # mark all yeasterday notifications as sent
      models.all_models.Notification.query.filter(
          sa.func.DATE(models.all_models.Notification.send_on) < date.today()
      ).update({models.all_models.Notification.sent_at:
                datetime.now() - timedelta(1)},
               synchronize_session="fetch")

      _, notif_data = common.get_daily_notifications()
      user_notifs = notif_data.get(user.email, {})

      actual_overdue = [n['title'] for n in
                        user_notifs.get("task_overdue", {}).itervalues()]
      actual_overdue.sort()
      self.assertEqual(actual_overdue, expected_overdue)

      self.assertEqual(
          [n['title'] for n in user_notifs.get("due_today", {}).itervalues()],
          expected_due_today)

      self.assertEqual(
          [n['title'] for n in user_notifs.get("due_in", {}).itervalues()],
          expected_due_in)
  def setUp(self):
    super(TestTaskDueNotifications, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    models.Notification.query.delete()

    self._fix_notification_init()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")

    role_id = models.all_models.AccessControlRole.query.filter(
        models.all_models.AccessControlRole.name == "Task Assignees",
        models.all_models.AccessControlRole.object_type == "TaskGroupTask",
    ).one().id

    self.one_time_workflow = {
        "title": "one time test workflow",
        "notify_on_change": True,
        "description": "some test workflow",
        "is_verification_needed": False,
        # admin will be current user with id == 1
        "task_groups": [{
            "title": "one time task group",
            "contact": {
                "href": "/api/people/{}".format(self.user.id),
                "id": self.user.id,
                "type": "Person",
            },
            "task_group_tasks": [{
                "title": "task 1",
                "description": "some task",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 5, 15),
                "end_date": date(2017, 6, 11),
            }, {
                "title": "task 2",
                "description": "some task 2",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 5, 8),
                "end_date": date(2017, 6, 12),
            }, {
                "title": "task 3",
                "description": "some task 3",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 5, 31),
                "end_date": date(2017, 6, 13),
            }, {
                "title": "task 4",
                "description": "some task 4",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 6, 2),
                "end_date": date(2017, 6, 14),
            }, {
                "title": "task 5",
                "description": "some task 5",
                "access_control_list": [
                    acl_helper.get_acl_json(role_id, self.user.id)],
                "start_date": date(2017, 6, 8),
                "end_date": date(2017, 6, 15),
            }],
            "task_group_objects": self.random_objects
        }]
    }
class TestNotificationsForDeletedObjects(TestCase):

  """ This class contains simple one time workflow tests that are not
  in the gsheet test grid
  """

  def setUp(self):
    super(TestNotificationsForDeletedObjects, self).setUp()
    self.api = Api()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    Notification.query.delete()

    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.user = self.object_generator.generate_person(
        user_role="Administrator")
    self.create_test_cases()

    def init_decorator(init):
      def new_init(self, *args, **kwargs):
        init(self, *args, **kwargs)
        if hasattr(self, "created_at"):
          self.created_at = datetime.now()
      return new_init

    Notification.__init__ = init_decorator(Notification.__init__)

  @patch("ggrc.notifications.common.send_email")
  def test_delete_activated_workflow(self, mock_mail):

    with freeze_time("2015-02-01 13:39:20"):
      _, workflow = self.wf_generator.generate_workflow(self.quarterly_wf_1)
      response, workflow = self.wf_generator.activate_workflow(workflow)

      self.assert200(response)

      user = Person.query.get(self.user.id)

    with freeze_time("2015-01-01 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertNotIn(user.email, notif_data)

    with freeze_time("2015-01-29 13:39:20"):
      _, notif_data = common.get_daily_notifications()
      self.assertIn(user.email, notif_data)
      self.assertIn("cycle_starts_in", notif_data[user.email])

      workflow = Workflow.query.get(workflow.id)
      # After workflow deletion its notifications object_ids updated to 0
      # value, this is the error, them should be deleted
      # so this query checks existence of notifications with object_id
      # equal to workflow id or 0 id before and
      # after deletion workflow instance
      exists_qs = db.session.query(
          Notification.query.filter(
              Notification.object_type == workflow.__class__.__name__,
              Notification.object_id.in_((workflow.id, 0))
          ).exists()
      )
      self.assertTrue(exists_qs.one()[0])
      response = self.wf_generator.api.delete(workflow)
      self.assert200(response)

      self.assertFalse(exists_qs.one()[0])

      _, notif_data = common.get_daily_notifications()
      user = Person.query.get(self.user.id)

      self.assertNotIn(user.email, notif_data)

  def create_test_cases(self):
    def person_dict(person_id):
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }

    self.quarterly_wf_1 = {
        "title": "quarterly wf 1",
        "notify_on_change": True,
        "description": "",
        "owners": [person_dict(self.user.id)],
        "frequency": "quarterly",
        "task_groups": [{
            "title": "tg_1",
            "contact": person_dict(self.user.id),
            "task_group_tasks": [{
                "contact": person_dict(self.user.id),
                "description": factories.random_str(100),
                "relative_start_day": 5,
                "relative_start_month": 2,
                "relative_end_day": 25,
                "relative_end_month": 2,
            },
            ],
        },
        ]
    }
class TestWorkflowCycleStatePropagantion(TestCase):
  """Test case for cycle task to cycle task group status propagation"""

  def setUp(self):
    super(TestWorkflowCycleStatePropagantion, self).setUp()
    self.api = Api()
    self.generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()

    self.weekly_wf = {
        "title": "weekly thingy",
        "description": "start this many a time",
        "frequency": "weekly",
        "task_groups": [{
            "title": "weekly task group",
            "task_group_tasks": [{
                "title": "weekly task 1",
                "relative_end_day": 1,
                "relative_end_month": None,
                "relative_start_day": 5,
                "relative_start_month": None,
            }, {
                "title": "weekly task 1",
                "relative_end_day": 1,
                "relative_end_month": None,
                "relative_start_day": 1,
                "relative_start_month": None,
            }
            ]},
        ]
    }

  def test_weekly_state_transitions_assigned_inprogress(self):
    "Test that starting one cycle task changes cycle task group"
    _, wf = self.generator.generate_workflow(self.weekly_wf)

    with freeze_time("2016-6-10 13:00:00"):  # Friday, 6/10/2016
      self.generator.activate_workflow(wf)

      ctg = db.session.query(CycleTaskGroup).join(
          Cycle).join(Workflow).filter(Workflow.id == wf.id).all()[0]
      self.assertEqual(ctg.status, "Assigned")

      cycle_tasks = db.session.query(CycleTaskGroupObjectTask).join(
          Cycle).join(Workflow).filter(Workflow.id == wf.id).all()
      first_ct, second_ct = cycle_tasks

      for cycle_task in cycle_tasks:
        self.assertEqual(cycle_task.status, "Assigned")

      # Move one task to InProgress
      _, first_ct = self.generator.modify_object(
          first_ct, {"status": "InProgress"})

      self.assertEqual(first_ct.status, "InProgress")
      ctg = db.session.query(CycleTaskGroup).get(ctg.id)
      self.assertEqual(ctg.status, "InProgress")

      # Undo operation
      _, first_ct = self.generator.modify_object(
          first_ct, {"status": "Assigned"})

      self.assertEqual(first_ct.status, "Assigned")
      ctg = db.session.query(CycleTaskGroup).get(ctg.id)
      self.assertEqual(ctg.status, "Assigned")

      # Move both to in progress
      for cycle_task in cycle_tasks:
        self.generator.modify_object(
            cycle_task, {"status": "InProgress"})

      ctg = db.session.query(CycleTaskGroup).get(ctg.id)
      self.assertEqual(ctg.status, "InProgress")

      # Undo one cycle task
      _, first_ct = self.generator.modify_object(
          first_ct, {"status": "Assigned"})
      second_ct = db.session.query(CycleTaskGroupObjectTask).get(second_ct.id)
      ctg = db.session.query(CycleTaskGroup).get(ctg.id)

      self.assertEqual(first_ct.status, "Assigned")
      self.assertEqual(second_ct.status, "InProgress")
      self.assertEqual(ctg.status, "InProgress")

      # Undo second cycle task
      _, second_ct = self.generator.modify_object(
          second_ct, {"status": "Assigned"})
      first_ct = db.session.query(CycleTaskGroupObjectTask).get(first_ct.id)
      ctg = db.session.query(CycleTaskGroup).get(ctg.id)

      self.assertEqual(first_ct.status, "Assigned")
      self.assertEqual(second_ct.status, "Assigned")
      self.assertEqual(ctg.status, "Assigned")

  def test_weekly_state_transitions_inprogress_finished(self):
    "Test In Progress to Finished transitions"
    _, wf = self.generator.generate_workflow(self.weekly_wf)

    with freeze_time("2016-6-10 13:00:00"):  # Friday, 6/10/2016
      self.generator.activate_workflow(wf)

      ctg = db.session.query(CycleTaskGroup).join(
          Cycle).join(Workflow).filter(Workflow.id == wf.id).all()[0]

      cycle_tasks = db.session.query(CycleTaskGroupObjectTask).join(
          Cycle).join(Workflow).filter(Workflow.id == wf.id).all()
      first_ct, second_ct = cycle_tasks

      # Move both tasks to InProgress
      for cycle_task in cycle_tasks:
        self.generator.modify_object(
            cycle_task, {"status": "InProgress"})

      # Test that moving one task to finished doesn't finish entire cycle
      _, first_ct = self.generator.modify_object(
          first_ct, {"status": "Finished"})
      second_ct = db.session.query(CycleTaskGroupObjectTask).get(second_ct.id)
      ctg = db.session.query(CycleTaskGroup).get(ctg.id)

      self.assertEqual(first_ct.status, "Finished")
      self.assertEqual(second_ct.status, "InProgress")
      self.assertEqual(ctg.status, "InProgress")

      # Test moving second task to Finished - entire cycle should be finished
      _, second_ct = self.generator.modify_object(
          second_ct, {"status": "Finished"})
      first_ct = db.session.query(CycleTaskGroupObjectTask).get(first_ct.id)
      ctg = db.session.query(CycleTaskGroup).get(ctg.id)

      self.assertEqual(second_ct.status, "Finished")
      self.assertEqual(first_ct.status, "Finished")
      self.assertEqual(ctg.status, "Finished")

      # Undo one task, cycle should be InProgress
      _, first_ct = self.generator.modify_object(
          first_ct, {"status": "InProgress"})
      second_ct = db.session.query(CycleTaskGroupObjectTask).get(second_ct.id)
      ctg = db.session.query(CycleTaskGroup).get(ctg.id)

      self.assertEqual(first_ct.status, "InProgress")
      self.assertEqual(second_ct.status, "Finished")
      self.assertEqual(ctg.status, "InProgress")

  def test_weekly_state_transitions_finished_verified(self):
    "Test Finished to Verified transitions"
    _, wf = self.generator.generate_workflow(self.weekly_wf)

    with freeze_time("2016-6-10 13:00:00"):  # Friday, 6/10/2016
      self.generator.activate_workflow(wf)

      ctg = db.session.query(CycleTaskGroup).join(
          Cycle).join(Workflow).filter(Workflow.id == wf.id).all()[0]

      cycle_tasks = db.session.query(CycleTaskGroupObjectTask).join(
          Cycle).join(Workflow).filter(Workflow.id == wf.id).all()
      first_ct, second_ct = cycle_tasks

      # Move both tasks to InProgress
      for cycle_task in cycle_tasks:
        self.generator.modify_object(
            cycle_task, {"status": "InProgress"})
        self.generator.modify_object(
            cycle_task, {"status": "Finished"})

      ctg = db.session.query(CycleTaskGroup).get(ctg.id)
      self.assertEqual(ctg.status, "Finished")

      for cycle_task in cycle_tasks:
        cycle_task = db.session.query(CycleTaskGroupObjectTask).get(
            cycle_task.id)
        self.assertEqual(cycle_task.status, "Finished")

      # Verify first CT
      _, first_ct = self.generator.modify_object(
          first_ct, {"status": "Verified"})

      second_ct = db.session.query(CycleTaskGroupObjectTask).get(second_ct.id)
      ctg = db.session.query(CycleTaskGroup).get(ctg.id)

      self.assertEqual(first_ct.status, "Verified")
      self.assertEqual(second_ct.status, "Finished")
      self.assertEqual(ctg.status, "Finished")

      # Verify second CT
      _, second_ct = self.generator.modify_object(
          second_ct, {"status": "Verified"})

      first_ct = db.session.query(CycleTaskGroupObjectTask).get(first_ct.id)
      ctg = db.session.query(CycleTaskGroup).get(ctg.id)

      self.assertEqual(first_ct.status, "Verified")
      self.assertEqual(second_ct.status, "Verified")
      self.assertEqual(ctg.status, "Verified")

  def test_weekly_state_transitions_finished_declined(self):
    "Test Finished to Declined transitions"
    _, wf = self.generator.generate_workflow(self.weekly_wf)

    with freeze_time("2016-6-10 13:00:00"):  # Friday, 6/10/2016
      self.generator.activate_workflow(wf)

      ctg = db.session.query(CycleTaskGroup).join(
          Cycle).join(Workflow).filter(Workflow.id == wf.id).all()[0]

      cycle_tasks = db.session.query(CycleTaskGroupObjectTask).join(
          Cycle).join(Workflow).filter(Workflow.id == wf.id).all()
      first_ct, second_ct = cycle_tasks

      # Move both tasks to InProgress
      for cycle_task in cycle_tasks:
        self.generator.modify_object(
            cycle_task, {"status": "InProgress"})
        self.generator.modify_object(
            cycle_task, {"status": "Finished"})

      ctg = db.session.query(CycleTaskGroup).get(ctg.id)
      self.assertEqual(ctg.status, "Finished")

      # Decline first CT
      _, first_ct = self.generator.modify_object(
          first_ct, {"status": "Declined"})

      second_ct = db.session.query(CycleTaskGroupObjectTask).get(second_ct.id)
      ctg = db.session.query(CycleTaskGroup).get(ctg.id)

      self.assertEqual(first_ct.status, "Declined")
      self.assertEqual(second_ct.status, "Finished")
      self.assertEqual(ctg.status, "InProgress")
 def setUp(self):
   super(TestWorkflowsCycleGeneration, self).setUp()
   self.api = Api()
   self.generator = WorkflowsGenerator()
   self.object_generator = ObjectGenerator()
class TestCycleTaskImportUpdate(BaseTestCycleTaskImportUpdate):

  """ This class contains simple cycle task update tests using import
  functionality
  """

  CSV_DIR = join(abspath(dirname(__file__)), "test_csvs/")

  def setUp(self):
    super(TestCycleTaskImportUpdate, self).setUp()
    self.wf_generator = WorkflowsGenerator()
    self.object_generator = ObjectGenerator()
    self.random_objects = self.object_generator.generate_random_objects(2)
    _, self.person_1 = self.object_generator.generate_person(
        user_role="Administrator")
    self.ftime_active = "2016-07-01"
    self.ftime_historical = "2014-05-01"
    self._create_test_cases_data()
    # It is needed because cycle-tasks are generated automatically with
    # 'slug' based on auto_increment 'id' field.
    # At start of each test we suppose that created cycle-task's 'slug'
    # lie in range from 1 to 10.
    db.session.execute('ALTER TABLE cycle_task_group_object_tasks '
                       'AUTO_INCREMENT = 1')

  def test_cycle_task_correct(self):
    """Test cycle task update via import with correct data"""
    self._generate_cycle_tasks()
    with freeze_time(self.ftime_active):
      response = self.import_file("cycle_task_correct.csv")
      self._check_csv_response(response, {})
      self._cmp_tasks(self.expected_cycle_task_correct)

  def test_cycle_task_warnings(self):
    """Test cycle task update via import with data which is the reason of
    warnings about non-importable columns."""
    self._generate_cycle_tasks()
    with freeze_time(self.ftime_active):
      response = self.import_file("cycle_task_warnings.csv")
      self._check_csv_response(response, self.expected_warnings)
      self._cmp_tasks(self.expected_cycle_task_correct)

  def test_cycle_task_create_error(self):
    """Test cycle task update via import with data which is the reason of
    errors about new cycle task creation."""
    self._generate_cycle_tasks()
    with freeze_time(self.ftime_active):
      response = self.import_file("cycle_task_create_error.csv")
      self._check_csv_response(response, self.expected_create_error)
      self._cmp_tasks(self.expected_cycle_task_correct)

  def test_cycle_task_date_error(self):
    """Test cycle task update via import with data which is the reason of
    errors about incorrect dates in csv file."""
    self._generate_cycle_tasks()
    with freeze_time(self.ftime_active):
      response = self.import_file("cycle_task_date_error.csv")
      self._check_csv_response(response, self.expected_date_error)
      self._cmp_tasks(self.expected_cycle_task_date_error)

  def test_cycle_task_permission_error(self):
    """Test cycle task update via import with non-admin user which is the
    reason of error. Only admin can update cycle tasks via import."""
    self._generate_cycle_tasks()
    with freeze_time(self.ftime_active):
      _, creator = self.object_generator.generate_person(user_role="Creator")
      response = self.import_file("cycle_task_correct.csv", person=creator)
      self._check_csv_response(response, self.expected_permission_error)
      # Cycle tasks' data shouldn't be changed in test DB after import run from
      # non-admin user
      expected_cycle_task_permission_error = {}
      expected_cycle_task_permission_error.update(
          self.generated_cycle_tasks_active)
      expected_cycle_task_permission_error.update(
          self.generated_cycle_tasks_historical)
      self._cmp_tasks(expected_cycle_task_permission_error)

  def _cmp_tasks(self, expected_ctasks):
    """Compare tasks values from argument's list and test DB."""
    for ctask in db.session.query(CycleTaskGroupObjectTask).all():
      if ctask.slug not in expected_ctasks:
        continue
      exp_task = expected_ctasks[ctask.slug]
      for attr, val in exp_task.iteritems():
        self.assertEqual(str(getattr(ctask, attr, None)), val)

  # pylint: disable=too-many-arguments
  def _activate_workflow(self, ftime, workflow, task_group, task_group_tasks,
                         random_object, cycle_tasks):
    """Helper which is responsible for active cycle-tasks creation"""
    with freeze_time(ftime):
      _, wf = self.wf_generator.generate_workflow(workflow)
      _, tg = self.wf_generator.generate_task_group(wf, task_group)
      for task in task_group_tasks:
        self.wf_generator.generate_task_group_task(tg, task)
      self.wf_generator.generate_task_group_object(tg, random_object)

      _, cycle = self.wf_generator.generate_cycle(wf)
      self.wf_generator.activate_workflow(wf)

      for exp_slug, exp_task in cycle_tasks.iteritems():
        obj = db.session.query(CycleTaskGroupObjectTask).filter_by(
            slug=exp_slug
        ).first()
        if exp_task["status"] == "Verified":
          self.wf_generator.modify_object(obj, {"status": "Finished"})
        self.wf_generator.modify_object(obj, {"status": exp_task["status"]})
    self._cmp_tasks(cycle_tasks)
    return cycle

  def _generate_cycle_tasks(self):
    """Helper which is responsible for test data creation"""
    self._activate_workflow(self.ftime_active, self.workflow_active,
                            self.task_group_active,
                            self.task_group_tasks_active,
                            self.random_objects[0],
                            self.generated_cycle_tasks_active)
    cycle = self._activate_workflow(self.ftime_historical,
                                    self.workflow_historical,
                                    self.task_group_historical,
                                    self.task_group_tasks_historical,
                                    self.random_objects[1],
                                    self.generated_cycle_tasks_historical)
    with freeze_time(self.ftime_historical):
      cycle = Cycle.query.get(cycle.id)
      self.wf_generator.modify_object(cycle, data={"is_current": False})

  def _create_test_cases_data(self):
    """Create test cases data: for object generation,
    expected data for checks"""
    def person_dict(person_id):
      """Return person data"""
      return {
          "href": "/api/people/%d" % person_id,
          "id": person_id,
          "type": "Person"
      }

    self.workflow_active = {
        "title": "workflow active title",
        "description": "workflow active description",
        "frequency": "one_time",
        "owners": [person_dict(self.person_1.id)],
        "notify_on_change": False,
    }

    self.task_group_active = {
        "title": "task group active title",
        "contact": person_dict(self.person_1.id),
    }

    self.task_group_tasks_active = [{
        "title": "task active title 1",
        "description": "task active description 1",
        "contact": person_dict(self.person_1.id),
        "start_date": "07/01/2016",
        "end_date": "07/06/2016",
    }, {
        "title": "task active title 2",
        "description": "task active description 2",
        "contact": person_dict(self.person_1.id),
        "start_date": "07/07/2016",
        "end_date": "07/12/2016",
    }, {
        "title": "task active title 3",
        "description": "task active description 3",
        "contact": person_dict(self.person_1.id),
        "start_date": "07/13/2016",
        "end_date": "07/18/2016",
    }, {
        "title": "task active title 4",
        "description": "task active description 4",
        "contact": person_dict(self.person_1.id),
        "start_date": "07/19/2016",
        "end_date": "07/24/2016",
    }, {
        "title": "task active title 5",
        "description": "task active description 5",
        "contact": person_dict(self.person_1.id),
        "start_date": "07/25/2016",
        "end_date": "07/30/2016",
    }]

    # Active cycle tasks which should be generated from previous structure
    # at the beginning of each test
    self.generated_cycle_tasks_active = {
        "CYCLETASK-1": {
            "title": self.task_group_tasks_active[0]["title"],
            "description": self.task_group_tasks_active[0]["description"],
            "start_date": "2016-07-01",
            "end_date": "2016-07-06",
            "finished_date": "None",
            "verified_date": "None",
            "status": "Assigned"
        },
        "CYCLETASK-2": {
            "title": self.task_group_tasks_active[1]["title"],
            "description": self.task_group_tasks_active[1]["description"],
            "start_date": "2016-07-07",
            "end_date": "2016-07-12",
            "finished_date": "None",
            "verified_date": "None",
            "status": "Declined"
        },
        "CYCLETASK-3": {
            "title": self.task_group_tasks_active[2]["title"],
            "description": self.task_group_tasks_active[2]["description"],
            "start_date": "2016-07-13",
            "end_date": "2016-07-18",
            "finished_date": "None",
            "verified_date": "None",
            "status": "InProgress"
        },
        "CYCLETASK-4": {
            "title": self.task_group_tasks_active[3]["title"],
            "description": self.task_group_tasks_active[3]["description"],
            "start_date": "2016-07-19",
            "end_date": "2016-07-24",
            "finished_date": "2016-07-01 00:00:00",
            "verified_date": "None",
            "status": "Finished"
        },
        "CYCLETASK-5": {
            "title": self.task_group_tasks_active[4]["title"],
            "description": self.task_group_tasks_active[4]["description"],
            "start_date": "2016-07-25",
            "end_date": "2016-07-30",
            "finished_date": "2016-07-01 00:00:00",
            "verified_date": "2016-07-01 00:00:00",
            "status": "Verified"
        }
    }

    self.workflow_historical = {
        "title": "workflow historical title",
        "description": "workflow historical description",
        "frequency": "one_time",
        "owners": [person_dict(self.person_1.id)],
        "notify_on_change": False,
    }

    self.task_group_historical = {
        "title": "task group historical title",
        "contact": person_dict(self.person_1.id),
    }

    self.task_group_tasks_historical = [{
        "title": "task historical title 1",
        "description": "task historical description 1",
        "contact": person_dict(self.person_1.id),
        "start_date": "05/01/2014",
        "end_date": "05/06/2014",
    }, {
        "title": "task historical title 2",
        "description": "task historical description 2",
        "contact": person_dict(self.person_1.id),
        "start_date": "05/07/2014",
        "end_date": "05/12/2014",
    }, {
        "title": "task historical title 3",
        "description": "task historical description 3",
        "contact": person_dict(self.person_1.id),
        "start_date": "05/13/2014",
        "end_date": "05/18/2014",
    }, {
        "title": "task historical title 4",
        "description": "task historical description 4",
        "contact": person_dict(self.person_1.id),
        "start_date": "05/19/2014",
        "end_date": "05/24/2014",
    }, {
        "title": "task historical title 5",
        "description": "task historical description 5",
        "contact": person_dict(self.person_1.id),
        "start_date": "05/25/2014",
        "end_date": "05/30/2014",
    },
    ]

    # Historical cycle tasks which should be generated from previous structure
    # at the beginning of each test.
    self.generated_cycle_tasks_historical = {
        "CYCLETASK-6": {
            "title": self.task_group_tasks_historical[0]["title"],
            "description": self.task_group_tasks_historical[0]["description"],
            "start_date": "2014-05-01",
            "end_date": "2014-05-06",
            "finished_date": "None",
            "verified_date": "None",
            "status": "Assigned"
        },
        "CYCLETASK-7": {
            "title": self.task_group_tasks_historical[1]["title"],
            "description": self.task_group_tasks_historical[1]["description"],
            "start_date": "2014-05-07",
            "end_date": "2014-05-12",
            "finished_date": "None",
            "verified_date": "None",
            "status": "Declined"
        },
        "CYCLETASK-8": {
            "title": self.task_group_tasks_historical[2]["title"],
            "description": self.task_group_tasks_historical[2]["description"],
            "start_date": "2014-05-13",
            "end_date": "2014-05-18",
            "finished_date": "None",
            "verified_date": "None",
            "status": "InProgress"
        },
        "CYCLETASK-9": {
            "title": self.task_group_tasks_historical[3]["title"],
            "description": self.task_group_tasks_historical[3]["description"],
            "start_date": "2014-05-19",
            "end_date": "2014-05-24",
            "finished_date": "2014-05-01 00:00:00",
            "verified_date": "None",
            "status": "Finished"
        },
        "CYCLETASK-10": {
            "title": self.task_group_tasks_historical[4]["title"],
            "description": self.task_group_tasks_historical[4]["description"],
            "start_date": "2014-05-25",
            "end_date": "2014-05-30",
            "finished_date": "2014-05-01 00:00:00",
            "verified_date": "2014-05-01 00:00:00",
            "status": "Verified"
        }
    }

    # Expected cycle tasks which should be created in correct cycle task update
    # case. It is needed for most tests.
    self.expected_cycle_task_correct = {
        "CYCLETASK-1": {
            "title": self.task_group_tasks_active[0]["title"] + " one",
            "description":
                self.task_group_tasks_active[0]["description"] + " one",
            "start_date": "2016-06-01",
            "end_date": "2016-06-06",
            "finished_date": "None",
            "verified_date": "None",
            "status": "Assigned"
        },
        "CYCLETASK-2": {
            "title": self.task_group_tasks_active[1]["title"] + " two",
            "description":
                self.task_group_tasks_active[1]["description"] + " two",
            "start_date": "2016-06-07",
            "end_date": "2016-06-12",
            "finished_date": "None",
            "verified_date": "None",
            "status": "Declined"
        },
        "CYCLETASK-3": {
            "title": self.task_group_tasks_active[2]["title"] + " three",
            "description":
                self.task_group_tasks_active[2]["description"] + " three",
            "start_date": "2016-06-13",
            "end_date": "2016-06-18",
            "finished_date": "None",
            "verified_date": "None",
            "status": "InProgress"
        },
        "CYCLETASK-4": {
            "title": self.task_group_tasks_active[3]["title"] + " four",
            "description":
                self.task_group_tasks_active[3]["description"] + " four",
            "start_date": "2016-06-19",
            "end_date": "2016-06-24",
            "finished_date": "2016-07-19 00:00:00",
            "verified_date": "None",
            "status": "Finished"
        },
        "CYCLETASK-5": {
            "title": self.task_group_tasks_active[4]["title"] + " five",
            "description":
                self.task_group_tasks_active[4]["description"] + " five",
            "start_date": "2016-06-25",
            "end_date": "2016-06-30",
            "finished_date": "2016-07-25 00:00:00",
            "verified_date": "2016-08-30 00:00:00",
            "status": "Verified"
        },
        "CYCLETASK-6": {
            "title": self.task_group_tasks_historical[0]["title"] + " one",
            "description":
                self.task_group_tasks_historical[0]["description"] + " one",
            "start_date": "2014-04-01",
            "end_date": "2014-04-06",
            "finished_date": "2014-05-01 00:00:00",
            "verified_date": "2014-06-06 00:00:00",
            "status": "Assigned"
        },
        "CYCLETASK-7": {
            "title": self.task_group_tasks_historical[1]["title"] + " two",
            "description":
                self.task_group_tasks_historical[1]["description"] + " two",
            "start_date": "2014-04-07",
            "end_date": "2014-04-12",
            "finished_date": "2014-05-07 00:00:00",
            "verified_date": "None",
            "status": "Declined"
        },
        "CYCLETASK-8": {
            "title": self.task_group_tasks_historical[2]["title"] + " three",
            "description":
                self.task_group_tasks_historical[2]["description"] + " three",
            "start_date": "2014-04-13",
            "end_date": "2014-04-18",
            "finished_date": "2014-05-13 00:00:00",
            "verified_date": "2014-06-18 00:00:00",
            "status": "InProgress"
        },
        "CYCLETASK-9": {
            "title": self.task_group_tasks_historical[3]["title"] + " four",
            "description":
                self.task_group_tasks_historical[3]["description"] + " four",
            "start_date": "2014-04-19",
            "end_date": "2014-04-24",
            "finished_date": "2014-05-19 00:00:00",
            "verified_date": "None",
            "status": "Finished"
        },
        "CYCLETASK-10": {
            "title": self.task_group_tasks_historical[4]["title"] + " five",
            "description":
                self.task_group_tasks_historical[4]["description"] + " five",
            "start_date": "2014-04-25",
            "end_date": "2014-04-30",
            "finished_date": "2014-05-25 00:00:00",
            "verified_date": "2014-06-30 00:00:00",
            "status": "Verified"
        }
    }

    # Below is description of warning for non-importable columns. It is needed
    # for test_cycle_task_warnings.
    importable_column_names = []
    for field_name in CycleTaskGroupObjectTask.IMPORTABLE_FIELDS:
      if field_name == 'slug':
        continue
      # pylint: disable=protected-access
      name = CycleTaskGroupObjectTask._aliases.get(field_name, field_name)
      if isinstance(name, dict):
        name = name['display_name']
      importable_column_names.append(name)
    self.expected_warnings = self.generate_expected_warning(
        *importable_column_names)

    # This is an error message which should be shown during
    # test_cycle_task_create_error test
    self.expected_create_error = {
        'Cycle Task': {
            'row_errors': {errors.CREATE_INSTANCE_ERROR.format(line=13)}
        }
    }

    # Below is expected date errors for test_cycle_task_date_error. They should
    # be shown during date validator's tests.
    self.expected_date_error = {
        'Cycle Task': {
            'row_errors': {
                errors.INVALID_START_END_DATES.format(
                    line=3,
                    start_date="Start Date",
                    end_date="End Date",
                ),
                errors.INVALID_STATUS_DATE_CORRELATION.format(
                    line=4,
                    date="Actual Finish Date",
                    status="not Finished",
                ),
                errors.INVALID_STATUS_DATE_CORRELATION.format(
                    line=5,
                    date="Actual Verified Date",
                    status="not Verified",
                ),
                errors.INVALID_STATUS_DATE_CORRELATION.format(
                    line=6,
                    date="Actual Verified Date",
                    status="not Verified",
                ),
                errors.INVALID_START_END_DATES.format(
                    line=7,
                    start_date="Actual Finish Date",
                    end_date="Actual Verified Date",
                ),
                errors.INVALID_START_END_DATES.format(
                    line=8,
                    start_date="Start Date",
                    end_date="End Date",
                ),
                errors.MISSING_VALUE_ERROR.format(
                    line=9,
                    column_name="Actual Finish Date",
                ),
                errors.INVALID_START_END_DATES.format(
                    line=10,
                    start_date="Actual Finish Date",
                    end_date="Actual Verified Date",
                ),
            },
        }
    }
    # Below is expected cycle-tasks data which should appear in test DB after
    # test_cycle_task_date_error run
    self.expected_cycle_task_date_error = dict()
    self.expected_cycle_task_date_error.update(
        self.generated_cycle_tasks_active)
    self.expected_cycle_task_date_error.update(
        self.generated_cycle_tasks_historical)
    self.expected_cycle_task_date_error["CYCLETASK-9"] = (
        self.expected_cycle_task_correct["CYCLETASK-9"])
    self.expected_cycle_task_date_error["CYCLETASK-10"] = (
        self.expected_cycle_task_correct["CYCLETASK-10"])

    # Expected error message which should be shown after
    # test_cycle_task_permission_error run
    self.expected_permission_error = {
        'Cycle Task': {
            'block_errors': {errors.PERMISSION_ERROR.format(line=2)}
        }
    }