From b85b74b6d7833d0eff1b2b411c269f040f3232c9 Mon Sep 17 00:00:00 2001 From: Prafful Sharma <115104695+DraKen0009@users.noreply.github.com> Date: Tue, 23 Apr 2024 00:19:30 +0530 Subject: [PATCH] test for Ambulance module (#2056) * added tests for ambulance endpoints * added tests for ambulance endpoints * Update care/facility/tests/test_ambulance_api.py Co-authored-by: Rithvik Nishad * Apply suggestions from code review --------- Co-authored-by: Aakash Singh Co-authored-by: Rithvik Nishad Co-authored-by: Vignesh Hari --- care/facility/api/viewsets/ambulance.py | 4 +- care/facility/tests/test_ambulance_api.py | 218 ++++++++++++++++++++++ care/utils/tests/test_utils.py | 24 +++ 3 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 care/facility/tests/test_ambulance_api.py diff --git a/care/facility/api/viewsets/ambulance.py b/care/facility/api/viewsets/ambulance.py index f67e3457a4..2f435067d5 100644 --- a/care/facility/api/viewsets/ambulance.py +++ b/care/facility/api/viewsets/ambulance.py @@ -65,7 +65,7 @@ def get_serializer_class(self): @extend_schema(tags=["ambulance"]) @action(methods=["POST"], detail=True) - def add_driver(self, request): + def add_driver(self, request, *args, **kwargs): ambulance = self.get_object() serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) @@ -78,7 +78,7 @@ def add_driver(self, request): @extend_schema(tags=["ambulance"]) @action(methods=["DELETE"], detail=True) - def remove_driver(self, request): + def remove_driver(self, request, *args, **kwargs): ambulance = self.get_object() serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) diff --git a/care/facility/tests/test_ambulance_api.py b/care/facility/tests/test_ambulance_api.py new file mode 100644 index 0000000000..c8c962c3f6 --- /dev/null +++ b/care/facility/tests/test_ambulance_api.py @@ -0,0 +1,218 @@ +""" +Test module for Ambulance API +""" + +from rest_framework.test import APITestCase + +from care.facility.models.ambulance import Ambulance +from care.utils.tests.test_utils import TestUtils + + +class AmbulanceViewSetTest(TestUtils, APITestCase): + """ + Test class for Ambulance + """ + + @classmethod + def setUpTestData(cls) -> None: + cls.state = cls.create_state() + cls.district = cls.create_district(cls.state) + cls.local_body = cls.create_local_body(cls.district) + cls.super_user = cls.create_super_user("su", cls.district) + cls.user = cls.create_user( + "user", district=cls.district, local_body=cls.local_body + ) + cls.facility = cls.create_facility(cls.super_user, cls.district, cls.local_body) + cls.patient = cls.create_patient( + cls.district, cls.facility, local_body=cls.local_body + ) + cls.ambulance = cls.create_ambulance(cls.district, cls.user) + + def get_base_url(self) -> str: + return "/api/v1/ambulance" + + def get_url(self, entry_id=None, action=None): + """ + Constructs the url for ambulance api + """ + base_url = f"{self.get_base_url()}/" + if entry_id is not None: + base_url += f"{entry_id}/" + if action is not None: + base_url += f"{action}/" + return base_url + + def get_detail_representation(self, obj=None) -> dict: + return { + "vehicle_number": obj.vehicle_number, + "ambulance_type": obj.ambulance_type, + "owner_name": obj.owner_name, + "owner_phone_number": obj.owner_phone_number, + "owner_is_smart_phone": obj.owner_is_smart_phone, + "deleted": obj.deleted, + "has_oxygen": obj.has_oxygen, + "has_ventilator": obj.has_ventilator, + "has_suction_machine": obj.has_suction_machine, + "has_defibrillator": obj.has_defibrillator, + "insurance_valid_till_year": obj.insurance_valid_till_year, + "has_free_service": obj.has_free_service, + "primary_district": obj.primary_district.id, + "primary_district_object": { + "id": obj.primary_district.id, + "name": obj.primary_district.name, + "state": obj.primary_district.state.id, + }, + "secondary_district": obj.secondary_district, + "third_district": obj.third_district, + "secondary_district_object": None, + "third_district_object": None, + } + + def get_list_representation(self, obj=None) -> dict: + return { + "drivers": list(obj.drivers), + **self.get_detail_representation(obj), + } + + def get_create_representation(self) -> dict: + """ + Returns a representation of a ambulance create request body + """ + return { + "vehicle_number": "WW73O2195", + "owner_name": "string", + "owner_phone_number": "+918800900466", + "owner_is_smart_phone": True, + "has_oxygen": True, + "has_ventilator": True, + "has_suction_machine": True, + "has_defibrillator": True, + "insurance_valid_till_year": 2020, + "ambulance_type": 1, + "primary_district": self.district.id, + } + + def test_create_ambulance(self): + """ + Test to create ambulance + """ + + # Test with invalid data + res = self.client.post( + self.get_url(action="create"), data=self.get_create_representation() + ) + self.assertEqual(res.status_code, 400) + self.assertEqual(res.json()["drivers"][0], "This field is required.") + + data = { + "drivers": [ + { + "name": "string", + "phone_number": "+919013526849", + "is_smart_phone": True, + } + ], + } + data.update(self.get_create_representation()) + res = self.client.post(self.get_url(action="create"), data=data, format="json") + self.assertEqual(res.status_code, 400) + self.assertEqual( + res.json()["non_field_errors"][0], + "The ambulance must provide a price or be marked as free", + ) + + # Test with valid data + data.update({"price_per_km": 100}) + res = self.client.post(self.get_url(action="create"), data=data, format="json") + self.assertEqual(res.status_code, 201) + self.assertTrue( + Ambulance.objects.filter(vehicle_number=data["vehicle_number"]).exists() + ) + + def test_list_ambulance(self): + """ + Test to list ambulance + """ + res = self.client.get(self.get_url()) + self.assertEqual(res.status_code, 200) + self.assertEqual(res.json()["count"], 1) + self.assertDictContainsSubset( + self.get_list_representation(self.ambulance), res.json()["results"][0] + ) + + def test_retrieve_ambulance(self): + """ + Test to retrieve ambulance + """ + res = self.client.get(f"/api/v1/ambulance/{self.ambulance.id}/") + self.assertEqual(res.status_code, 200) + self.assertDictContainsSubset( + self.get_detail_representation(self.ambulance), res.json() + ) + + def test_update_ambulance(self): + """ + Test to update ambulance + """ + + res = self.client.patch( + self.get_url(entry_id=self.ambulance.id), + data={"vehicle_number": "WW73O2200", "has_free_service": True}, + ) + self.assertEqual(res.status_code, 200) + self.ambulance.refresh_from_db() + self.assertEqual(self.ambulance.vehicle_number, "WW73O2200") + + def test_delete_ambulance(self): + """ + Test to delete ambulance + """ + res = self.client.delete(self.get_url(entry_id=self.ambulance.id)) + self.assertEqual(res.status_code, 204) + self.ambulance.refresh_from_db() + self.assertTrue(self.ambulance.deleted) + + def test_add_driver(self): + """ + Test to add driver + """ + + res = self.client.post( + self.get_url(entry_id=self.ambulance.id, action="add_driver"), + data={ + "name": "string", + "phone_number": "+919013526800", + "is_smart_phone": True, + }, + ) + + self.assertEqual(res.status_code, 201) + self.assertTrue( + self.ambulance.drivers.filter(phone_number="+919013526800").exists() + ) + + def test_remove_driver(self): + """ + Test to remove driver + """ + + res = self.client.post( + self.get_url(entry_id=self.ambulance.id, action="add_driver"), + data={ + "name": "string", + "phone_number": "+919013526800", + "is_smart_phone": True, + }, + ) + + driver_id = res.json()["id"] + + res = self.client.delete( + self.get_url( + entry_id=self.ambulance.id, + action="remove_driver", + ), + data={"driver_id": driver_id}, + ) + self.assertEqual(res.status_code, 204) + self.assertFalse(self.ambulance.drivers.exists()) diff --git a/care/utils/tests/test_utils.py b/care/utils/tests/test_utils.py index a6c2307312..2b8471338b 100644 --- a/care/utils/tests/test_utils.py +++ b/care/utils/tests/test_utils.py @@ -13,6 +13,7 @@ CATEGORY_CHOICES, DISEASE_CHOICES_MAP, SYMPTOM_CHOICES, + Ambulance, Disease, DiseaseStatusEnum, Facility, @@ -457,6 +458,29 @@ def clone_object(cls, obj, save=True): new_obj.save() return new_obj + @classmethod + def get_ambulance_data(cls, district, user) -> dict: + return { + "vehicle_number": "KL01AB1234", + "owner_name": "Foo", + "owner_phone_number": "9998887776", + "primary_district": district, + "has_oxygen": True, + "has_ventilator": True, + "has_suction_machine": True, + "has_defibrillator": True, + "insurance_valid_till_year": 2021, + "price_per_km": 10, + "has_free_service": False, + "created_by": user, + } + + @classmethod + def create_ambulance(cls, district: District, user: User, **kwargs) -> Ambulance: + data = cls.get_ambulance_data(district, user) + data.update(**kwargs) + return Ambulance.objects.create(**data) + def get_list_representation(self, obj) -> dict: """ Returns the dict representation of the obj in list API