• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

gcivil-nyu-org / team4-wed-spring25 / 391

08 Apr 2025 07:09PM UTC coverage: 97.251% (+0.3%) from 96.976%
391

push

travis-pro

divya603
Fix formatting: autoformat with Black and fix flake8 blank lines issue

955 of 982 relevant lines covered (97.25%)

0.97 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.3
/parks/tests.py
1
from django.test import TestCase, Client
1✔
2
from django.urls import reverse
1✔
3
from django.contrib.auth.models import User
1✔
4
from .models import DogRunNew, Review, ParkImage, ReviewReport, ImageReport
1✔
5
from parks.templatetags.display_rating import render_stars
1✔
6
from django.utils.text import slugify
1✔
7
from django.core import mail
1✔
8

9

10
class ErrorPageTests(TestCase):
1✔
11
    def test_trigger_400(self):
1✔
12
        response = self.client.get("/test400/")
1✔
13
        self.assertEqual(response.status_code, 400)
1✔
14

15
    def test_trigger_403(self):
1✔
16
        response = self.client.get("/test403/")
1✔
17
        self.assertEqual(response.status_code, 403)
1✔
18

19
    def test_trigger_404(self):
1✔
20
        response = self.client.get("/test404/")
1✔
21
        self.assertEqual(response.status_code, 404)
1✔
22

23
    def test_trigger_500(self):
1✔
24
        with self.assertRaises(Exception) as context:
1✔
25
            self.client.get("/test500/")
1✔
26
        self.assertIn("Intentional server error", str(context.exception))
1✔
27

28

29
class UniqueEmailTests(TestCase):
1✔
30
    def setUp(self):
1✔
31
        self.client = Client()
1✔
32
        User.objects.create_user(
1✔
33
            username="existinguser",
34
            email="duplicate@pawpark.com",
35
            password="SomeStrongPassword1",
36
        )
37
        self.register_url = reverse("register")
1✔
38

39
    def test_duplicate_email_registration(self):
1✔
40
        """
41
        Attempting to register a new user with an email that already exists should
42
        re-render the form with an error message.
43
        """
44
        response = self.client.post(
1✔
45
            self.register_url,
46
            {
47
                "username": "newuser",
48
                "email": "duplicate@pawpark.com",
49
                "password1": "StrongPass123",
50
                "password2": "StrongPass123",
51
                "role": "user",
52
                "admin_access_code": "",
53
            },
54
        )
55
        self.assertEqual(response.status_code, 200)
1✔
56
        self.assertContains(response, "A user with that email address already exists.")
1✔
57
        self.assertFalse(User.objects.filter(username="newuser").exists())
1✔
58

59

60
class WeakPasswordTests(TestCase):
1✔
61
    def setUp(self):
1✔
62
        self.client = Client()
1✔
63
        self.register_url = reverse("register")
1✔
64

65
    def test_too_short_password(self):
1✔
66
        response = self.client.post(
1✔
67
            self.register_url,
68
            {
69
                "username": "weakuser",
70
                "password1": "123",
71
                "password2": "123",
72
                "role": "user",
73
            },
74
        )
75
        self.assertEqual(response.status_code, 200)
1✔
76
        self.assertFalse(User.objects.filter(username="weakuser").exists())
1✔
77
        self.assertContains(response, "must contain at least 8 characters")
1✔
78

79
    def test_entirely_numeric_password(self):
1✔
80
        response = self.client.post(
1✔
81
            self.register_url,
82
            {
83
                "username": "numericuser",
84
                "password1": "12345678",
85
                "password2": "12345678",
86
                "role": "user",
87
            },
88
        )
89
        self.assertEqual(response.status_code, 200)
1✔
90
        self.assertFalse(User.objects.filter(username="numericuser").exists())
1✔
91
        self.assertContains(response, "can’t be entirely numeric")
1✔
92

93

94
class PasswordResetTests(TestCase):
1✔
95
    def setUp(self):
1✔
96
        self.client = Client()
1✔
97
        self.user = User.objects.create_user(
1✔
98
            "resetuser", "reset@pawpark.com", "Pass123456"
99
        )
100

101
    def test_password_reset_page_loads(self):
1✔
102
        url = reverse("password_reset")
1✔
103
        response = self.client.get(url)
1✔
104
        self.assertEqual(response.status_code, 200)
1✔
105
        self.assertTemplateUsed(response, "registration/password_reset_form.html")
1✔
106

107
    def test_password_reset_flow(self):
1✔
108
        """
109
        Ensure that posting an email to password_reset
110
        sends the user to password_reset_done,
111
        and optionally check that an email was
112
        "sent" (console backend or etc.)
113
        """
114
        url = reverse("password_reset")
1✔
115
        response = self.client.post(url, {"email": "reset@pawpark.com"})
1✔
116
        self.assertEqual(response.status_code, 302)
1✔
117
        self.assertRedirects(response, reverse("password_reset_done"))
1✔
118

119
        self.assertEqual(len(mail.outbox), 1)
1✔
120
        self.assertIn("resetuser", mail.outbox[0].body)
1✔
121

122

123
class AdminSignUpTests(TestCase):
1✔
124
    def setUp(self):
1✔
125
        self.client = Client()
1✔
126
        self.register_url = reverse("register")
1✔
127

128
    def test_admin_signup_with_correct_code(self):
1✔
129
        """
130
        Signing up as admin with correct access code should create a staff user.
131
        """
132
        response = self.client.post(
1✔
133
            self.register_url,
134
            {
135
                "username": "adminuser",
136
                "password1": "StrongAdminPass123",
137
                "password2": "StrongAdminPass123",
138
                "role": "admin",
139
                "admin_access_code": "SUPERDOG123",
140
            },
141
        )
142
        self.assertEqual(response.status_code, 302)
1✔
143
        self.assertTrue(User.objects.filter(username="adminuser").exists())
1✔
144
        user = User.objects.get(username="adminuser")
1✔
145
        self.assertTrue(user.is_staff)
1✔
146

147
    def test_admin_signup_with_wrong_code(self):
1✔
148
        """
149
        Signing up as admin with wrong code should fail and not create staff user.
150
        """
151
        response = self.client.post(
1✔
152
            self.register_url,
153
            {
154
                "username": "fakeadmin",
155
                "password1": "StrongAdminPass123",
156
                "password2": "StrongAdminPass123",
157
                "role": "admin",
158
                "admin_access_code": "WRONGCODE",
159
            },
160
        )
161
        self.assertEqual(response.status_code, 200)
1✔
162
        self.assertFalse(User.objects.filter(username="fakeadmin").exists())
1✔
163

164
    def test_signup_as_normal_user_ignores_access_code(self):
1✔
165
        """
166
        If someone chooses 'user' role, the admin_access_code is irrelevant.
167
        """
168
        response = self.client.post(
1✔
169
            self.register_url,
170
            {
171
                "username": "normaluser",
172
                "password1": "StrongPass456",
173
                "password2": "StrongPass456",
174
                "role": "user",
175
                "admin_access_code": "SUPERDOG123",
176
            },
177
        )
178
        self.assertEqual(response.status_code, 302)
1✔
179
        self.assertTrue(User.objects.filter(username="normaluser").exists())
1✔
180
        user = User.objects.get(username="normaluser")
1✔
181
        self.assertFalse(user.is_staff)
1✔
182

183

184
class LoginTests(TestCase):
1✔
185
    def setUp(self):
1✔
186
        self.client = Client()
1✔
187
        self.user = User.objects.create_user(
1✔
188
            username="testuser", password="StrongPass123"
189
        )
190

191
    def test_login_page_loads(self):
1✔
192
        """Ensure the login page loads properly."""
193
        response = self.client.get(reverse("login"))
1✔
194
        self.assertEqual(response.status_code, 200)
1✔
195
        self.assertTemplateUsed(response, "parks/login.html")
1✔
196

197
    def test_valid_login(self):
1✔
198
        """Ensure a valid user can log in."""
199
        response = self.client.post(
1✔
200
            reverse("login"), {"username": "testuser", "password": "StrongPass123"}
201
        )
202
        self.assertEqual(response.status_code, 302)
1✔
203

204

205
class AuthTests(TestCase):
1✔
206
    def setUp(self):
1✔
207
        self.client = Client()
1✔
208

209
    def test_register_page_loads(self):
1✔
210
        """Ensure the registration page loads properly."""
211
        response = self.client.get(reverse("register"))
1✔
212
        self.assertEqual(response.status_code, 200)
1✔
213
        self.assertTemplateUsed(response, "parks/register.html")
1✔
214

215
    def test_user_registration(self):
1✔
216
        """Ensure a new user can register successfully."""
217
        response = self.client.post(
1✔
218
            reverse("register"),
219
            {
220
                "username": "testuser",
221
                "password1": "StrongPass123",
222
                "password2": "StrongPass123",
223
                "role": "user",  # Ensure this field is required
224
            },
225
        )
226
        self.assertEqual(response.status_code, 302)
1✔
227
        self.assertTrue(User.objects.filter(username="testuser").exists())
1✔
228

229

230
class ParkModelTest(TestCase):
1✔
231
    def setUp(self):
1✔
232
        self.client = Client()
1✔
233
        self.park = DogRunNew.objects.create(
1✔
234
            id="1",
235
            prop_id="1234",
236
            name="Central Park",
237
            address="New York, NY",
238
            dogruns_type="Small",
239
            accessible="Yes",
240
            notes="Test park notes",
241
            google_name="Central Park",
242
            borough="M",
243
            zip_code="United States",
244
            formatted_address="Central Pk N, New York, NY, USA",
245
            latitude=40.7987768,
246
            longitude=-73.9537196,
247
            additional={
248
                "geometry": {
249
                    "bounds": {
250
                        "northeast": {"lat": 40.8009264, "lng": -73.9495752},
251
                        "southwest": {"lat": 40.796948, "lng": -73.9580246},
252
                    },
253
                    "location": {"lat": 40.7987768, "lng": -73.9537196},
254
                    "location_type": "GEOMETRIC_CENTER",
255
                    "viewport": {
256
                        "northeast": {"lat": 40.8009264, "lng": -73.9495752},
257
                        "southwest": {"lat": 40.796948, "lng": -73.9580246},
258
                    },
259
                }
260
            },
261
            display_name="Central Park",
262
            slug=slugify(f"{'Central Park'}-{'1234'}"),
263
        )
264

265
    def test_park_creation(self):
1✔
266
        self.assertEqual(self.park.name, "Central Park")
1✔
267
        self.assertEqual(self.park.address, "New York, NY")
1✔
268
        self.assertEqual(self.park.notes, "Test park notes")
1✔
269
        self.assertEqual(self.park.slug, "central-park-1234")
1✔
270

271

272
class ReviewModelTest(TestCase):
1✔
273
    def setUp(self):
1✔
274
        self.user = User.objects.create_user(username="testuser", password="123456abc")
1✔
275
        self.park = DogRunNew.objects.create(
1✔
276
            id="2",
277
            prop_id="5678",
278
            name="Brooklyn Park",
279
            address="Brooklyn, NY",
280
            dogruns_type="Large",
281
            accessible="No",
282
            notes="Another test park",
283
            display_name="Brooklyn Park",
284
            slug=slugify(f"{'Brooklyn Park'}-{'5678'}"),
285
        )
286
        self.review = Review.objects.create(
1✔
287
            park=self.park, text="Great park!", rating=5, user=self.user
288
        )
289

290
    def test_review_creation(self):
1✔
291
        self.assertEqual(self.review.text, "Great park!")
1✔
292
        self.assertEqual(self.review.rating, 5)
1✔
293
        self.assertEqual(self.review.park.name, "Brooklyn Park")
1✔
294

295
    def test_review_str_method(self):
1✔
296
        self.assertEqual(str(self.review), "Review for Brooklyn Park (5 stars)")
1✔
297

298

299
class ParkListViewTest(TestCase):
1✔
300
    def setUp(self):
1✔
301
        self.client = Client()
1✔
302
        self.park = DogRunNew.objects.create(
1✔
303
            id="1",
304
            prop_id="1234",
305
            name="Central Park",
306
            address="New York, NY",
307
            dogruns_type="Small",
308
            accessible="Yes",
309
            notes="Test park notes",
310
            google_name="Central Park",
311
            borough="M",
312
            zip_code="United States",
313
            formatted_address="Central Pk N, New York, NY, USA",
314
            latitude=40.7987768,
315
            longitude=-73.9537196,
316
            additional={
317
                "geometry": {
318
                    "bounds": {
319
                        "northeast": {"lat": 40.8009264, "lng": -73.9495752},
320
                        "southwest": {"lat": 40.796948, "lng": -73.9580246},
321
                    },
322
                    "location": {"lat": 40.7987768, "lng": -73.9537196},
323
                    "location_type": "GEOMETRIC_CENTER",
324
                    "viewport": {
325
                        "northeast": {"lat": 40.8009264, "lng": -73.9495752},
326
                        "southwest": {"lat": 40.796948, "lng": -73.9580246},
327
                    },
328
                }
329
            },
330
            display_name="Central Park",
331
            slug=slugify(f"{'Central Park'}-{'1234'}"),
332
        )
333

334
    def test_park_list_view(self):
1✔
335
        response = self.client.get(reverse("park_list"))
1✔
336
        self.assertEqual(response.status_code, 200)
1✔
337
        self.assertContains(response, "Central Park")
1✔
338

339

340
class MapViewTest(TestCase):
1✔
341
    def setUp(self):
1✔
342
        self.client = Client()
1✔
343

344
    def test_map_view(self):
1✔
345
        response = self.client.get(reverse("map"))
1✔
346
        self.assertEqual(response.status_code, 200)
1✔
347

348

349
class CombinedViewTest(TestCase):
1✔
350
    def test_combined_view(self):
1✔
351
        response = self.client.get(reverse("park_and_map"))
1✔
352
        self.assertEqual(response.status_code, 200)
1✔
353

354
    def setUp(self):
1✔
355
        self.client = Client()
1✔
356
        # One park in Manhattan
357
        self.park_manhattan = DogRunNew.objects.create(
1✔
358
            id="1",
359
            prop_id="1234",
360
            name="Central Park",
361
            address="New York, NY",
362
            dogruns_type="Small",
363
            accessible="Yes",
364
            notes="Manhattan park",
365
            google_name="Central Park",
366
            borough="M",
367
            zip_code="10024",
368
            latitude=40.7987768,
369
            longitude=-73.9537196,
370
            display_name="Central Park",
371
        )
372
        # One park in Brooklyn
373
        self.park_brooklyn = DogRunNew.objects.create(
1✔
374
            id="2",
375
            prop_id="5678",
376
            name="Brooklyn Bridge Park",
377
            address="Brooklyn, NY",
378
            dogruns_type="Large",
379
            accessible="Yes",
380
            notes="Brooklyn park",
381
            google_name="Brooklyn Bridge Park",
382
            borough="B",
383
            zip_code="11201",
384
            latitude=40.700292,
385
            longitude=-73.996123,
386
            display_name="Brooklyn Bridge Park",
387
        )
388

389
    def test_combined_view_filters_by_borough(self):
1✔
390
        response = self.client.get(reverse("park_and_map"), {"borough": "M"})
1✔
391
        self.assertEqual(response.status_code, 200)
1✔
392
        self.assertContains(response, "Central Park")
1✔
393
        self.assertNotContains(response, "Brooklyn Bridge Park")
1✔
394

395

396
class ParkDetailViewTest(TestCase):
1✔
397
    def setUp(self):
1✔
398
        """Set up the test client and create a test park."""
399
        self.client = Client()
×
400

401
        self.park = DogRunNew.objects.create(
×
402
            id="1",
403
            prop_id="1234",
404
            name="Central Park",
405
            address="New York, NY",
406
            dogruns_type="Small",
407
            accessible="Yes",
408
            notes="Test park notes",
409
            google_name="Central Park",
410
            borough="M",
411
            zip_code="United States",
412
            formatted_address="Central Pk N, New York, NY, USA",
413
            latitude=40.7987768,
414
            longitude=-73.9537196,
415
            additional={
416
                "geometry": {
417
                    "bounds": {
418
                        "northeast": {"lat": 40.8009264, "lng": -73.9495752},
419
                        "southwest": {"lat": 40.796948, "lng": -73.9580246},
420
                    },
421
                    "location": {"lat": 40.7987768, "lng": -73.9537196},
422
                    "location_type": "GEOMETRIC_CENTER",
423
                    "viewport": {
424
                        "northeast": {"lat": 40.8009264, "lng": -73.9495752},
425
                        "southwest": {"lat": 40.796948, "lng": -73.9580246},
426
                    },
427
                }
428
            },
429
        )
430

431

432
class ReportFunctionalityTests(TestCase):
1✔
433
    def setUp(self):
1✔
434
        self.client = Client()
1✔
435
        self.user = User.objects.create_user(
1✔
436
            username="reporter", password="testpass123"
437
        )
438
        self.other_user = User.objects.create_user(
1✔
439
            username="uploader", password="testpass123"
440
        )
441

442
        self.park = DogRunNew.objects.create(
1✔
443
            id="10",
444
            prop_id="9999",
445
            name="Test Park",
446
            address="Test Address",
447
            dogruns_type="All",
448
            accessible="Yes",
449
            formatted_address="Test Address",
450
            latitude=40.0,
451
            longitude=-73.0,
452
        )
453

454
        self.image = ParkImage.objects.create(
1✔
455
            park=self.park,
456
            image="https://res.cloudinary.com/demo/image/upload/sample.jpg",
457
            user=self.other_user,
458
        )
459

460
        self.review = Review.objects.create(
1✔
461
            park=self.park, text="Nice place!", rating=4, user=self.other_user
462
        )
463

464
        self.client.login(username="reporter", password="testpass123")
1✔
465

466
    def test_report_image_creates_record(self):
1✔
467
        response = self.client.post(
1✔
468
            reverse("report_image", args=[self.image.id]),
469
            {"reason": "Inappropriate image"},
470
        )
471
        self.assertEqual(response.status_code, 302)
1✔
472
        self.assertEqual(self.image.reports.count(), 1)
1✔
473
        report = self.image.reports.first()
1✔
474
        self.assertEqual(report.reason, "Inappropriate image")
1✔
475
        self.assertEqual(report.user, self.user)
1✔
476

477
    def test_report_review_creates_record(self):
1✔
478
        response = self.client.post(
1✔
479
            reverse("park_detail", args=[self.park.slug, self.park.id]),
480
            {
481
                "form_type": "report_review",
482
                "review_id": self.review.id,
483
                "reason": "Offensive content",
484
            },
485
        )
486
        self.assertEqual(response.status_code, 302)
1✔
487
        self.assertEqual(self.review.reports.count(), 1)
1✔
488
        report = self.review.reports.first()
1✔
489
        self.assertEqual(report.reason, "Offensive content")
1✔
490
        self.assertEqual(report.reported_by, self.user)
1✔
491

492
    def test_submit_review(self):
1✔
493
        response = self.client.post(
1✔
494
            reverse("park_detail", args=[self.park.slug, self.park.id]),
495
            {"form_type": "submit_review", "text": "Another review!", "rating": "5"},
496
        )
497
        self.assertEqual(response.status_code, 302)
1✔
498
        self.assertEqual(Review.objects.filter(park=self.park).count(), 2)
1✔
499

500
    def test_review_report_str(self):
1✔
501
        report = ReviewReport.objects.create(
1✔
502
            review=self.review, reported_by=self.user, reason="Inappropriate content"
503
        )
504
        self.assertIn("Reported by", str(report))
1✔
505
        self.assertIn(str(self.review.id), str(report))
1✔
506

507
    def test_image_report_str(self):
1✔
508
        report = ImageReport.objects.create(
1✔
509
            image=self.image, user=self.user, reason="Offensive image"
510
        )
511
        self.assertIn("Report by", str(report))
1✔
512
        self.assertIn(str(self.image.id), str(report))
1✔
513

514
    def test_missing_reason_does_not_create_report(self):
1✔
515
        self.client.login(username="user2", password="testpass")
1✔
516
        response = self.client.post(
1✔
517
            reverse("report_image", args=[self.image.id]),
518
            {"reason": ""},
519
        )
520
        self.assertEqual(ImageReport.objects.count(), 0)
1✔
521
        self.assertEqual(response.status_code, 302)
1✔
522

523

524
class DeleteTests(TestCase):
1✔
525
    def setUp(self):
1✔
526
        self.client = Client()
1✔
527
        self.user = User.objects.create_user(username="deleter", password="123pass")
1✔
528
        self.client.login(username="deleter", password="123pass")
1✔
529

530
        self.park = DogRunNew.objects.create(
1✔
531
            id="22",
532
            prop_id="9988",
533
            name="Del Park",
534
            address="Somewhere",
535
            dogruns_type="All",
536
            accessible="Yes",
537
            formatted_address="Addr",
538
            latitude=40.0,
539
            longitude=-73.0,
540
        )
541
        self.review = Review.objects.create(
1✔
542
            park=self.park, text="Review", rating=4, user=self.user
543
        )
544
        self.image = ParkImage.objects.create(
1✔
545
            park=self.park,
546
            image="https://res.cloudinary.com/demo/image/upload/sample.jpg",
547
            user=self.user,
548
        )
549

550
    def test_delete_review(self):
1✔
551
        response = self.client.post(reverse("delete_review", args=[self.review.id]))
1✔
552
        self.assertEqual(response.status_code, 302)
1✔
553
        self.assertFalse(Review.objects.filter(id=self.review.id).exists())
1✔
554

555
    def test_delete_image(self):
1✔
556
        response = self.client.post(reverse("delete_image", args=[self.image.id]))
1✔
557
        self.assertEqual(response.status_code, 302)
1✔
558
        self.assertFalse(ParkImage.objects.filter(id=self.image.id).exists())
1✔
559

560

561
class ParkImageModelTest(TestCase):
1✔
562
    def setUp(self):
1✔
563
        """Set up a test park and associated images."""
564
        self.park = DogRunNew.objects.create(
1✔
565
            id="1",
566
            prop_id="1234",
567
            name="Central Park",
568
            address="New York, NY",
569
            dogruns_type="Small",
570
            accessible="Yes",
571
            notes="Test park notes",
572
            google_name="Central Park",
573
            borough="M",
574
            zip_code="United States",
575
            formatted_address="Central Pk N, New York, NY, USA",
576
            latitude=40.7987768,
577
            longitude=-73.9537196,
578
            additional={
579
                "geometry": {
580
                    "bounds": {
581
                        "northeast": {"lat": 40.8009264, "lng": -73.9495752},
582
                        "southwest": {"lat": 40.796948, "lng": -73.9580246},
583
                    },
584
                    "location": {"lat": 40.7987768, "lng": -73.9537196},
585
                    "location_type": "GEOMETRIC_CENTER",
586
                    "viewport": {
587
                        "northeast": {"lat": 40.8009264, "lng": -73.9495752},
588
                        "southwest": {"lat": 40.796948, "lng": -73.9580246},
589
                    },
590
                }
591
            },
592
        )
593
        self.image = ParkImage.objects.create(
1✔
594
            park=self.park,
595
            image="https://res.cloudinary.com/demo/image/upload/sample.jpg",
596
        )
597

598
    def test_park_image_creation(self):
1✔
599
        """Test that a ParkImage object is created successfully."""
600
        self.assertEqual(self.image.park, self.park)
1✔
601
        self.assertEqual(
1✔
602
            self.image.image, "https://res.cloudinary.com/demo/image/upload/sample.jpg"
603
        )
604

605
    def test_park_image_str(self):
1✔
606
        """Test the string representation of a ParkImage object."""
607
        self.assertEqual(str(self.image), f"Image for {self.park.name}")
1✔
608

609

610
class ParkDetailViewImageTest(TestCase):
1✔
611
    def setUp(self):
1✔
612
        """Set up a test park and associated images."""
613
        self.client = Client()
1✔
614
        self.park = DogRunNew.objects.create(
1✔
615
            id="1",
616
            prop_id="1234",
617
            name="Central Park",
618
            address="New York, NY",
619
            dogruns_type="Small",
620
            accessible="Yes",
621
            notes="Test park notes",
622
            google_name="Central Park",
623
            borough="M",
624
            zip_code="United States",
625
            formatted_address="Central Pk N, New York, NY, USA",
626
            latitude=40.7987768,
627
            longitude=-73.9537196,
628
            additional={
629
                "geometry": {
630
                    "bounds": {
631
                        "northeast": {"lat": 40.8009264, "lng": -73.9495752},
632
                        "southwest": {"lat": 40.796948, "lng": -73.9580246},
633
                    },
634
                    "location": {"lat": 40.7987768, "lng": -73.9537196},
635
                    "location_type": "GEOMETRIC_CENTER",
636
                    "viewport": {
637
                        "northeast": {"lat": 40.8009264, "lng": -73.9495752},
638
                        "southwest": {"lat": 40.796948, "lng": -73.9580246},
639
                    },
640
                }
641
            },
642
        )
643
        self.image = ParkImage.objects.create(
1✔
644
            park=self.park,
645
            image="https://res.cloudinary.com/demo/image/upload/sample.jpg",
646
        )
647

648
    def test_park_detail_view_with_images(self):
1✔
649
        """Test that the park detail view displays associated images."""
650
        response = self.client.get(
1✔
651
            reverse("park_detail", args=[self.park.slug, self.park.id])
652
        )
653
        self.assertEqual(response.status_code, 200)
1✔
654
        self.assertContains(response, self.park.name)
1✔
655
        # self.assertIn(self.image.image, response.content.decode())
656

657

658
class RenderStarsTests(TestCase):
1✔
659
    def test_int_stars(self):
1✔
660
        size = 20
1✔
661
        result = render_stars(4, size)
1✔
662
        self.assertEqual(result["filled_stars"], 4)
1✔
663
        self.assertEqual(result["half_stars"], 0)
1✔
664
        self.assertEqual(result["empty_stars"], 1)
1✔
665
        self.assertEqual(result["size"], size)
1✔
666

667
    def test_full_stars(self):
1✔
668
        size = 15
1✔
669
        result = render_stars(5, size)
1✔
670
        self.assertEqual(result["filled_stars"], 5)
1✔
671
        self.assertEqual(result["half_stars"], 0)
1✔
672
        self.assertEqual(result["empty_stars"], 0)
1✔
673
        self.assertEqual(result["size"], size)
1✔
674

675
    def test_no_stars(self):
1✔
676
        size = 10
1✔
677
        result = render_stars(0, size)
1✔
678
        self.assertEqual(result["filled_stars"], 0)
1✔
679
        self.assertEqual(result["half_stars"], 0)
1✔
680
        self.assertEqual(result["empty_stars"], 5)
1✔
681
        self.assertEqual(result["size"], size)
1✔
682

683
    def test_half_stars(self):
1✔
684
        size = 20
1✔
685
        result = render_stars(2.5, size)
1✔
686
        self.assertEqual(result["filled_stars"], 2)
1✔
687
        self.assertEqual(result["half_stars"], 1)
1✔
688
        self.assertEqual(result["empty_stars"], 2)
1✔
689
        self.assertEqual(result["size"], size)
1✔
690

691
    # >= X.25 -> one half star
692
    def test_round_up_to_half(self):
1✔
693
        size = 20
1✔
694
        result = render_stars(4.25, size)
1✔
695
        self.assertEqual(result["filled_stars"], 4)
1✔
696
        self.assertEqual(result["half_stars"], 1)
1✔
697
        self.assertEqual(result["empty_stars"], 0)
1✔
698
        self.assertEqual(result["size"], size)
1✔
699

700
    # < X.25 -> round down to whole
701
    def test_round_down_to_whole(self):
1✔
702
        size = 20
1✔
703
        result = render_stars(3.24, size)
1✔
704
        self.assertEqual(result["filled_stars"], 3)
1✔
705
        self.assertEqual(result["half_stars"], 0)
1✔
706
        self.assertEqual(result["empty_stars"], 2)
1✔
707
        self.assertEqual(result["size"], size)
1✔
708

709
    # < X.75 -> one half star
710
    def test_round_down_to_half(self):
1✔
711
        size = 20
1✔
712
        result = render_stars(2.74, size)
1✔
713
        self.assertEqual(result["filled_stars"], 2)
1✔
714
        self.assertEqual(result["half_stars"], 1)
1✔
715
        self.assertEqual(result["empty_stars"], 2)
1✔
716
        self.assertEqual(result["size"], size)
1✔
717

718
    # >= X.75 -> round up to next whole
719
    def test_round_up_to_whole(self):
1✔
720
        size = 20
1✔
721
        result = render_stars(4.75, size)
1✔
722
        self.assertEqual(result["filled_stars"], 5)
1✔
723
        self.assertEqual(result["half_stars"], 0)
1✔
724
        self.assertEqual(result["empty_stars"], 0)
1✔
725
        self.assertEqual(result["size"], size)
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc