Coverage for src/api/tests/test_spot_creation.py: 100%

63 statements  

« prev     ^ index     » next       coverage.py v7.11.1, created at 2025-11-08 10:41 +0000

1# src/api/tests/test_spot_creation.py 

2 

3from django.urls import reverse 

4from rest_framework.test import APIClient 

5from rest_framework import status 

6from django.contrib.auth.models import User 

7from src.api.models import ParkingLot, OperatorProfile 

8import pytest 

9 

10 

11@pytest.mark.django_db 

12class TestSpotCreation: 

13 """Test suite for spot creation by operators""" 

14 

15 def setup_method(self): 

16 """Set up test data before each test""" 

17 # Create parking lots 

18 self.lot = ParkingLot.objects.create( 

19 name="Central", 

20 city="Kyiv", 

21 street="Main" 

22 ) 

23 self.other_lot = ParkingLot.objects.create( 

24 name="West", 

25 city="Lviv", 

26 street="Green" 

27 ) 

28 

29 # Create users (no password needed with force_authenticate) 

30 self.operator = User.objects.create_user(username="op1") 

31 self.not_operator = User.objects.create_user(username="u1") 

32 

33 # Assign operator to lot 

34 OperatorProfile.objects.create(user=self.operator, lot=self.lot) 

35 

36 # Create client 

37 self.client = APIClient() 

38 

39 def test_operator_creates_spot_in_own_lot_201(self): 

40 """Operator can successfully create a spot in their assigned lot""" 

41 # Use force_authenticate instead of login 

42 self.client.force_authenticate(user=self.operator) 

43 

44 url = f"/api/v1/lots/{self.lot.id}/spots/create/" 

45 payload = {"number": "A1", "is_ev": True, "is_disabled": False} 

46 

47 resp = self.client.post(url, payload, format="json") 

48 

49 assert resp.status_code == status.HTTP_201_CREATED 

50 assert resp.data["number"] == "A1" 

51 assert resp.data["lot"] == self.lot.id 

52 

53 def test_operator_cannot_create_duplicate_spot_number_400(self): 

54 """Operator cannot create spots with duplicate numbers in same lot""" 

55 self.client.force_authenticate(user=self.operator) 

56 

57 url = f"/api/v1/lots/{self.lot.id}/spots/create/" 

58 payload = {"number": "A1", "is_ev": True, "is_disabled": False} 

59 

60 # Create first spot 

61 resp1 = self.client.post(url, payload, format="json") 

62 assert resp1.status_code == status.HTTP_201_CREATED 

63 

64 # Try to create duplicate 

65 resp2 = self.client.post(url, payload, format="json") 

66 assert resp2.status_code == status.HTTP_400_BAD_REQUEST 

67 assert "number" in resp2.data 

68 

69 def test_operator_cannot_create_spot_in_other_lot(self): 

70 """Operator cannot create spots in lots they don't manage""" 

71 self.client.force_authenticate(user=self.operator) 

72 

73 url = f"/api/v1/lots/{self.other_lot.id}/spots/create/" 

74 payload = {"number": "X1", "is_ev": False, "is_disabled": False} 

75 

76 resp = self.client.post(url, payload, format="json") 

77 

78 assert resp.status_code == status.HTTP_403_FORBIDDEN 

79 assert "detail" in resp.data 

80 

81 def test_non_operator_cannot_create_spot(self): 

82 """Regular users without operator profile cannot create spots""" 

83 self.client.force_authenticate(user=self.not_operator) 

84 

85 url = f"/api/v1/lots/{self.lot.id}/spots/create/" 

86 payload = {"number": "B1", "is_ev": False, "is_disabled": False} 

87 

88 resp = self.client.post(url, payload, format="json") 

89 

90 assert resp.status_code == status.HTTP_403_FORBIDDEN 

91 assert "detail" in resp.data 

92 

93 def test_operator_cannot_create_spot_with_empty_number(self): 

94 """Operator cannot create spot with empty spot number""" 

95 self.client.force_authenticate(user=self.operator) 

96 

97 url = f"/api/v1/lots/{self.lot.id}/spots/create/" 

98 payload = {"number": "", "is_ev": False, "is_disabled": False} 

99 

100 resp = self.client.post(url, payload, format="json") 

101 

102 assert resp.status_code == status.HTTP_400_BAD_REQUEST 

103 assert "number" in resp.data 

104 

105 def test_operator_cannot_create_spot_with_same_number_different_case(self): 

106 """Spot numbers are case-insensitive (A1 == a1)""" 

107 self.client.force_authenticate(user=self.operator) 

108 

109 url = f"/api/v1/lots/{self.lot.id}/spots/create/" 

110 

111 # Create first spot 

112 payload1 = {"number": "A1", "is_ev": False, "is_disabled": False} 

113 resp1 = self.client.post(url, payload1, format="json") 

114 assert resp1.status_code == status.HTTP_201_CREATED 

115 

116 # Try to create same number with different case 

117 payload2 = {"number": "a1", "is_ev": False, "is_disabled": False} 

118 resp2 = self.client.post(url, payload2, format="json") 

119 

120 assert resp2.status_code == status.HTTP_400_BAD_REQUEST 

121 assert "number" in resp2.data