test_threadslists.py 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467
  1. from datetime import timedelta
  2. from json import loads as json_loads
  3. from django.conf import settings
  4. from django.utils import timezone
  5. from misago.acl.testutils import override_acl
  6. from misago.categories.models import Category
  7. from misago.core import threadstore
  8. from misago.core.cache import cache
  9. from misago.readtracker import categoriestracker, threadstracker
  10. from misago.users.testutils import AuthenticatedUserTestCase
  11. from misago.threads import testutils
  12. LISTS_URLS = (
  13. '',
  14. 'my/',
  15. 'new/',
  16. 'unread/',
  17. 'subscribed/'
  18. )
  19. class ThreadsListTestCase(AuthenticatedUserTestCase):
  20. def setUp(self):
  21. super(ThreadsListTestCase, self).setUp()
  22. self.api_link = '/api/threads/'
  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.clear_state()
  73. Category.objects.partial_rebuild(self.root.tree_id)
  74. self.root = Category.objects.root_category()
  75. self.category_a = Category.objects.get(slug='category-a')
  76. self.category_b = Category.objects.get(slug='category-b')
  77. self.category_c = Category.objects.get(slug='category-c')
  78. self.category_d = Category.objects.get(slug='category-d')
  79. self.category_e = Category.objects.get(slug='category-e')
  80. self.category_f = Category.objects.get(slug='category-f')
  81. self.access_all_categories()
  82. def access_all_categories(self, extra=None):
  83. self.clear_state()
  84. categories_acl = {'categories': {}, 'visible_categories': []}
  85. for category in Category.objects.all_categories():
  86. categories_acl['visible_categories'].append(category.pk)
  87. categories_acl['categories'][category.pk] = {
  88. 'can_see': 1,
  89. 'can_browse': 1,
  90. 'can_see_all_threads': 1,
  91. 'can_see_own_threads': 0,
  92. 'can_hide_threads': 0,
  93. 'can_review_moderated_content': 0,
  94. }
  95. if extra:
  96. categories_acl['categories'][category.pk].update(extra)
  97. override_acl(self.user, categories_acl)
  98. return categories_acl
  99. class AllThreadsListTests(ThreadsListTestCase):
  100. def test_list_renders_empty(self):
  101. """empty threads list renders"""
  102. for url in LISTS_URLS:
  103. self.access_all_categories()
  104. response = self.client.get('/' + url)
  105. self.assertEqual(response.status_code, 200)
  106. self.assertIn("empty-message", response.content)
  107. self.access_all_categories()
  108. response = self.client.get(self.category_b.get_absolute_url() + url)
  109. self.assertEqual(response.status_code, 200)
  110. self.assertIn(self.category_b.name, response.content)
  111. self.assertIn("empty-message", response.content)
  112. self.access_all_categories()
  113. response = self.client.get(
  114. '%s?list=%s' % (self.api_link, url.strip('/')))
  115. self.assertEqual(response.status_code, 200)
  116. response_json = json_loads(response.content)
  117. self.assertEqual(len(response_json['results']), 0)
  118. def test_list_authenticated_only_views(self):
  119. """authenticated only views return 403 for guests"""
  120. for url in LISTS_URLS:
  121. self.access_all_categories()
  122. response = self.client.get('/' + url)
  123. self.assertEqual(response.status_code, 200)
  124. self.access_all_categories()
  125. response = self.client.get(self.category_b.get_absolute_url() + url)
  126. self.assertEqual(response.status_code, 200)
  127. self.assertIn(self.category_b.name, response.content)
  128. self.access_all_categories()
  129. self.access_all_categories()
  130. response = self.client.get('%s?category=%s&list=%s' % (
  131. self.api_link,
  132. self.category_b.pk,
  133. url.strip('/'),
  134. ))
  135. self.assertEqual(response.status_code, 200)
  136. self.logout_user()
  137. self.user = self.get_anonymous_user()
  138. for url in LISTS_URLS[1:]:
  139. self.access_all_categories()
  140. response = self.client.get('/' + url)
  141. self.assertEqual(response.status_code, 403)
  142. self.access_all_categories()
  143. response = self.client.get(self.category_b.get_absolute_url() + url)
  144. self.assertEqual(response.status_code, 403)
  145. self.access_all_categories()
  146. response = self.client.get('%s?category=%s&list=%s' % (
  147. self.api_link,
  148. self.category_b.pk,
  149. url.strip('/'),
  150. ))
  151. self.assertEqual(response.status_code, 403)
  152. def test_empty_list_hides_categories_picker(self):
  153. """categories picker is hidden on empty list"""
  154. Category(
  155. name='Hidden Category',
  156. slug='hidden-category',
  157. ).insert_at(self.root, position='last-child', save=True)
  158. test_category = Category.objects.get(slug='hidden-category')
  159. self.access_all_categories()
  160. response = self.client.get('/')
  161. self.assertEqual(response.status_code, 200)
  162. self.assertNotIn(
  163. 'subcategory-%s' % self.category_a.css_class, response.content)
  164. self.assertNotIn(
  165. 'subcategory-%s' % self.category_e.css_class, response.content)
  166. self.access_all_categories()
  167. response = self.client.get(self.category_a.get_absolute_url())
  168. self.assertEqual(response.status_code, 200)
  169. self.assertNotIn(
  170. 'subcategory-%s' % self.category_b.css_class, response.content)
  171. self.access_all_categories()
  172. response = self.client.get(self.api_link)
  173. self.assertEqual(response.status_code, 200)
  174. response_json = json_loads(response.content)
  175. self.assertEqual(len(response_json['subcategories']), 0)
  176. def test_list_renders_categories_picker(self):
  177. """categories picker renders valid categories"""
  178. Category(
  179. name='Hidden Category',
  180. slug='hidden-category',
  181. ).insert_at(self.root, position='last-child', save=True)
  182. test_category = Category.objects.get(slug='hidden-category')
  183. testutils.post_thread(
  184. category=self.category_b,
  185. )
  186. response = self.client.get('/')
  187. self.assertEqual(response.status_code, 200)
  188. self.assertIn(
  189. 'subcategory-%s' % self.category_a.css_class, response.content)
  190. # readable categories, but non-accessible directly
  191. self.assertNotIn(
  192. 'subcategory-%s' % self.category_b.css_class, response.content)
  193. self.assertNotIn(
  194. 'subcategory-%s' % self.category_c.css_class, response.content)
  195. self.assertNotIn(
  196. 'subcategory-%s' % self.category_d.css_class, response.content)
  197. self.assertNotIn(
  198. 'subcategory-%s' % self.category_f.css_class, response.content)
  199. # hidden category
  200. self.assertNotIn(
  201. 'subcategory-%s' % test_category.css_class, response.content)
  202. self.access_all_categories()
  203. response = self.client.get(self.api_link)
  204. self.assertEqual(response.status_code, 200)
  205. response_json = json_loads(response.content)
  206. self.assertEqual(
  207. response_json['subcategories'][0], self.category_a.pk)
  208. # test category view
  209. self.access_all_categories()
  210. response = self.client.get(self.category_a.get_absolute_url())
  211. self.assertEqual(response.status_code, 200)
  212. self.assertIn(
  213. 'subcategory-%s' % self.category_b.css_class, response.content)
  214. # readable categories, but non-accessible directly
  215. self.assertNotIn(
  216. 'subcategory-%s' % self.category_c.css_class, response.content)
  217. self.assertNotIn(
  218. 'subcategory-%s' % self.category_d.css_class, response.content)
  219. self.assertNotIn(
  220. 'subcategory-%s' % self.category_f.css_class, response.content)
  221. self.access_all_categories()
  222. response = self.client.get(
  223. '%s?category=%s' % (self.api_link, self.category_a.pk))
  224. self.assertEqual(response.status_code, 200)
  225. response_json = json_loads(response.content)
  226. self.assertEqual(
  227. response_json['subcategories'][0], self.category_b.pk)
  228. def test_display_pinned_threads(self):
  229. """
  230. threads list displays globally pinned threads first
  231. and locally ones inbetween other
  232. """
  233. globally = testutils.post_thread(
  234. category=self.first_category,
  235. is_global=True,
  236. )
  237. locally = testutils.post_thread(
  238. category=self.first_category,
  239. is_pinned=True,
  240. )
  241. standard = testutils.post_thread(category=self.first_category)
  242. response = self.client.get('/')
  243. self.assertEqual(response.status_code, 200)
  244. positions = {
  245. 'g': response.content.find(globally.get_absolute_url()),
  246. 'l': response.content.find(locally.get_absolute_url()),
  247. 's': response.content.find(standard.get_absolute_url()),
  248. }
  249. # global announcement before others
  250. self.assertTrue(positions['g'] < positions['l'])
  251. self.assertTrue(positions['g'] < positions['s'])
  252. # standard in the middle
  253. self.assertTrue(positions['s'] < positions['l'])
  254. self.assertTrue(positions['s'] > positions['g'])
  255. # pinned last
  256. self.assertTrue(positions['l'] > positions['g'])
  257. self.assertTrue(positions['l'] > positions['s'])
  258. # API behaviour is identic
  259. response = self.client.get('/api/threads/')
  260. self.assertEqual(response.status_code, 200)
  261. positions = {
  262. 'g': response.content.find(globally.get_absolute_url()),
  263. 'l': response.content.find(locally.get_absolute_url()),
  264. 's': response.content.find(standard.get_absolute_url()),
  265. }
  266. # global announcement before others
  267. self.assertTrue(positions['g'] < positions['l'])
  268. self.assertTrue(positions['g'] < positions['s'])
  269. # standard in the middle
  270. self.assertTrue(positions['s'] < positions['l'])
  271. self.assertTrue(positions['s'] > positions['g'])
  272. # pinned last
  273. self.assertTrue(positions['l'] > positions['g'])
  274. self.assertTrue(positions['l'] > positions['s'])
  275. class CategoryThreadsListTests(ThreadsListTestCase):
  276. def test_access_hidden_category(self):
  277. """hidden category returns 404"""
  278. Category(
  279. name='Hidden Category',
  280. slug='hidden-category',
  281. ).insert_at(self.root, position='last-child', save=True)
  282. test_category = Category.objects.get(slug='hidden-category')
  283. for url in LISTS_URLS:
  284. response = self.client.get(test_category.get_absolute_url() + url)
  285. self.assertEqual(response.status_code, 404)
  286. response = self.client.get(
  287. '%s?category=%s' % (self.api_link, test_category.pk))
  288. self.assertEqual(response.status_code, 404)
  289. def test_access_protected_category(self):
  290. """protected category returns 403"""
  291. Category(
  292. name='Hidden Category',
  293. slug='hidden-category',
  294. ).insert_at(self.root, position='last-child', save=True)
  295. test_category = Category.objects.get(slug='hidden-category')
  296. for url in LISTS_URLS:
  297. override_acl(self.user, {
  298. 'visible_categories': [test_category.pk],
  299. 'categories': {
  300. test_category.pk: {
  301. 'can_see': 1,
  302. 'can_browse': 0,
  303. }
  304. }
  305. });
  306. response = self.client.get(test_category.get_absolute_url() + url)
  307. self.assertEqual(response.status_code, 403)
  308. override_acl(self.user, {
  309. 'visible_categories': [test_category.pk],
  310. 'categories': {
  311. test_category.pk: {
  312. 'can_see': 1,
  313. 'can_browse': 0,
  314. }
  315. }
  316. });
  317. response = self.client.get('%s?category=%s&list=%s' % (
  318. self.api_link,
  319. test_category.pk,
  320. url.strip('/'),
  321. ))
  322. self.assertEqual(response.status_code, 403)
  323. def test_display_pinned_threads(self):
  324. """
  325. category threads list displays globally pinned threads first
  326. then locally ones and unpinned last
  327. """
  328. globally = testutils.post_thread(
  329. category=self.first_category,
  330. is_global=True,
  331. )
  332. locally = testutils.post_thread(
  333. category=self.first_category,
  334. is_pinned=True,
  335. )
  336. standard = testutils.post_thread(category=self.first_category)
  337. response = self.client.get(self.first_category.get_absolute_url())
  338. self.assertEqual(response.status_code, 200)
  339. positions = {
  340. 'g': response.content.find(globally.get_absolute_url()),
  341. 'l': response.content.find(locally.get_absolute_url()),
  342. 's': response.content.find(standard.get_absolute_url()),
  343. }
  344. # global announcement before others
  345. self.assertTrue(positions['g'] < positions['l'])
  346. self.assertTrue(positions['g'] < positions['s'])
  347. # pinned in the middle
  348. self.assertTrue(positions['l'] < positions['s'])
  349. self.assertTrue(positions['l'] > positions['g'])
  350. # standard last
  351. self.assertTrue(positions['s'] > positions['g'])
  352. self.assertTrue(positions['s'] > positions['g'])
  353. # API behaviour is identic
  354. response = self.client.get(
  355. '/api/threads/?category=%s' % self.first_category.pk)
  356. self.assertEqual(response.status_code, 200)
  357. positions = {
  358. 'g': response.content.find(globally.get_absolute_url()),
  359. 'l': response.content.find(locally.get_absolute_url()),
  360. 's': response.content.find(standard.get_absolute_url()),
  361. }
  362. # global announcement before others
  363. self.assertTrue(positions['g'] < positions['l'])
  364. self.assertTrue(positions['g'] < positions['s'])
  365. # pinned in the middle
  366. self.assertTrue(positions['l'] < positions['s'])
  367. self.assertTrue(positions['l'] > positions['g'])
  368. # standard last
  369. self.assertTrue(positions['s'] > positions['g'])
  370. self.assertTrue(positions['s'] > positions['g'])
  371. class ThreadsVisibilityTests(ThreadsListTestCase):
  372. def test_list_renders_test_thread(self):
  373. """list renders test thread with valid top category"""
  374. test_thread = testutils.post_thread(
  375. category=self.category_c,
  376. )
  377. response = self.client.get('/')
  378. self.assertEqual(response.status_code, 200)
  379. self.assertIn(test_thread.get_absolute_url(), response.content)
  380. self.assertIn(
  381. 'subcategory-%s' % self.category_a.css_class, response.content)
  382. self.assertIn(
  383. 'thread-category-%s' % self.category_a.css_class, response.content)
  384. self.assertIn(
  385. 'thread-category-%s' % self.category_c.css_class, response.content)
  386. # other top category is hidden from user
  387. self.assertNotIn(
  388. 'subcategory-%s' % self.category_e.css_class, response.content)
  389. # api displays same data
  390. self.access_all_categories()
  391. response = self.client.get(self.api_link)
  392. self.assertEqual(response.status_code, 200)
  393. response_json = json_loads(response.content)
  394. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  395. self.assertEqual(len(response_json['subcategories']), 1)
  396. self.assertEqual(
  397. response_json['subcategories'][0], self.category_a.pk)
  398. # test category view
  399. self.access_all_categories()
  400. response = self.client.get(self.category_b.get_absolute_url())
  401. self.assertEqual(response.status_code, 200)
  402. # thread displays
  403. self.assertIn(test_thread.get_absolute_url(), response.content)
  404. self.assertNotIn(
  405. 'thread-category-%s' % self.category_b.css_class, response.content)
  406. self.assertIn(
  407. 'thread-category-%s' % self.category_c.css_class, response.content)
  408. # category picker was changed
  409. self.assertIn(
  410. 'subcategory-%s' % self.category_c.css_class, response.content)
  411. self.assertNotIn(
  412. 'subcategory-%s' % self.category_d.css_class, response.content)
  413. # api displays same data
  414. self.access_all_categories()
  415. response = self.client.get(
  416. '%s?category=%s' % (self.api_link, self.category_b.pk))
  417. self.assertEqual(response.status_code, 200)
  418. response_json = json_loads(response.content)
  419. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  420. self.assertEqual(len(response_json['subcategories']), 1)
  421. self.assertEqual(
  422. response_json['subcategories'][0], self.category_c.pk)
  423. def test_list_hides_hidden_thread(self):
  424. """list renders empty due to no permission to see thread"""
  425. Category(
  426. name='Hidden Category',
  427. slug='hidden-category',
  428. ).insert_at(self.root, position='last-child', save=True)
  429. test_category = Category.objects.get(slug='hidden-category')
  430. test_thread = testutils.post_thread(
  431. category=test_category,
  432. )
  433. response = self.client.get('/')
  434. self.assertEqual(response.status_code, 200)
  435. self.assertIn("empty-message", response.content)
  436. def test_api_hides_hidden_thread(self):
  437. """api returns empty due to no permission to see thread"""
  438. Category(
  439. name='Hidden Category',
  440. slug='hidden-category',
  441. ).insert_at(self.root, position='last-child', save=True)
  442. test_category = Category.objects.get(slug='hidden-category')
  443. test_thread = testutils.post_thread(
  444. category=test_category,
  445. )
  446. response = self.client.get(self.api_link)
  447. self.assertEqual(response.status_code, 200)
  448. response_json = json_loads(response.content)
  449. self.assertEqual(len(response_json['results']), 0)
  450. def test_list_user_see_own_moderated_thread(self):
  451. """list renders moderated thread that belongs to viewer"""
  452. test_thread = testutils.post_thread(
  453. category=self.category_a,
  454. poster=self.user,
  455. is_moderated=True,
  456. )
  457. response = self.client.get('/')
  458. self.assertEqual(response.status_code, 200)
  459. self.assertIn(test_thread.get_absolute_url(), response.content)
  460. # test api
  461. self.access_all_categories()
  462. response = self.client.get(self.api_link)
  463. self.assertEqual(response.status_code, 200)
  464. response_json = json_loads(response.content)
  465. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  466. def test_list_user_cant_see_moderated_thread(self):
  467. """list hides moderated thread that belongs to other user"""
  468. test_thread = testutils.post_thread(
  469. category=self.category_a,
  470. is_moderated=True,
  471. )
  472. response = self.client.get('/')
  473. self.assertEqual(response.status_code, 200)
  474. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  475. # test api
  476. self.access_all_categories()
  477. response = self.client.get(self.api_link)
  478. self.assertEqual(response.status_code, 200)
  479. response_json = json_loads(response.content)
  480. self.assertEqual(len(response_json['results']), 0)
  481. def test_list_user_cant_see_hidden_thread(self):
  482. """list hides hidden thread that belongs to other user"""
  483. test_thread = testutils.post_thread(
  484. category=self.category_a,
  485. is_hidden=True,
  486. )
  487. response = self.client.get('/')
  488. self.assertEqual(response.status_code, 200)
  489. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  490. # test api
  491. self.access_all_categories()
  492. response = self.client.get(self.api_link)
  493. self.assertEqual(response.status_code, 200)
  494. response_json = json_loads(response.content)
  495. self.assertEqual(len(response_json['results']), 0)
  496. def test_list_user_cant_see_own_hidden_thread(self):
  497. """list hides hidden thread that belongs to viewer"""
  498. test_thread = testutils.post_thread(
  499. category=self.category_a,
  500. poster=self.user,
  501. is_hidden=True,
  502. )
  503. response = self.client.get('/')
  504. self.assertEqual(response.status_code, 200)
  505. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  506. # test api
  507. self.access_all_categories()
  508. response = self.client.get(self.api_link)
  509. self.assertEqual(response.status_code, 200)
  510. response_json = json_loads(response.content)
  511. self.assertEqual(len(response_json['results']), 0)
  512. def test_list_user_can_see_own_hidden_thread(self):
  513. """list shows hidden thread that belongs to viewer due to permission"""
  514. test_thread = testutils.post_thread(
  515. category=self.category_a,
  516. poster=self.user,
  517. is_hidden=True,
  518. )
  519. self.access_all_categories({
  520. 'can_hide_threads': 1
  521. })
  522. response = self.client.get('/')
  523. self.assertEqual(response.status_code, 200)
  524. self.assertIn(test_thread.get_absolute_url(), response.content)
  525. # test api
  526. self.access_all_categories({
  527. 'can_hide_threads': 1
  528. })
  529. response = self.client.get(self.api_link)
  530. self.assertEqual(response.status_code, 200)
  531. response_json = json_loads(response.content)
  532. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  533. def test_list_user_can_see_hidden_thread(self):
  534. """
  535. list shows hidden thread that belongs to other user due to permission
  536. """
  537. test_thread = testutils.post_thread(
  538. category=self.category_a,
  539. is_hidden=True,
  540. )
  541. self.access_all_categories({
  542. 'can_hide_threads': 1
  543. })
  544. response = self.client.get('/')
  545. self.assertEqual(response.status_code, 200)
  546. self.assertIn(test_thread.get_absolute_url(), response.content)
  547. # test api
  548. self.access_all_categories({
  549. 'can_hide_threads': 1
  550. })
  551. response = self.client.get(self.api_link)
  552. self.assertEqual(response.status_code, 200)
  553. response_json = json_loads(response.content)
  554. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  555. def test_list_user_can_see_moderated_thread(self):
  556. """
  557. list shows hidden thread that belongs to other user due to permission
  558. """
  559. test_thread = testutils.post_thread(
  560. category=self.category_a,
  561. is_moderated=True,
  562. )
  563. self.access_all_categories({
  564. 'can_review_moderated_content': 1
  565. })
  566. response = self.client.get('/')
  567. self.assertEqual(response.status_code, 200)
  568. self.assertIn(test_thread.get_absolute_url(), response.content)
  569. # test api
  570. self.access_all_categories({
  571. 'can_review_moderated_content': 1
  572. })
  573. response = self.client.get(self.api_link)
  574. self.assertEqual(response.status_code, 200)
  575. response_json = json_loads(response.content)
  576. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  577. class MyThreadsListTests(ThreadsListTestCase):
  578. def test_list_renders_empty(self):
  579. """list renders empty"""
  580. self.access_all_categories()
  581. response = self.client.get('/my/')
  582. self.assertEqual(response.status_code, 200)
  583. self.assertIn("empty-message", response.content)
  584. self.access_all_categories()
  585. response = self.client.get(self.category_a.get_absolute_url() + 'my/')
  586. self.assertEqual(response.status_code, 200)
  587. self.assertIn("empty-message", response.content)
  588. # test api
  589. self.access_all_categories()
  590. response = self.client.get('%s?list=my' % self.api_link)
  591. self.assertEqual(response.status_code, 200)
  592. response_json = json_loads(response.content)
  593. self.assertEqual(len(response_json['results']), 0)
  594. self.access_all_categories()
  595. response = self.client.get(
  596. '%s?list=my&category=%s' % (self.api_link, self.category_a.pk))
  597. response_json = json_loads(response.content)
  598. self.assertEqual(len(response_json['results']), 0)
  599. def test_list_renders_test_thread(self):
  600. """list renders only threads posted by user"""
  601. test_thread = testutils.post_thread(
  602. category=self.category_a,
  603. poster=self.user,
  604. )
  605. other_thread = testutils.post_thread(
  606. category=self.category_a,
  607. )
  608. self.access_all_categories()
  609. response = self.client.get('/my/')
  610. self.assertEqual(response.status_code, 200)
  611. self.assertIn(test_thread.get_absolute_url(), response.content)
  612. self.assertNotIn(other_thread.get_absolute_url(), response.content)
  613. self.access_all_categories()
  614. response = self.client.get(self.category_a.get_absolute_url() + 'my/')
  615. self.assertEqual(response.status_code, 200)
  616. self.assertIn(test_thread.get_absolute_url(), response.content)
  617. self.assertNotIn(other_thread.get_absolute_url(), response.content)
  618. # test api
  619. self.access_all_categories()
  620. response = self.client.get('%s?list=my' % self.api_link)
  621. self.assertEqual(response.status_code, 200)
  622. response_json = json_loads(response.content)
  623. self.assertEqual(len(response_json['results']), 1)
  624. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  625. self.access_all_categories()
  626. response = self.client.get(
  627. '%s?list=my&category=%s' % (self.api_link, self.category_a.pk))
  628. self.assertEqual(response.status_code, 200)
  629. response_json = json_loads(response.content)
  630. self.assertEqual(len(response_json['results']), 1)
  631. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  632. class NewThreadsListTests(ThreadsListTestCase):
  633. def test_list_renders_empty(self):
  634. """list renders empty"""
  635. self.access_all_categories()
  636. response = self.client.get('/new/')
  637. self.assertEqual(response.status_code, 200)
  638. self.assertIn("empty-message", response.content)
  639. self.access_all_categories()
  640. response = self.client.get(self.category_a.get_absolute_url() + 'new/')
  641. self.assertEqual(response.status_code, 200)
  642. self.assertIn("empty-message", response.content)
  643. # test api
  644. self.access_all_categories()
  645. response = self.client.get('%s?list=new' % self.api_link)
  646. self.assertEqual(response.status_code, 200)
  647. response_json = json_loads(response.content)
  648. self.assertEqual(len(response_json['results']), 0)
  649. self.access_all_categories()
  650. response = self.client.get(
  651. '%s?list=new&category=%s' % (self.api_link, self.category_a.pk))
  652. response_json = json_loads(response.content)
  653. self.assertEqual(len(response_json['results']), 0)
  654. def test_list_renders_new_thread(self):
  655. """list renders new thread"""
  656. test_thread = testutils.post_thread(
  657. category=self.category_a,
  658. )
  659. self.access_all_categories()
  660. response = self.client.get('/new/')
  661. self.assertEqual(response.status_code, 200)
  662. self.assertIn(test_thread.get_absolute_url(), response.content)
  663. self.access_all_categories()
  664. response = self.client.get(self.category_a.get_absolute_url() + 'new/')
  665. self.assertEqual(response.status_code, 200)
  666. self.assertIn(test_thread.get_absolute_url(), response.content)
  667. # test api
  668. self.access_all_categories()
  669. response = self.client.get('%s?list=new' % self.api_link)
  670. self.assertEqual(response.status_code, 200)
  671. response_json = json_loads(response.content)
  672. self.assertEqual(len(response_json['results']), 1)
  673. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  674. self.access_all_categories()
  675. response = self.client.get(
  676. '%s?list=new&category=%s' % (self.api_link, self.category_a.pk))
  677. self.assertEqual(response.status_code, 200)
  678. response_json = json_loads(response.content)
  679. self.assertEqual(len(response_json['results']), 1)
  680. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  681. def test_list_renders_thread_bumped_after_user_cutoff(self):
  682. """list renders new thread bumped after user cutoff"""
  683. self.user.joined_on = timezone.now() - timedelta(days=10)
  684. self.user.save()
  685. test_thread = testutils.post_thread(
  686. category=self.category_a,
  687. started_on=self.user.joined_on - timedelta(days=2)
  688. )
  689. testutils.reply_thread(test_thread,
  690. posted_on=self.user.joined_on + timedelta(days=4)
  691. )
  692. self.access_all_categories()
  693. response = self.client.get('/new/')
  694. self.assertEqual(response.status_code, 200)
  695. self.assertIn(test_thread.get_absolute_url(), response.content)
  696. self.access_all_categories()
  697. response = self.client.get(
  698. self.category_a.get_absolute_url() + 'new/')
  699. self.assertEqual(response.status_code, 200)
  700. self.assertIn(test_thread.get_absolute_url(), response.content)
  701. # test api
  702. self.access_all_categories()
  703. response = self.client.get('%s?list=new' % self.api_link)
  704. self.assertEqual(response.status_code, 200)
  705. response_json = json_loads(response.content)
  706. self.assertEqual(len(response_json['results']), 1)
  707. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  708. self.access_all_categories()
  709. response = self.client.get(
  710. '%s?list=new&category=%s' % (self.api_link, self.category_a.pk))
  711. self.assertEqual(response.status_code, 200)
  712. response_json = json_loads(response.content)
  713. self.assertEqual(len(response_json['results']), 1)
  714. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  715. def test_list_hides_global_cutoff_thread(self):
  716. """list hides thread started before global cutoff"""
  717. self.user.joined_on = timezone.now() - timedelta(days=10)
  718. self.user.save()
  719. test_thread = testutils.post_thread(
  720. category=self.category_a,
  721. started_on=timezone.now() - timedelta(
  722. days=settings.MISAGO_FRESH_CONTENT_PERIOD + 1
  723. )
  724. )
  725. self.access_all_categories()
  726. response = self.client.get('/new/')
  727. self.assertEqual(response.status_code, 200)
  728. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  729. self.access_all_categories()
  730. response = self.client.get(self.category_a.get_absolute_url() + 'new/')
  731. self.assertEqual(response.status_code, 200)
  732. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  733. # test api
  734. self.access_all_categories()
  735. response = self.client.get('%s?list=new' % self.api_link)
  736. self.assertEqual(response.status_code, 200)
  737. response_json = json_loads(response.content)
  738. self.assertEqual(len(response_json['results']), 0)
  739. self.access_all_categories()
  740. response = self.client.get(
  741. '%s?list=new&category=%s' % (self.api_link, self.category_a.pk))
  742. self.assertEqual(response.status_code, 200)
  743. response_json = json_loads(response.content)
  744. self.assertEqual(len(response_json['results']), 0)
  745. def test_list_hides_user_cutoff_thread(self):
  746. """list hides thread started before users cutoff"""
  747. self.user.joined_on = timezone.now() - timedelta(days=5)
  748. self.user.save()
  749. test_thread = testutils.post_thread(
  750. category=self.category_a,
  751. started_on=self.user.joined_on - timedelta(minutes=1)
  752. )
  753. self.access_all_categories()
  754. response = self.client.get('/new/')
  755. self.assertEqual(response.status_code, 200)
  756. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  757. self.access_all_categories()
  758. response = self.client.get(self.category_a.get_absolute_url() + 'new/')
  759. self.assertEqual(response.status_code, 200)
  760. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  761. # test api
  762. self.access_all_categories()
  763. response = self.client.get('%s?list=new' % self.api_link)
  764. self.assertEqual(response.status_code, 200)
  765. response_json = json_loads(response.content)
  766. self.assertEqual(len(response_json['results']), 0)
  767. self.access_all_categories()
  768. response = self.client.get(
  769. '%s?list=new&category=%s' % (self.api_link, self.category_a.pk))
  770. self.assertEqual(response.status_code, 200)
  771. response_json = json_loads(response.content)
  772. self.assertEqual(len(response_json['results']), 0)
  773. def test_list_hides_user_read_thread(self):
  774. """list hides thread already read by user"""
  775. self.user.joined_on = timezone.now() - timedelta(days=5)
  776. self.user.save()
  777. test_thread = testutils.post_thread(
  778. category=self.category_a
  779. )
  780. threadstracker.make_thread_read_aware(self.user, test_thread)
  781. threadstracker.read_thread(
  782. self.user, test_thread, test_thread.last_post)
  783. self.access_all_categories()
  784. response = self.client.get('/new/')
  785. self.assertEqual(response.status_code, 200)
  786. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  787. self.access_all_categories()
  788. response = self.client.get(self.category_a.get_absolute_url() + 'new/')
  789. self.assertEqual(response.status_code, 200)
  790. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  791. # test api
  792. self.access_all_categories()
  793. response = self.client.get('%s?list=new' % self.api_link)
  794. self.assertEqual(response.status_code, 200)
  795. response_json = json_loads(response.content)
  796. self.assertEqual(len(response_json['results']), 0)
  797. self.access_all_categories()
  798. response = self.client.get(
  799. '%s?list=new&category=%s' % (self.api_link, self.category_a.pk))
  800. self.assertEqual(response.status_code, 200)
  801. response_json = json_loads(response.content)
  802. self.assertEqual(len(response_json['results']), 0)
  803. def test_list_hides_category_read_thread(self):
  804. """list hides thread already read by user"""
  805. self.user.joined_on = timezone.now() - timedelta(days=5)
  806. self.user.save()
  807. test_thread = testutils.post_thread(
  808. category=self.category_a
  809. )
  810. self.user.categoryread_set.create(
  811. category=self.category_a,
  812. last_read_on=timezone.now(),
  813. )
  814. self.access_all_categories()
  815. response = self.client.get('/new/')
  816. self.assertEqual(response.status_code, 200)
  817. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  818. self.access_all_categories()
  819. response = self.client.get(self.category_a.get_absolute_url() + 'new/')
  820. self.assertEqual(response.status_code, 200)
  821. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  822. # test api
  823. self.access_all_categories()
  824. response = self.client.get('%s?list=new' % self.api_link)
  825. self.assertEqual(response.status_code, 200)
  826. response_json = json_loads(response.content)
  827. self.assertEqual(len(response_json['results']), 0)
  828. self.access_all_categories()
  829. response = self.client.get(
  830. '%s?list=new&category=%s' % (self.api_link, self.category_a.pk))
  831. self.assertEqual(response.status_code, 200)
  832. response_json = json_loads(response.content)
  833. self.assertEqual(len(response_json['results']), 0)
  834. class UnreadThreadsListTests(ThreadsListTestCase):
  835. def test_list_renders_empty(self):
  836. """list renders empty"""
  837. self.access_all_categories()
  838. response = self.client.get('/unread/')
  839. self.assertEqual(response.status_code, 200)
  840. self.assertIn("empty-message", response.content)
  841. self.access_all_categories()
  842. response = self.client.get(
  843. self.category_a.get_absolute_url() + 'unread/')
  844. self.assertEqual(response.status_code, 200)
  845. self.assertIn("empty-message", response.content)
  846. # test api
  847. self.access_all_categories()
  848. response = self.client.get('%s?list=unread' % self.api_link)
  849. self.assertEqual(response.status_code, 200)
  850. response_json = json_loads(response.content)
  851. self.assertEqual(len(response_json['results']), 0)
  852. self.access_all_categories()
  853. response = self.client.get(
  854. '%s?list=unread&category=%s' % (self.api_link, self.category_a.pk))
  855. self.assertEqual(response.status_code, 200)
  856. response_json = json_loads(response.content)
  857. self.assertEqual(len(response_json['results']), 0)
  858. def test_list_renders_unread_thread(self):
  859. """list renders thread with unread posts"""
  860. self.user.joined_on = timezone.now() - timedelta(days=5)
  861. self.user.save()
  862. test_thread = testutils.post_thread(
  863. category=self.category_a
  864. )
  865. threadstracker.make_thread_read_aware(self.user, test_thread)
  866. threadstracker.read_thread(
  867. self.user, test_thread, test_thread.last_post)
  868. testutils.reply_thread(test_thread)
  869. self.access_all_categories()
  870. response = self.client.get('/unread/')
  871. self.assertEqual(response.status_code, 200)
  872. self.assertIn(test_thread.get_absolute_url(), response.content)
  873. self.access_all_categories()
  874. response = self.client.get(
  875. self.category_a.get_absolute_url() + 'unread/')
  876. self.assertEqual(response.status_code, 200)
  877. self.assertIn(test_thread.get_absolute_url(), response.content)
  878. # test api
  879. self.access_all_categories()
  880. response = self.client.get('%s?list=unread' % self.api_link)
  881. self.assertEqual(response.status_code, 200)
  882. response_json = json_loads(response.content)
  883. self.assertEqual(len(response_json['results']), 1)
  884. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  885. self.access_all_categories()
  886. response = self.client.get(
  887. '%s?list=unread&category=%s' % (self.api_link, self.category_a.pk))
  888. self.assertEqual(response.status_code, 200)
  889. response_json = json_loads(response.content)
  890. self.assertEqual(len(response_json['results']), 1)
  891. self.assertEqual(response_json['results'][0]['id'], test_thread.pk)
  892. def test_list_hides_never_read_thread(self):
  893. """list hides never read thread"""
  894. self.user.joined_on = timezone.now() - timedelta(days=5)
  895. self.user.save()
  896. test_thread = testutils.post_thread(
  897. category=self.category_a
  898. )
  899. self.access_all_categories()
  900. response = self.client.get('/unread/')
  901. self.assertEqual(response.status_code, 200)
  902. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  903. self.access_all_categories()
  904. response = self.client.get(
  905. self.category_a.get_absolute_url() + 'unread/')
  906. self.assertEqual(response.status_code, 200)
  907. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  908. # test api
  909. self.access_all_categories()
  910. response = self.client.get('%s?list=unread' % self.api_link)
  911. self.assertEqual(response.status_code, 200)
  912. response_json = json_loads(response.content)
  913. self.assertEqual(len(response_json['results']), 0)
  914. self.access_all_categories()
  915. response = self.client.get(
  916. '%s?list=unread&category=%s' % (self.api_link, self.category_a.pk))
  917. self.assertEqual(response.status_code, 200)
  918. response_json = json_loads(response.content)
  919. self.assertEqual(len(response_json['results']), 0)
  920. def test_list_hides_read_thread(self):
  921. """list hides read thread"""
  922. self.user.joined_on = timezone.now() - timedelta(days=5)
  923. self.user.save()
  924. test_thread = testutils.post_thread(
  925. category=self.category_a
  926. )
  927. threadstracker.make_thread_read_aware(self.user, test_thread)
  928. threadstracker.read_thread(
  929. self.user, test_thread, test_thread.last_post)
  930. self.access_all_categories()
  931. response = self.client.get('/unread/')
  932. self.assertEqual(response.status_code, 200)
  933. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  934. self.access_all_categories()
  935. response = self.client.get(
  936. self.category_a.get_absolute_url() + 'unread/')
  937. self.assertEqual(response.status_code, 200)
  938. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  939. # test api
  940. self.access_all_categories()
  941. response = self.client.get('%s?list=unread' % self.api_link)
  942. self.assertEqual(response.status_code, 200)
  943. response_json = json_loads(response.content)
  944. self.assertEqual(len(response_json['results']), 0)
  945. self.access_all_categories()
  946. response = self.client.get(
  947. '%s?list=unread&category=%s' % (self.api_link, self.category_a.pk))
  948. self.assertEqual(response.status_code, 200)
  949. response_json = json_loads(response.content)
  950. self.assertEqual(len(response_json['results']), 0)
  951. def test_list_hides_global_cutoff_thread(self):
  952. """list hides thread replied before global cutoff"""
  953. self.user.joined_on = timezone.now() - timedelta(days=10)
  954. self.user.save()
  955. test_thread = testutils.post_thread(
  956. category=self.category_a,
  957. started_on=timezone.now() - timedelta(
  958. days=settings.MISAGO_FRESH_CONTENT_PERIOD + 5
  959. )
  960. )
  961. threadstracker.make_thread_read_aware(self.user, test_thread)
  962. threadstracker.read_thread(
  963. self.user, test_thread, test_thread.last_post)
  964. testutils.reply_thread(test_thread,
  965. posted_on=test_thread.started_on + timedelta(days=1)
  966. )
  967. self.access_all_categories()
  968. response = self.client.get('/unread/')
  969. self.assertEqual(response.status_code, 200)
  970. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  971. self.access_all_categories()
  972. response = self.client.get(
  973. self.category_a.get_absolute_url() + 'unread/')
  974. self.assertEqual(response.status_code, 200)
  975. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  976. # test api
  977. self.access_all_categories()
  978. response = self.client.get('%s?list=unread' % self.api_link)
  979. self.assertEqual(response.status_code, 200)
  980. response_json = json_loads(response.content)
  981. self.assertEqual(len(response_json['results']), 0)
  982. self.access_all_categories()
  983. response = self.client.get(
  984. '%s?list=unread&category=%s' % (self.api_link, self.category_a.pk))
  985. self.assertEqual(response.status_code, 200)
  986. response_json = json_loads(response.content)
  987. self.assertEqual(len(response_json['results']), 0)
  988. def test_list_hides_user_cutoff_thread(self):
  989. """list hides thread replied before user cutoff"""
  990. self.user.joined_on = timezone.now() - timedelta(days=10)
  991. self.user.save()
  992. test_thread = testutils.post_thread(
  993. category=self.category_a,
  994. started_on=self.user.joined_on - timedelta(days=2)
  995. )
  996. threadstracker.make_thread_read_aware(self.user, test_thread)
  997. threadstracker.read_thread(
  998. self.user, test_thread, test_thread.last_post)
  999. testutils.reply_thread(test_thread,
  1000. posted_on=test_thread.started_on + timedelta(days=1)
  1001. )
  1002. self.access_all_categories()
  1003. response = self.client.get('/unread/')
  1004. self.assertEqual(response.status_code, 200)
  1005. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  1006. self.access_all_categories()
  1007. response = self.client.get(
  1008. self.category_a.get_absolute_url() + 'unread/')
  1009. self.assertEqual(response.status_code, 200)
  1010. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  1011. # test api
  1012. self.access_all_categories()
  1013. response = self.client.get('%s?list=unread' % self.api_link)
  1014. self.assertEqual(response.status_code, 200)
  1015. response_json = json_loads(response.content)
  1016. self.assertEqual(len(response_json['results']), 0)
  1017. self.access_all_categories()
  1018. response = self.client.get(
  1019. '%s?list=unread&category=%s' % (self.api_link, self.category_a.pk))
  1020. self.assertEqual(response.status_code, 200)
  1021. response_json = json_loads(response.content)
  1022. self.assertEqual(len(response_json['results']), 0)
  1023. def test_list_hides_category_cutoff_thread(self):
  1024. """list hides thread replied before category cutoff"""
  1025. self.user.joined_on = timezone.now() - timedelta(days=10)
  1026. self.user.save()
  1027. test_thread = testutils.post_thread(
  1028. category=self.category_a,
  1029. started_on=self.user.joined_on - timedelta(days=2)
  1030. )
  1031. threadstracker.make_thread_read_aware(self.user, test_thread)
  1032. threadstracker.read_thread(
  1033. self.user, test_thread, test_thread.last_post)
  1034. testutils.reply_thread(test_thread)
  1035. self.user.categoryread_set.create(
  1036. category=self.category_a,
  1037. last_read_on=timezone.now(),
  1038. )
  1039. self.access_all_categories()
  1040. response = self.client.get('/unread/')
  1041. self.assertEqual(response.status_code, 200)
  1042. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  1043. self.access_all_categories()
  1044. response = self.client.get(
  1045. self.category_a.get_absolute_url() + 'unread/')
  1046. self.assertEqual(response.status_code, 200)
  1047. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  1048. # test api
  1049. self.access_all_categories()
  1050. response = self.client.get('%s?list=unread' % self.api_link)
  1051. self.assertEqual(response.status_code, 200)
  1052. response_json = json_loads(response.content)
  1053. self.assertEqual(len(response_json['results']), 0)
  1054. self.access_all_categories()
  1055. response = self.client.get(
  1056. '%s?list=unread&category=%s' % (self.api_link, self.category_a.pk))
  1057. self.assertEqual(response.status_code, 200)
  1058. response_json = json_loads(response.content)
  1059. self.assertEqual(len(response_json['results']), 0)
  1060. class SubscribedThreadsListTests(ThreadsListTestCase):
  1061. def test_list_shows_subscribed_thread(self):
  1062. """list shows subscribed thread"""
  1063. test_thread = testutils.post_thread(category=self.category_a)
  1064. self.user.subscription_set.create(
  1065. thread=test_thread,
  1066. category=self.category_a,
  1067. last_read_on=test_thread.last_post_on,
  1068. )
  1069. self.access_all_categories()
  1070. response = self.client.get('/subscribed/')
  1071. self.assertEqual(response.status_code, 200)
  1072. self.assertIn(test_thread.get_absolute_url(), response.content)
  1073. self.access_all_categories()
  1074. response = self.client.get(
  1075. self.category_a.get_absolute_url() + 'subscribed/')
  1076. self.assertEqual(response.status_code, 200)
  1077. self.assertIn(test_thread.get_absolute_url(), response.content)
  1078. # test api
  1079. self.access_all_categories()
  1080. response = self.client.get('%s?list=subscribed' % self.api_link)
  1081. self.assertEqual(response.status_code, 200)
  1082. response_json = json_loads(response.content)
  1083. self.assertEqual(len(response_json['results']), 1)
  1084. self.assertIn(test_thread.get_absolute_url(), response.content)
  1085. self.access_all_categories()
  1086. response = self.client.get(
  1087. '%s?list=subscribed&category=%s' % (
  1088. self.api_link, self.category_a.pk
  1089. ))
  1090. self.assertEqual(response.status_code, 200)
  1091. response_json = json_loads(response.content)
  1092. self.assertEqual(len(response_json['results']), 1)
  1093. self.assertIn(test_thread.get_absolute_url(), response.content)
  1094. def test_list_hides_unsubscribed_thread(self):
  1095. """list shows subscribed thread"""
  1096. test_thread = testutils.post_thread(category=self.category_a)
  1097. self.access_all_categories()
  1098. response = self.client.get('/subscribed/')
  1099. self.assertEqual(response.status_code, 200)
  1100. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  1101. self.access_all_categories()
  1102. response = self.client.get(
  1103. self.category_a.get_absolute_url() + 'subscribed/')
  1104. self.assertEqual(response.status_code, 200)
  1105. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  1106. # test api
  1107. self.access_all_categories()
  1108. response = self.client.get('%s?list=subscribed' % self.api_link)
  1109. self.assertEqual(response.status_code, 200)
  1110. response_json = json_loads(response.content)
  1111. self.assertEqual(len(response_json['results']), 0)
  1112. self.assertNotIn(test_thread.get_absolute_url(), response.content)
  1113. self.access_all_categories()
  1114. response = self.client.get(
  1115. '%s?list=subscribed&category=%s' % (
  1116. self.api_link, self.category_a.pk
  1117. ))
  1118. self.assertEqual(response.status_code, 200)
  1119. response_json = json_loads(response.content)
  1120. self.assertEqual(len(response_json['results']), 0)
  1121. self.assertNotIn(test_thread.get_absolute_url(), response.content)