punkweb-bb 0.1.1__py3-none-any.whl → 0.1.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. punkweb_bb/__pycache__/apps.cpython-311.pyc +0 -0
  2. punkweb_bb/__pycache__/bbcode_tags.cpython-311.pyc +0 -0
  3. punkweb_bb/__pycache__/models.cpython-311.pyc +0 -0
  4. punkweb_bb/__pycache__/parsers.cpython-311.pyc +0 -0
  5. punkweb_bb/__pycache__/settings.cpython-311.pyc +0 -0
  6. punkweb_bb/__pycache__/tests.cpython-311.pyc +0 -0
  7. punkweb_bb/__pycache__/views.cpython-311.pyc +0 -0
  8. punkweb_bb/migrations/0002_thread_view_count.py +18 -0
  9. punkweb_bb/migrations/__pycache__/0001_initial.cpython-311.pyc +0 -0
  10. punkweb_bb/migrations/__pycache__/0002_thread_view_count.cpython-311.pyc +0 -0
  11. punkweb_bb/models.py +4 -0
  12. punkweb_bb/parsers.py +52 -48
  13. punkweb_bb/settings.py +1 -0
  14. punkweb_bb/static/punkweb_bb/css/profile.css +7 -0
  15. punkweb_bb/templates/punkweb_bb/base.html +1 -1
  16. punkweb_bb/templates/punkweb_bb/index.html +2 -0
  17. punkweb_bb/templates/punkweb_bb/subcategory.html +7 -1
  18. punkweb_bb/templates/punkweb_bb/thread.html +5 -2
  19. punkweb_bb/templates/punkweb_bb/thread_create.html +3 -0
  20. punkweb_bb/templates/punkweb_bb/thread_update.html +3 -0
  21. punkweb_bb/templatetags/__pycache__/__init__.cpython-311.pyc +0 -0
  22. punkweb_bb/templatetags/__pycache__/humanize_count.cpython-311.pyc +0 -0
  23. punkweb_bb/templatetags/__pycache__/humanize_int.cpython-311.pyc +0 -0
  24. punkweb_bb/templatetags/__pycache__/shoutbox_bbcode.cpython-311.pyc +0 -0
  25. punkweb_bb/templatetags/humanize_int.py +12 -0
  26. punkweb_bb/templatetags/shoutbox_bbcode.py +2 -2
  27. punkweb_bb/tests.py +518 -2
  28. punkweb_bb/views.py +12 -3
  29. punkweb_bb-0.1.3.dist-info/METADATA +171 -0
  30. {punkweb_bb-0.1.1.dist-info → punkweb_bb-0.1.3.dist-info}/RECORD +33 -45
  31. punkweb_bb/__pycache__/conf.cpython-311.pyc +0 -0
  32. punkweb_bb/__pycache__/fields.cpython-311.pyc +0 -0
  33. punkweb_bb/__pycache__/utils.cpython-311.pyc +0 -0
  34. punkweb_bb/migrations/__pycache__/0002_category_alter_boardprofile_options_subcategory.cpython-311.pyc +0 -0
  35. punkweb_bb/migrations/__pycache__/0002_create_board_profiles.cpython-311.pyc +0 -0
  36. punkweb_bb/migrations/__pycache__/0002_remove_shout__content_rendered_alter_shout_content.cpython-311.pyc +0 -0
  37. punkweb_bb/migrations/__pycache__/0003_thread_post.cpython-311.pyc +0 -0
  38. punkweb_bb/migrations/__pycache__/0004_category_slug_subcategory_slug.cpython-311.pyc +0 -0
  39. punkweb_bb/migrations/__pycache__/0005_alter_category_slug_alter_subcategory_slug.cpython-311.pyc +0 -0
  40. punkweb_bb/migrations/__pycache__/0006_boardprofile_image.cpython-311.pyc +0 -0
  41. punkweb_bb/migrations/__pycache__/0007_alter_boardprofile_image.cpython-311.pyc +0 -0
  42. punkweb_bb/migrations/__pycache__/0008_shout.cpython-311.pyc +0 -0
  43. punkweb_bb/migrations/__pycache__/0009_remove_category__description_rendered_and_more.cpython-311.pyc +0 -0
  44. punkweb_bb/migrations/__pycache__/0010_alter_boardprofile_options_alter_category_options_and_more.cpython-311.pyc +0 -0
  45. punkweb_bb/migrations/__pycache__/0011_alter_thread_options_thread_last_post_created_at.cpython-311.pyc +0 -0
  46. punkweb_bb/migrations/__pycache__/0011_thread_is_closed.cpython-311.pyc +0 -0
  47. punkweb_bb/migrations/__pycache__/0012_subcategory_staff_post_only.cpython-311.pyc +0 -0
  48. punkweb_bb-0.1.1.dist-info/METADATA +0 -72
  49. {punkweb_bb-0.1.1.dist-info → punkweb_bb-0.1.3.dist-info}/LICENSE +0 -0
  50. {punkweb_bb-0.1.1.dist-info → punkweb_bb-0.1.3.dist-info}/WHEEL +0 -0
  51. {punkweb_bb-0.1.1.dist-info → punkweb_bb-0.1.3.dist-info}/top_level.txt +0 -0
punkweb_bb/tests.py CHANGED
@@ -2,7 +2,9 @@ import math
2
2
 
3
3
  from django.contrib.auth import get_user_model
4
4
  from django.core.cache import cache
5
- from django.test import TestCase
5
+ from django.forms import ValidationError
6
+ from django.test import Client, TestCase
7
+ from django.urls import reverse
6
8
  from django.utils import timezone
7
9
 
8
10
  from punkweb_bb.models import (
@@ -141,7 +143,7 @@ class ThreadTestCase(TestCase):
141
143
  self.user = User.objects.create_user(username="test", password="test")
142
144
  self.category = Category.objects.create(name="test")
143
145
  self.subcategory = Subcategory.objects.create(
144
- name="test", category=self.category
146
+ name="test", category=self.category, slug="test"
145
147
  )
146
148
 
147
149
  def test_thread_str(self):
@@ -175,6 +177,64 @@ class ThreadTestCase(TestCase):
175
177
 
176
178
  self.assertEqual(thread.latest_post, post_2)
177
179
 
180
+ def test_last_post_created_at(self):
181
+ thread = Thread.objects.create(
182
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
183
+ )
184
+ initial_last_post_created_at = thread.last_post_created_at
185
+ Post.objects.create(thread=thread, user=self.user, content="test")
186
+ new_last_post_created_at = thread.last_post_created_at
187
+
188
+ self.assertGreater(new_last_post_created_at, initial_last_post_created_at)
189
+
190
+ def test_is_closed(self):
191
+ thread = Thread.objects.create(
192
+ subcategory=self.subcategory,
193
+ user=self.user,
194
+ title="test",
195
+ content="test",
196
+ is_closed=True,
197
+ )
198
+ self.assertEqual(thread.is_closed, True)
199
+
200
+ post = Post(
201
+ thread=thread,
202
+ user=self.user,
203
+ content="test",
204
+ )
205
+
206
+ self.assertRaises(ValidationError, post.save)
207
+
208
+ def test_is_pinned(self):
209
+ thread = Thread.objects.create(
210
+ subcategory=self.subcategory,
211
+ user=self.user,
212
+ title="test1",
213
+ content="test1",
214
+ is_pinned=True,
215
+ )
216
+ self.assertEqual(thread.is_pinned, True)
217
+
218
+ Thread.objects.create(
219
+ subcategory=self.subcategory, user=self.user, title="test2", content="test2"
220
+ )
221
+
222
+ threads = Thread.objects.all()
223
+
224
+ self.assertEqual(threads[0], thread)
225
+
226
+ def test_bump(self):
227
+ thread1 = Thread.objects.create(
228
+ subcategory=self.subcategory, user=self.user, title="test1", content="test1"
229
+ )
230
+ Thread.objects.create(
231
+ subcategory=self.subcategory, user=self.user, title="test2", content="test2"
232
+ )
233
+ Post.objects.create(thread=thread1, user=self.user, content="test1")
234
+ threads = Thread.objects.all()
235
+
236
+ self.assertEqual(threads[0], thread1)
237
+
178
238
  def test_get_absolute_url(self):
179
239
  thread = Thread.objects.create(
180
240
  subcategory=self.subcategory, user=self.user, title="test", content="test"
@@ -228,3 +288,459 @@ class ShoutTestCase(TestCase):
228
288
  def test_str(self):
229
289
  shout = Shout.objects.create(user=self.user, content="test")
230
290
  self.assertEqual(str(shout), f"{shout.user} > {shout.created_at}")
291
+
292
+
293
+ class IndexViewTestCase(TestCase):
294
+ def setUp(self):
295
+ self.client = Client()
296
+ self.url = reverse("punkweb_bb:index")
297
+ self.user = User.objects.create(username="test", password="test")
298
+ self.staff_user = User.objects.create(
299
+ username="staff", password="staff", is_staff=True
300
+ )
301
+
302
+ def test_users_online(self):
303
+ response = self.client.get(self.url)
304
+ self.assertEqual(len(response.context["users_online"]), 0)
305
+
306
+ self.client.force_login(self.user)
307
+ response = self.client.get(self.url)
308
+
309
+ self.assertEqual(len(response.context["users_online"]), 1)
310
+
311
+ def test_staff_online(self):
312
+ response = self.client.get(self.url)
313
+ self.assertEqual(len(response.context["staff_online"]), 0)
314
+
315
+ self.client.force_login(self.staff_user)
316
+ response = self.client.get(self.url)
317
+
318
+ self.assertEqual(len(response.context["staff_online"]), 1)
319
+
320
+ def test_newest_user(self):
321
+ response = self.client.get(self.url)
322
+ self.assertEqual(response.context["newest_user"], self.staff_user)
323
+
324
+ def test_users_count(self):
325
+ response = self.client.get(self.url)
326
+ self.assertEqual(response.context["users"].count(), 2)
327
+
328
+
329
+ class LoginViewTestCase(TestCase):
330
+ def setUp(self):
331
+ self.client = Client()
332
+ self.url = reverse("punkweb_bb:login")
333
+ self.user = User.objects.create_user(username="test", password="test")
334
+
335
+ def test_redirect_authenticated_user(self):
336
+ self.client.force_login(self.user)
337
+ response = self.client.get(self.url)
338
+
339
+ self.assertRedirects(response, reverse("punkweb_bb:index"))
340
+
341
+ def test_login(self):
342
+ response = self.client.post(
343
+ self.url, {"username": "test", "password": "test"}, follow=True
344
+ )
345
+
346
+ self.assertRedirects(response, reverse("punkweb_bb:index"))
347
+ self.assertTrue(response.context["user"].is_authenticated)
348
+
349
+
350
+ class LogoutViewTestCase(TestCase):
351
+ def setUp(self):
352
+ self.client = Client()
353
+ self.url = reverse("punkweb_bb:logout")
354
+ self.user = User.objects.create_user(username="test", password="test")
355
+
356
+ def test_logout(self):
357
+ self.client.force_login(self.user)
358
+ response = self.client.get(self.url, follow=True)
359
+
360
+ self.assertRedirects(response, reverse("punkweb_bb:login"))
361
+ self.assertFalse(response.context["user"].is_authenticated)
362
+
363
+
364
+ class SignupViewTestCase(TestCase):
365
+ def setUp(self):
366
+ self.client = Client()
367
+ self.url = reverse("punkweb_bb:signup")
368
+ self.user = User.objects.create_user(username="test1", password="test")
369
+
370
+ def test_redirect_authenticated_user(self):
371
+ self.client.force_login(self.user)
372
+ response = self.client.get(self.url)
373
+
374
+ self.assertRedirects(response, reverse("punkweb_bb:index"))
375
+
376
+ def test_signup(self):
377
+ response = self.client.post(
378
+ self.url,
379
+ {
380
+ "username": "test2",
381
+ "password1": "needsmorecomplexity",
382
+ "password2": "needsmorecomplexity",
383
+ },
384
+ )
385
+
386
+ self.assertRedirects(response, reverse("punkweb_bb:login"))
387
+
388
+
389
+ class SettingsViewTestCase(TestCase):
390
+ def setUp(self):
391
+ self.client = Client()
392
+ self.url = reverse("punkweb_bb:settings")
393
+ self.user = User.objects.create_user(username="test", password="test")
394
+
395
+ def test_redirect_unauthenticated_user(self):
396
+ response = self.client.get(self.url)
397
+
398
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
399
+
400
+ def test_settings(self):
401
+ self.client.force_login(self.user)
402
+ response = self.client.get(self.url)
403
+
404
+ self.assertEqual(response.status_code, 200)
405
+
406
+ self.client.post(
407
+ self.url,
408
+ {
409
+ "signature": "[b]test[/b]",
410
+ },
411
+ )
412
+
413
+ self.user.profile.refresh_from_db()
414
+ self.assertEqual(self.user.profile._signature_rendered, "<strong>test</strong>")
415
+
416
+ self.assertEqual(response.status_code, 200)
417
+
418
+
419
+ class ThreadCreateViewTestCase(TestCase):
420
+ def setUp(self):
421
+ self.client = Client()
422
+ self.user = User.objects.create_user(username="test", password="test")
423
+ self.category = Category.objects.create(name="test")
424
+ self.subcategory = Subcategory.objects.create(
425
+ name="test", category=self.category, slug="test"
426
+ )
427
+ self.staff_subcategory = Subcategory.objects.create(
428
+ name="staff", category=self.category, slug="staff", staff_post_only=True
429
+ )
430
+ self.url = reverse("punkweb_bb:thread_create", args=[self.subcategory.slug])
431
+ self.staff_only_url = reverse(
432
+ "punkweb_bb:thread_create", args=[self.staff_subcategory.slug]
433
+ )
434
+
435
+ def test_redirect_unauthenticated_user(self):
436
+ response = self.client.get(self.url)
437
+
438
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
439
+
440
+ def test_thread_create(self):
441
+ self.client.force_login(self.user)
442
+ response = self.client.get(self.url)
443
+
444
+ self.assertEqual(response.status_code, 200)
445
+
446
+ response = self.client.post(
447
+ self.url,
448
+ {
449
+ "title": "test",
450
+ "content": "test",
451
+ },
452
+ follow=True,
453
+ )
454
+
455
+ new_thread = Thread.objects.first()
456
+
457
+ self.assertRedirects(response, new_thread.get_absolute_url())
458
+ self.assertEqual(Thread.objects.count(), 1)
459
+ self.assertEqual(new_thread.user, self.user)
460
+ self.assertEqual(new_thread.subcategory, self.subcategory)
461
+
462
+ def test_thread_create_staff_post_only(self):
463
+ self.client.force_login(self.user)
464
+ response = self.client.get(self.staff_only_url)
465
+
466
+ self.assertRedirects(response, self.staff_subcategory.get_absolute_url())
467
+
468
+
469
+ class ThreadViewTestCase(TestCase):
470
+ def setUp(self):
471
+ self.client = Client()
472
+ self.user = User.objects.create_user(username="test", password="test")
473
+ self.category = Category.objects.create(name="test")
474
+ self.subcategory = Subcategory.objects.create(
475
+ name="test", category=self.category, slug="test"
476
+ )
477
+ self.thread = Thread.objects.create(
478
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
479
+ )
480
+ self.url = reverse("punkweb_bb:thread", args=[self.thread.id])
481
+
482
+ def test_view_count(self):
483
+ response = self.client.get(self.url)
484
+ self.assertEqual(response.context["thread"].view_count, 1)
485
+
486
+ # ensure that the view count does not increase when viewed again from the same session
487
+
488
+ response = self.client.get(self.url)
489
+ self.assertEqual(response.context["thread"].view_count, 1)
490
+
491
+
492
+ class ThreadUpdateViewTestCase(TestCase):
493
+ def setUp(self):
494
+ self.client = Client()
495
+ self.user = User.objects.create_user(username="test", password="test")
496
+ self.other_user = User.objects.create_user(username="other", password="other")
497
+ self.category = Category.objects.create(name="test")
498
+ self.subcategory = Subcategory.objects.create(
499
+ name="test", category=self.category, slug="test"
500
+ )
501
+ self.thread = Thread.objects.create(
502
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
503
+ )
504
+ self.url = reverse("punkweb_bb:thread_update", args=[self.thread.id])
505
+
506
+ def test_redirect_unauthenticated_user(self):
507
+ response = self.client.get(self.url)
508
+
509
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
510
+
511
+ def test_is_author(self):
512
+ self.client.force_login(self.other_user)
513
+ response = self.client.get(self.url)
514
+ self.assertEqual(response.status_code, 404)
515
+
516
+ self.client.force_login(self.user)
517
+ response = self.client.get(self.url)
518
+ self.assertEqual(response.status_code, 200)
519
+
520
+ def test_thread_update(self):
521
+ self.client.force_login(self.user)
522
+ response = self.client.get(self.url)
523
+
524
+ self.assertEqual(response.status_code, 200)
525
+
526
+ response = self.client.post(
527
+ self.url,
528
+ {
529
+ "title": "edit",
530
+ "content": "edit",
531
+ },
532
+ follow=True,
533
+ )
534
+
535
+ self.assertRedirects(response, self.thread.get_absolute_url())
536
+ self.thread.refresh_from_db()
537
+ self.assertEqual(self.thread.title, "edit")
538
+ self.assertEqual(self.thread._content_rendered, "edit")
539
+
540
+
541
+ class ThreadDeleteViewTestCase(TestCase):
542
+ def setUp(self):
543
+ self.client = Client()
544
+ self.user = User.objects.create_user(username="test", password="test")
545
+ self.other_user = User.objects.create_user(username="other", password="other")
546
+ self.category = Category.objects.create(name="test")
547
+ self.subcategory = Subcategory.objects.create(
548
+ name="test", category=self.category, slug="test"
549
+ )
550
+ self.thread = Thread.objects.create(
551
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
552
+ )
553
+ self.url = reverse("punkweb_bb:thread_delete", args=[self.thread.id])
554
+
555
+ def test_redirect_unauthenticated_user(self):
556
+ response = self.client.get(self.url)
557
+
558
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
559
+
560
+ def test_is_author(self):
561
+ self.client.force_login(self.other_user)
562
+ response = self.client.get(self.url)
563
+ self.assertEqual(response.status_code, 404)
564
+
565
+ self.client.force_login(self.user)
566
+ response = self.client.get(self.url)
567
+ self.assertEqual(response.status_code, 200)
568
+
569
+ def test_thread_delete(self):
570
+ self.client.force_login(self.user)
571
+ response = self.client.get(self.url)
572
+
573
+ self.assertEqual(response.status_code, 200)
574
+
575
+ response = self.client.delete(self.url, follow=True)
576
+
577
+ self.assertEqual(
578
+ response.headers["HX-Redirect"], self.subcategory.get_absolute_url()
579
+ )
580
+ self.assertEqual(Thread.objects.count(), 0)
581
+
582
+
583
+ class PostCreateViewTestCase(TestCase):
584
+ def setUp(self):
585
+ self.client = Client()
586
+ self.user = User.objects.create_user(username="test", password="test")
587
+ self.category = Category.objects.create(name="test")
588
+ self.subcategory = Subcategory.objects.create(
589
+ name="test", category=self.category, slug="test"
590
+ )
591
+ self.thread = Thread.objects.create(
592
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
593
+ )
594
+ self.url = reverse("punkweb_bb:post_create", args=[self.thread.id])
595
+
596
+ def test_redirect_unauthenticated_user(self):
597
+ response = self.client.get(self.url)
598
+
599
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
600
+
601
+ def test_post_create(self):
602
+ self.client.force_login(self.user)
603
+
604
+ response = self.client.post(
605
+ self.url,
606
+ {
607
+ "content": "test",
608
+ },
609
+ follow=True,
610
+ )
611
+
612
+ new_post = Post.objects.first()
613
+
614
+ self.assertRedirects(response, new_post.get_absolute_url())
615
+ self.assertEqual(Post.objects.count(), 1)
616
+ self.assertEqual(new_post.user, self.user)
617
+ self.assertEqual(new_post.thread, self.thread)
618
+
619
+
620
+ class PostUpdateViewTestCase(TestCase):
621
+ def setUp(self):
622
+ self.client = Client()
623
+ self.user = User.objects.create_user(username="test", password="test")
624
+ self.other_user = User.objects.create_user(username="other", password="other")
625
+ self.category = Category.objects.create(name="test")
626
+ self.subcategory = Subcategory.objects.create(
627
+ name="test", category=self.category, slug="test"
628
+ )
629
+ self.thread = Thread.objects.create(
630
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
631
+ )
632
+ self.post = Post.objects.create(
633
+ thread=self.thread, user=self.user, content="test"
634
+ )
635
+ self.url = reverse("punkweb_bb:post_update", args=[self.post.id])
636
+
637
+ def test_redirect_unauthenticated_user(self):
638
+ response = self.client.get(self.url)
639
+
640
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
641
+
642
+ def test_is_author(self):
643
+ self.client.force_login(self.other_user)
644
+ response = self.client.get(self.url)
645
+ self.assertEqual(response.status_code, 404)
646
+
647
+ self.client.force_login(self.user)
648
+ response = self.client.get(self.url)
649
+ self.assertEqual(response.status_code, 200)
650
+
651
+ def test_post_update(self):
652
+ self.client.force_login(self.user)
653
+ response = self.client.get(self.url)
654
+
655
+ self.assertEqual(response.status_code, 200)
656
+
657
+ response = self.client.post(
658
+ self.url,
659
+ {
660
+ "content": "edit",
661
+ },
662
+ follow=True,
663
+ )
664
+
665
+ self.assertRedirects(response, self.post.get_absolute_url())
666
+ self.post.refresh_from_db()
667
+ self.assertEqual(self.post._content_rendered, "edit")
668
+
669
+
670
+ class PostDeleteViewTestCase(TestCase):
671
+ def setUp(self):
672
+ self.client = Client()
673
+ self.user = User.objects.create_user(username="test", password="test")
674
+ self.other_user = User.objects.create_user(username="other", password="other")
675
+ self.category = Category.objects.create(name="test")
676
+ self.subcategory = Subcategory.objects.create(
677
+ name="test", category=self.category, slug="test"
678
+ )
679
+ self.thread = Thread.objects.create(
680
+ subcategory=self.subcategory, user=self.user, title="test", content="test"
681
+ )
682
+ self.post = Post.objects.create(
683
+ thread=self.thread, user=self.user, content="test"
684
+ )
685
+ self.url = reverse("punkweb_bb:post_delete", args=[self.post.id])
686
+
687
+ def test_redirect_unauthenticated_user(self):
688
+ response = self.client.get(self.url)
689
+
690
+ self.assertRedirects(response, f"{reverse('punkweb_bb:login')}?next={self.url}")
691
+
692
+ def test_is_author(self):
693
+ self.client.force_login(self.other_user)
694
+ response = self.client.get(self.url)
695
+ self.assertEqual(response.status_code, 404)
696
+
697
+ self.client.force_login(self.user)
698
+ response = self.client.get(self.url)
699
+ self.assertEqual(response.status_code, 200)
700
+
701
+ def test_post_delete(self):
702
+ self.client.force_login(self.user)
703
+ response = self.client.get(self.url)
704
+
705
+ self.assertEqual(response.status_code, 200)
706
+
707
+ response = self.client.delete(self.url, follow=True)
708
+
709
+ self.assertEqual(
710
+ response.headers["HX-Redirect"], self.thread.get_absolute_url()
711
+ )
712
+ self.assertEqual(Post.objects.count(), 0)
713
+
714
+
715
+ class ShoutCreateViewTestCase(TestCase):
716
+ def setUp(self):
717
+ self.client = Client()
718
+ self.user = User.objects.create_user(username="test", password="test")
719
+ self.url = reverse("punkweb_bb:shout_create")
720
+
721
+ def test_unauthenticated(self):
722
+ response = self.client.get(self.url)
723
+
724
+ self.client.post(
725
+ self.url,
726
+ {
727
+ "content": "test",
728
+ },
729
+ )
730
+
731
+ self.assertEqual(Shout.objects.count(), 0)
732
+ self.assertEqual(response.status_code, 200)
733
+
734
+ def test_shout_create(self):
735
+ self.client.force_login(self.user)
736
+
737
+ response = self.client.post(
738
+ self.url,
739
+ {
740
+ "content": "test",
741
+ },
742
+ follow=True,
743
+ )
744
+
745
+ self.assertEqual(Shout.objects.count(), 1)
746
+ self.assertEqual(response.status_code, 200)
punkweb_bb/views.py CHANGED
@@ -108,7 +108,9 @@ def profile_view(request, user_id):
108
108
 
109
109
 
110
110
  def members_view(request):
111
- users = paginate_qs(request, User.objects.select_related("profile").all())
111
+ users = paginate_qs(
112
+ request, User.objects.select_related("profile").order_by("username")
113
+ )
112
114
 
113
115
  context = {
114
116
  "users": users,
@@ -185,6 +187,13 @@ def thread_view(request, thread_id):
185
187
 
186
188
  post_form = PostModelForm()
187
189
 
190
+ # Increment view count if this session hasn't viewed the thread before
191
+ viewed_threads = request.session.get("viewed_threads", [])
192
+ if thread_id not in viewed_threads:
193
+ thread.view_count += 1
194
+ thread.save()
195
+ request.session["viewed_threads"] = viewed_threads + [thread_id]
196
+
188
197
  context = {
189
198
  "thread": thread,
190
199
  "posts": posts,
@@ -235,7 +244,7 @@ def post_create_view(request, thread_id):
235
244
  thread = get_object_or_404(Thread, pk=thread_id)
236
245
 
237
246
  if thread.is_closed:
238
- return HttpResponseForbidden("This thread is closed.")
247
+ return HttpResponseForbidden("Cannot add posts to a closed thread.")
239
248
 
240
249
  form = PostModelForm(request.POST)
241
250
 
@@ -336,7 +345,7 @@ def bbcode_view(request):
336
345
  ("Url", "[url=https://google.com]Link Text[/url]"),
337
346
  (
338
347
  "Image",
339
- "[img]https://punkweb.net/media/music/artists/system-lynx_EklOGpj.png.200x200_q85_crop.png[/img]",
348
+ "[img]https://placehold.co/400[/img]",
340
349
  ),
341
350
  # Custom
342
351
  ("Horizontal Rule", "[hr]"),