Beispiel #1
0
    def test_project_admin_queryset_is_annotated_with_latest_charge(self):
        Project(name='Test').validate_and_save()
        Project(name='Test 2').validate_and_save()

        queryset = self.model_admin.get_queryset(HttpRequest())

        for project in queryset:
            self.assertTrue(hasattr(project, 'db_latest_charge'))
Beispiel #2
0
    def test_project_name_must_be_unique(self):
        test_name = 'Test'

        Project(name=test_name).validate_and_save()

        with self.assertRaises(ValidationError) as context_manager:
            Project(name=test_name).validate_and_save()

        self.assertValidationMessagePresent(
            context_manager.exception.error_dict,
            field='name',
            error_code='unique')
Beispiel #3
0
    def test_dashboard_view_has_all_projects_selected_unless_otherwise_specified(self):
        project_a = Project(name='Project A').validate_and_save()
        project_b = Project(name='Project B').validate_and_save()

        self.performLogin()

        response = self.client.get(reverse('admin:dashboard'))

        self.assertEqual(response.context['projects'], [
            {'id': project_a.pk, 'name': project_a.name, 'selected': True},
            {'id': project_b.pk, 'name': project_b.name, 'selected': True}
        ])
Beispiel #4
0
    def test_dashboard_view_has_correct_projects_selected_based_on_request_params(self):
        project_a = Project(name='Project A').validate_and_save()
        project_b = Project(name='Project B').validate_and_save()

        self.performLogin()

        response = self.client.get('{url}?project={project}'.format(
            url=reverse('admin:dashboard'),
            project=project_a.pk
        ))

        self.assertEqual(response.context['projects'], [
            {'id': project_a.pk, 'name': project_a.name, 'selected': True},
            {'id': project_b.pk, 'name': project_b.name, 'selected': False}
        ])
Beispiel #5
0
 def test_charge_update_view_redirects_when_not_logged_in(self):
     now = timezone.now()
     project = Project(name='Test').validate_and_save()
     charge = Charge(project=project, start_time=now).validate_and_save()
     response = self.client.get(
         reverse('project:charge-update', args=(charge.pk, )))
     self.assertEqual(response.status_code, 302)
Beispiel #6
0
    def test_project_admin_has_read_only_project_name_when_project_is_not_active(
            self):
        project = Project(name='Test', active=False).validate_and_save()
        readonly_fields = self.model_admin.get_readonly_fields(
            HttpRequest, project)

        self.assertSequenceEqual(readonly_fields, ('name', ))
Beispiel #7
0
    def test_project_name_field_cannot_exceed_255_characters(self):
        with self.assertRaises(ValidationError) as context_manager:
            Project(name=''.zfill(256)).full_clean()

        self.assertValidationMessagePresent(
            context_manager.exception.error_dict,
            field='name',
            error_code='max_length')
Beispiel #8
0
 def test_charge_update_view_is_ok(self):
     now = timezone.now()
     self.performLogin()
     project = Project(name='Test').validate_and_save()
     charge = Charge(project=project, start_time=now).validate_and_save()
     response = self.client.get(
         reverse('project:charge-update', args=(charge.pk, )))
     self.assertEqual(response.status_code, 200)
Beispiel #9
0
 def test_charge_close_view_redirects_when_not_logged_in(self):
     now = timezone.now()
     end = now + timedelta(minutes=1)
     project = Project(name='Test').validate_and_save()
     charge = Charge(project=project, start_time=now,
                     end_time=end).validate_and_save()
     response = self.client.get(
         reverse('project:close-charge', args=(charge.pk, )))
     self.assertEqual(response.status_code, 302)
Beispiel #10
0
 def test_charge_close_view(self):
     now = timezone.now()
     end = now + timedelta(minutes=1)
     self.performLogin()
     project = Project(name='Test').validate_and_save()
     charge = Charge(project=project, start_time=now,
                     end_time=end).validate_and_save()
     response = self.client.post(
         reverse('project:close-charge', args=(charge.pk, )))
     charge.refresh_from_db()
     self.assertTrue(charge.closed)
     self.assertEqual(response.status_code, 302)
Beispiel #11
0
    def test_charge_project_must_be_active_project(self):
        start_datetime = timezone.make_aware(
            datetime(2019, 1, 1, hour=8, minute=0, second=0))

        inactive_project = Project(name='Test 2',
                                   active=False).validate_and_save()

        charge = Charge(project=inactive_project,
                        start_time=start_datetime,
                        end_time=start_datetime + timedelta(hours=1))

        with self.assertRaises(ValidationError) as context_manager:
            charge.full_clean()

        self.assertValidationMessagePresent(
            context_manager.exception.error_dict,
            field='project',
            error_code='project_must_be_active')
Beispiel #12
0
    def test_project_cannot_be_modified_when_inactive(self):
        project = Project(name='Test', active=False).validate_and_save()

        # Should raise a generic validation error if attempting to
        # save on a inactive project
        with self.assertRaises(ValidationError) as context_manager:
            project.validate_and_save()

        self.assertValidationMessagePresent(
            context_manager.exception.error_dict,
            field='__all__',
            error_code='cannot_modify_when_inactive')

        # But should be able to save the change if it is
        # re-opening the project
        project.active = True
        project.validate_and_save()
        self.assertEqual(project.active, True)
Beispiel #13
0
 def test_project_active_field_defaults_to_true(self):
     project = Project(name='Test').validate_and_save()
     self.assertTrue(project.active)
Beispiel #14
0
 def setUp(self):
     self.project = Project(name='Test').validate_and_save()
     self.model_admin = ChargeAdmin(model=Charge, admin_site=admin_site)
Beispiel #15
0
class ChargeModelAdminTestCase(TestCase):
    def setUp(self):
        self.project = Project(name='Test').validate_and_save()
        self.model_admin = ChargeAdmin(model=Charge, admin_site=admin_site)

    def test_charge_admin_date_hierarchy_is_set_to_start_time(self):
        # This property configures the admin to support browsing
        # through Charge records via a more granular date picker.
        self.assertEqual(self.model_admin.date_hierarchy, 'start_time')

    def test_charge_admin_queryset_is_annotated_with_time_charged(self):
        Charge(project=self.project,
               start_time=timezone.now()).validate_and_save()
        Charge(project=self.project,
               start_time=timezone.now()).validate_and_save()

        queryset = self.model_admin.get_queryset(HttpRequest())

        for charge in queryset:
            self.assertTrue(hasattr(charge, 'db_time_charged'))

    def test_charge_admin_list_display_contains_time_charged(self):
        self.assertTrue('time_spent' in self.model_admin.list_display)
        obj = types.SimpleNamespace()
        obj.db_time_charged = 'Test'
        self.assertEqual(self.model_admin.time_spent(obj), 'Test')

    def test_charge_admin_time_charged_field_is_sortable_in_list(self):
        self.assertTrue(
            hasattr(self.model_admin.time_spent, 'admin_order_field'))
        self.assertEqual(self.model_admin.time_spent.admin_order_field,
                         'db_time_charged')

    def test_charge_admin_has_all_fields_editable_when_creating_new_charge(
            self):
        readonly_fields = self.model_admin.get_readonly_fields(
            HttpRequest, None)

        self.assertEqual(len(readonly_fields), 0)

    def test_charge_admin_has_all_fields_editable_when_project_is_active_and_charge_is_not_closed(
            self):
        self.project.active = True
        self.project.validate_and_save()

        charge = Charge(project=self.project,
                        start_time=timezone.now(),
                        closed=False).validate_and_save()

        readonly_fields = self.model_admin.get_readonly_fields(
            HttpRequest(), charge)

        self.assertEqual(len(readonly_fields), 0)

    def test_charge_admin_has_read_only_start_and_end_time_when_project_not_active_and_charge_closed(
            self):
        charge = Charge(project=self.project,
                        start_time=timezone.now(),
                        end_time=timezone.now() + timedelta(hours=1),
                        closed=True).validate_and_save()

        self.project.active = False
        self.project.validate_and_save()

        readonly_fields = self.model_admin.get_readonly_fields(
            HttpRequest(), charge)

        self.assertSequenceEqual(readonly_fields, (
            'start_time',
            'end_time',
        ))

    def test_charge_admin_has_read_only_start_time_end_time_and_project_when_charge_is_closed(
            self):
        self.project.active = True
        self.project.validate_and_save()

        charge = Charge(project=self.project,
                        start_time=timezone.now(),
                        end_time=timezone.now() + timedelta(hours=1),
                        closed=True).validate_and_save()

        readonly_fields = self.model_admin.get_readonly_fields(
            HttpRequest(), charge)

        self.assertSequenceEqual(readonly_fields, (
            'start_time',
            'end_time',
            'project',
        ))

    def test_charge_admin_has_read_only_start_time_end_time_and_closed_status_when_project_not_active(
            self):
        charge = Charge(project=self.project,
                        start_time=timezone.now(),
                        closed=False).validate_and_save()

        self.project.active = False
        self.project.validate_and_save()

        readonly_fields = self.model_admin.get_readonly_fields(
            HttpRequest(), charge)

        self.assertSequenceEqual(readonly_fields, (
            'start_time',
            'end_time',
            'closed',
        ))
Beispiel #16
0
 def test_project_admin_has_all_fields_editable_when_project_is_active(
         self):
     project = Project(name='Test', active=True).validate_and_save()
     readonly_fields = self.model_admin.get_readonly_fields(
         HttpRequest, project)
     self.assertEqual(len(readonly_fields), 0)
Beispiel #17
0
 def test_project_update_view_redirects_when_not_logged_in(self):
     project = Project(name='Test').validate_and_save()
     response = self.client.get(
         reverse('project:project-update', args=(project.pk, )))
     self.assertEqual(response.status_code, 302)
Beispiel #18
0
 def setUpClass(cls):
     super().setUpClass()
     cls.project = Project(name='Test')
Beispiel #19
0
 def setUpTestData(cls):
     cls.project = Project(name='Test').validate_and_save()
Beispiel #20
0
 def test_project_update_view_is_ok(self):
     self.performLogin()
     project = Project(name='Test').validate_and_save()
     response = self.client.get(
         reverse('project:project-update', args=(project.pk, )))
     self.assertEqual(response.status_code, 200)
Beispiel #21
0
 def test_project_active_field_is_not_required(self):
     Project(name='Test').validate_and_save()
Beispiel #22
0
    def test_project_name_must_be_unique_in_database(self):
        test_name = 'Test'

        Project(name=test_name).validate_and_save()
        with self.assertRaises(IntegrityError):
            Project.objects.create(name=test_name)
Beispiel #23
0
    def test_project_has_descriptive_string_representation(self):
        project = Project(name='Test')
        self.assertEqual(str(project), 'Test')

        project.active = False
        self.assertEqual(str(project), 'Test (Inactive)')
Beispiel #24
0
    def test_project_can_be_created(self):
        test_name = 'Test'
        project = Project(name=test_name).validate_and_save()

        self.assertIsNotNone(project.pk)
        self.assertEqual(project.name, test_name)
Beispiel #25
0
    def test_visualization_creation_whitebox(self):
        project_a = Project(name='Project A').validate_and_save()
        project_b = Project(name='Project B').validate_and_save()

        # Create some test charges in the current month

        project_a_current_charges = [
            timedelta(hours=4),
            timedelta(hours=4),
        ]

        project_b_current_charges = [
            timedelta(hours=4),
            timedelta(hours=4),
        ]

        for charge in project_a_current_charges:
            ChargeFactory.today(project=project_a,
                                charge_time=charge).validate_and_save()

        for charge in project_b_current_charges:
            ChargeFactory.today(project=project_b,
                                charge_time=charge).validate_and_save()

        # Create some unclosed charges in the current month
        Charge(project=project_a,
               start_time=get_start_of_today()).validate_and_save()

        Charge(project=project_b,
               start_time=get_start_of_today()).validate_and_save()

        # Create charges in a past month

        ChargeFactory.past_month(
            project=project_a,
            charge_time=timedelta(hours=1)).validate_and_save()

        ChargeFactory.past_month(
            project=project_b,
            charge_time=timedelta(hours=1)).validate_and_save()

        # Create charges in a future month

        ChargeFactory.future_month(
            project=project_a,
            charge_time=timedelta(hours=1)).validate_and_save()

        ChargeFactory.future_month(
            project=project_b,
            charge_time=timedelta(hours=1)).validate_and_save()

        # Should return data on all projects

        dataframe = report_helpers.get_monthly_summary_series(
            timezone.localtime())

        self.assertIsInstance(dataframe, pd.DataFrame)
        self.assertEqual(len(dataframe), 2)

        self.assertIsInstance(dataframe['charge'], pd.Series)
        self.assertIsInstance(dataframe['value'], pd.Series)
        self.assertIsInstance(dataframe['angle'], pd.Series)
        self.assertIsInstance(dataframe['color'], pd.Series)

        project_a_dataframe = dataframe[dataframe.charge == project_a.name]
        project_b_dataframe = dataframe[dataframe.charge == project_b.name]

        self.assertFalse(project_a_dataframe.empty)
        self.assertFalse(project_b_dataframe.empty)

        self.assertEqual(project_a_dataframe.iloc[0].value, 8.0)
        self.assertEqual(project_b_dataframe.iloc[0].value, 8.0)

        self.assertIsInstance(project_a_dataframe.iloc[0].angle, float)
        self.assertIsInstance(project_b_dataframe.iloc[0].angle, float)

        self.assertIsInstance(project_a_dataframe.iloc[0].color, str)
        self.assertIsInstance(project_b_dataframe.iloc[0].color, str)

        div, chart = report_helpers.get_monthly_summary_chart_components(
            dataframe)
        self.assertGreater(len(div), 0)
        self.assertGreater(len(chart), 0)

        # Should return data on only the requested projects

        dataframe = report_helpers.get_monthly_summary_series(
            timezone.localtime(), project_ids=[project_a.pk])

        self.assertIsInstance(dataframe, pd.DataFrame)
        self.assertEqual(len(dataframe), 1)

        self.assertIsInstance(dataframe['charge'], pd.Series)
        self.assertIsInstance(dataframe['value'], pd.Series)
        self.assertIsInstance(dataframe['angle'], pd.Series)
        self.assertIsInstance(dataframe['color'], pd.Series)

        self.assertEqual(dataframe.iloc[0].charge, project_a.name)
        self.assertEqual(dataframe.iloc[0].value, 8.0)
        self.assertIsInstance(dataframe.iloc[0].angle, float)
        self.assertIsInstance(dataframe.iloc[0].color, str)

        div, chart = report_helpers.get_monthly_summary_chart_components(
            dataframe)
        self.assertGreater(len(div), 0)
        self.assertGreater(len(chart), 0)
Beispiel #26
0
    def test_project_active_field_is_set_to_given_value(self):
        project = Project(name='Test', active=True).validate_and_save()
        self.assertTrue(project.active)

        project = Project(name='Test 2', active=False).validate_and_save()
        self.assertFalse(project.active)