test_threadslists_views.py 26 KB

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