test_pagure_flask_ui_roadmap.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2016 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. """
  7. __requires__ = ['SQLAlchemy >= 0.8']
  8. import pkg_resources
  9. import datetime
  10. import json
  11. import unittest
  12. import shutil
  13. import sys
  14. import tempfile
  15. import os
  16. import pygit2
  17. from mock import patch
  18. sys.path.insert(0, os.path.join(os.path.dirname(
  19. os.path.abspath(__file__)), '..'))
  20. import pagure.lib
  21. import tests
  22. from pagure.lib.repo import PagureRepo
  23. class PagureFlaskRoadmaptests(tests.Modeltests):
  24. """ Tests for the pagure's roadmap """
  25. def setUp(self):
  26. """ Set up the environnment, ran before every tests. """
  27. super(PagureFlaskRoadmaptests, self).setUp()
  28. pagure.APP.config['TESTING'] = True
  29. pagure.SESSION = self.session
  30. pagure.ui.SESSION = self.session
  31. pagure.ui.app.SESSION = self.session
  32. pagure.ui.filters.SESSION = self.session
  33. pagure.ui.repo.SESSION = self.session
  34. pagure.ui.issues.SESSION = self.session
  35. pagure.APP.config['GIT_FOLDER'] = tests.HERE
  36. pagure.APP.config['REQUESTS_FOLDER'] = os.path.join(
  37. tests.HERE, 'requests')
  38. pagure.APP.config['TICKETS_FOLDER'] = os.path.join(
  39. tests.HERE, 'tickets')
  40. pagure.APP.config['DOCS_FOLDER'] = os.path.join(
  41. tests.HERE, 'docs')
  42. self.app = pagure.APP.test_client()
  43. @patch('pagure.lib.git.update_git')
  44. @patch('pagure.lib.notify.send_email')
  45. def test_ticket_with_no_roadmap(self, p_send_email, p_ugt):
  46. """ Test creating a ticket without roadmap. """
  47. p_send_email.return_value = True
  48. p_ugt.return_value = True
  49. tests.create_projects(self.session)
  50. tests.create_projects_git(os.path.join(tests.HERE), bare=True)
  51. user = tests.FakeUser()
  52. user.username = 'pingou'
  53. with tests.user_set(pagure.APP, user):
  54. # Get the CSRF token
  55. output = self.app.get('/test/new_issue')
  56. self.assertEqual(output.status_code, 200)
  57. self.assertTrue(
  58. u'<div class="card-header">\n New issue'
  59. in output.data)
  60. csrf_token = output.data.split(
  61. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  62. data = {
  63. 'title': 'Test issue',
  64. 'issue_content': 'We really should improve on this issue',
  65. 'status': 'Open',
  66. 'csrf_token': csrf_token,
  67. }
  68. # Create the issue
  69. output = self.app.post(
  70. '/test/new_issue', data=data, follow_redirects=True)
  71. self.assertEqual(output.status_code, 200)
  72. self.assertIn(
  73. u'<title>Issue #1: Test issue - test - Pagure</title>',
  74. output.data)
  75. self.assertIn(
  76. u'<a class="btn btn-primary btn-sm" '
  77. 'href="/test/issue/1/edit" title="Edit this issue">',
  78. output.data)
  79. @patch('pagure.lib.git.update_git')
  80. @patch('pagure.lib.notify.send_email')
  81. def test_ticket_with_roadmap(self, p_send_email, p_ugt):
  82. """ Test creating a ticket with roadmap. """
  83. p_send_email.return_value = True
  84. p_ugt.return_value = True
  85. tests.create_projects(self.session)
  86. tests.create_projects_git(os.path.join(tests.HERE), bare=True)
  87. # Set some milestone
  88. repo = pagure.lib.get_project(self.session, 'test')
  89. repo.milestone = {'v1.0': '', 'v2.0': 'Tomorrow!'}
  90. self.session.add(repo)
  91. self.session.commit()
  92. user = tests.FakeUser()
  93. user.username = 'pingou'
  94. with tests.user_set(pagure.APP, user):
  95. # Get the CSRF token
  96. output = self.app.get('/test/new_issue')
  97. self.assertEqual(output.status_code, 200)
  98. self.assertTrue(
  99. u'<div class="card-header">\n New issue'
  100. in output.data)
  101. csrf_token = output.data.split(
  102. u'name="csrf_token" type="hidden" value="')[1].split(u'">')[0]
  103. data = {
  104. 'title': 'Test issue',
  105. 'issue_content': 'We really should improve on this issue',
  106. 'status': 'Open',
  107. 'csrf_token': csrf_token,
  108. }
  109. # Create the issue
  110. output = self.app.post(
  111. '/test/new_issue', data=data, follow_redirects=True)
  112. self.assertEqual(output.status_code, 200)
  113. self.assertIn(
  114. u'<title>Issue #1: Test issue - test - Pagure</title>',
  115. output.data)
  116. self.assertIn(
  117. u'<a class="btn btn-primary btn-sm" '
  118. 'href="/test/issue/1/edit" title="Edit this issue">',
  119. output.data)
  120. # Mark the ticket for the roadmap
  121. data = {
  122. 'tag': 'roadmap',
  123. 'csrf_token': csrf_token,
  124. }
  125. output = self.app.post(
  126. '/test/issue/1/update', data=data, follow_redirects=True)
  127. self.assertEqual(output.status_code, 200)
  128. self.assertIn(
  129. u'<title>Issue #1: Test issue - test - Pagure</title>',
  130. output.data)
  131. self.assertIn(
  132. u'<a class="btn btn-primary btn-sm" '
  133. 'href="/test/issue/1/edit" title="Edit this issue">',
  134. output.data)
  135. self.assertIn(
  136. u'</button>\n Tag added: roadmap',
  137. output.data)
  138. def test_update_milestones(self):
  139. """ Test updating milestones of a repo. """
  140. tests.create_projects(self.session)
  141. tests.create_projects_git(os.path.join(tests.HERE), bare=True)
  142. # Set some milestones
  143. repo = pagure.lib.get_project(self.session, 'test')
  144. self.assertEqual(repo.milestones, {})
  145. user = tests.FakeUser()
  146. user.username = 'pingou'
  147. with tests.user_set(pagure.APP, user):
  148. # Get the CSRF token
  149. output = self.app.get('/test/settings')
  150. self.assertEqual(output.status_code, 200)
  151. self.assertIn(
  152. u'<title>Settings - test - Pagure</title>', output.data)
  153. self.assertIn(u'<h3>Settings for test</h3>', output.data)
  154. csrf_token = output.data.split(
  155. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  156. data = {
  157. 'milestones': 1,
  158. 'milestone_dates': 'Tomorrow',
  159. }
  160. output = self.app.post(
  161. '/test/update/milestones', data=data, follow_redirects=True)
  162. self.assertEqual(output.status_code, 200)
  163. # Check the redirect
  164. self.assertIn(
  165. u'<title>Settings - test - Pagure</title>', output.data)
  166. self.assertIn('<h3>Settings for test</h3>', output.data)
  167. # Check the result of the action -- None, no CSRF
  168. repo = pagure.lib.get_project(self.session, 'test')
  169. self.assertEqual(repo.milestones, {})
  170. data = {
  171. 'milestones': 1,
  172. 'milestone_dates': 'Tomorrow',
  173. 'csrf_token': csrf_token,
  174. }
  175. output = self.app.post(
  176. '/test/update/milestones', data=data, follow_redirects=True)
  177. self.assertEqual(output.status_code, 200)
  178. # Check the redirect
  179. self.assertIn(
  180. u'<title>Settings - test - Pagure</title>', output.data)
  181. self.assertIn(u'<h3>Settings for test</h3>', output.data)
  182. self.assertIn(u'Milestones updated', output.data)
  183. # Check the result of the action -- Milestones recorded
  184. repo = pagure.lib.get_project(self.session, 'test')
  185. self.assertEqual(repo.milestones, {u'1': u'Tomorrow'})
  186. data = {
  187. 'milestones': ['v1.0', 'v2.0'],
  188. 'milestone_dates': ['Tomorrow', ''],
  189. 'csrf_token': csrf_token,
  190. }
  191. output = self.app.post(
  192. '/test/update/milestones', data=data, follow_redirects=True)
  193. self.assertEqual(output.status_code, 200)
  194. # Check the redirect
  195. self.assertIn(
  196. u'<title>Settings - test - Pagure</title>', output.data)
  197. self.assertIn(u'<h3>Settings for test</h3>', output.data)
  198. self.assertIn(u'Milestones updated', output.data)
  199. # Check the result of the action -- Milestones recorded
  200. repo = pagure.lib.get_project(self.session, 'test')
  201. self.assertEqual(
  202. repo.milestones, {u'v1.0': u'Tomorrow', u'v2.0': u''}
  203. )
  204. # Check error - less milestones than dates
  205. data = {
  206. 'milestones': ['v1.0', 'v2.0'],
  207. 'milestone_dates': ['Tomorrow', 'Next week', 'Next Year'],
  208. 'csrf_token': csrf_token,
  209. }
  210. output = self.app.post(
  211. '/test/update/milestones', data=data, follow_redirects=True)
  212. self.assertEqual(output.status_code, 200)
  213. # Check the redirect
  214. self.assertIn(
  215. u'<title>Settings - test - Pagure</title>', output.data)
  216. self.assertIn(u'<h3>Settings for test</h3>', output.data)
  217. self.assertIn(
  218. u'</button>\n'
  219. ' Milestones and dates are not of the '
  220. 'same length', output.data)
  221. # Check the result of the action -- Milestones un-changed
  222. repo = pagure.lib.get_project(self.session, 'test')
  223. self.assertEqual(
  224. repo.milestones, {u'v1.0': u'Tomorrow', u'v2.0': u''}
  225. )
  226. # Check error - Twice the same milestone
  227. data = {
  228. 'milestones': ['v1.0', 'v2.0', 'v2.0'],
  229. 'milestone_dates': ['Tomorrow', 'Next week', 'Next Year'],
  230. 'csrf_token': csrf_token,
  231. }
  232. output = self.app.post(
  233. '/test/update/milestones', data=data, follow_redirects=True)
  234. self.assertEqual(output.status_code, 200)
  235. # Check the redirect
  236. self.assertIn(
  237. u'<title>Settings - test - Pagure</title>', output.data)
  238. self.assertIn(u'<h3>Settings for test</h3>', output.data)
  239. self.assertIn(
  240. u'</button>\n'
  241. ' Milestone v2.0 is present 2 times',
  242. output.data)
  243. # Check the result of the action -- Milestones un-changed
  244. repo = pagure.lib.get_project(self.session, 'test')
  245. self.assertEqual(
  246. repo.milestones, {u'v1.0': u'Tomorrow', u'v2.0': u''}
  247. )
  248. # Check error - Twice the same date
  249. data = {
  250. 'milestones': ['v1.0', 'v2.0', 'v3.0'],
  251. 'milestone_dates': ['Tomorrow', 'Next week', 'Next week'],
  252. 'csrf_token': csrf_token,
  253. }
  254. output = self.app.post(
  255. '/test/update/milestones', data=data, follow_redirects=True)
  256. self.assertEqual(output.status_code, 200)
  257. # Check the redirect
  258. self.assertIn(
  259. u'<title>Settings - test - Pagure</title>', output.data)
  260. self.assertIn(u'<h3>Settings for test</h3>', output.data)
  261. self.assertIn(
  262. u'</button>\n'
  263. ' Date Next week is present 2 times',
  264. output.data)
  265. # Check the result of the action -- Milestones un-changed
  266. repo = pagure.lib.get_project(self.session, 'test')
  267. self.assertEqual(
  268. repo.milestones, {u'v1.0': u'Tomorrow', u'v2.0': u''}
  269. )
  270. # Check for an invalid project
  271. output = self.app.post(
  272. '/foo/update/milestones', data=data)
  273. self.assertEqual(output.status_code, 404)
  274. # Check the behavior if the project disabled the issue tracker
  275. settings = repo.settings
  276. settings['issue_tracker'] = False
  277. repo.settings = settings
  278. self.session.add(repo)
  279. self.session.commit()
  280. output = self.app.post(
  281. '/test/update/milestones', data=data)
  282. self.assertEqual(output.status_code, 404)
  283. # Check for a non-admin user
  284. settings = repo.settings
  285. settings['issue_tracker'] = True
  286. repo.settings = settings
  287. self.session.add(repo)
  288. self.session.commit()
  289. user.username = 'ralph'
  290. with tests.user_set(pagure.APP, user):
  291. output = self.app.post(
  292. '/test/update/milestones', data=data)
  293. self.assertEqual(output.status_code, 403)
  294. @patch('pagure.lib.git.update_git')
  295. @patch('pagure.lib.notify.send_email')
  296. def test_milestones_without_dates(self, p_send_email, p_ugt):
  297. """ Test creating two milestones with no dates. """
  298. tests.create_projects(self.session)
  299. tests.create_projects_git(os.path.join(tests.HERE), bare=True)
  300. user = tests.FakeUser()
  301. user.username = 'pingou'
  302. with tests.user_set(pagure.APP, user):
  303. # Get the CSRF token
  304. output = self.app.get('/test/settings')
  305. csrf_token = output.data.split(
  306. 'name="csrf_token" type="hidden" value="')[1].split('">')[0]
  307. data = {
  308. 'milestones': ['v1.0', 'v2.0'],
  309. 'milestone_dates': ['', ''],
  310. 'csrf_token': csrf_token,
  311. }
  312. output = self.app.post(
  313. '/test/update/milestones', data=data, follow_redirects=True)
  314. self.assertEqual(output.status_code, 200)
  315. # Check the redirect
  316. self.assertIn(
  317. u'<title>Settings - test - Pagure</title>', output.data)
  318. self.assertIn(u'<h3>Settings for test</h3>', output.data)
  319. self.assertIn(u'Milestones updated', output.data)
  320. # Check the result of the action -- Milestones recorded
  321. repo = pagure.lib.get_project(self.session, 'test')
  322. self.assertEqual(repo.milestones, {u'v1.0': u'', u'v2.0': u''})
  323. @patch('pagure.lib.git.update_git')
  324. @patch('pagure.lib.notify.send_email')
  325. def test_roadmap_ui(self, p_send_email, p_ugt):
  326. """ Test viewing the roadmap of a repo. """
  327. p_send_email.return_value = True
  328. p_ugt.return_value = True
  329. self.test_update_milestones()
  330. user = tests.FakeUser()
  331. user.username = 'pingou'
  332. with tests.user_set(pagure.APP, user):
  333. # Get the CSRF token
  334. output = self.app.get('/test/new_issue')
  335. self.assertEqual(output.status_code, 200)
  336. self.assertTrue(
  337. u'<div class="card-header">\n New issue'
  338. in output.data)
  339. csrf_token = output.data.split(
  340. u'name="csrf_token" type="hidden" value="')[1].split(u'">')[0]
  341. # Create the issues
  342. for cnt in range(6):
  343. cnt += 1
  344. data = {
  345. 'title': 'Test issue %s' % cnt,
  346. 'issue_content': 'We really should improve on this '
  347. 'issue %s' % cnt,
  348. 'status': 'Open',
  349. 'csrf_token': csrf_token,
  350. }
  351. output = self.app.post(
  352. '/test/new_issue', data=data, follow_redirects=True)
  353. self.assertEqual(output.status_code, 200)
  354. self.assertIn(
  355. u'<title>Issue #{0}: Test issue {0} - test - '
  356. 'Pagure</title>'.format(cnt),
  357. output.data)
  358. self.assertIn(
  359. u'<a class="btn btn-primary btn-sm" '
  360. 'href="/test/issue/%s/edit" title="Edit this '
  361. 'issue">' % cnt,
  362. output.data)
  363. # Mark the ticket for the roadmap
  364. data = {
  365. 'tag': ['roadmap, v%s.0' % cnt],
  366. 'csrf_token': csrf_token,
  367. }
  368. output = self.app.post(
  369. '/test/issue/%s/update' % cnt, data=data,
  370. follow_redirects=True)
  371. self.assertEqual(output.status_code, 200)
  372. self.assertIn(
  373. u'<title>Issue #{0}: Test issue {0} - test - '
  374. 'Pagure</title>'.format(cnt),
  375. output.data)
  376. self.assertIn(
  377. u'<a class="btn btn-primary btn-sm" '
  378. 'href="/test/issue/%s/edit" title="Edit this '
  379. 'issue">' % cnt,
  380. output.data)
  381. self.assertIn(
  382. u'</button>\n '
  383. 'Tag added: v%s.0, roadmap' % cnt,
  384. output.data)
  385. repo = pagure.lib.get_project(self.session, 'test')
  386. # Mark ticket #1 as Fixed
  387. ticket = pagure.lib.search_issues(
  388. self.session,
  389. repo,
  390. issueid=1
  391. )
  392. ticket.status = 'Fixed'
  393. self.session.add(ticket)
  394. self.session.commit()
  395. # test the roadmap view
  396. output = self.app.get('/test/roadmap')
  397. self.assertEqual(output.status_code, 200)
  398. self.assertIn(u'2 Milestones', output.data)
  399. self.assertIn(u'Milestone: v2.0', output.data)
  400. self.assertIn(u'Milestone: unplanned', output.data)
  401. self.assertEqual(
  402. output.data.count(u'<span class="label label-default">#'), 5)
  403. # test the roadmap view for all milestones
  404. output = self.app.get('/test/roadmap?status=All')
  405. self.assertEqual(output.status_code, 200)
  406. self.assertIn(u'3 Milestones', output.data)
  407. self.assertIn(u'Milestone: v1.0', output.data)
  408. self.assertIn(u'Milestone: v2.0', output.data)
  409. self.assertIn(u'Milestone: unplanned', output.data)
  410. self.assertEqual(
  411. output.data.count(u'<span class="label label-default">#'), 6)
  412. # test the roadmap view for a specific milestone
  413. output = self.app.get('/test/roadmap?milestone=v2.0')
  414. self.assertEqual(output.status_code, 200)
  415. self.assertIn(u'1 Milestones', output.data)
  416. self.assertIn(u'Milestone: v2.0', output.data)
  417. self.assertEqual(
  418. output.data.count(u'<span class="label label-default">#'), 1)
  419. # test the roadmap view for a specific milestone - closed
  420. output = self.app.get('/test/roadmap?milestone=v1.0')
  421. self.assertEqual(output.status_code, 200)
  422. self.assertIn(u'1 Milestones', output.data)
  423. self.assertIn(u'Milestone: v1.0', output.data)
  424. self.assertEqual(
  425. output.data.count(u'<span class="label label-default">#'), 0)
  426. # test the roadmap view for a specific milestone - closed
  427. output = self.app.get('/test/roadmap?milestone=v1.0&status=All')
  428. self.assertEqual(output.status_code, 200)
  429. self.assertIn(u'1 Milestones', output.data)
  430. self.assertIn(u'Milestone: v1.0', output.data)
  431. self.assertEqual(
  432. output.data.count(u'<span class="label label-default">#'), 1)
  433. # test the roadmap view for errors
  434. output = self.app.get('/foo/roadmap')
  435. self.assertEqual(output.status_code, 404)
  436. repo = pagure.lib.get_project(self.session, 'test')
  437. settings = repo.settings
  438. settings['issue_tracker'] = False
  439. repo.settings = settings
  440. self.session.add(repo)
  441. self.session.commit()
  442. output = self.app.get('/test/roadmap', data=data)
  443. self.assertEqual(output.status_code, 404)
  444. if __name__ == '__main__':
  445. SUITE = unittest.TestLoader().loadTestsFromTestCase(
  446. PagureFlaskRoadmaptests)
  447. unittest.TextTestRunner(verbosity=2).run(SUITE)