Coverage for src/api/tests/test_models.py: 94%

98 statements  

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

1import pytest 

2from django.db import IntegrityError 

3from django.utils import timezone 

4from django.contrib.auth import get_user_model 

5from src.api.models import ParkingLot, Spot, Booking, OperatorProfile 

6from rest_framework.test import APITestCase 

7from django.utils import timezone 

8from datetime import timedelta 

9from django.contrib.auth.models import User 

10from django.conf import settings 

11 

12TEST_PASSWORD = settings.TEST_USER_PASSWORD 

13 

14TEST_PASSWORD = "pass" 

15 

16class BookingTests(APITestCase): 

17 def setUp(self): 

18 self.user = User.objects.create_user(username="test") 

19 self.client.force_authenticate(user=self.user) 

20 self.lot = ParkingLot.objects.create(name="River Mall", city="Kyiv", street="Dnipro") 

21 self.spot = Spot.objects.create(number="P1", lot=self.lot) 

22 self.start = timezone.now() + timedelta(hours=1) 

23 self.end = timezone.now() + timedelta(hours=2) 

24 

25 

26# ──────────────────────────────────────────────── 

27# ParkingLot model 

28# ──────────────────────────────────────────────── 

29 

30@pytest.mark.django_db 

31def test_create_parking_lot_success(): 

32 lot = ParkingLot.objects.create( 

33 name="SkyMall", 

34 city="Kyiv", 

35 street="Petrivka", 

36 building="10A" 

37 ) 

38 assert lot.id is not None 

39 assert str(lot) == "SkyMall (Kyiv, Petrivka 10A)" 

40 assert "Kyiv" in str(lot) 

41 

42 

43@pytest.mark.django_db 

44def test_parking_lot_str_without_building(): 

45 lot = ParkingLot.objects.create( 

46 name="Center Lot", 

47 city="Lviv", 

48 street="Main Street" 

49 ) 

50 result = str(lot) 

51 assert "Center Lot" in result 

52 assert "Main Street" in result 

53 assert "None" not in result 

54 

55 

56# ──────────────────────────────────────────────── 

57# Spot model 

58# ──────────────────────────────────────────────── 

59 

60@pytest.mark.django_db 

61def test_spot_creation_and_str(): 

62 lot = ParkingLot.objects.create(name="Lot A", city="Kyiv", street="Main") 

63 spot = Spot.objects.create(number="A1", lot=lot, is_ev=True, is_disabled=False) 

64 assert spot.lot == lot 

65 assert "#A1" in str(spot) 

66 assert "Lot A" in str(spot) 

67 

68 

69@pytest.mark.django_db 

70def test_spot_unique_together_same_lot(): 

71 lot = ParkingLot.objects.create(name="Lot B", city="Kyiv", street="Main") 

72 Spot.objects.create(number="X1", lot=lot) 

73 with pytest.raises(IntegrityError): 

74 Spot.objects.create(number="X1", lot=lot) # дубль у межах того ж лоту 

75 

76 

77@pytest.mark.django_db 

78def test_spot_number_can_repeat_in_different_lots(): 

79 lot1 = ParkingLot.objects.create(name="Lot1", city="Kyiv", street="Main") 

80 lot2 = ParkingLot.objects.create(name="Lot2", city="Lviv", street="Market") 

81 Spot.objects.create(number="S1", lot=lot1) 

82 spot2 = Spot.objects.create(number="S1", lot=lot2) 

83 assert spot2.lot != lot1 

84 assert spot2.number == "S1" 

85 

86 

87# ──────────────────────────────────────────────── 

88# Booking model 

89# ──────────────────────────────────────────────── 

90 

91@pytest.mark.django_db 

92def test_booking_creation_defaults(): 

93 lot = ParkingLot.objects.create(name="LotX", city="Dnipro", street="River") 

94 spot = Spot.objects.create(number="A5", lot=lot) 

95 booking = Booking.objects.create( 

96 spot=spot, 

97 start_at=timezone.now(), 

98 end_at=timezone.now() + timezone.timedelta(hours=2) 

99 ) 

100 

101 assert booking.status == "confirmed" 

102 assert booking.cancellation_reason == "" 

103 assert booking.payment_intent_id == "" 

104 assert booking.user is None 

105 

106 

107@pytest.mark.django_db 

108def test_booking_with_user_relationship(): 

109 user = User.objects.create_user(username="testuser") 

110 lot = ParkingLot.objects.create(name="LotY", city="Kyiv", street="Street") 

111 spot = Spot.objects.create(number="Y1", lot=lot) 

112 booking = Booking.objects.create( 

113 user=user, 

114 spot=spot, 

115 start_at=timezone.now(), 

116 end_at=timezone.now() + timezone.timedelta(hours=1) 

117 ) 

118 

119 assert booking.user.username == "testuser" 

120 assert booking.spot == spot 

121 assert booking.status == "confirmed" 

122 

123 

124@pytest.mark.django_db 

125def test_booking_has_index_fields(): 

126 """Перевіряємо, що індекс існує для (spot, start_at, end_at, status).""" 

127 fields = [tuple(i.fields) for i in Booking._meta.indexes] 

128 assert ("spot", "start_at", "end_at", "status") in fields 

129 

130 

131# ──────────────────────────────────────────────── 

132# OperatorProfile model 

133# ──────────────────────────────────────────────── 

134 

135@pytest.mark.django_db 

136def test_operator_profile_str_and_relation(): 

137 user = User.objects.create_user(username="operator1") 

138 lot = ParkingLot.objects.create(name="Central", city="Kyiv", street="Main") 

139 profile = OperatorProfile.objects.create(user=user, lot=lot) 

140 

141 assert profile.user == user 

142 assert profile.lot == lot 

143 assert "operator1" in str(profile) 

144 assert "Central" in str(profile) 

145 

146 

147@pytest.mark.django_db 

148def test_operator_profile_without_lot(): 

149 user = User.objects.create_user(username="solo") 

150 profile = OperatorProfile.objects.create(user=user, lot=None) 

151 

152 assert "N/A" in str(profile) 

153 assert "solo" in str(profile) 

154 

155@pytest.mark.django_db 

156def test_operator_profile_user_must_be_unique_fails(): 

157 user = User.objects.create_user(username="operator_gulliver") 

158 lot = ParkingLot.objects.create(name="Central", city="Kyiv", street="Main") 

159 

160 OperatorProfile.objects.create(user=user, lot=lot) 

161 with pytest.raises(IntegrityError): 

162 OperatorProfile.objects.create(user=user, lot=None)