From 013542165590f5f46050b89755c294e22ec1a861 Mon Sep 17 00:00:00 2001 From: JKuijperM Date: Fri, 31 Jul 2026 11:03:30 +0200 Subject: [PATCH] Added other test to the navigation --- expenses_manager/expenses/tests/test_fuel.py | 162 +++++++++++++++++++ 1 file changed, 162 insertions(+) diff --git a/expenses_manager/expenses/tests/test_fuel.py b/expenses_manager/expenses/tests/test_fuel.py index 72be9a4..c00a4e6 100644 --- a/expenses_manager/expenses/tests/test_fuel.py +++ b/expenses_manager/expenses/tests/test_fuel.py @@ -67,3 +67,165 @@ def test_fuel_delete_post_cascades_to_fuelentry(auth_client, user, account, cate assert not Expense.objects.filter(pk=expense.pk).exists() assert not FuelEntry.objects.filter(pk=entry.pk).exists() + + +def _edit_payload(account, edit_date, amount, odometer, liters, next_url=None): + payload = { + "date": edit_date.strftime("%Y-%m-%d"), + "amount": str(amount), + "account": account.pk, + "odometer": str(odometer), + "liters": str(liters), + } + if next_url is not None: + payload["next"] = next_url + return payload + + +def test_fuel_edit_post_updates_expense_and_fuelentry(auth_client, user, account, category): + entry = _make_fuel_entry(user, account, category, odometer=1000, liters=Decimal("20"), amount=Decimal("50")) + expense = entry.expense + new_date = date(2024, 3, 1) + + response = auth_client.post( + reverse('fuel_edit', args=[expense.pk]), + _edit_payload(account, new_date, Decimal("45.50"), 1200, Decimal("22.5")), + ) + + assert response.status_code == 302 + + expense.refresh_from_db() + entry.refresh_from_db() + + assert expense.amount == Decimal("45.50") + assert expense.date == new_date + assert expense.account_id == account.pk + assert entry.odometer == 1200 + assert entry.liters == Decimal("22.5") + + +def test_fuel_edit_invalid_post_returns_200_and_does_not_modify(auth_client, user, account, category): + entry = _make_fuel_entry(user, account, category, odometer=1000, liters=Decimal("20"), amount=Decimal("50")) + expense = entry.expense + original_date = expense.date + + payload = _edit_payload(account, date(2024, 3, 1), Decimal("45.50"), 1200, Decimal("22.5")) + payload["liters"] = "" + + response = auth_client.post(reverse('fuel_edit', args=[expense.pk]), payload) + + assert response.status_code == 200 + + expense.refresh_from_db() + entry.refresh_from_db() + + assert expense.amount == Decimal("50") + assert expense.date == original_date + assert entry.odometer == 1000 + assert entry.liters == Decimal("20") + + +def test_fuel_edit_redirects_to_next_when_relative(auth_client, user, account, category): + entry = _make_fuel_entry(user, account, category, odometer=1000, liters=Decimal("20")) + expense = entry.expense + next_url = reverse('expense_list') + + response = auth_client.post( + reverse('fuel_edit', args=[expense.pk]), + _edit_payload(account, date(2024, 3, 1), Decimal("45.50"), 1200, Decimal("22.5"), next_url=next_url), + ) + + assert response.status_code == 302 + assert response.url == next_url + + +def test_fuel_edit_ignores_external_next(auth_client, user, account, category): + entry = _make_fuel_entry(user, account, category, odometer=1000, liters=Decimal("20")) + expense = entry.expense + + response = auth_client.post( + reverse('fuel_edit', args=[expense.pk]), + _edit_payload( + account, date(2024, 3, 1), Decimal("45.50"), 1200, Decimal("22.5"), + next_url="https://evil.com", + ), + ) + + assert response.status_code == 302 + assert response.url == reverse('expense_list') + + +def test_fuel_delete_get_does_not_delete(auth_client, user, account, category): + entry = _make_fuel_entry(user, account, category, odometer=1000, liters=Decimal("20")) + expense = entry.expense + + response = auth_client.get(reverse('fuel_delete', args=[expense.pk])) + + assert response.status_code == 200 + assert Expense.objects.filter(pk=expense.pk).exists() + assert FuelEntry.objects.filter(pk=entry.pk).exists() + + +def test_fuel_delete_get_cancel_link_uses_next_when_provided(auth_client, user, account, category): + entry = _make_fuel_entry(user, account, category, odometer=1000, liters=Decimal("20")) + expense = entry.expense + next_url = reverse('expense_list') + + response = auth_client.get(reverse('fuel_delete', args=[expense.pk]), {"next": next_url}) + + assert response.status_code == 200 + assert f'Cancelar'.encode() in response.content + + +def test_fuel_delete_get_cancel_link_falls_back_to_fuel_list_without_next(auth_client, user, account, category): + entry = _make_fuel_entry(user, account, category, odometer=1000, liters=Decimal("20")) + expense = entry.expense + fuel_list_url = reverse('fuel_list') + + response = auth_client.get(reverse('fuel_delete', args=[expense.pk])) + + assert response.status_code == 200 + assert f'Cancelar'.encode() in response.content + + +def test_fuel_delete_post_redirects_to_next_when_relative(auth_client, user, account, category): + entry = _make_fuel_entry(user, account, category, odometer=1000, liters=Decimal("20")) + expense = entry.expense + next_url = reverse('expense_list') + + response = auth_client.post(reverse('fuel_delete', args=[expense.pk]), {"next": next_url}) + + assert response.status_code == 302 + assert response.url == next_url + + +def test_fuel_delete_post_ignores_external_next(auth_client, user, account, category): + entry = _make_fuel_entry(user, account, category, odometer=1000, liters=Decimal("20")) + expense = entry.expense + + response = auth_client.post(reverse('fuel_delete', args=[expense.pk]), {"next": "https://evil.com"}) + + assert response.status_code == 302 + assert response.url == reverse('fuel_list') + + +def test_fuel_delete_get_ignores_unsafe_next_in_cancel_link(auth_client, user, account, category): + entry = _make_fuel_entry(user, account, category, odometer=1000, liters=Decimal("20")) + expense = entry.expense + fuel_list_url = reverse('fuel_list') + + response = auth_client.get(reverse('fuel_delete', args=[expense.pk]), {"next": "javascript:alert(1)"}) + + assert response.status_code == 200 + assert b"javascript:" not in response.content + assert f'Cancelar'.encode() in response.content + + +def test_fuel_edit_get_ignores_unsafe_next_in_cancel_link(auth_client, user, account, category): + entry = _make_fuel_entry(user, account, category, odometer=1000, liters=Decimal("20")) + expense = entry.expense + + response = auth_client.get(reverse('fuel_edit', args=[expense.pk]), {"next": "javascript:alert(1)"}) + + assert response.status_code == 200 + assert b"javascript:" not in response.content