Files
Backend/dashboard/tests.py
T

187 lines
7.7 KiB
Python
Raw Normal View History

2026-03-26 15:39:31 +03:30
from copy import deepcopy
2026-04-02 23:25:39 +03:30
from django.contrib.auth import get_user_model
from django.test import TestCase
from rest_framework.test import APIRequestFactory, force_authenticate
2026-03-26 15:39:31 +03:30
2026-04-03 23:51:00 +03:30
from access_control.models import AccessFeature, AccessRule
2026-04-02 23:25:39 +03:30
from farm_hub.models import FarmHub, FarmType
2026-03-26 15:39:31 +03:30
2026-05-05 21:01:58 +03:30
from .defaults import DEFAULT_CONFIG
2026-04-02 23:25:39 +03:30
from .models import FarmDashboardConfig
from .views import FarmDashboardCardsView, FarmDashboardConfigView
2026-03-26 15:39:31 +03:30
2026-04-02 23:25:39 +03:30
class DashboardBaseTestCase(TestCase):
2026-03-26 15:39:31 +03:30
def setUp(self):
self.factory = APIRequestFactory()
2026-04-02 23:25:39 +03:30
self.user = get_user_model().objects.create_user(
username="farmer",
password="secret123",
email="farmer@example.com",
phone_number="09120000000",
)
self.other_user = get_user_model().objects.create_user(
username="other-farmer",
password="secret123",
email="other@example.com",
phone_number="09120000001",
)
self.farm_type = FarmType.objects.create(name="زراعی")
self.farm = FarmHub.objects.create(owner=self.user, farm_type=self.farm_type, name="Farm 1")
self.other_farm = FarmHub.objects.create(owner=self.other_user, farm_type=self.farm_type, name="Farm 2")
2026-04-03 23:51:00 +03:30
self.dashboard_feature = AccessFeature.objects.create(
code="greenhouse-dashboard",
name="Greenhouse Dashboard",
feature_type=AccessFeature.PAGE,
)
self.allow_dashboard_rule = AccessRule.objects.create(
code="allow-greenhouse-dashboard",
name="Allow Greenhouse Dashboard",
priority=10,
)
self.allow_dashboard_rule.features.add(self.dashboard_feature)
2026-03-26 15:39:31 +03:30
2026-04-02 23:25:39 +03:30
class FarmDashboardConfigViewTests(DashboardBaseTestCase):
def test_get_returns_default_config_and_persists_it(self):
request = self.factory.get(f"/api/farm-dashboard-config/?farm_uuid={self.farm.farm_uuid}")
force_authenticate(request, user=self.user)
2026-03-26 15:39:31 +03:30
response = FarmDashboardConfigView.as_view()(request)
2026-04-02 23:25:39 +03:30
expected = deepcopy(DEFAULT_CONFIG)
expected["farm_uuid"] = str(self.farm.farm_uuid)
2026-03-26 15:39:31 +03:30
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["code"], 200)
self.assertEqual(response.data["msg"], "OK")
2026-04-02 23:25:39 +03:30
self.assertEqual(response.data["data"], expected)
self.assertTrue(FarmDashboardConfig.objects.filter(farm=self.farm).exists())
def test_get_requires_farm_uuid(self):
request = self.factory.get("/api/farm-dashboard-config/")
force_authenticate(request, user=self.user)
response = FarmDashboardConfigView.as_view()(request)
self.assertEqual(response.status_code, 400)
self.assertEqual(response.data["farm_uuid"][0], "This field is required.")
def test_get_rejects_foreign_farm_uuid(self):
request = self.factory.get(f"/api/farm-dashboard-config/?farm_uuid={self.other_farm.farm_uuid}")
force_authenticate(request, user=self.user)
response = FarmDashboardConfigView.as_view()(request)
self.assertEqual(response.status_code, 400)
self.assertEqual(response.data["farm_uuid"][0], "Farm not found.")
2026-03-26 15:39:31 +03:30
def test_patch_partial_update_returns_full_final_config(self):
request = self.factory.patch(
"/api/farm-dashboard-config/",
2026-04-02 23:25:39 +03:30
{
"farm_uuid": str(self.farm.farm_uuid),
"disabled_card_ids": ["farmWeatherCard"],
},
2026-03-26 15:39:31 +03:30
format="json",
)
2026-04-02 23:25:39 +03:30
force_authenticate(request, user=self.user)
2026-03-26 15:39:31 +03:30
response = FarmDashboardConfigView.as_view()(request)
expected = deepcopy(DEFAULT_CONFIG)
2026-04-02 23:25:39 +03:30
expected["farm_uuid"] = str(self.farm.farm_uuid)
2026-03-26 15:39:31 +03:30
expected["disabled_card_ids"] = ["farmWeatherCard"]
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["data"], expected)
2026-04-02 23:25:39 +03:30
self.assertEqual(
FarmDashboardConfig.objects.get(farm=self.farm).disabled_card_ids,
["farmWeatherCard"],
)
2026-03-26 15:39:31 +03:30
def test_patch_only_drag_flag_still_returns_full_config(self):
request = self.factory.patch(
"/api/farm-dashboard-config/",
2026-04-02 23:25:39 +03:30
{
"farm_uuid": str(self.farm.farm_uuid),
"enable_drag_reorder": False,
},
2026-03-26 15:39:31 +03:30
format="json",
)
2026-04-02 23:25:39 +03:30
force_authenticate(request, user=self.user)
2026-03-26 15:39:31 +03:30
response = FarmDashboardConfigView.as_view()(request)
expected = deepcopy(DEFAULT_CONFIG)
2026-04-02 23:25:39 +03:30
expected["farm_uuid"] = str(self.farm.farm_uuid)
2026-03-26 15:39:31 +03:30
expected["enable_drag_reorder"] = False
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data["data"], expected)
self.assertIn("disabled_card_ids", response.data["data"])
self.assertIn("row_order", response.data["data"])
def test_patch_rejects_invalid_row_order(self):
request = self.factory.patch(
"/api/farm-dashboard-config/",
2026-04-02 23:25:39 +03:30
{
"farm_uuid": str(self.farm.farm_uuid),
"row_order": ["overviewKpis"],
},
2026-03-26 15:39:31 +03:30
format="json",
)
2026-04-02 23:25:39 +03:30
force_authenticate(request, user=self.user)
2026-03-26 15:39:31 +03:30
response = FarmDashboardConfigView.as_view()(request)
self.assertEqual(response.status_code, 400)
self.assertIn("row_order", response.data)
2026-04-02 23:25:39 +03:30
class FarmDashboardCardsViewTests(DashboardBaseTestCase):
2026-04-11 03:54:15 +03:30
def test_get_returns_locally_aggregated_cards(self):
2026-04-02 23:25:39 +03:30
request = self.factory.get(f"/api/farm-dashboard/?farm_uuid={self.farm.farm_uuid}")
force_authenticate(request, user=self.user)
response = FarmDashboardCardsView.as_view()(request)
self.assertEqual(response.status_code, 200)
2026-04-11 03:54:15 +03:30
self.assertEqual(response.data["code"], 200)
self.assertEqual(response.data["msg"], "OK")
self.assertIn("farmWeatherCard", response.data["data"])
self.assertIn("farmAlertsTracker", response.data["data"])
self.assertIn("yieldPredictionChart", response.data["data"])
self.assertIn("ndviHealthCard", response.data["data"])
self.assertIn("sensorRadarChart", response.data["data"])
self.assertIn("soilMoistureHeatmap", response.data["data"])
self.assertIn("economicOverview", response.data["data"])
self.assertEqual(response.data["data"]["farmOverviewKpis"]["kpis"][0]["id"], "farm_health_score")
self.assertEqual(response.data["data"]["farmOverviewKpis"]["kpis"][2]["id"], "avg_soil_moisture")
2026-05-05 23:54:44 +03:30
kpi_ids = [item["id"] for item in response.data["data"]["farmOverviewKpis"]["kpis"]]
self.assertIn("disease_risk", kpi_ids)
self.assertIn("pest_risk", kpi_ids)
self.assertIn("yield_prediction", kpi_ids)
self.assertIn("quality_score", kpi_ids)
self.assertIn("days_until_harvest", kpi_ids)
2026-04-02 23:25:39 +03:30
def test_get_requires_farm_uuid(self):
request = self.factory.get("/api/farm-dashboard/")
force_authenticate(request, user=self.user)
response = FarmDashboardCardsView.as_view()(request)
self.assertEqual(response.status_code, 400)
self.assertEqual(response.data["farm_uuid"][0], "This field is required.")
2026-04-03 23:51:00 +03:30
def test_get_denies_access_when_feature_is_blocked(self):
deny_rule = AccessRule.objects.create(
code="deny-greenhouse-dashboard",
name="Deny Greenhouse Dashboard",
priority=20,
effect=AccessRule.DENY,
)
deny_rule.features.add(self.dashboard_feature)
request = self.factory.get(f"/api/farm-dashboard/?farm_uuid={self.farm.farm_uuid}")
force_authenticate(request, user=self.user)
response = FarmDashboardCardsView.as_view()(request)
self.assertEqual(response.status_code, 403)