test_threadslists_views.py 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. from datetime import timedelta
  2. from django.conf import settings
  3. from django.utils import timezone
  4. from misago.acl.testutils import override_acl
  5. from misago.categories.models import Category
  6. from misago.core import threadstore
  7. from misago.core.cache import cache
  8. from misago.readtracker import categoriestracker, threadstracker
  9. from misago.users.testutils import AuthenticatedUserTestCase
  10. from misago.threads import testutils
  11. LISTS_URLS = (
  12. '',
  13. 'my/',
  14. 'new/',
  15. 'unread/',
  16. 'subscribed/'
  17. )
  18. class ThreadsListTestCase(AuthenticatedUserTestCase):
  19. def setUp(self):
  20. super(ThreadsListTestCase, self).setUp()
  21. cache.clear()
  22. threadstore.clear()
  23. self.root = Category.objects.root_category()
  24. self.first_category = Category.objects.get(slug='first-category')
  25. """
  26. Create categories tree for test cases:
  27. First category (created by migration)
  28. Category A
  29. + Category B
  30. + Subcategory C
  31. + Subcategory D
  32. Category E
  33. + Subcategory F
  34. """
  35. Category(
  36. name='Category A',
  37. slug='category-a',
  38. css_class='showing-category-a',
  39. ).insert_at(self.root, position='last-child', save=True)
  40. Category(
  41. name='Category E',
  42. slug='category-e',
  43. css_class='showing-category-e',
  44. ).insert_at(self.root, position='last-child', save=True)
  45. self.root = Category.objects.root_category()
  46. self.category_a = Category.objects.get(slug='category-a')
  47. Category(
  48. name='Category B',
  49. slug='category-b',
  50. css_class='showing-category-b',
  51. ).insert_at(self.category_a, position='last-child', save=True)
  52. self.category_b = Category.objects.get(slug='category-b')
  53. Category(
  54. name='Category C',
  55. slug='category-c',
  56. css_class='showing-category-c',
  57. ).insert_at(self.category_b, position='last-child', save=True)
  58. Category(
  59. name='Category D',
  60. slug='category-d',
  61. css_class='showing-category-d',
  62. ).insert_at(self.category_b, position='last-child', save=True)
  63. self.category_c = Category.objects.get(slug='category-c')
  64. self.category_d = Category.objects.get(slug='category-d')
  65. self.category_e = Category.objects.get(slug='category-e')
  66. Category(
  67. name='Category F',
  68. slug='category-f',
  69. css_class='showing-category-f',
  70. ).insert_at(self.category_e, position='last-child', save=True)
  71. self.category_f = Category.objects.get(slug='category-f')
  72. self.access_all_categories()
  73. def access_all_categories(self, extra=None):
  74. cache.clear()
  75. threadstore.clear()
  76. categories_acl = {'categories': {}, 'visible_categories': []}
  77. for category in Category.objects.all_categories():
  78. categories_acl['visible_categories'].append(category.pk)
  79. categories_acl['categories'][category.pk] = {
  80. 'can_see': 1,
  81. 'can_browse': 1,
  82. 'can_see_all_threads': 1,
  83. 'can_see_own_threads': 0,
  84. 'can_hide_threads': 0,
  85. 'can_review_moderated_content': 0,
  86. }
  87. if extra:
  88. categories_acl['categories'][category.pk].update(extra)
  89. override_acl(self.user, categories_acl)
  90. return categories_acl
  91. class ListsTests(ThreadsListTestCase):
  92. def test_list_renders_empty(self):
  93. """empty threads list renders"""
  94. for url in LISTS_URLS:
  95. self.access_all_categories()
  96. response = self.client.get('/' + url)
  97. self.assertEqual(response.status_code, 200)
  98. self.assertIn("empty-message", response.content)
  99. self.access_all_categories()
  100. response = self.client.get(self.category_b.get_absolute_url() + url)
  101. self.assertEqual(response.status_code, 200)
  102. self.assertIn(self.category_b.name, response.content)
  103. self.assertIn("empty-message", response.content)
  104. def test_list_authenticated_only_views(self):
  105. """authenticated only views return 403 for guests"""
  106. for url in LISTS_URLS:
  107. self.access_all_categories()
  108. response = self.client.get('/' + url)
  109. self.assertEqual(response.status_code, 200)
  110. self.access_all_categories()
  111. response = self.client.get(self.category_b.get_absolute_url() + url)
  112. self.assertEqual(response.status_code, 200)
  113. self.assertIn(self.category_b.name, response.content)
  114. self.logout_user()
  115. self.user = self.get_anonymous_user()
  116. for url in LISTS_URLS[1:]:
  117. self.access_all_categories()
  118. response = self.client.get('/' + url)
  119. self.assertEqual(response.status_code, 403)
  120. self.access_all_categories()
  121. response = self.client.get(self.category_b.get_absolute_url() + url)
  122. self.assertEqual(response.status_code, 403)
  123. def test_empty_list_hides_categories_picker(self):
  124. """categories picker is hidden on empty list"""
  125. Category(
  126. name='Hidden Category',
  127. slug='hidden-category',
  128. ).insert_at(self.root, position='last-child', save=True)
  129. test_category = Category.objects.get(slug='hidden-category')
  130. self.access_all_categories()
  131. response = self.client.get('/')
  132. self.assertEqual(response.status_code, 200)
  133. self.assertNotIn(
  134. 'subcategory-%s' % self.category_a.css_class, response.content)
  135. self.assertNotIn(
  136. 'subcategory-%s' % self.category_e.css_class, response.content)
  137. self.access_all_categories()
  138. response = self.client.get(self.category_a.get_absolute_url())
  139. self.assertEqual(response.status_code, 200)
  140. self.assertNotIn(
  141. 'subcategory-%s' % self.category_b.css_class, response.content)
  142. def test_list_renders_categories_picker(self):
  143. """categories picker renders valid categories"""
  144. Category(
  145. name='Hidden Category',
  146. slug='hidden-category',
  147. ).insert_at(self.root, position='last-child', save=True)
  148. test_category = Category.objects.get(slug='hidden-category')
  149. testutils.post_thread(
  150. category=self.category_b,
  151. )
  152. response = self.client.get('/')
  153. self.assertEqual(response.status_code, 200)
  154. self.assertIn(
  155. 'subcategory-%s' % self.category_a.css_class, response.content)
  156. # readable categories, but non-accessible directly
  157. self.assertNotIn(
  158. 'subcategory-%s' % self.category_b.css_class, response.content)
  159. self.assertNotIn(
  160. 'subcategory-%s' % self.category_c.css_class, response.content)
  161. self.assertNotIn(
  162. 'subcategory-%s' % self.category_d.css_class, response.content)
  163. self.assertNotIn(
  164. 'subcategory-%s' % self.category_f.css_class, response.content)
  165. # hidden category
  166. self.assertNotIn(
  167. 'subcategory-%s' % test_category.css_class, response.content)
  168. # test category view
  169. self.access_all_categories()
  170. response = self.client.get(self.category_a.get_absolute_url())
  171. self.assertEqual(response.status_code, 200)
  172. self.assertIn(
  173. 'subcategory-%s' % self.category_b.css_class, response.content)
  174. # readable categories, but non-accessible directly
  175. self.assertNotIn(
  176. 'subcategory-%s' % self.category_c.css_class, response.content)
  177. self.assertNotIn(
  178. 'subcategory-%s' % self.category_d.css_class, response.content)
  179. self.assertNotIn(
  180. 'subcategory-%s' % self.category_f.css_class, response.content)
  181. class CategoryThreadsListTests(ThreadsListTestCase):
  182. def test_access_hidden_category(self):
  183. """hidden category returns 404"""
  184. Category(
  185. name='Hidden Category',
  186. slug='hidden-category',
  187. ).insert_at(self.root, position='last-child', save=True)
  188. test_category = Category.objects.get(slug='hidden-category')
  189. for url in LISTS_URLS:
  190. response = self.client.get(test_category.get_absolute_url() + url)
  191. self.assertEqual(response.status_code, 404)
  192. def test_access_protected_category(self):
  193. """protected category returns 403"""
  194. Category(
  195. name='Hidden Category',
  196. slug='hidden-category',
  197. ).insert_at(self.root, position='last-child', save=True)
  198. test_category = Category.objects.get(slug='hidden-category')
  199. for url in LISTS_URLS:
  200. override_acl(self.user, {
  201. 'visible_categories': [test_category.pk],
  202. 'categories': {
  203. test_category.pk: {
  204. 'can_see': 1,
  205. 'can_browse': 0,
  206. }
  207. }
  208. });
  209. response = self.client.get(test_category.get_absolute_url() + url)
  210. self.assertEqual(response.status_code, 403)
  211. class ThreadsVisibilityTests(ThreadsListTestCase):
  212. def test_list_renders_test_thread(self):
  213. """list renders test thread with valid top category"""
  214. test_thread = testutils.post_thread(
  215. category=self.category_c,
  216. )
  217. response = self.client.get('/')
  218. self.assertEqual(response.status_code, 200)
  219. self.assertIn(test_thread.get_absolute_url(), response.content)
  220. self.assertIn(
  221. 'subcategory-%s' % self.category_a.css_class, response.content)
  222. self.assertIn(
  223. 'thread-category-%s' % self.category_a.css_class, response.content)
  224. self.assertIn(
  225. 'thread-category-%s' % self.category_c.css_class, response.content)
  226. # other top category is hidden from user
  227. self.assertNotIn(
  228. 'subcategory-%s' % self.category_e.css_class, response.content)
  229. # test category view
  230. self.access_all_categories()
  231. response = self.client.get(self.category_b.get_absolute_url())
  232. self.assertEqual(response.status_code, 200)
  233. # thread displays
  234. self.assertIn(test_thread.get_absolute_url(), response.content)
  235. self.assertNotIn(
  236. 'thread-category-%s' % self.category_b.css_class, response.content)
  237. self.assertIn(
  238. 'thread-category-%s' % self.category_c.css_class, response.content)
  239. # category picker was update
  240. self.assertIn(
  241. 'subcategory-%s' % self.category_c.css_class, response.content)
  242. self.assertNotIn(
  243. 'subcategory-%s' % self.category_d.css_class, response.content)
  244. def test_list_renders_hidden_thread(self):
  245. """list renders empty due to no permission to see thread"""
  246. Category(
  247. name='Hidden Category',
  248. slug='hidden-category',
  249. ).insert_at(self.root, position='last-child', save=True)
  250. test_category = Category.objects.get(slug='hidden-category')
  251. test_thread = testutils.post_thread(
  252. category=test_category,
  253. )
  254. response = self.client.get('/')
  255. self.assertEqual(response.status_code, 200)
  256. self.assertIn("empty-message", response.content)
  257. def test_list_user_see_own_moderated_thread(self):
  258. """list renders moderated thread that belongs to viewer"""
  259. test_thread = testutils.post_thread(
  260. category=self.category_a,
  261. poster=self.user,
  262. is_moderated=True,
  263. )
  264. response = self.client.get('/')
  265. self.assertEqual(response.status_code, 200)
  266. self.assertIn(test_thread.get_absolute_url(), response.content)
  267. def test_list_user_cant_see_moderated_thread(self):
  268. """list hides moderated thread that belongs to other user"""
  269. test_thread = testutils.post_thread(
  270. category=self.category_a,
  271. is_moderated=True,
  272. )
  273. response = self.client.get('/')
  274. self.assertEqual(response.status_code, 200)
  275. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  276. def test_list_user_cant_see_hidden_thread(self):
  277. """list hides hidden thread that belongs to other user"""
  278. test_thread = testutils.post_thread(
  279. category=self.category_a,
  280. is_hidden=True,
  281. )
  282. response = self.client.get('/')
  283. self.assertEqual(response.status_code, 200)
  284. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  285. def test_list_user_cant_see_own_hidden_thread(self):
  286. """list hides hidden thread that belongs to viewer"""
  287. test_thread = testutils.post_thread(
  288. category=self.category_a,
  289. poster=self.user,
  290. is_hidden=True,
  291. )
  292. response = self.client.get('/')
  293. self.assertEqual(response.status_code, 200)
  294. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  295. def test_list_user_can_see_own_hidden_thread(self):
  296. """list shows hidden thread that belongs to viewer due to permission"""
  297. test_thread = testutils.post_thread(
  298. category=self.category_a,
  299. poster=self.user,
  300. is_hidden=True,
  301. )
  302. self.access_all_categories({
  303. 'can_hide_threads': 1
  304. })
  305. response = self.client.get('/')
  306. self.assertEqual(response.status_code, 200)
  307. self.assertIn(test_thread.get_absolute_url(), response.content)
  308. def test_list_user_can_see_hidden_thread(self):
  309. """
  310. list shows hidden thread that belongs to other user due to permission
  311. """
  312. test_thread = testutils.post_thread(
  313. category=self.category_a,
  314. is_hidden=True,
  315. )
  316. self.access_all_categories({
  317. 'can_hide_threads': 1
  318. })
  319. response = self.client.get('/')
  320. self.assertEqual(response.status_code, 200)
  321. self.assertIn(test_thread.get_absolute_url(), response.content)
  322. def test_list_user_can_see_moderated_thread(self):
  323. """
  324. list shows hidden thread that belongs to other user due to permission
  325. """
  326. test_thread = testutils.post_thread(
  327. category=self.category_a,
  328. is_moderated=True,
  329. )
  330. self.access_all_categories({
  331. 'can_review_moderated_content': 1
  332. })
  333. response = self.client.get('/')
  334. self.assertEqual(response.status_code, 200)
  335. self.assertIn(test_thread.get_absolute_url(), response.content)
  336. class MyThreadsListTests(ThreadsListTestCase):
  337. def test_list_renders_empty(self):
  338. """list renders empty"""
  339. self.access_all_categories()
  340. response = self.client.get('/my/')
  341. self.assertEqual(response.status_code, 200)
  342. self.assertIn("empty-message", response.content)
  343. self.access_all_categories()
  344. response = self.client.get(self.category_a.get_absolute_url() + 'my/')
  345. self.assertEqual(response.status_code, 200)
  346. self.assertIn("empty-message", response.content)
  347. def test_list_renders_test_thread(self):
  348. """list renders only threads posted by user"""
  349. test_thread = testutils.post_thread(
  350. category=self.category_a,
  351. poster=self.user,
  352. )
  353. other_thread = testutils.post_thread(
  354. category=self.category_a,
  355. )
  356. self.access_all_categories()
  357. response = self.client.get('/my/')
  358. self.assertEqual(response.status_code, 200)
  359. self.assertIn(test_thread.get_absolute_url(), response.content)
  360. self.assertNotIn(other_thread.get_absolute_url(), response.content)
  361. self.access_all_categories()
  362. response = self.client.get(self.category_a.get_absolute_url() + 'my/')
  363. self.assertEqual(response.status_code, 200)
  364. self.assertIn(test_thread.get_absolute_url(), response.content)
  365. self.assertNotIn(other_thread.get_absolute_url(), response.content)
  366. class NewThreadsListTests(ThreadsListTestCase):
  367. def test_list_renders_empty(self):
  368. """list renders empty"""
  369. self.access_all_categories()
  370. response = self.client.get('/new/')
  371. self.assertEqual(response.status_code, 200)
  372. self.assertIn("empty-message", response.content)
  373. self.access_all_categories()
  374. response = self.client.get(self.category_a.get_absolute_url() + 'new/')
  375. self.assertEqual(response.status_code, 200)
  376. self.assertIn("empty-message", response.content)
  377. def test_list_renders_new_thread(self):
  378. """list renders new thread"""
  379. test_thread = testutils.post_thread(
  380. category=self.category_a,
  381. )
  382. self.access_all_categories()
  383. response = self.client.get('/new/')
  384. self.assertEqual(response.status_code, 200)
  385. self.assertIn(test_thread.get_absolute_url(), response.content)
  386. self.access_all_categories()
  387. response = self.client.get(self.category_a.get_absolute_url() + 'new/')
  388. self.assertEqual(response.status_code, 200)
  389. self.assertIn(test_thread.get_absolute_url(), response.content)
  390. def test_list_renders_thread_bumped_after_user_cutoff(self):
  391. """list renders new thread bumped after user cutoff"""
  392. self.user.reads_cutoff = timezone.now() - timedelta(days=10)
  393. self.user.joined_on = self.user.reads_cutoff
  394. self.user.save()
  395. test_thread = testutils.post_thread(
  396. category=self.category_a,
  397. started_on=self.user.reads_cutoff - timedelta(days=2)
  398. )
  399. testutils.reply_thread(test_thread,
  400. posted_on=self.user.reads_cutoff + timedelta(days=4)
  401. )
  402. self.access_all_categories()
  403. response = self.client.get('/new/')
  404. self.assertEqual(response.status_code, 200)
  405. self.assertIn(test_thread.get_absolute_url(), response.content)
  406. self.access_all_categories()
  407. response = self.client.get(
  408. self.category_a.get_absolute_url() + 'new/')
  409. self.assertEqual(response.status_code, 200)
  410. self.assertIn(test_thread.get_absolute_url(), response.content)
  411. def test_list_hides_global_cutoff_thread(self):
  412. """list hides thread started before global cutoff"""
  413. self.user.reads_cutoff = timezone.now() - timedelta(days=10)
  414. self.user.joined_on = self.user.reads_cutoff
  415. self.user.save()
  416. test_thread = testutils.post_thread(
  417. category=self.category_a,
  418. started_on=timezone.now() - timedelta(
  419. days=settings.MISAGO_FRESH_CONTENT_PERIOD + 1
  420. )
  421. )
  422. self.access_all_categories()
  423. response = self.client.get('/new/')
  424. self.assertEqual(response.status_code, 200)
  425. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  426. self.access_all_categories()
  427. response = self.client.get(self.category_a.get_absolute_url() + 'new/')
  428. self.assertEqual(response.status_code, 200)
  429. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  430. def test_list_hides_user_cutoff_thread(self):
  431. """list hides thread started before users cutoff"""
  432. self.user.reads_cutoff = timezone.now() - timedelta(days=5)
  433. self.user.joined_on = self.user.reads_cutoff
  434. self.user.save()
  435. test_thread = testutils.post_thread(
  436. category=self.category_a,
  437. started_on=self.user.reads_cutoff - timedelta(minutes=1)
  438. )
  439. self.access_all_categories()
  440. response = self.client.get('/new/')
  441. self.assertEqual(response.status_code, 200)
  442. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  443. self.access_all_categories()
  444. response = self.client.get(self.category_a.get_absolute_url() + 'new/')
  445. self.assertEqual(response.status_code, 200)
  446. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  447. def test_list_hides_user_read_thread(self):
  448. """list hides thread already read by user"""
  449. self.user.reads_cutoff = timezone.now() - timedelta(days=5)
  450. self.user.joined_on = self.user.reads_cutoff
  451. self.user.save()
  452. test_thread = testutils.post_thread(
  453. category=self.category_a
  454. )
  455. threadstracker.make_thread_read_aware(self.user, test_thread)
  456. threadstracker.read_thread(
  457. self.user, test_thread, test_thread.last_post)
  458. self.access_all_categories()
  459. response = self.client.get('/new/')
  460. self.assertEqual(response.status_code, 200)
  461. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  462. self.access_all_categories()
  463. response = self.client.get(self.category_a.get_absolute_url() + 'new/')
  464. self.assertEqual(response.status_code, 200)
  465. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  466. def test_list_hides_category_read_thread(self):
  467. """list hides thread already read by user"""
  468. self.user.reads_cutoff = timezone.now() - timedelta(days=5)
  469. self.user.joined_on = self.user.reads_cutoff
  470. self.user.save()
  471. test_thread = testutils.post_thread(
  472. category=self.category_a
  473. )
  474. self.user.categoryread_set.create(
  475. category=self.category_a,
  476. last_read_on=timezone.now(),
  477. )
  478. self.access_all_categories()
  479. response = self.client.get('/new/')
  480. self.assertEqual(response.status_code, 200)
  481. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  482. self.access_all_categories()
  483. response = self.client.get(self.category_a.get_absolute_url() + 'new/')
  484. self.assertEqual(response.status_code, 200)
  485. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  486. class UnreadThreadsListTests(ThreadsListTestCase):
  487. def test_list_renders_empty(self):
  488. """list renders empty"""
  489. self.access_all_categories()
  490. response = self.client.get('/unread/')
  491. self.assertEqual(response.status_code, 200)
  492. self.assertIn("empty-message", response.content)
  493. self.access_all_categories()
  494. response = self.client.get(
  495. self.category_a.get_absolute_url() + 'unread/')
  496. self.assertEqual(response.status_code, 200)
  497. self.assertIn("empty-message", response.content)
  498. def test_list_renders_unread_thread(self):
  499. """list renders thread with unread posts"""
  500. self.user.reads_cutoff = timezone.now() - timedelta(days=5)
  501. self.user.joined_on = self.user.reads_cutoff
  502. self.user.save()
  503. test_thread = testutils.post_thread(
  504. category=self.category_a
  505. )
  506. threadstracker.make_thread_read_aware(self.user, test_thread)
  507. threadstracker.read_thread(
  508. self.user, test_thread, test_thread.last_post)
  509. testutils.reply_thread(test_thread)
  510. self.access_all_categories()
  511. response = self.client.get('/unread/')
  512. self.assertEqual(response.status_code, 200)
  513. self.assertIn(test_thread.get_absolute_url(), response.content)
  514. self.access_all_categories()
  515. response = self.client.get(
  516. self.category_a.get_absolute_url() + 'unread/')
  517. self.assertEqual(response.status_code, 200)
  518. self.assertIn(test_thread.get_absolute_url(), response.content)
  519. def test_list_hides_never_read_thread(self):
  520. """list hides never read thread"""
  521. self.user.reads_cutoff = timezone.now() - timedelta(days=5)
  522. self.user.joined_on = self.user.reads_cutoff
  523. self.user.save()
  524. test_thread = testutils.post_thread(
  525. category=self.category_a
  526. )
  527. self.access_all_categories()
  528. response = self.client.get('/unread/')
  529. self.assertEqual(response.status_code, 200)
  530. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  531. self.access_all_categories()
  532. response = self.client.get(
  533. self.category_a.get_absolute_url() + 'unread/')
  534. self.assertEqual(response.status_code, 200)
  535. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  536. def test_list_hides_read_thread(self):
  537. """list hides read thread"""
  538. self.user.reads_cutoff = timezone.now() - timedelta(days=5)
  539. self.user.joined_on = self.user.reads_cutoff
  540. self.user.save()
  541. test_thread = testutils.post_thread(
  542. category=self.category_a
  543. )
  544. threadstracker.make_thread_read_aware(self.user, test_thread)
  545. threadstracker.read_thread(
  546. self.user, test_thread, test_thread.last_post)
  547. self.access_all_categories()
  548. response = self.client.get('/unread/')
  549. self.assertEqual(response.status_code, 200)
  550. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  551. self.access_all_categories()
  552. response = self.client.get(
  553. self.category_a.get_absolute_url() + 'unread/')
  554. self.assertEqual(response.status_code, 200)
  555. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  556. def test_list_hides_global_cutoff_thread(self):
  557. """list hides thread replied before global cutoff"""
  558. self.user.reads_cutoff = timezone.now() - timedelta(days=10)
  559. self.user.joined_on = self.user.reads_cutoff
  560. self.user.save()
  561. test_thread = testutils.post_thread(
  562. category=self.category_a,
  563. started_on=timezone.now() - timedelta(
  564. days=settings.MISAGO_FRESH_CONTENT_PERIOD + 5
  565. )
  566. )
  567. threadstracker.make_thread_read_aware(self.user, test_thread)
  568. threadstracker.read_thread(
  569. self.user, test_thread, test_thread.last_post)
  570. testutils.reply_thread(test_thread,
  571. posted_on=test_thread.started_on + timedelta(days=1)
  572. )
  573. self.access_all_categories()
  574. response = self.client.get('/unread/')
  575. self.assertEqual(response.status_code, 200)
  576. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  577. self.access_all_categories()
  578. response = self.client.get(
  579. self.category_a.get_absolute_url() + 'unread/')
  580. self.assertEqual(response.status_code, 200)
  581. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  582. def test_list_hides_user_cutoff_thread(self):
  583. """list hides thread replied before user cutoff"""
  584. self.user.reads_cutoff = timezone.now() - timedelta(days=10)
  585. self.user.joined_on = self.user.reads_cutoff
  586. self.user.save()
  587. test_thread = testutils.post_thread(
  588. category=self.category_a,
  589. started_on=self.user.reads_cutoff - timedelta(days=2)
  590. )
  591. threadstracker.make_thread_read_aware(self.user, test_thread)
  592. threadstracker.read_thread(
  593. self.user, test_thread, test_thread.last_post)
  594. testutils.reply_thread(test_thread,
  595. posted_on=test_thread.started_on + timedelta(days=1)
  596. )
  597. self.access_all_categories()
  598. response = self.client.get('/unread/')
  599. self.assertEqual(response.status_code, 200)
  600. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  601. self.access_all_categories()
  602. response = self.client.get(
  603. self.category_a.get_absolute_url() + 'unread/')
  604. self.assertEqual(response.status_code, 200)
  605. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  606. def test_list_hides_category_cutoff_thread(self):
  607. """list hides thread replied before category cutoff"""
  608. self.user.reads_cutoff = timezone.now() - timedelta(days=10)
  609. self.user.joined_on = self.user.reads_cutoff
  610. self.user.save()
  611. test_thread = testutils.post_thread(
  612. category=self.category_a,
  613. started_on=self.user.reads_cutoff - timedelta(days=2)
  614. )
  615. threadstracker.make_thread_read_aware(self.user, test_thread)
  616. threadstracker.read_thread(
  617. self.user, test_thread, test_thread.last_post)
  618. testutils.reply_thread(test_thread)
  619. self.user.categoryread_set.create(
  620. category=self.category_a,
  621. last_read_on=timezone.now(),
  622. )
  623. self.access_all_categories()
  624. response = self.client.get('/unread/')
  625. self.assertEqual(response.status_code, 200)
  626. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  627. self.access_all_categories()
  628. response = self.client.get(
  629. self.category_a.get_absolute_url() + 'unread/')
  630. self.assertEqual(response.status_code, 200)
  631. self.assertNotIn(test_thread.get_absolute_url(), response.content)