diff --git a/expenses_manager/expenses/tests/test_dashboard.py b/expenses_manager/expenses/tests/test_dashboard.py index 3e0d2b7..469db7f 100644 --- a/expenses_manager/expenses/tests/test_dashboard.py +++ b/expenses_manager/expenses/tests/test_dashboard.py @@ -2,7 +2,7 @@ import pytest from datetime import date from decimal import Decimal from django.urls import reverse -from expenses.models import Expense, Category +from expenses.models import Account, Expense, Category, Income pytestmark = pytest.mark.django_db @@ -80,3 +80,146 @@ def test_dashboard_filters_by_year(auth_client, user, account, category): assert len(chart_data) == 12 assert chart_data[4] == 20.0 # May = month 5 -> index 4 assert sum(chart_data) == 20.0 # only the 2024 expense contributes + + +def test_dashboard_preset_this_month(auth_client): + today = date.today() + + response = auth_client.get(reverse('dashboard'), {'period': 'this_month'}) + + assert response.context['selected_year'] == today.year + assert response.context['selected_month'] == today.month + + +def test_dashboard_preset_last_month(auth_client): + today = date.today() + expected_month = today.month - 1 or 12 + expected_year = today.year if today.month > 1 else today.year - 1 + + response = auth_client.get(reverse('dashboard'), {'period': 'last_month'}) + + assert response.context['selected_year'] == expected_year + assert response.context['selected_month'] == expected_month + + +def test_dashboard_preset_this_year_has_no_month(auth_client): + today = date.today() + + response = auth_client.get(reverse('dashboard'), {'period': 'this_year'}) + + assert response.context['selected_year'] == today.year + assert response.context['selected_month'] is None + + +def test_dashboard_filters_by_account(auth_client, user, account, category): + other = Account.objects.create( + owner=user, name="Otra", initial_balance=Decimal("100"), active=True + ) + Expense.objects.create( + owner=user, account=account, category=category, + amount=Decimal("10"), date=date(2024, 3, 1), + ) + Expense.objects.create( + owner=user, account=other, category=category, + amount=Decimal("25"), date=date(2024, 3, 1), + ) + + response = auth_client.get( + reverse('dashboard'), + {'year': 2024, 'account': other.id}, + ) + + assert response.context['kpi_total'] == Decimal('25') + assert response.context['kpi_count'] == 1 + assert response.context['kpi_balance'] == Decimal('75') # 100 - 25 + + +def test_dashboard_without_compare_keeps_comparison_defaults(auth_client): + response = auth_client.get(reverse('dashboard'), {'year': 2024}) + + assert response.context['compare_enabled'] is False + assert response.context['kpi_previous_total'] == 0 + assert response.context['kpi_difference'] == 0 + assert response.context['kpi_percentage'] == 0 + assert response.context['kpi_trend'] == 'equal' + assert response.context['category_comparison'] == [] + + +def test_dashboard_compare_fills_difference_and_trend(auth_client, user, account, category): + Expense.objects.create( + owner=user, account=account, category=category, + amount=Decimal("20"), date=date(2024, 2, 15), + ) + Expense.objects.create( + owner=user, account=account, category=category, + amount=Decimal("30"), date=date(2024, 3, 10), + ) + + response = auth_client.get( + reverse('dashboard'), + {'year': 2024, 'month': 3, 'compare': '1'}, + ) + + assert response.context['compare_enabled'] is True + assert response.context['kpi_previous_total'] == Decimal('20') + assert response.context['kpi_difference'] == Decimal('10') + assert response.context['kpi_trend'] == 'up' + assert float(response.context['kpi_percentage']) == 50.0 + + rows = {row['category']: row for row in response.context['category_comparison']} + assert rows[category.name]['current'] == 30.0 + assert rows[category.name]['previous'] == 20.0 + assert rows[category.name]['difference'] == 10.0 + + +def test_dashboard_chart_type_is_day_when_a_month_is_selected(auth_client): + response = auth_client.get(reverse('dashboard'), {'year': 2024, 'month': 3}) + + assert response.context['chart_type'] == 'day' + + +def test_dashboard_chart_type_is_month_for_the_whole_year(auth_client): + response = auth_client.get(reverse('dashboard'), {'year': 2024}) + + assert response.context['chart_type'] == 'month' + + +def test_dashboard_category_chart_keeps_only_top_ten(auth_client, user, account): + for i in range(12): + cat = Category.objects.create(name=f"Cat {i:02d}", owner=user) + Expense.objects.create( + owner=user, account=account, category=cat, + amount=Decimal(str(i + 1)), date=date(2024, 6, 1), + ) + + response = auth_client.get(reverse('dashboard'), {'year': 2024}) + + assert len(response.context['by_category_chart']) == 10 + assert len(list(response.context['by_category'])) == 12 + + +def test_dashboard_kpi_balance_matches_sum_of_current_balances(auth_client, user, account, category): + savings = Account.objects.create( + owner=user, name="Ahorro", initial_balance=Decimal("500"), active=True + ) + Account.objects.create( + owner=user, name="Cerrada", initial_balance=Decimal("999"), active=False + ) + + Expense.objects.create( + owner=user, account=account, category=category, + amount=Decimal("40"), date=date(2024, 4, 1), + ) + Income.objects.create( + owner=user, account=savings, name="Nomina", + amount=Decimal("60"), date=date(2024, 4, 2), + ) + + response = auth_client.get(reverse('dashboard'), {'year': 2024}) + + expected = sum( + acc.current_balance() + for acc in Account.objects.filter(owner=user, active=True) + ) + assert expected == Decimal('520') # (0 - 40) + (500 + 60), sin la inactiva + assert response.context['kpi_balance'] == expected