예제 #1
0
파일: views.py 프로젝트: tovmeod/anaf
def task_status_add(request, response_format='html'):
    """TaskStatus add"""

    if not request.user.profile.is_admin('anaf.projects'):
        return user_denied(request, message="You don't have administrator access to the Projects module")

    if request.POST:
        if 'cancel' not in request.POST:
            status = TaskStatus()
            form = TaskStatusForm(
                request.user.profile, request.POST, instance=status)
            if form.is_valid():
                status = form.save()
                status.set_user_from_request(request)
                return HttpResponseRedirect(reverse('projects_index_by_status', args=[status.id]))
        else:
            return HttpResponseRedirect(reverse('projects_settings_view'))
    else:
        form = TaskStatusForm(request.user.profile)

    context = _get_default_context(request)
    context.update({'form': form})

    return render_to_response('projects/status_add', context,
                              context_instance=RequestContext(request), response_format=response_format)
예제 #2
0
    def setUp(self):
        self.project = Project(name='test')
        self.project.save()

        self.taskstatus = TaskStatus(name='test')
        self.taskstatus.save()

        self.task = Task(name='test', project=self.project, status=self.taskstatus)
        self.task.save()
예제 #3
0
    def setUp(self):
        self.group, created = Group.objects.get_or_create(name='test')
        self.user, created = DjangoUser.objects.get_or_create(username=self.username)
        self.user.set_password(self.password)
        self.user.save()
        perspective, created = Perspective.objects.get_or_create(name='default')
        perspective.set_default_user()
        perspective.save()

        ModuleSetting.set('default_perspective', perspective.id)

        self.contact_type = ContactType(name='test')
        self.contact_type.set_default_user()
        self.contact_type.save()

        self.contact = Contact(name='test', contact_type=self.contact_type)
        self.contact.related_user = self.user.profile
        self.contact.set_default_user()
        self.contact.save()

        self.project = Project(name='test', manager=self.contact, client=self.contact)
        self.project.set_default_user()
        self.project.save()

        self.status = TaskStatus(name='test')
        self.status.set_default_user()
        self.status.save()

        self.milestone = Milestone(name='test', project=self.project, status=self.status)
        self.milestone.set_default_user()
        self.milestone.save()

        self.task = Task(name='test', project=self.project, status=self.status, caller=self.contact)
        self.task.set_default_user()
        self.task.save()

        self.task_assigned = Task(name='test', project=self.project, status=self.status)
        self.task_assigned.save()
        self.task_assigned.assigned.add(self.user.profile)

        self.time_slot = TaskTimeSlot(task=self.task, details='test', time_from=datetime.now(), user=self.user.profile)
        self.time_slot.set_default_user()
        self.time_slot.save()

        self.parent = Project(name='test')
        self.parent.set_default_user()
        self.parent.save()

        self.parent_task = Task(
            name='test', project=self.project, status=self.status, priority=3)
        self.parent_task.set_default_user()
        self.parent_task.save()

        self.client = Client()

        self.client.login(username=self.username, password=self.password)
예제 #4
0
 def test_model_task_status(self):
     """Test task status"""
     obj = TaskStatus(name='test')
     obj.save()
     self.assertEquals('test', obj.name)
     self.assertNotEquals(obj.id, None)
     obj.get_absolute_url()
     obj.delete()
예제 #5
0
    def setUp(self):
        self.group, created = Group.objects.get_or_create(name='test_group')
        self.user, created = DjangoUser.objects.get_or_create(username=self.username)
        self.user.set_password(self.password)
        self.user.save()

        self.project = Project(name='test')
        self.project.save()

        self.taskstatus = TaskStatus(name='test')
        self.taskstatus.save()

        self.task = Task(name='test', project=self.project, status=self.taskstatus)
        self.task.save()

        self.time_from = datetime(year=2015, month=8, day=3)
        self.total_time = timedelta(minutes=61)
        self.time_to = self.time_from + self.total_time
        self.timeslot = TaskTimeSlot(task=self.task, user=self.user.profile, time_from=self.time_from,
                                     time_to=self.time_to)
        self.timeslot.save()
예제 #6
0
def create_status():
    data = request.get_json()
    status = TaskStatus.create_from_dict(data)

    db_session.add(status)

    try:
        db_session.commit()
    except IntegrityError:
        db_session.rollback()
        return jsonify(dict(message='Status name must be unique.')), 409

    return jsonify(status.to_dict()), 201
예제 #7
0
    def test_create_status_from_dict_invalid_data(self):
        count_before_insert = TaskStatus.query.count()

        status_dict = dict()

        with self.assertRaises(ValidationError):
            status = TaskStatus.create_from_dict(status_dict)
            db_session.add(status)
            db_session.commit()

        count_after_insert = TaskStatus.query.count()

        self.assertEqual(count_before_insert, count_after_insert)
예제 #8
0
def create_db():
    import os
    if os.path.exists(DB_PATH):
        return

    db.create_all()

    roles = [u'user', u'operator', u'administrator']
    subjects = [u'Programming']
    categories = [
        u'ASP.NET', u'Assembler', u'C', u'C#', u'C++', u'Delphi | Pascal',
        u'Java', u'HTML | CSS | JavaScript', u'Oracle', u'Python', u'QT',
        u'SQL | MySQL | MS SQL | PL/SQL', u'Visual Basic', u'Other'
    ]
    os_list = [u'Windows', u'Unix-like']

    task_statuses = [
        ('New',
         'Client submitted the new task and operator hasn\'t got it yet'),
        ('Discussion', 'Operator discussing details with Client'),
        ('Solving', 'Task went off to solving'),
        ('Pending', 'Payment is going to be delivered soon by PayPal'),
        ('Done', 'User received solution'),
    ]

    for r in roles:
        db.session.add(Role(r))
    db.session.commit()

    for s in subjects:
        db.session.add(Subject(s))
    db.session.commit()

    s = Subject.query.filter_by(name=u'Programming').first()

    for c in categories:
        db.session.add(Category(name=c, subject_id=s.id))

    for o in os_list:
        db.session.add(OS(n=o))

    for ts in task_statuses:
        db.session.add(TaskStatus(*ts))

    db.session.commit()
예제 #9
0
    def test_create_status_from_dict_invalid_type(self):
        count_before_insert = TaskStatus.query.count()

        status_list = [
            'Odroczone'
        ]

        with self.assertRaises(TypeError):
            status = TaskStatus.create_from_dict(status_list)
            db_session.add(status)
            db_session.commit()

        count_after_insert = TaskStatus.query.count()

        status = TaskStatus.query.filter_by(name='Odroczone').first()

        self.assertIsNone(status)
        self.assertEqual(count_before_insert, count_after_insert)
예제 #10
0
    def test_create_status_from_dict(self):
        count_before_insert = TaskStatus.query.count()

        status_dict = dict(
            name='Odroczone'
        )

        status = TaskStatus.create_from_dict(status_dict)
        db_session.add(status)
        db_session.commit()

        count_after_insert = TaskStatus.query.count()

        self.assertEqual(count_before_insert + 1, count_after_insert)

        status = TaskStatus.query.filter_by(name='Odroczone').first()

        self.assertIsNotNone(status)
        self.assertEqual(status_dict['name'], status.name)
예제 #11
0
    def test_create_status_duplicate(self):
        status_dict = dict(
            name='Odroczone',
        )

        status = TaskStatus.create_from_dict(status_dict)
        db_session.add(status)
        db_session.commit()

        count_before_insert = TaskStatus.query.count()

        response = self.client.post(
            '/task/status',
            data=json.dumps(status_dict),
            headers={'Content-Type': 'application/json'}
        )

        count_after_insert = TaskStatus.query.count()

        self.assertStatus(response, 409)
        self.assertEqual(count_before_insert, count_after_insert)
예제 #12
0
    def test_update_status_duplicate_data(self):
        status_dict = dict(
            name='Odroczone',
        )

        status = TaskStatus.create_from_dict(status_dict)
        db_session.add(status)
        db_session.commit()

        status2 = TaskStatus.query.first()

        response = self.client.put(
            '/task/status/' + str(status2.id),
            data=json.dumps(status_dict),
            headers={'Content-Type': 'application/json'}
        )

        self.assertStatus(response, 409)

        status2 = TaskStatus.query.first()

        self.assertNotEqual(status2.name, status_dict['name'])
예제 #13
0
class ProjectsViewsTest(TestCase):
    username = "******"
    password = "******"

    def setUp(self):
        self.group, created = Group.objects.get_or_create(name='test')
        self.user, created = DjangoUser.objects.get_or_create(username=self.username)
        self.user.set_password(self.password)
        self.user.save()
        perspective, created = Perspective.objects.get_or_create(name='default')
        perspective.set_default_user()
        perspective.save()

        ModuleSetting.set('default_perspective', perspective.id)

        self.contact_type = ContactType(name='test')
        self.contact_type.set_default_user()
        self.contact_type.save()

        self.contact = Contact(name='test', contact_type=self.contact_type)
        self.contact.related_user = self.user.profile
        self.contact.set_default_user()
        self.contact.save()

        self.project = Project(name='test', manager=self.contact, client=self.contact)
        self.project.set_default_user()
        self.project.save()

        self.status = TaskStatus(name='test')
        self.status.set_default_user()
        self.status.save()

        self.milestone = Milestone(name='test', project=self.project, status=self.status)
        self.milestone.set_default_user()
        self.milestone.save()

        self.task = Task(name='test', project=self.project, status=self.status, caller=self.contact)
        self.task.set_default_user()
        self.task.save()

        self.task_assigned = Task(name='test', project=self.project, status=self.status)
        self.task_assigned.save()
        self.task_assigned.assigned.add(self.user.profile)

        self.time_slot = TaskTimeSlot(task=self.task, details='test', time_from=datetime.now(), user=self.user.profile)
        self.time_slot.set_default_user()
        self.time_slot.save()

        self.parent = Project(name='test')
        self.parent.set_default_user()
        self.parent.save()

        self.parent_task = Task(
            name='test', project=self.project, status=self.status, priority=3)
        self.parent_task.set_default_user()
        self.parent_task.save()

        self.client = Client()

        self.client.login(username=self.username, password=self.password)

    def test_index(self):
        """Test project index page with login at /projects/"""
        response = self.client.get(reverse('projects'))
        self.assertEquals(response.status_code, 200)

    def assertQuerysetEqual(self, qs, values, transform=repr, ordered=True, msg=None):
        return super(ProjectsViewsTest, self).assertQuerysetEqual(qs, map(repr, values), transform, ordered, msg)

    def test_index_owned(self):
        """Test owned tasks page at /task/owned/"""
        response = self.client.get(reverse('projects_index_owned'))
        self.assertEquals(response.status_code, 200)
        self.assertQuerysetEqual(response.context['milestones'], [self.milestone])
        self.assertQuerysetEqual(response.context['tasks'], [self.task])
        self.assertEqual(type(response.context['filters']), FilterForm)
        # todo: actually test the form generated, if it has the right fields and querysets
        # self.assertEqual(str(response.context['filters']), str(filterform))

    def test_index_assigned(self):
        """Test assigned tasks page at /task/assigned/"""
        response = self.client.get(reverse('projects_index_assigned'))
        self.assertEquals(response.status_code, 200)
        self.assertQuerysetEqual(response.context['milestones'], [self.milestone])
        self.assertQuerysetEqual(response.context['tasks'], [self.task_assigned])
        self.assertEqual(type(response.context['filters']), FilterForm)

    # Projects
    def test_project_add(self):
        """Test index page with login at /projects/add/"""
        response = self.client.get(reverse('project_add'))
        self.assertEquals(response.status_code, 200)
        self.assertEqual(type(response.context['form']), ProjectForm)

        projects_qty = Project.objects.count()
        form_params = {'name': 'project_name', 'details': 'new project details'}
        response = self.client.post(reverse('project_add'), data=form_params)
        self.assertEquals(response.status_code, 302)
        project_id = response['Location'].split('/')[-1]
        self.assertRedirects(response, reverse('projects_project_view', args=[project_id]))
        self.assertEqual(Project.objects.count(), projects_qty+1)
        project = Project.objects.get(id=project_id)
        self.assertEqual(project.name, form_params['name'])
        self.assertEqual(project.details, form_params['details'])

    def test_project_add_typed(self):
        """Test index page with login at /projects/add/<project_id>/"""
        response = self.client.get(reverse('projects_project_add_typed', args=[self.parent.id]))
        self.assertEquals(response.status_code, 200)

    def test_project_view_login(self):
        """Test index page with login at /projects/view/<project_id>"""
        response = self.client.get(reverse('projects_project_view', args=[self.project.id]))
        self.assertEquals(response.status_code, 200)

    def test_project_edit_login(self):
        """Test index page with login at /projects/edit//<project_id>"""
        response = self.client.get(reverse('projects_project_edit', args=[self.project.id]))
        self.assertEquals(response.status_code, 200)

    def test_project_delete_login(self):
        """Test index page with login at /projects/delete//<project_id>"""
        response = self.client.get(reverse('projects_project_delete', args=[self.project.id]))
        self.assertEquals(response.status_code, 200)

    # Milestones
    def test_milestone_add(self):
        """Test index page with login at /projects/milestone/add"""
        response = self.client.get(reverse('projects_milestone_add'))
        self.assertEquals(response.status_code, 200)

    def test_milestone_add_typed(self):
        """Test index page with login at /projects/milestone/add/<project_id>"""
        response = self.client.get(reverse('projects_milestone_add_typed', args=[self.parent.id]))
        self.assertEquals(response.status_code, 200)

    def test_milestone_view_login(self):
        """Test index page with login at /projects/milestone/view/<milestone_id>"""
        response = self.client.get(reverse('projects_milestone_view', args=[self.milestone.id]))
        self.assertEquals(response.status_code, 200)

    def test_milestone_edit_login(self):
        """Test index page with login at /projects/milestone/edit/<milestone_id>"""
        response = self.client.get(reverse('projects_milestone_edit', args=[self.milestone.id]))
        self.assertEquals(response.status_code, 200)

    def test_milestone_delete_login(self):
        """Test index page with login at /projects/milestone/delete/<milestone_id>"""
        response = self.client.get(reverse('projects_milestone_delete', args=[self.milestone.id]))
        self.assertEquals(response.status_code, 200)

    # Tasks
    def test_task_add(self):
        """Test index page with login at /projects/task/add/"""
        response = self.client.get(reverse('projects_task_add'))
        self.assertEquals(response.status_code, 200)

    def test_task_add_typed(self):
        """Test index page with login at /projects/task/add/<project_id>"""
        response = self.client.get(reverse('projects_task_add_typed', args=[self.project.id]))
        self.assertEquals(response.status_code, 200)

    def test_task_add_to_milestone(self):
        """Test index page with login at /projects/task/add/<milestone_id>"""
        response = self.client.get(reverse('projects_task_add_to_milestone', args=[self.milestone.id]))
        self.assertEquals(response.status_code, 200)

    def test_task_add_subtask(self):
        """Test index page with login at /projects/task/add/<task_id>/"""
        response = self.client.get(reverse('projects_task_add_subtask', args=[self.parent_task.id]))
        self.assertEquals(response.status_code, 200)

    def test_task_set_status(self):
        """Test index page with login at /projects/task/add/<task_id>/status/<status_id>"""
        response = self.client.get(reverse('projects_task_set_status', args=[self.task.id, self.status.id]))
        self.assertEquals(response.status_code, 200)

    def test_task_view_login(self):
        """Test index page with login at /projects/task/view/<task_id>"""
        response = self.client.get(reverse('projects_task_view', args=[self.task.id]))
        self.assertEquals(response.status_code, 200)

    def test_task_edit_login(self):
        """Test index page with login at /projects/task/edit/<task_id>"""
        response = self.client.get(reverse('projects_task_edit', args=[self.task.id]))
        self.assertEquals(response.status_code, 200)

    def test_task_delete_login(self):
        """Test index page with login at /projects/task/delete/<task_id>"""
        response = self.client.get(reverse('projects_task_delete', args=[self.task.id]))
        self.assertEquals(response.status_code, 200)

    # Task Time Slots
    def test_time_slot_add(self):
        """Test index page with login at /projects/task/view/time/<task_id>add/"""
        response = self.client.get(reverse('projects_task_time_slot_add', args=[self.task.id]))
        self.assertEquals(response.status_code, 200)

    def test_time_slot_view_login(self):
        """Test index page with login at /projects/task/view/time/<time_slot_id>"""
        response = self.client.get(reverse('projects_task_view', args=[self.task.id]))
        self.assertEquals(response.status_code, 200)

    def test_time_slot_edit_login(self):
        """Test index page with login at /projects/task/edit/time/<time_slot_id>"""
        response = self.client.get(reverse('projects_task_edit', args=[self.task.id]))
        self.assertEquals(response.status_code, 200)

    def test_time_slot_delete_login(self):
        """Test index page with login at /projects/task/delete/time/<time_slot_id>"""
        response = self.client.get(reverse('projects_task_delete', args=[self.task.id]))
        self.assertEquals(response.status_code, 200)

    # Task Statuses
    def test_task_status_add(self):
        """Test index page with login at /projects/task/status/add/"""
        response = self.client.get(reverse('projects_task_status_add'))
        self.assertEquals(response.status_code, 200)

    def test_task_status_view_login(self):
        """Test index page with login at /projects/task/status/view/<status_id>/"""
        response = self.client.get(reverse('projects_index_by_status', args=[self.status.id]))
        self.assertEquals(response.status_code, 200)

    def test_task_status_edit_login(self):
        """Test index page with login at /projects/task/status/edit/<status_id>/"""
        response = self.client.get(reverse('projects_task_status_edit', args=[self.status.id]))
        self.assertEquals(response.status_code, 200)

    def test_task_status_delete_login(self):
        """Test index page with login at /projects/task/status/delete/<status_id>/"""
        response = self.client.get(reverse('projects_task_status_delete', args=[self.status.id]))
        self.assertEquals(response.status_code, 200)

    # Settings

    def test_project_settings_view(self):
        """Test index page with login at /projects/settings/view/"""
        response = self.client.get(reverse('projects_settings_view'))
        self.assertEquals(response.status_code, 200)

    def test_project_settings_edit(self):
        """Test index page with login at /projects/settings/edit/"""
        response = self.client.get(reverse('projects_settings_edit'))
        self.assertEquals(response.status_code, 200)
예제 #14
0
class TestModelTaskTimeSlot(TestCase):
    username = "******"
    password = "******"

    def setUp(self):
        self.group, created = Group.objects.get_or_create(name='test_group')
        self.user, created = DjangoUser.objects.get_or_create(username=self.username)
        self.user.set_password(self.password)
        self.user.save()

        self.project = Project(name='test')
        self.project.save()

        self.taskstatus = TaskStatus(name='test')
        self.taskstatus.save()

        self.task = Task(name='test', project=self.project, status=self.taskstatus)
        self.task.save()

        self.time_from = datetime(year=2015, month=8, day=3)
        self.total_time = timedelta(minutes=61)
        self.time_to = self.time_from + self.total_time
        self.timeslot = TaskTimeSlot(task=self.task, user=self.user.profile, time_from=self.time_from,
                                     time_to=self.time_to)
        self.timeslot.save()

    def test_get_absolute_url(self):
        self.timeslot.get_absolute_url()

    def test_get_time_secs(self):
        with freeze_time(datetime(year=2015, month=8, day=4)):
            self.assertEqual(self.timeslot.get_time_secs(), 86400)

    def test_get_time(self):
        """A time slot without a time from or time to will return a delta of 0"""
        timeslot2 = TaskTimeSlot(task=self.task, user=self.user.profile, time_from=self.time_from)
        timeslot3 = TaskTimeSlot(task=self.task, user=self.user.profile, time_to=self.time_to)
        self.assertEqual(timeslot2.get_time(), timedelta(0))
        self.assertEqual(timeslot3.get_time(), timedelta(0))
        self.assertEqual(self.timeslot.get_time(), self.total_time)

    def test_get_time_tuple(self):
        h, m, s = self.timeslot.get_time_tuple()
        self.assertEqual((h, m, s), (1, 1, 0))
        timeslot2 = TaskTimeSlot(task=self.task, user=self.user.profile, time_to=self.time_to)
        self.assertIsNone(timeslot2.get_time_tuple())

    def test_get_time_string(self):
        self.assertEqual(self.timeslot.get_time_string(), ' 1 hours  1 minutes')

        total_time = timedelta(minutes=1)
        self.timeslot.time_to = self.time_from + total_time
        self.assertEqual(self.timeslot.get_time_string(), ' 1 minutes')

        # if it has a timedelta of zero it will use now-time_from
        total_time = timedelta(minutes=0)
        self.timeslot.time_to = self.time_from + total_time
        with freeze_time(datetime(year=2015, month=8, day=4)):
            self.assertEqual(self.timeslot.get_time_string(), '24 hours ')

        total_time = timedelta(seconds=30)
        self.timeslot.time_to = self.time_from + total_time
        self.assertEqual(self.timeslot.get_time_string(), 'Less than 1 minute')

        total_time = timedelta(minutes=60)
        self.timeslot.time_to = self.time_from + total_time
        self.assertEqual(self.timeslot.get_time_string(), ' 1 hours ')

        self.timeslot.time_from = None
        self.assertEqual(self.timeslot.get_time_string(), '')

        self.timeslot.time_from = self.time_from
        self.timeslot.time_to = None
        with freeze_time(datetime(year=2015, month=8, day=4)):
            self.assertEqual(self.timeslot.get_time_string(), '24 hours ')

    def test_is_open(self):
        # a time slot with both time_from and time_to means it is closed
        self.assertFalse(self.timeslot.is_open())
        self.timeslot.time_to = None
        self.assertTrue(self.timeslot.is_open())
예제 #15
0
 def test_model_milestone(self):
     tstatus = TaskStatus(name='test')
     tstatus.save()
     mstone = Milestone(project=self.project, status=tstatus)
     mstone.save()
     mstone.get_absolute_url()
예제 #16
0
class ProjectsModelsTest(TestCase):
    """ Documents models tests"""
    def setUp(self):
        self.project = Project(name='test')
        self.project.save()

        self.taskstatus = TaskStatus(name='test')
        self.taskstatus.save()

        self.task = Task(name='test', project=self.project, status=self.taskstatus)
        self.task.save()

    def test_task_priority_human(self):
        """Default priority should be 3, text representation should be 'Normal'
        """
        self.assertEqual(self.task.priority, 3)
        self.assertEqual(self.task.priority_human(), 'Normal')

    def test_get_estimated_time_default(self):
        """Default estimated time is None, string representation is empty string """
        self.assertIsNone(self.task.estimated_time)
        self.assertEqual(self.task.get_estimated_time(), '')

    def test_get_estimated_time_one_min(self):
        self.task.estimated_time = 1
        self.assertEqual(self.task.get_estimated_time(), ' 1 minutes')

    def test_get_estimated_time_zero_min(self):
        self.task.estimated_time = 0
        self.assertEqual(self.task.get_estimated_time(), 'Less than 1 minute')

    def test_get_estimated_time_60_min(self):
        self.task.estimated_time = 60
        self.assertEqual(self.task.get_estimated_time(), ' 1 hours ')

    def test_get_estimated_time_61_min(self):
        self.task.estimated_time = 61
        self.assertEqual(self.task.get_estimated_time(), ' 1 hours  1 minutes')

    def test_model_task_get_absolute_url(self):
        self.task.get_absolute_url()

    # def test_save TODO: save is overridden and has some extra logic

    def test_get_absolute_url(self):
        """Test if get_absolute_url works without raising any exception"""
        self.project.get_absolute_url()

    def add_time_slot(self, total_time):
        duser, created = DjangoUser.objects.get_or_create(username='******')
        time_from = datetime(year=2015, month=8, day=3)
        time_to = time_from + total_time
        timeslot = TaskTimeSlot(task=self.task, user=duser.profile, time_from=time_from, time_to=time_to)
        timeslot.save()

    def test_get_total_time_default(self):
        self.assertEqual(self.task.get_total_time(), timedelta())

    def test_get_total_time_with_timeslots1(self):
        total_time = timedelta(hours=3)
        self.add_time_slot(total_time)
        self.assertEqual(self.task.get_total_time(), total_time)

    def test_get_total_time_tuple_default(self):
        self.assertIsNone(self.task.get_total_time_tuple())

    def test_get_total_time_tuple(self):
        total_time = timedelta(hours=3)
        self.add_time_slot(total_time)
        h, m, s = self.task.get_total_time_tuple()
        self.assertEqual((h, m, s), (3, 0, 0))

    def test_get_total_time_string_default(self):
        self.assertEqual(self.task.get_total_time_string(), '0 minutes')

    def test_get_total_time_string_one_min(self):
        total_time = timedelta(minutes=1)
        self.add_time_slot(total_time)
        self.assertEqual(self.task.get_total_time_string(), ' 1 minutes')

    def test_get_total_time_string_zero_min(self):
        total_time = timedelta(minutes=0)
        self.add_time_slot(total_time)
        self.assertEqual(self.task.get_total_time_string(), '0 minutes')

    def test_get_total_time_string_30_secs(self):
        total_time = timedelta(seconds=30)
        self.add_time_slot(total_time)
        self.assertEqual(self.task.get_total_time_string(), 'Less than 1 minute')

    def test_get_total_time_string_60_min(self):
        total_time = timedelta(minutes=60)
        self.add_time_slot(total_time)
        self.assertEqual(self.task.get_total_time_string(), ' 1 hours ')

    def test_get_total_time_string_61_min(self):
        total_time = timedelta(minutes=61)
        self.add_time_slot(total_time)
        self.assertEqual(self.task.get_total_time_string(), ' 1 hours  1 minutes')

    def test_is_being_done_by(self):
        duser, created = DjangoUser.objects.get_or_create(username='******')
        self.assertFalse(self.task.is_being_done_by(duser.profile))

        time_from = datetime(year=2015, month=8, day=3)
        timeslot = TaskTimeSlot(task=self.task, user=duser.profile, time_from=time_from)
        timeslot.save()
        self.task.save()

        self.assertTrue(self.task.is_being_done_by(duser.profile))

    def test_model_task_status(self):
        """Test task status"""
        obj = TaskStatus(name='test')
        obj.save()
        self.assertEquals('test', obj.name)
        self.assertNotEquals(obj.id, None)
        obj.get_absolute_url()
        obj.delete()

    def test_model_milestone(self):
        tstatus = TaskStatus(name='test')
        tstatus.save()
        mstone = Milestone(project=self.project, status=tstatus)
        mstone.save()
        mstone.get_absolute_url()