From 03519f0b86256af006a3e14738fc07a5b81f2af5 Mon Sep 17 00:00:00 2001 From: prafful Date: Sun, 13 Oct 2024 06:11:37 +0530 Subject: [PATCH 1/5] added test cases for asset bed --- care/facility/api/serializers/bed.py | 12 +- care/facility/tests/test_assetbed_api.py | 366 +++++++++++++++++++++++ care/facility/tests/test_bed_api.py | 17 +- care/utils/tests/test_utils.py | 8 +- 4 files changed, 398 insertions(+), 5 deletions(-) create mode 100644 care/facility/tests/test_assetbed_api.py diff --git a/care/facility/api/serializers/bed.py b/care/facility/api/serializers/bed.py index 41597e186d..1ac1a9269a 100644 --- a/care/facility/api/serializers/bed.py +++ b/care/facility/api/serializers/bed.py @@ -2,7 +2,7 @@ from django.db.models import Exists, OuterRef, Q from django.shortcuts import get_object_or_404 from django.utils import timezone -from rest_framework.exceptions import ValidationError +from rest_framework.exceptions import PermissionDenied, ValidationError from rest_framework.serializers import ( BooleanField, CharField, @@ -74,7 +74,10 @@ def validate(self, attrs): if (not facilities.filter(id=location.facility.id).exists()) or ( not facilities.filter(id=facility.id).exists() ): - raise PermissionError + error_message = ( + "You do not have permission to access this facility's bed." + ) + raise PermissionDenied(error_message) del attrs["location"] attrs["location"] = location attrs["facility"] = facility @@ -110,7 +113,10 @@ def validate(self, attrs): if ( not facilities.filter(id=asset.current_location.facility.id).exists() ) or (not facilities.filter(id=bed.facility.id).exists()): - raise PermissionError + error_message = ( + "You do not have permission to access this facility's assetbed." + ) + raise PermissionDenied(error_message) if asset.asset_class not in [ AssetClasses.HL7MONITOR.name, AssetClasses.ONVIF.name, diff --git a/care/facility/tests/test_assetbed_api.py b/care/facility/tests/test_assetbed_api.py new file mode 100644 index 0000000000..21fb9e7e1b --- /dev/null +++ b/care/facility/tests/test_assetbed_api.py @@ -0,0 +1,366 @@ +from rest_framework import status +from rest_framework.test import APITestCase + +from care.facility.models import AssetBed, Bed +from care.utils.assetintegration.asset_classes import AssetClasses +from care.utils.tests.test_utils import TestUtils + + +class AssetBedViewSetTests(TestUtils, APITestCase): + """ + Test class for AssetBed + """ + + @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.facility = cls.create_facility(cls.super_user, cls.district, cls.local_body) + cls.facility2 = cls.create_facility( + cls.super_user, cls.district, cls.local_body + ) + cls.user = cls.create_user( + "user", + district=cls.district, + local_body=cls.local_body, + home_facility=cls.facility, + ) # user from facility + cls.foreign_user = cls.create_user( + "foreign_user", + district=cls.district, + local_body=cls.local_body, + home_facility=cls.facility2, + ) # user outside the facility + cls.patient = cls.create_patient( + cls.district, cls.facility, local_body=cls.local_body + ) + cls.asset_location1 = cls.create_asset_location(cls.facility) + cls.asset1 = cls.create_asset( + cls.asset_location1, asset_class=AssetClasses.HL7MONITOR.name + ) + cls.bed1 = Bed.objects.create( + name="bed1", location=cls.asset_location1, facility=cls.facility + ) + cls.asset_location2 = cls.create_asset_location(cls.facility) + cls.asset2 = cls.create_asset( + cls.asset_location2, asset_class=AssetClasses.ONVIF.name + ) + cls.bed2 = Bed.objects.create( + name="bed2", location=cls.asset_location2, facility=cls.facility + ) + cls.asset_location3 = cls.create_asset_location(cls.facility) + cls.asset3 = cls.create_asset( + cls.asset_location3, asset_class=AssetClasses.VENTILATOR.name + ) + cls.bed3 = Bed.objects.create( + name="bed3", location=cls.asset_location3, facility=cls.facility + ) + cls.foreign_asset_location = cls.create_asset_location(cls.facility2) + cls.foreign_asset = cls.create_asset(cls.foreign_asset_location) + cls.foreign_bed = Bed.objects.create( + name="foreign_bed", + location=cls.foreign_asset_location, + facility=cls.facility2, + ) + + cls.create_assetbed(bed=cls.bed2, asset=cls.asset2) + cls.create_assetbed(bed=cls.bed3, asset=cls.asset3) + + # assetbed for different facility + cls.create_assetbed(bed=cls.foreign_bed, asset=cls.foreign_asset) + + def setUp(self) -> None: + super().setUp() + self.assetbed = self.create_assetbed(bed=self.bed1, asset=self.asset1) + + def get_base_url(self) -> str: + return "/api/v1/assetbed" + + def get_url(self, external_id=None): + """ + Constructs the url for ambulance api + """ + base_url = f"{self.get_base_url()}/" + if external_id is not None: + base_url += f"{external_id}/" + return base_url + + def test_list_assetbed(self): + # assetbed accessible to facility 1 user (current user) + response = self.client.get(self.get_url()) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data["count"], 3) + + # logging in as foreign user + self.client.force_login(self.foreign_user) + + # assetbed accessible to facility 2 user (foreign user) + response = self.client.get(self.get_url()) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data["count"], 1) + + # logging in as superuser + self.client.force_login(self.super_user) + + # access to all assetbed + response = self.client.get(self.get_url()) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data["count"], AssetBed.objects.count()) + + # testing for filters + response = self.client.get(self.get_url(), {"asset": self.asset1.external_id}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual( + response.data["count"], AssetBed.objects.filter(asset=self.asset1).count() + ) + + response = self.client.get(self.get_url(), {"bed": self.bed1.external_id}) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual( + response.data["count"], AssetBed.objects.filter(bed=self.bed1).count() + ) + self.assertEqual( + response.data["results"][0]["bed_object"]["name"], self.bed1.name + ) + + response = self.client.get( + self.get_url(), {"facility": self.facility.external_id} + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual( + response.data["count"], + AssetBed.objects.filter(bed__facility=self.facility).count(), + ) + + def test_create_assetbed(self): + # Missing asset and bed + missing_fields_data = {} + response = self.client.post(self.get_url(), missing_fields_data, format="json") + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertIn("asset", response.data) + self.assertIn("bed", response.data) + + # Invalid asset UUID + invalid_asset_uuid_data = { + "asset": "invalid-uuid", + "bed": str(self.bed1.external_id), + } + response = self.client.post( + self.get_url(), invalid_asset_uuid_data, format="json" + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertIn("asset", response.data) + + # Invalid bed UUID + invalid_bed_uuid_data = { + "asset": str(self.asset1.external_id), + "bed": "invalid-uuid", + } + response = self.client.post( + self.get_url(), invalid_bed_uuid_data, format="json" + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertIn("bed", response.data) + + # Non-existent asset UUID + non_existent_asset_uuid_data = { + "asset": "11111111-1111-1111-1111-111111111111", + "bed": str(self.bed1.external_id), + } + response = self.client.post( + self.get_url(), non_existent_asset_uuid_data, format="json" + ) + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + # Non-existent bed UUID + non_existent_bed_uuid_data = { + "asset": str(self.asset1.external_id), + "bed": "11111111-1111-1111-1111-111111111111", + } + response = self.client.post( + self.get_url(), non_existent_bed_uuid_data, format="json" + ) + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + # User does not have access to foreign facility + foreign_user_data = { + "asset": str(self.foreign_asset.external_id), + "bed": str(self.foreign_bed.external_id), + } + self.client.force_login(self.user) # Ensure current user is logged in + response = self.client.post(self.get_url(), foreign_user_data, format="json") + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + + # Invalid asset class (e.g., VENTILATOR) + invalid_asset_class_data = { + "asset": str(self.asset3.external_id), # VENTILATOR asset class + "bed": str(self.bed1.external_id), + } + response = self.client.post( + self.get_url(), invalid_asset_class_data, format="json" + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertIn("asset", response.data) + + # Asset and bed in different facilities + asset_bed_different_facilities = { + "asset": str(self.foreign_asset.external_id), + "bed": str(self.bed1.external_id), + } + response = self.client.post( + self.get_url(), asset_bed_different_facilities, format="json" + ) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + + # Duplicate asset class assigned to the same bed + duplicate_asset_class_data = { + "asset": str(self.asset1.external_id), # asset1 is already assigned to bed1 + "bed": str(self.bed1.external_id), + } + response = self.client.post( + self.get_url(), duplicate_asset_class_data, format="json" + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + # Successfully create AssetBed with valid data + valid_data = { + "asset": str(self.asset2.external_id), + "bed": str(self.bed2.external_id), + } + response = self.client.post(self.get_url(), valid_data, format="json") + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + def test_retrieve_assetbed(self): + response = self.client.get(self.get_url(external_id=self.assetbed.external_id)) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual( + response.data["asset_object"]["id"], str(self.assetbed.asset.external_id) + ) + self.assertEqual( + response.data["bed_object"]["id"], str(self.assetbed.bed.external_id) + ) + + def test_update_assetbed(self): + # checking old values + response = self.client.get(self.get_url(external_id=self.assetbed.external_id)) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data["meta"], {}) + self.assertEqual( + response.data["asset_object"]["id"], str(self.assetbed.asset.external_id) + ) + self.assertEqual( + response.data["bed_object"]["id"], str(self.assetbed.bed.external_id) + ) + + invalid_updated_data = { + "asset": self.asset2.external_id, + "meta": {"sample_data": "sample value"}, + } + response = self.client.put( + self.get_url(external_id=self.assetbed.external_id), + invalid_updated_data, + format="json", + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + invalid_updated_data = { + "bed": self.bed2.external_id, + "meta": {"sample_data": "sample value"}, + } + response = self.client.put( + self.get_url(external_id=self.assetbed.external_id), + invalid_updated_data, + format="json", + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + updated_data = { + "bed": self.bed2.external_id, + "asset": self.asset2.external_id, + "meta": {"sample_data": "sample value"}, + } + response = self.client.put( + self.get_url(external_id=self.assetbed.external_id), + updated_data, + format="json", + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assetbed.refresh_from_db() + + self.assertEqual(self.assetbed.bed.external_id, self.bed2.external_id) + self.assertEqual(self.assetbed.asset.external_id, self.asset2.external_id) + self.assertEqual(self.assetbed.meta, {"sample_data": "sample value"}) + + def test_patch_assetbed(self): + # checking old values + response = self.client.get(self.get_url(external_id=self.assetbed.external_id)) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertEqual(response.data["meta"], {}) + self.assertEqual( + response.data["asset_object"]["id"], str(self.assetbed.asset.external_id) + ) + self.assertEqual( + response.data["bed_object"]["id"], str(self.assetbed.bed.external_id) + ) + + invalid_updated_data = { + "asset": self.asset2.external_id, + "meta": {"sample_data": "sample value"}, + } + response = self.client.put( + self.get_url(external_id=self.assetbed.external_id), + invalid_updated_data, + format="json", + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + invalid_updated_data = { + "bed": self.bed2.external_id, + "meta": {"sample_data": "sample value"}, + } + response = self.client.put( + self.get_url(external_id=self.assetbed.external_id), + invalid_updated_data, + format="json", + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + updated_data = { + "bed": self.bed2.external_id, + "asset": self.asset2.external_id, + } + + response = self.client.put( + self.get_url(external_id=self.assetbed.external_id), + updated_data, + format="json", + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + self.assetbed.refresh_from_db() + + self.assertEqual(self.assetbed.bed.external_id, self.bed2.external_id) + self.assertEqual(self.assetbed.asset.external_id, self.asset2.external_id) + + def test_delete_assetbed(self): + # confirming that the object exist + response = self.client.get(self.get_url(external_id=self.assetbed.external_id)) + self.assertEqual(response.status_code, status.HTTP_200_OK) + + response = self.client.delete( + self.get_url(external_id=self.assetbed.external_id) + ) + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + + # confirming if it's deleted + response = self.client.get(self.get_url(external_id=self.assetbed.external_id)) + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + # confirming using db + self.assetbed.refresh_from_db() + self.assertFalse( + AssetBed.objects.filter(external_id=self.assetbed.external_id).exists() + ) diff --git a/care/facility/tests/test_bed_api.py b/care/facility/tests/test_bed_api.py index ce334dd6e4..9bceece342 100644 --- a/care/facility/tests/test_bed_api.py +++ b/care/facility/tests/test_bed_api.py @@ -75,7 +75,7 @@ def test_list_beds(self): self.client.logout() def test_create_beds(self): - sample_data = { + base_data = { "name": "Sample Beds", "bed_type": 2, "location": self.asset_location.external_id, @@ -83,23 +83,27 @@ def test_create_beds(self): "number_of_beds": 10, "description": "This is a sample bed description", } + sample_data = base_data.copy() # Create a fresh copy of the base data response = self.client.post("/api/v1/bed/", sample_data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(Bed.objects.filter(bed_type=2).count(), 10) # without location + sample_data = base_data.copy() sample_data.update({"location": None}) response = self.client.post("/api/v1/bed/", sample_data, format="json") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.data["location"][0], "This field may not be null.") # without facility + sample_data = base_data.copy() sample_data.update({"facility": None}) response = self.client.post("/api/v1/bed/", sample_data, format="json") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertEqual(response.data["facility"][0], "This field may not be null.") # Test - if beds > 100 + sample_data = base_data.copy() sample_data.update({"number_of_beds": 200}) response = self.client.post("/api/v1/bed/", sample_data, format="json") self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @@ -108,6 +112,17 @@ def test_create_beds(self): "Cannot create more than 100 beds at once.", ) + # creating bed in different facility + sample_data = base_data.copy() + sample_data.update( + { + "location": self.asset_location2.external_id, + "facility": self.facility2.external_id, + } + ) + response = self.client.post("/api/v1/bed/", sample_data, format="json") + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + def test_retrieve_bed(self): response = self.client.get(f"/api/v1/bed/{self.bed1.external_id}/") self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/care/utils/tests/test_utils.py b/care/utils/tests/test_utils.py index 1f858c7258..fbc286a337 100644 --- a/care/utils/tests/test_utils.py +++ b/care/utils/tests/test_utils.py @@ -38,7 +38,7 @@ Ward, ) from care.facility.models.asset import Asset, AssetLocation -from care.facility.models.bed import Bed, ConsultationBed +from care.facility.models.bed import AssetBed, Bed, ConsultationBed from care.facility.models.facility import FacilityUser from care.facility.models.icd11_diagnosis import ( ConditionVerificationStatus, @@ -722,6 +722,12 @@ def create_prescription( data.update(**kwargs) return Prescription.objects.create(**data) + @classmethod + def create_assetbed(cls, bed: Bed, asset: Asset, **kwargs) -> AssetBed: + data = {"bed": bed, "asset": asset} + data.update(kwargs) + return AssetBed.objects.create(**data) + def get_list_representation(self, obj) -> dict: """ Returns the dict representation of the obj in list API From 4ae4ef5212ae797d9cf142a8621324c860457749 Mon Sep 17 00:00:00 2001 From: prafful Date: Sun, 13 Oct 2024 17:36:59 +0530 Subject: [PATCH 2/5] updated PermissionError to PermissionDenied --- care/facility/api/serializers/asset.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/care/facility/api/serializers/asset.py b/care/facility/api/serializers/asset.py index f403361e1a..ddb6a8e5d4 100644 --- a/care/facility/api/serializers/asset.py +++ b/care/facility/api/serializers/asset.py @@ -7,7 +7,7 @@ from django.utils.timezone import now from drf_spectacular.utils import extend_schema_field from rest_framework import serializers -from rest_framework.exceptions import ValidationError +from rest_framework.exceptions import PermissionDenied, ValidationError from rest_framework.serializers import ( CharField, JSONField, @@ -174,11 +174,14 @@ def validate(self, attrs): facilities = get_facility_queryset(user) if not facilities.filter(id=location.facility.id).exists(): - raise PermissionError + error_message = ( + "You do not have permission to access this facility's asset." + ) + raise PermissionDenied(error_message) del attrs["location"] attrs["current_location"] = location - # validate that warraty date is not in the past + # validate that warranty date is not in the past if warranty_amc_end_of_validity := attrs.get("warranty_amc_end_of_validity"): # pop out warranty date if it is not changed if ( From 204460e497426578df65c9f5077bd5e7d4eadb8f Mon Sep 17 00:00:00 2001 From: prafful Date: Sat, 19 Oct 2024 03:47:03 +0530 Subject: [PATCH 3/5] merged redundent code --- care/facility/tests/test_asset_bed_api.py | 183 ---------------------- care/facility/tests/test_assetbed_api.py | 166 ++++++++++++++++++-- care/utils/tests/test_utils.py | 6 - 3 files changed, 153 insertions(+), 202 deletions(-) delete mode 100644 care/facility/tests/test_asset_bed_api.py diff --git a/care/facility/tests/test_asset_bed_api.py b/care/facility/tests/test_asset_bed_api.py deleted file mode 100644 index d22aae9bfd..0000000000 --- a/care/facility/tests/test_asset_bed_api.py +++ /dev/null @@ -1,183 +0,0 @@ -from rest_framework import status -from rest_framework.test import APITestCase - -from care.users.models import User -from care.utils.assetintegration.asset_classes import AssetClasses -from care.utils.tests.test_utils import TestUtils - - -class AssetBedViewSetTestCase(TestUtils, APITestCase): - @classmethod - def setUpTestData(cls): - 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.facility = cls.create_facility(cls.super_user, cls.district, cls.local_body) - cls.user = cls.create_user( - User.TYPE_VALUE_MAP["DistrictAdmin"], - cls.district, - home_facility=cls.facility, - ) - cls.asset_location = cls.create_asset_location(cls.facility) - cls.asset = cls.create_asset(cls.asset_location) - cls.camera_asset = cls.create_asset( - cls.asset_location, asset_class=AssetClasses.ONVIF.name - ) - cls.bed = cls.create_bed(cls.facility, cls.asset_location) - - def test_link_disallowed_asset_class_asset_to_bed(self): - data = { - "asset": self.asset.external_id, - "bed": self.bed.external_id, - } - res = self.client.post("/api/v1/assetbed/", data) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) - - def test_link_asset_to_bed_and_attempt_duplicate_linking(self): - data = { - "asset": self.camera_asset.external_id, - "bed": self.bed.external_id, - } - res = self.client.post("/api/v1/assetbed/", data) - self.assertEqual(res.status_code, status.HTTP_201_CREATED) - # Attempt linking same camera to the same bed again. - res = self.client.post("/api/v1/assetbed/", data) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) - # List asset beds filtered by asset and bed ID and check only 1 result exists - res = self.client.get("/api/v1/assetbed/", data) - self.assertEqual(res.status_code, status.HTTP_200_OK) - self.assertEqual(res.data["count"], 1) - - -class AssetBedCameraPresetViewSetTestCase(TestUtils, APITestCase): - @classmethod - def setUpTestData(cls): - 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.facility = cls.create_facility(cls.super_user, cls.district, cls.local_body) - cls.user = cls.create_user( - User.TYPE_VALUE_MAP["DistrictAdmin"], - cls.district, - home_facility=cls.facility, - ) - cls.asset_location = cls.create_asset_location(cls.facility) - cls.asset1 = cls.create_asset( - cls.asset_location, asset_class=AssetClasses.ONVIF.name - ) - cls.asset2 = cls.create_asset( - cls.asset_location, asset_class=AssetClasses.ONVIF.name - ) - cls.bed = cls.create_bed(cls.facility, cls.asset_location) - cls.asset_bed1 = cls.create_asset_bed(cls.asset1, cls.bed) - cls.asset_bed2 = cls.create_asset_bed(cls.asset2, cls.bed) - - def get_base_url(self, asset_bed_id=None): - return f"/api/v1/assetbed/{asset_bed_id or self.asset_bed1.external_id}/camera_presets/" - - def test_create_camera_preset_without_position(self): - res = self.client.post( - self.get_base_url(), - { - "name": "Preset without position", - "position": {}, - }, - format="json", - ) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) - - def test_create_camera_preset_with_missing_required_keys_in_position(self): - res = self.client.post( - self.get_base_url(), - { - "name": "Preset with invalid position", - "position": {"key": "value"}, - }, - format="json", - ) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) - - def test_create_camera_preset_with_position_not_number(self): - res = self.client.post( - self.get_base_url(), - { - "name": "Preset with invalid position", - "position": { - "x": "not a number", - "y": 1, - "zoom": 1, - }, - }, - format="json", - ) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) - - def test_create_camera_preset_with_position_values_as_string(self): - res = self.client.post( - self.get_base_url(), - { - "name": "Preset with invalid position", - "position": { - "x": "1", - "y": "1", - "zoom": "1", - }, - }, - format="json", - ) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) - - def test_create_camera_preset_and_presence_in_various_preset_list_apis(self): - asset_bed = self.asset_bed1 - res = self.client.post( - self.get_base_url(asset_bed.external_id), - { - "name": "Preset with proper position", - "position": { - "x": 1.0, - "y": 1.0, - "zoom": 1.0, - }, - }, - format="json", - ) - self.assertEqual(res.status_code, status.HTTP_201_CREATED) - preset_external_id = res.data["id"] - - # Check if preset in asset-bed preset list - res = self.client.get(self.get_base_url(asset_bed.external_id)) - self.assertEqual(res.status_code, status.HTTP_200_OK) - self.assertContains(res, preset_external_id) - - # Check if preset in asset preset list - res = self.client.get( - f"/api/v1/asset/{asset_bed.asset.external_id}/camera_presets/" - ) - self.assertEqual(res.status_code, status.HTTP_200_OK) - self.assertContains(res, preset_external_id) - - # Check if preset in bed preset list - res = self.client.get( - f"/api/v1/bed/{asset_bed.bed.external_id}/camera_presets/" - ) - self.assertEqual(res.status_code, status.HTTP_200_OK) - self.assertContains(res, preset_external_id) - - def test_create_camera_preset_with_same_name_in_same_bed(self): - data = { - "name": "Duplicate Preset Name", - "position": { - "x": 1.0, - "y": 1.0, - "zoom": 1.0, - }, - } - self.client.post( - self.get_base_url(self.asset_bed1.external_id), data, format="json" - ) - res = self.client.post( - self.get_base_url(self.asset_bed2.external_id), data, format="json" - ) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) diff --git a/care/facility/tests/test_assetbed_api.py b/care/facility/tests/test_assetbed_api.py index 21fb9e7e1b..cbbc47d527 100644 --- a/care/facility/tests/test_assetbed_api.py +++ b/care/facility/tests/test_assetbed_api.py @@ -2,6 +2,7 @@ from rest_framework.test import APITestCase from care.facility.models import AssetBed, Bed +from care.users.models import User from care.utils.assetintegration.asset_classes import AssetClasses from care.utils.tests.test_utils import TestUtils @@ -44,6 +45,7 @@ def setUpTestData(cls) -> None: name="bed1", location=cls.asset_location1, facility=cls.facility ) cls.asset_location2 = cls.create_asset_location(cls.facility) + # camera asset cls.asset2 = cls.create_asset( cls.asset_location2, asset_class=AssetClasses.ONVIF.name ) @@ -57,6 +59,10 @@ def setUpTestData(cls) -> None: cls.bed3 = Bed.objects.create( name="bed3", location=cls.asset_location3, facility=cls.facility ) + # for testing create, put and patch requests + cls.bed4 = Bed.objects.create( + name="bed4", location=cls.asset_location3, facility=cls.facility + ) cls.foreign_asset_location = cls.create_asset_location(cls.facility2) cls.foreign_asset = cls.create_asset(cls.foreign_asset_location) cls.foreign_bed = Bed.objects.create( @@ -214,10 +220,11 @@ def test_create_assetbed(self): ) self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) - # Duplicate asset class assigned to the same bed + # Trying to create a duplicate assetbed with bed2 and asset2 (assetbed already exist with same bed and asset) + # This also include linking same camera to the same bed again duplicate_asset_class_data = { - "asset": str(self.asset1.external_id), # asset1 is already assigned to bed1 - "bed": str(self.bed1.external_id), + "asset": str(self.asset2.external_id), # asset1 is already assigned to bed1 + "bed": str(self.bed2.external_id), } response = self.client.post( self.get_url(), duplicate_asset_class_data, format="json" @@ -226,8 +233,8 @@ def test_create_assetbed(self): # Successfully create AssetBed with valid data valid_data = { - "asset": str(self.asset2.external_id), - "bed": str(self.bed2.external_id), + "asset": str(self.asset1.external_id), + "bed": str(self.bed4.external_id), } response = self.client.post(self.get_url(), valid_data, format="json") self.assertEqual(response.status_code, status.HTTP_201_CREATED) @@ -277,7 +284,7 @@ def test_update_assetbed(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) updated_data = { - "bed": self.bed2.external_id, + "bed": self.bed4.external_id, "asset": self.asset2.external_id, "meta": {"sample_data": "sample value"}, } @@ -290,7 +297,7 @@ def test_update_assetbed(self): self.assetbed.refresh_from_db() - self.assertEqual(self.assetbed.bed.external_id, self.bed2.external_id) + self.assertEqual(self.assetbed.bed.external_id, self.bed4.external_id) self.assertEqual(self.assetbed.asset.external_id, self.asset2.external_id) self.assertEqual(self.assetbed.meta, {"sample_data": "sample value"}) @@ -310,7 +317,7 @@ def test_patch_assetbed(self): "asset": self.asset2.external_id, "meta": {"sample_data": "sample value"}, } - response = self.client.put( + response = self.client.patch( self.get_url(external_id=self.assetbed.external_id), invalid_updated_data, format="json", @@ -318,10 +325,10 @@ def test_patch_assetbed(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) invalid_updated_data = { - "bed": self.bed2.external_id, + "bed": self.bed4.external_id, "meta": {"sample_data": "sample value"}, } - response = self.client.put( + response = self.client.patch( self.get_url(external_id=self.assetbed.external_id), invalid_updated_data, format="json", @@ -329,11 +336,11 @@ def test_patch_assetbed(self): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) updated_data = { - "bed": self.bed2.external_id, + "bed": self.bed4.external_id, "asset": self.asset2.external_id, } - response = self.client.put( + response = self.client.patch( self.get_url(external_id=self.assetbed.external_id), updated_data, format="json", @@ -342,7 +349,7 @@ def test_patch_assetbed(self): self.assetbed.refresh_from_db() - self.assertEqual(self.assetbed.bed.external_id, self.bed2.external_id) + self.assertEqual(self.assetbed.bed.external_id, self.bed4.external_id) self.assertEqual(self.assetbed.asset.external_id, self.asset2.external_id) def test_delete_assetbed(self): @@ -364,3 +371,136 @@ def test_delete_assetbed(self): self.assertFalse( AssetBed.objects.filter(external_id=self.assetbed.external_id).exists() ) + + +class AssetBedCameraPresetViewSetTestCase(TestUtils, APITestCase): + @classmethod + def setUpTestData(cls): + 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.facility = cls.create_facility(cls.super_user, cls.district, cls.local_body) + cls.user = cls.create_user( + User.TYPE_VALUE_MAP["DistrictAdmin"], + cls.district, + home_facility=cls.facility, + ) + cls.asset_location = cls.create_asset_location(cls.facility) + cls.asset1 = cls.create_asset( + cls.asset_location, asset_class=AssetClasses.ONVIF.name + ) + cls.asset2 = cls.create_asset( + cls.asset_location, asset_class=AssetClasses.ONVIF.name + ) + cls.bed = cls.create_bed(cls.facility, cls.asset_location) + cls.asset_bed1 = cls.create_assetbed(cls.bed, cls.asset1) + cls.asset_bed2 = cls.create_assetbed(cls.bed, cls.asset2) + + def get_base_url(self, asset_bed_id=None): + return f"/api/v1/assetbed/{asset_bed_id or self.asset_bed1.external_id}/camera_presets/" + + def test_create_camera_preset_without_position(self): + res = self.client.post( + self.get_base_url(), + { + "name": "Preset without position", + "position": {}, + }, + format="json", + ) + self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) + + def test_create_camera_preset_with_missing_required_keys_in_position(self): + res = self.client.post( + self.get_base_url(), + { + "name": "Preset with invalid position", + "position": {"key": "value"}, + }, + format="json", + ) + self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) + + def test_create_camera_preset_with_position_not_number(self): + res = self.client.post( + self.get_base_url(), + { + "name": "Preset with invalid position", + "position": { + "x": "not a number", + "y": 1, + "zoom": 1, + }, + }, + format="json", + ) + self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) + + def test_create_camera_preset_with_position_values_as_string(self): + res = self.client.post( + self.get_base_url(), + { + "name": "Preset with invalid position", + "position": { + "x": "1", + "y": "1", + "zoom": "1", + }, + }, + format="json", + ) + self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) + + def test_create_camera_preset_and_presence_in_various_preset_list_apis(self): + asset_bed = self.asset_bed1 + res = self.client.post( + self.get_base_url(asset_bed.external_id), + { + "name": "Preset with proper position", + "position": { + "x": 1.0, + "y": 1.0, + "zoom": 1.0, + }, + }, + format="json", + ) + self.assertEqual(res.status_code, status.HTTP_201_CREATED) + preset_external_id = res.data["id"] + + # Check if preset in asset-bed preset list + res = self.client.get(self.get_base_url(asset_bed.external_id)) + self.assertEqual(res.status_code, status.HTTP_200_OK) + self.assertContains(res, preset_external_id) + + # Check if preset in asset preset list + res = self.client.get( + f"/api/v1/asset/{asset_bed.asset.external_id}/camera_presets/" + ) + self.assertEqual(res.status_code, status.HTTP_200_OK) + self.assertContains(res, preset_external_id) + + # Check if preset in bed preset list + res = self.client.get( + f"/api/v1/bed/{asset_bed.bed.external_id}/camera_presets/" + ) + self.assertEqual(res.status_code, status.HTTP_200_OK) + self.assertContains(res, preset_external_id) + + def test_create_camera_preset_with_same_name_in_same_bed(self): + data = { + "name": "Duplicate Preset Name", + "position": { + "x": 1.0, + "y": 1.0, + "zoom": 1.0, + }, + } + self.client.post( + self.get_base_url(self.asset_bed1.external_id), data, format="json" + ) + res = self.client.post( + self.get_base_url(self.asset_bed2.external_id), data, format="json" + ) + self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) diff --git a/care/utils/tests/test_utils.py b/care/utils/tests/test_utils.py index 64dca134e9..fbc286a337 100644 --- a/care/utils/tests/test_utils.py +++ b/care/utils/tests/test_utils.py @@ -446,12 +446,6 @@ def create_bed(cls, facility: Facility, location: AssetLocation, **kwargs): data.update(kwargs) return Bed.objects.create(**data) - @classmethod - def create_asset_bed(cls, asset: Asset, bed: Bed, **kwargs): - data = {"asset": asset, "bed": bed} - data.update(kwargs) - return AssetBed.objects.create(**data) - @classmethod def create_consultation_bed( cls, From 9ac25f4ed353c4958a4f1ddcb186b852f1f1f8fe Mon Sep 17 00:00:00 2001 From: prafful Date: Thu, 24 Oct 2024 03:22:51 +0530 Subject: [PATCH 4/5] merged redundent code --- care/facility/tests/test_asset_bed_api.py | 219 ---------------------- care/facility/tests/test_assetbed_api.py | 29 ++- 2 files changed, 27 insertions(+), 221 deletions(-) delete mode 100644 care/facility/tests/test_asset_bed_api.py diff --git a/care/facility/tests/test_asset_bed_api.py b/care/facility/tests/test_asset_bed_api.py deleted file mode 100644 index 4ed81a36b8..0000000000 --- a/care/facility/tests/test_asset_bed_api.py +++ /dev/null @@ -1,219 +0,0 @@ -from rest_framework import status -from rest_framework.test import APITestCase - -from care.users.models import User -from care.utils.assetintegration.asset_classes import AssetClasses -from care.utils.tests.test_utils import TestUtils - - -class AssetBedViewSetTestCase(TestUtils, APITestCase): - @classmethod - def setUpTestData(cls): - 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.facility = cls.create_facility(cls.super_user, cls.district, cls.local_body) - cls.user = cls.create_user( - User.TYPE_VALUE_MAP["DistrictAdmin"], - cls.district, - home_facility=cls.facility, - ) - cls.asset_location = cls.create_asset_location(cls.facility) - cls.asset = cls.create_asset(cls.asset_location) - cls.monitor_asset_1 = cls.create_asset( - cls.asset_location, asset_class=AssetClasses.HL7MONITOR.name - ) - cls.monitor_asset_2 = cls.create_asset( - cls.asset_location, asset_class=AssetClasses.HL7MONITOR.name - ) - cls.camera_asset = cls.create_asset( - cls.asset_location, asset_class=AssetClasses.ONVIF.name - ) - cls.camera_asset_1 = cls.create_asset( - cls.asset_location, asset_class=AssetClasses.ONVIF.name, name="Camera 1" - ) - cls.camera_asset_2 = cls.create_asset( - cls.asset_location, asset_class=AssetClasses.ONVIF.name, name="Camera 2" - ) - cls.bed = cls.create_bed(cls.facility, cls.asset_location) - - def test_link_disallowed_asset_class_asset_to_bed(self): - data = { - "asset": self.asset.external_id, - "bed": self.bed.external_id, - } - res = self.client.post("/api/v1/assetbed/", data) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) - - def test_link_asset_to_bed_and_attempt_duplicate_linking(self): - data = { - "asset": self.camera_asset.external_id, - "bed": self.bed.external_id, - } - res = self.client.post("/api/v1/assetbed/", data) - self.assertEqual(res.status_code, status.HTTP_201_CREATED) - # Attempt linking same camera to the same bed again. - res = self.client.post("/api/v1/assetbed/", data) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) - # List asset beds filtered by asset and bed ID and check only 1 result exists - res = self.client.get("/api/v1/assetbed/", data) - self.assertEqual(res.status_code, status.HTTP_200_OK) - self.assertEqual(res.data["count"], 1) - - def test_linking_multiple_cameras_to_a_bed(self): - data = { - "asset": self.camera_asset_1.external_id, - "bed": self.bed.external_id, - } - res = self.client.post("/api/v1/assetbed/", data) - self.assertEqual(res.status_code, status.HTTP_201_CREATED) - # Attempt linking another camera to same bed. - data["asset"] = self.camera_asset_2.external_id - res = self.client.post("/api/v1/assetbed/", data) - self.assertEqual(res.status_code, status.HTTP_201_CREATED) - - def test_linking_multiple_hl7_monitors_to_a_bed(self): - data = { - "asset": self.monitor_asset_1.external_id, - "bed": self.bed.external_id, - } - res = self.client.post("/api/v1/assetbed/", data) - self.assertEqual(res.status_code, status.HTTP_201_CREATED) - # Attempt linking another hl7 monitor to same bed. - data["asset"] = self.monitor_asset_2.external_id - res = self.client.post("/api/v1/assetbed/", data) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) - - -class AssetBedCameraPresetViewSetTestCase(TestUtils, APITestCase): - @classmethod - def setUpTestData(cls): - 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.facility = cls.create_facility(cls.super_user, cls.district, cls.local_body) - cls.user = cls.create_user( - User.TYPE_VALUE_MAP["DistrictAdmin"], - cls.district, - home_facility=cls.facility, - ) - cls.asset_location = cls.create_asset_location(cls.facility) - cls.asset1 = cls.create_asset( - cls.asset_location, asset_class=AssetClasses.ONVIF.name - ) - cls.asset2 = cls.create_asset( - cls.asset_location, asset_class=AssetClasses.ONVIF.name - ) - cls.bed = cls.create_bed(cls.facility, cls.asset_location) - cls.asset_bed1 = cls.create_asset_bed(cls.asset1, cls.bed) - cls.asset_bed2 = cls.create_asset_bed(cls.asset2, cls.bed) - - def get_base_url(self, asset_bed_id=None): - return f"/api/v1/assetbed/{asset_bed_id or self.asset_bed1.external_id}/camera_presets/" - - def test_create_camera_preset_without_position(self): - res = self.client.post( - self.get_base_url(), - { - "name": "Preset without position", - "position": {}, - }, - format="json", - ) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) - - def test_create_camera_preset_with_missing_required_keys_in_position(self): - res = self.client.post( - self.get_base_url(), - { - "name": "Preset with invalid position", - "position": {"key": "value"}, - }, - format="json", - ) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) - - def test_create_camera_preset_with_position_not_number(self): - res = self.client.post( - self.get_base_url(), - { - "name": "Preset with invalid position", - "position": { - "x": "not a number", - "y": 1, - "zoom": 1, - }, - }, - format="json", - ) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) - - def test_create_camera_preset_with_position_values_as_string(self): - res = self.client.post( - self.get_base_url(), - { - "name": "Preset with invalid position", - "position": { - "x": "1", - "y": "1", - "zoom": "1", - }, - }, - format="json", - ) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) - - def test_create_camera_preset_and_presence_in_various_preset_list_apis(self): - asset_bed = self.asset_bed1 - res = self.client.post( - self.get_base_url(asset_bed.external_id), - { - "name": "Preset with proper position", - "position": { - "x": 1.0, - "y": 1.0, - "zoom": 1.0, - }, - }, - format="json", - ) - self.assertEqual(res.status_code, status.HTTP_201_CREATED) - preset_external_id = res.data["id"] - - # Check if preset in asset-bed preset list - res = self.client.get(self.get_base_url(asset_bed.external_id)) - self.assertEqual(res.status_code, status.HTTP_200_OK) - self.assertContains(res, preset_external_id) - - # Check if preset in asset preset list - res = self.client.get( - f"/api/v1/asset/{asset_bed.asset.external_id}/camera_presets/" - ) - self.assertEqual(res.status_code, status.HTTP_200_OK) - self.assertContains(res, preset_external_id) - - # Check if preset in bed preset list - res = self.client.get( - f"/api/v1/bed/{asset_bed.bed.external_id}/camera_presets/" - ) - self.assertEqual(res.status_code, status.HTTP_200_OK) - self.assertContains(res, preset_external_id) - - def test_create_camera_preset_with_same_name_in_same_bed(self): - data = { - "name": "Duplicate Preset Name", - "position": { - "x": 1.0, - "y": 1.0, - "zoom": 1.0, - }, - } - self.client.post( - self.get_base_url(self.asset_bed1.external_id), data, format="json" - ) - res = self.client.post( - self.get_base_url(self.asset_bed2.external_id), data, format="json" - ) - self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) diff --git a/care/facility/tests/test_assetbed_api.py b/care/facility/tests/test_assetbed_api.py index cbbc47d527..2129ef1a00 100644 --- a/care/facility/tests/test_assetbed_api.py +++ b/care/facility/tests/test_assetbed_api.py @@ -221,9 +221,8 @@ def test_create_assetbed(self): self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) # Trying to create a duplicate assetbed with bed2 and asset2 (assetbed already exist with same bed and asset) - # This also include linking same camera to the same bed again duplicate_asset_class_data = { - "asset": str(self.asset2.external_id), # asset1 is already assigned to bed1 + "asset": str(self.asset2.external_id), # asset2 is already assigned to bed2 "bed": str(self.bed2.external_id), } response = self.client.post( @@ -372,6 +371,32 @@ def test_delete_assetbed(self): AssetBed.objects.filter(external_id=self.assetbed.external_id).exists() ) + def test_linking_multiple_cameras_to_a_bed(self): + # We already have camera linked(asset2) to bed2 + # Attempt linking another camera to same bed. + new_camera_asset = self.create_asset( + self.asset_location2, asset_class=AssetClasses.ONVIF.name + ) + data = { + "bed": self.bed2.external_id, + "asset": new_camera_asset.external_id, + } + res = self.client.post(self.get_url(), data, format="json") + self.assertEqual(res.status_code, status.HTTP_201_CREATED) + + def test_linking_multiple_hl7_monitors_to_a_bed(self): + # We already have hl7 monitor linked(asset1) to bed1) + # Attempt linking another hl7 monitor to same bed. + new_hl7_monitor_asset = self.create_asset( + self.asset_location2, asset_class=AssetClasses.HL7MONITOR.name + ) + data = { + "bed": self.bed1.external_id, + "asset": new_hl7_monitor_asset.external_id, + } + res = self.client.post("/api/v1/assetbed/", data, format="json") + self.assertEqual(res.status_code, status.HTTP_400_BAD_REQUEST) + class AssetBedCameraPresetViewSetTestCase(TestUtils, APITestCase): @classmethod From 6566caa6b900cfdd311a413f6e97a6f6d764a592 Mon Sep 17 00:00:00 2001 From: prafful Date: Sat, 26 Oct 2024 20:17:59 +0530 Subject: [PATCH 5/5] modified to accomodate new changes --- care/facility/tests/test_asset_location_api.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/care/facility/tests/test_asset_location_api.py b/care/facility/tests/test_asset_location_api.py index 9e8280d617..6bcfed7850 100644 --- a/care/facility/tests/test_asset_location_api.py +++ b/care/facility/tests/test_asset_location_api.py @@ -21,7 +21,7 @@ def setUpTestData(cls) -> None: asset_class=AssetClasses.HL7MONITOR.name, ) cls.bed = cls.create_bed(cls.facility, cls.asset_location_with_linked_bed) - cls.asset_bed = cls.create_asset_bed(cls.asset, cls.bed) + cls.asset_bed = cls.create_assetbed(cls.bed, cls.asset) cls.patient = cls.create_patient(cls.district, cls.facility) cls.consultation = cls.create_consultation(cls.patient, cls.facility) cls.consultation_bed = cls.create_consultation_bed(cls.consultation, cls.bed) @@ -36,8 +36,8 @@ def setUpTestData(cls) -> None: cls.asset_second_location, asset_class=AssetClasses.HL7MONITOR.name ) cls.asset_bed_second = cls.create_bed(cls.facility, cls.asset_second_location) - cls.assetbed_second = cls.create_asset_bed( - cls.asset_second, cls.asset_bed_second + cls.assetbed_second = cls.create_assetbed( + cls.asset_bed_second, cls.asset_second ) def test_list_asset_locations(self):