test_pagure_flask_api_user.py 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244
  1. # -*- coding: utf-8 -*-
  2. """
  3. (c) 2015-2018 - Copyright Red Hat Inc
  4. Authors:
  5. Pierre-Yves Chibon <pingou@pingoured.fr>
  6. """
  7. from __future__ import unicode_literals
  8. __requires__ = ['SQLAlchemy >= 0.8']
  9. import pkg_resources
  10. import datetime
  11. import unittest
  12. import shutil
  13. import sys
  14. import os
  15. import json
  16. from mock import patch
  17. sys.path.insert(0, os.path.join(os.path.dirname(
  18. os.path.abspath(__file__)), '..'))
  19. import pagure.api
  20. import pagure.config
  21. import pagure.lib
  22. import pagure.lib.model as model
  23. import tests
  24. class PagureFlaskApiUSertests(tests.Modeltests):
  25. """ Tests for the flask API of pagure for issue """
  26. maxDiff = None
  27. def setUp(self):
  28. """ Set up the environnment, ran before every tests. """
  29. super(PagureFlaskApiUSertests, self).setUp()
  30. pagure.config.config['REQUESTS_FOLDER'] = None
  31. def test_api_users(self):
  32. """ Test the api_users function. """
  33. output = self.app.get('/api/0/users')
  34. self.assertEqual(output.status_code, 200)
  35. data = json.loads(output.get_data(as_text=True))
  36. self.assertEqual(sorted(data['users']), ['foo', 'pingou'])
  37. self.assertEqual(sorted(data.keys()), ['mention', 'total_users', 'users'])
  38. self.assertEqual(data['total_users'], 2)
  39. output = self.app.get('/api/0/users?pattern=p')
  40. self.assertEqual(output.status_code, 200)
  41. data = json.loads(output.get_data(as_text=True))
  42. self.assertEqual(data['users'], ['pingou'])
  43. self.assertEqual(sorted(data.keys()), ['mention', 'total_users', 'users'])
  44. self.assertEqual(data['total_users'], 1)
  45. def test_api_view_user(self):
  46. """
  47. Test the api_view_user method of the flask api
  48. The tested user has no project or forks.
  49. """
  50. output = self.app.get('/api/0/user/pingou')
  51. self.assertEqual(output.status_code, 200)
  52. exp = {
  53. "forks": [],
  54. 'forks_pagination': {
  55. 'first': 'http://localhost...',
  56. 'last': 'http://localhost...',
  57. 'next': None,
  58. 'forkpage': 1,
  59. 'pages': 0,
  60. 'per_page': 20,
  61. 'prev': None},
  62. "repos": [],
  63. 'repos_pagination': {
  64. 'first': 'http://localhost...',
  65. 'last': 'http://localhost...',
  66. 'next': None,
  67. 'repopage': 1,
  68. 'pages': 0,
  69. 'per_page': 20,
  70. 'prev': None},
  71. "user": { "fullname": "PY C", "name": "pingou"}}
  72. data = json.loads(output.get_data(as_text=True))
  73. for k in ['forks_pagination', 'repos_pagination']:
  74. for k2 in ['first', 'last']:
  75. self.assertIsNotNone(data[k][k2])
  76. data[k][k2] = 'http://localhost...'
  77. self.assertEqual(data, exp)
  78. def test_api_view_user_with_project(self):
  79. """
  80. Test the api_view_user method of the flask api,
  81. this time the user has some project defined.
  82. """
  83. tests.create_projects(self.session)
  84. output = self.app.get('/api/0/user/pingou')
  85. self.assertEqual(output.status_code, 200)
  86. data = json.loads(output.get_data(as_text=True))
  87. data['repos'][0]['date_created'] = "1490272832"
  88. data['repos'][0]['date_modified'] = "1490272832"
  89. data['repos'][1]['date_created'] = "1490272832"
  90. data['repos'][1]['date_modified'] = "1490272832"
  91. data['repos'][2]['date_created'] = "1490272832"
  92. data['repos'][2]['date_modified'] = "1490272832"
  93. for k in ['forks_pagination', 'repos_pagination']:
  94. for k2 in ['first', 'last']:
  95. self.assertIsNotNone(data[k][k2])
  96. data[k][k2] = 'http://localhost...'
  97. expected_data = {
  98. "forks": [],
  99. 'forks_pagination': {
  100. 'first': 'http://localhost...',
  101. 'last': 'http://localhost...',
  102. 'next': None,
  103. 'forkpage': 1,
  104. 'pages': 0,
  105. 'per_page': 20,
  106. 'prev': None},
  107. "repos": [
  108. {
  109. "access_groups": {
  110. "admin": [],
  111. "commit": [],
  112. "ticket": []
  113. },
  114. "access_users": {
  115. "admin": [],
  116. "commit": [],
  117. "owner": ["pingou"],
  118. "ticket": []
  119. },
  120. "close_status": [
  121. "Invalid",
  122. "Insufficient data",
  123. "Fixed",
  124. "Duplicate"
  125. ],
  126. "custom_keys": [],
  127. "date_created": "1490272832",
  128. "date_modified": "1490272832",
  129. "description": "test project #1",
  130. "fullname": "test",
  131. "url_path": "test",
  132. "id": 1,
  133. "milestones": {},
  134. "name": "test",
  135. "namespace": None,
  136. "parent": None,
  137. "priorities": {},
  138. "tags": [],
  139. "user": {
  140. "fullname": "PY C",
  141. "name": "pingou"
  142. }
  143. },
  144. {
  145. "access_groups": {
  146. "admin": [],
  147. "commit": [],
  148. "ticket": []
  149. },
  150. "access_users": {
  151. "admin": [],
  152. "commit": [],
  153. "owner": ["pingou"],
  154. "ticket": []
  155. },
  156. "close_status": [
  157. "Invalid",
  158. "Insufficient data",
  159. "Fixed",
  160. "Duplicate"
  161. ],
  162. "custom_keys": [],
  163. "date_created": "1490272832",
  164. "date_modified": "1490272832",
  165. "description": "test project #2",
  166. "fullname": "test2",
  167. "url_path": "test2",
  168. "id": 2,
  169. "milestones": {},
  170. "name": "test2",
  171. "namespace": None,
  172. "parent": None,
  173. "priorities": {},
  174. "tags": [],
  175. "user": {
  176. "fullname": "PY C",
  177. "name": "pingou"
  178. }
  179. },
  180. {
  181. "access_groups": {
  182. "admin": [],
  183. "commit": [],
  184. "ticket": []},
  185. "access_users": {
  186. "admin": [],
  187. "commit": [],
  188. "owner": ["pingou"],
  189. "ticket": []
  190. },
  191. "close_status": [
  192. "Invalid",
  193. "Insufficient data",
  194. "Fixed",
  195. "Duplicate"
  196. ],
  197. "custom_keys": [],
  198. "date_created": "1490272832",
  199. "date_modified": "1490272832",
  200. "description": "namespaced test project",
  201. "fullname": "somenamespace/test3",
  202. "url_path": "somenamespace/test3",
  203. "id": 3,
  204. "milestones": {},
  205. "name": "test3",
  206. "namespace": "somenamespace",
  207. "parent": None,
  208. "priorities": {},
  209. "tags": [],
  210. "user": {
  211. "fullname": "PY C",
  212. "name": "pingou"
  213. }
  214. }
  215. ],
  216. 'repos_pagination': {
  217. 'first': 'http://localhost...',
  218. 'last': 'http://localhost...',
  219. 'next': None,
  220. 'repopage': 1,
  221. 'pages': 1,
  222. 'per_page': 20,
  223. 'prev': None},
  224. "user": {
  225. "fullname": "PY C",
  226. "name": "pingou"
  227. }
  228. }
  229. self.assertEqual(data, expected_data)
  230. @patch('pagure.lib.notify.send_email')
  231. def test_api_view_user_activity_stats(self, mockemail):
  232. """ Test the api_view_user_activity_stats method of the flask user
  233. api. """
  234. mockemail.return_value = True
  235. tests.create_projects(self.session)
  236. tests.create_tokens(self.session)
  237. tests.create_tokens_acl(self.session)
  238. headers = {'Authorization': 'token aaabbbcccddd'}
  239. # Create a pull-request
  240. repo = pagure.lib._get_project(self.session, 'test')
  241. forked_repo = pagure.lib._get_project(self.session, 'test')
  242. req = pagure.lib.new_pull_request(
  243. session=self.session,
  244. repo_from=forked_repo,
  245. branch_from='master',
  246. repo_to=repo,
  247. branch_to='master',
  248. title='test pull-request',
  249. user='pingou',
  250. )
  251. self.session.commit()
  252. self.assertEqual(req.id, 1)
  253. self.assertEqual(req.title, 'test pull-request')
  254. # Check comments before
  255. self.session.commit()
  256. request = pagure.lib.search_pull_requests(
  257. self.session, project_id=1, requestid=1)
  258. self.assertEqual(len(request.comments), 0)
  259. data = {
  260. 'comment': 'This is a very interesting question',
  261. }
  262. # Valid request
  263. output = self.app.post(
  264. '/api/0/test/pull-request/1/comment', data=data, headers=headers)
  265. self.assertEqual(output.status_code, 200)
  266. data = json.loads(output.get_data(as_text=True))
  267. self.assertDictEqual(
  268. data,
  269. {'message': 'Comment added'}
  270. )
  271. # One comment added
  272. self.session.commit()
  273. request = pagure.lib.search_pull_requests(
  274. self.session, project_id=1, requestid=1)
  275. self.assertEqual(len(request.comments), 1)
  276. # Close PR
  277. output = self.app.post(
  278. '/api/0/test/pull-request/1/close', headers=headers)
  279. self.assertEqual(output.status_code, 200)
  280. data = json.loads(output.get_data(as_text=True))
  281. self.assertDictEqual(
  282. data,
  283. {"message": "Pull-request closed!"}
  284. )
  285. # PR closed
  286. self.session.commit()
  287. request = pagure.lib.search_pull_requests(
  288. self.session, project_id=1, requestid=1)
  289. self.assertEqual(request.status, 'Closed')
  290. # Finally retrieve the user's logs
  291. output = self.app.get('/api/0/user/pingou/activity/stats')
  292. self.assertEqual(output.status_code, 200)
  293. data = json.loads(output.get_data(as_text=True))
  294. date = datetime.datetime.utcnow().date().strftime('%Y-%m-%d')
  295. self.assertDictEqual(data, {date: 4})
  296. @patch('pagure.lib.notify.send_email')
  297. def test_api_view_user_activity_date(self, mockemail):
  298. """ Test the api_view_user_activity_date method of the flask user
  299. api. """
  300. self.test_api_view_user_activity_stats()
  301. # Invalid date
  302. output = self.app.get('/api/0/user/pingou/activity/AABB')
  303. self.assertEqual(output.status_code, 400)
  304. # Invalid date
  305. output = self.app.get('/api/0/user/pingou/activity/2016asd')
  306. self.assertEqual(output.status_code, 200)
  307. exp = {
  308. "activities": [],
  309. "date": "2016-01-01"
  310. }
  311. self.assertEqual(json.loads(output.get_data(as_text=True)), exp)
  312. # Date parsed, just not really as expected
  313. output = self.app.get('/api/0/user/pingou/activity/20161245')
  314. self.assertEqual(output.status_code, 200)
  315. exp = {
  316. "activities": [],
  317. "date": "1970-08-22"
  318. }
  319. self.assertEqual(json.loads(output.get_data(as_text=True)), exp)
  320. date = datetime.datetime.utcnow().date().strftime('%Y-%m-%d')
  321. # Retrieve the user's logs for today
  322. output = self.app.get('/api/0/user/pingou/activity/%s' % date)
  323. self.assertEqual(output.status_code, 200)
  324. data = json.loads(output.get_data(as_text=True))
  325. exp = {
  326. "activities": [
  327. {
  328. "date": date,
  329. "date_created": "1477558752",
  330. "type": "pull-request",
  331. "description_mk": "<p>pingou created PR <a href=\"/test/pull-request/1\" title=\"[Closed] test pull-request\">test#1</a></p>",
  332. "id": 1,
  333. "ref_id": "1",
  334. "type": "created",
  335. "user": {
  336. "fullname": "PY C",
  337. "name": "pingou"
  338. }
  339. },
  340. {
  341. "date": date,
  342. "date_created": "1477558752",
  343. "type": "pull-request",
  344. "description_mk": "<p>pingou commented on PR <a href=\"/test/pull-request/1\" title=\"[Closed] test pull-request\">test#1</a></p>",
  345. "id": 2,
  346. "ref_id": "1",
  347. "type": "commented",
  348. "user": {
  349. "fullname": "PY C",
  350. "name": "pingou"
  351. }
  352. },
  353. {
  354. "date": date,
  355. "date_created": "1477558752",
  356. "type": "pull-request",
  357. "description_mk": "<p>pingou closed PR <a href=\"/test/pull-request/1\" title=\"[Closed] test pull-request\">test#1</a></p>",
  358. "id": 3,
  359. "ref_id": "1",
  360. "type": "closed",
  361. "user": {
  362. "fullname": "PY C",
  363. "name": "pingou"
  364. }
  365. },
  366. {
  367. "date": date,
  368. "date_created": "1477558752",
  369. "type": "pull-request",
  370. "description_mk": "<p>pingou commented on PR <a href=\"/test/pull-request/1\" title=\"[Closed] test pull-request\">test#1</a></p>",
  371. "id": 4,
  372. "ref_id": "1",
  373. "type": "commented",
  374. "user": {
  375. "fullname": "PY C",
  376. "name": "pingou"
  377. }
  378. }
  379. ],
  380. "date": date,
  381. }
  382. for idx, act in enumerate(data['activities']):
  383. act['date_created'] = '1477558752'
  384. data['activities'][idx] = act
  385. self.assertEqual(data, exp)
  386. @patch('pagure.lib.notify.send_email')
  387. def test_api_view_user_activity_date_1_activity(self, mockemail):
  388. """ Test the api_view_user_activity_date method of the flask user
  389. api when the user only did one action. """
  390. tests.create_projects(self.session)
  391. repo = pagure.lib._get_project(self.session, 'test')
  392. now = datetime.datetime.utcnow()
  393. date = now.date().strftime('%Y-%m-%d')
  394. # Create a single commit log
  395. log = model.PagureLog(
  396. user_id=1,
  397. user_email='foo@bar.com',
  398. project_id=1,
  399. log_type='committed',
  400. ref_id='githash',
  401. date=now.date(),
  402. date_created=now
  403. )
  404. self.session.add(log)
  405. self.session.commit()
  406. # Retrieve the user's logs for today
  407. output = self.app.get(
  408. '/api/0/user/pingou/activity/%s?grouped=1' % date)
  409. self.assertEqual(output.status_code, 200)
  410. data = json.loads(output.get_data(as_text=True))
  411. exp = {
  412. "activities": [
  413. {
  414. "description_mk": "<p>pingou committed on test#githash</p>"
  415. }
  416. ],
  417. "date": date,
  418. }
  419. self.assertEqual(data, exp)
  420. @patch('pagure.lib.notify.send_email')
  421. def test_api_view_user_activity_timezone_negative(self, mockemail):
  422. """Test api_view_user_activity{_stats,_date} with the America/
  423. New York timezone, which is 5 hours behind UTC in winter and
  424. 4 hours behind UTC in summer (daylight savings). The events
  425. will occur on 2018-02-15 in UTC, but on 2018-02-14 local.
  426. """
  427. tests.create_projects(self.session)
  428. repo = pagure.lib._get_project(self.session, 'test')
  429. dateobj = datetime.datetime(2018, 2, 15, 3, 30)
  430. utcdate = '2018-02-15'
  431. # the Unix timestamp for 2018-02-15 12:00 UTC
  432. utcts = '1518696000'
  433. localdate = '2018-02-14'
  434. # the Unix timestamp for 2018-02-14 12:00 America/New_York
  435. localts = '1518627600'
  436. # Create a single commit log
  437. log = model.PagureLog(
  438. user_id=1,
  439. user_email='foo@bar.com',
  440. project_id=1,
  441. log_type='committed',
  442. ref_id='githash',
  443. date=dateobj.date(),
  444. date_created=dateobj
  445. )
  446. self.session.add(log)
  447. self.session.commit()
  448. # Retrieve the user's stats with no timezone specified (==UTC)
  449. output = self.app.get('/api/0/user/pingou/activity/stats')
  450. self.assertEqual(output.status_code, 200)
  451. data = json.loads(output.get_data(as_text=True))
  452. # date in output should be UTC date
  453. self.assertDictEqual(data, {utcdate: 1})
  454. # Now in timestamp format...
  455. output = self.app.get('/api/0/user/pingou/activity/stats?format=timestamp')
  456. self.assertEqual(output.status_code, 200)
  457. data = json.loads(output.get_data(as_text=True))
  458. # timestamp in output should be UTC ts
  459. self.assertDictEqual(data, {utcts: 1})
  460. # Retrieve the user's stats with local timezone specified
  461. output = self.app.get('/api/0/user/pingou/activity/stats?tz=America/New_York')
  462. self.assertEqual(output.status_code, 200)
  463. data = json.loads(output.get_data(as_text=True))
  464. # date in output should be local date
  465. self.assertDictEqual(data, {localdate: 1})
  466. # Now in timestamp format...
  467. output = self.app.get('/api/0/user/pingou/activity/stats?format=timestamp&tz=America/New_York')
  468. self.assertEqual(output.status_code, 200)
  469. data = json.loads(output.get_data(as_text=True))
  470. # timestamp in output should be local ts
  471. self.assertDictEqual(data, {localts: 1})
  472. # Retrieve the user's logs for 2018-02-15 with no timezone
  473. output = self.app.get(
  474. '/api/0/user/pingou/activity/%s?grouped=1' % utcdate)
  475. self.assertEqual(output.status_code, 200)
  476. data = json.loads(output.get_data(as_text=True))
  477. exp = {
  478. "activities": [
  479. {
  480. "description_mk": "<p>pingou committed on test#githash</p>"
  481. }
  482. ],
  483. "date": utcdate,
  484. }
  485. self.assertEqual(data, exp)
  486. # Now retrieve the user's logs for 2018-02-14 with local time
  487. output = self.app.get(
  488. '/api/0/user/pingou/activity/%s?grouped=1&tz=America/New_York' % localdate)
  489. self.assertEqual(output.status_code, 200)
  490. data = json.loads(output.get_data(as_text=True))
  491. exp['date'] = localdate
  492. self.assertEqual(data, exp)
  493. @patch('pagure.lib.notify.send_email')
  494. def test_api_view_user_activity_timezone_positive(self, mockemail):
  495. """Test api_view_user_activity{_stats,_date} with the Asia/
  496. Dubai timezone, which is 4 hours ahead of UTC. The events will
  497. occur on 2018-02-15 in UTC, but on 2018-02-16 in local time.
  498. """
  499. tests.create_projects(self.session)
  500. repo = pagure.lib._get_project(self.session, 'test')
  501. dateobj = datetime.datetime(2018, 2, 15, 22, 30)
  502. utcdate = '2018-02-15'
  503. # the Unix timestamp for 2018-02-15 12:00 UTC
  504. utcts = '1518696000'
  505. localdate = '2018-02-16'
  506. # the Unix timestamp for 2018-02-16 12:00 Asia/Dubai
  507. localts = '1518768000'
  508. # Create a single commit log
  509. log = model.PagureLog(
  510. user_id=1,
  511. user_email='foo@bar.com',
  512. project_id=1,
  513. log_type='committed',
  514. ref_id='githash',
  515. date=dateobj.date(),
  516. date_created=dateobj
  517. )
  518. self.session.add(log)
  519. self.session.commit()
  520. # Retrieve the user's stats with no timezone specified (==UTC)
  521. output = self.app.get('/api/0/user/pingou/activity/stats')
  522. self.assertEqual(output.status_code, 200)
  523. data = json.loads(output.get_data(as_text=True))
  524. # date in output should be UTC date
  525. self.assertDictEqual(data, {utcdate: 1})
  526. # Now in timestamp format...
  527. output = self.app.get('/api/0/user/pingou/activity/stats?format=timestamp')
  528. self.assertEqual(output.status_code, 200)
  529. data = json.loads(output.get_data(as_text=True))
  530. # timestamp in output should be UTC ts
  531. self.assertDictEqual(data, {utcts: 1})
  532. # Retrieve the user's stats with local timezone specified
  533. output = self.app.get('/api/0/user/pingou/activity/stats?tz=Asia/Dubai')
  534. self.assertEqual(output.status_code, 200)
  535. data = json.loads(output.get_data(as_text=True))
  536. # date in output should be local date
  537. self.assertDictEqual(data, {localdate: 1})
  538. # Now in timestamp format...
  539. output = self.app.get('/api/0/user/pingou/activity/stats?format=timestamp&tz=Asia/Dubai')
  540. self.assertEqual(output.status_code, 200)
  541. data = json.loads(output.get_data(as_text=True))
  542. # timestamp in output should be local ts
  543. self.assertDictEqual(data, {localts: 1})
  544. # Retrieve the user's logs for 2018-02-15 with no timezone
  545. output = self.app.get(
  546. '/api/0/user/pingou/activity/%s?grouped=1' % utcdate)
  547. self.assertEqual(output.status_code, 200)
  548. data = json.loads(output.get_data(as_text=True))
  549. exp = {
  550. "activities": [
  551. {
  552. "description_mk": "<p>pingou committed on test#githash</p>"
  553. }
  554. ],
  555. "date": utcdate,
  556. }
  557. self.assertEqual(data, exp)
  558. # Now retrieve the user's logs for 2018-02-16 with local time
  559. output = self.app.get(
  560. '/api/0/user/pingou/activity/%s?grouped=1&tz=Asia/Dubai' % localdate)
  561. self.assertEqual(output.status_code, 200)
  562. data = json.loads(output.get_data(as_text=True))
  563. exp['date'] = localdate
  564. self.assertEqual(data, exp)
  565. class PagureFlaskApiUsertestrequests(tests.Modeltests):
  566. """ Tests for the user requests endpoints """
  567. maxDiff = None
  568. def setUp(self):
  569. """ Set up the environnment, ran before every tests. """
  570. super(PagureFlaskApiUsertestrequests, self).setUp()
  571. pagure.config.config['REQUESTS_FOLDER'] = None
  572. tests.create_projects(self.session)
  573. # Create few pull-requests
  574. repo = pagure.lib.get_authorized_project(self.session, 'test')
  575. forked_repo = pagure.lib.get_authorized_project(self.session, 'test')
  576. pagure.lib.new_pull_request(
  577. session=self.session,
  578. repo_from=forked_repo,
  579. branch_from='master',
  580. repo_to=repo,
  581. branch_to='master',
  582. title='open pullrequest by user foo on repo test',
  583. user='foo',
  584. )
  585. repo = pagure.lib.get_authorized_project(self.session, 'test2')
  586. forked_repo = pagure.lib.get_authorized_project(self.session, 'test2')
  587. pagure.lib.new_pull_request(
  588. session=self.session,
  589. repo_from=forked_repo,
  590. branch_from='master',
  591. repo_to=repo,
  592. branch_to='master',
  593. title='open pullrequest by user foo on repo test2',
  594. user='foo',
  595. )
  596. self.session.commit()
  597. repo = pagure.lib.get_authorized_project(self.session, 'test')
  598. forked_repo = pagure.lib.get_authorized_project(self.session, 'test')
  599. pagure.lib.new_pull_request(
  600. session=self.session,
  601. repo_from=forked_repo,
  602. branch_from='master',
  603. repo_to=repo,
  604. branch_to='master',
  605. title='closed pullrequest by user foo on repo test',
  606. user='foo',
  607. status='Closed',
  608. )
  609. repo = pagure.lib.get_authorized_project(self.session, 'test2')
  610. forked_repo = pagure.lib.get_authorized_project(self.session, 'test2')
  611. pagure.lib.new_pull_request(
  612. session=self.session,
  613. repo_from=forked_repo,
  614. branch_from='master',
  615. repo_to=repo,
  616. branch_to='master',
  617. title='closed pullrequest by user foo on repo test2',
  618. user='foo',
  619. status='Closed',
  620. )
  621. self.session.commit()
  622. repo = pagure.lib.get_authorized_project(self.session, 'test')
  623. forked_repo = pagure.lib.get_authorized_project(self.session, 'test')
  624. pagure.lib.new_pull_request(
  625. session=self.session,
  626. repo_from=forked_repo,
  627. branch_from='master',
  628. repo_to=repo,
  629. branch_to='master',
  630. title='merged pullrequest by user foo on repo test',
  631. user='foo',
  632. status='Merged',
  633. )
  634. repo = pagure.lib.get_authorized_project(self.session, 'test2')
  635. forked_repo = pagure.lib.get_authorized_project(self.session, 'test2')
  636. pagure.lib.new_pull_request(
  637. session=self.session,
  638. repo_from=forked_repo,
  639. branch_from='master',
  640. repo_to=repo,
  641. branch_to='master',
  642. title='merged pullrequest by user foo on repo test2',
  643. user='foo',
  644. status='Merged',
  645. )
  646. self.session.commit()
  647. repo = pagure.lib.get_authorized_project(self.session, 'test')
  648. forked_repo = pagure.lib.get_authorized_project(self.session, 'test')
  649. pagure.lib.new_pull_request(
  650. session=self.session,
  651. repo_from=forked_repo,
  652. branch_from='master',
  653. repo_to=repo,
  654. branch_to='master',
  655. title='open pullrequest by user pingou on repo test',
  656. user='pingou',
  657. )
  658. self.session.commit()
  659. repo = pagure.lib.get_authorized_project(self.session, 'test2')
  660. forked_repo = pagure.lib.get_authorized_project(self.session, 'test2')
  661. pagure.lib.new_pull_request(
  662. session=self.session,
  663. repo_from=forked_repo,
  664. branch_from='master',
  665. repo_to=repo,
  666. branch_to='master',
  667. title='open pullrequest by user pingou on repo test2',
  668. user='pingou',
  669. )
  670. self.session.commit()
  671. repo = pagure.lib.get_authorized_project(self.session, 'test')
  672. forked_repo = pagure.lib.get_authorized_project(self.session, 'test')
  673. pagure.lib.new_pull_request(
  674. session=self.session,
  675. repo_from=forked_repo,
  676. branch_from='master',
  677. repo_to=repo,
  678. branch_to='master',
  679. title='closed pullrequest by user pingou on repo test',
  680. user='pingou',
  681. status="Closed",
  682. )
  683. self.session.commit()
  684. repo = pagure.lib.get_authorized_project(self.session, 'test2')
  685. forked_repo = pagure.lib.get_authorized_project(self.session, 'test2')
  686. pagure.lib.new_pull_request(
  687. session=self.session,
  688. repo_from=forked_repo,
  689. branch_from='master',
  690. repo_to=repo,
  691. branch_to='master',
  692. title='closed pullrequest by user pingou on repo test2',
  693. user='pingou',
  694. status="Closed",
  695. )
  696. self.session.commit()
  697. repo = pagure.lib.get_authorized_project(self.session, 'test')
  698. forked_repo = pagure.lib.get_authorized_project(self.session, 'test')
  699. pagure.lib.new_pull_request(
  700. session=self.session,
  701. repo_from=forked_repo,
  702. branch_from='master',
  703. repo_to=repo,
  704. branch_to='master',
  705. title='merged pullrequest by user pingou on repo test',
  706. user='pingou',
  707. status="Merged",
  708. )
  709. self.session.commit()
  710. repo = pagure.lib.get_authorized_project(self.session, 'test2')
  711. forked_repo = pagure.lib.get_authorized_project(self.session, 'test2')
  712. pagure.lib.new_pull_request(
  713. session=self.session,
  714. repo_from=forked_repo,
  715. branch_from='master',
  716. repo_to=repo,
  717. branch_to='master',
  718. title='merged pullrequest by user pingou on repo test2',
  719. user='pingou',
  720. status="Merged",
  721. )
  722. self.session.commit()
  723. @patch('pagure.lib.notify.send_email')
  724. def test_api_view_user_requests_filed(self, mockemail):
  725. """ Test the api_view_user_requests_filed method of the flask user
  726. api """
  727. # First we test without the status parameter. It should default to `open`
  728. output = self.app.get(
  729. '/api/0/user/pingou/requests/filed')
  730. self.assertEqual(output.status_code, 200)
  731. data = json.loads(output.get_data(as_text=True))
  732. self.assertEqual(len(data['requests']), 2)
  733. self.assertEqual(
  734. sorted(data.keys()),
  735. [u'args', u'pagination', u'requests', u'total_requests'])
  736. self.assertEqual(data['requests'][0]['user']['name'], "pingou")
  737. self.assertEqual(data['requests'][1]['user']['name'], "pingou")
  738. self.assertEqual(data['requests'][0]['status'], "Open")
  739. self.assertEqual(data['requests'][1]['status'], "Open")
  740. self.assertEqual(data['requests'][0]['title'], "open pullrequest by user pingou on repo test2")
  741. self.assertEqual(data['requests'][1]['title'], "open pullrequest by user pingou on repo test")
  742. self.assertEqual(data['args']['status'], "open")
  743. self.assertEqual(data['args']['page'], 1)
  744. # Next test with the status parameter set to `open`.
  745. output = self.app.get(
  746. '/api/0/user/pingou/requests/filed?status=open')
  747. self.assertEqual(output.status_code, 200)
  748. data = json.loads(output.get_data(as_text=True))
  749. self.assertEqual(len(data['requests']), 2)
  750. self.assertEqual(
  751. sorted(data.keys()),
  752. [u'args', u'pagination', u'requests', u'total_requests'])
  753. self.assertEqual(data['requests'][0]['user']['name'], "pingou")
  754. self.assertEqual(data['requests'][1]['user']['name'], "pingou")
  755. self.assertEqual(data['requests'][0]['status'], "Open")
  756. self.assertEqual(data['requests'][1]['status'], "Open")
  757. self.assertEqual(data['requests'][0]['title'], "open pullrequest by user pingou on repo test2")
  758. self.assertEqual(data['requests'][1]['title'], "open pullrequest by user pingou on repo test")
  759. self.assertEqual(data['args']['status'], "open")
  760. self.assertEqual(data['args']['page'], 1)
  761. # Next test with the status parameter set to `closed`.
  762. output = self.app.get(
  763. '/api/0/user/pingou/requests/filed?status=closed')
  764. self.assertEqual(output.status_code, 200)
  765. data = json.loads(output.get_data(as_text=True))
  766. self.assertEqual(len(data['requests']), 2)
  767. self.assertEqual(
  768. sorted(data.keys()),
  769. [u'args', u'pagination', u'requests', u'total_requests'])
  770. self.assertEqual(data['requests'][0]['user']['name'], "pingou")
  771. self.assertEqual(data['requests'][1]['user']['name'], "pingou")
  772. self.assertEqual(data['requests'][0]['status'], "Closed")
  773. self.assertEqual(data['requests'][1]['status'], "Closed")
  774. self.assertEqual(data['requests'][0]['title'], "closed pullrequest by user pingou on repo test2")
  775. self.assertEqual(data['requests'][1]['title'], "closed pullrequest by user pingou on repo test")
  776. self.assertEqual(data['args']['status'], "closed")
  777. self.assertEqual(data['args']['page'], 1)
  778. # Next test with the status parameter set to `merged`.
  779. output = self.app.get(
  780. '/api/0/user/pingou/requests/filed?status=merged')
  781. self.assertEqual(output.status_code, 200)
  782. data = json.loads(output.get_data(as_text=True))
  783. self.assertEqual(len(data['requests']), 2)
  784. self.assertEqual(
  785. sorted(data.keys()),
  786. [u'args', u'pagination', u'requests', u'total_requests'])
  787. self.assertEqual(data['requests'][0]['user']['name'], "pingou")
  788. self.assertEqual(data['requests'][1]['user']['name'], "pingou")
  789. self.assertEqual(data['requests'][0]['status'], "Merged")
  790. self.assertEqual(data['requests'][1]['status'], "Merged")
  791. self.assertEqual(data['requests'][0]['title'], "merged pullrequest by user pingou on repo test2")
  792. self.assertEqual(data['requests'][1]['title'], "merged pullrequest by user pingou on repo test")
  793. self.assertEqual(data['args']['status'], "merged")
  794. self.assertEqual(data['args']['page'], 1)
  795. # Finally, test with the status parameter set to `all`.
  796. output = self.app.get(
  797. '/api/0/user/pingou/requests/filed?status=all')
  798. self.assertEqual(output.status_code, 200)
  799. data = json.loads(output.get_data(as_text=True))
  800. self.assertEqual(len(data['requests']), 6)
  801. self.assertEqual(
  802. sorted(data.keys()),
  803. [u'args', u'pagination', u'requests', u'total_requests'])
  804. self.assertEqual(data['requests'][0]['user']['name'], "pingou")
  805. self.assertEqual(data['requests'][1]['user']['name'], "pingou")
  806. self.assertEqual(data['requests'][2]['user']['name'], "pingou")
  807. self.assertEqual(data['requests'][3]['user']['name'], "pingou")
  808. self.assertEqual(data['requests'][4]['user']['name'], "pingou")
  809. self.assertEqual(data['requests'][5]['user']['name'], "pingou")
  810. self.assertEqual(data['requests'][0]['status'], "Merged")
  811. self.assertEqual(data['requests'][1]['status'], "Merged")
  812. self.assertEqual(data['requests'][2]['status'], "Closed")
  813. self.assertEqual(data['requests'][3]['status'], "Closed")
  814. self.assertEqual(data['requests'][4]['status'], "Open")
  815. self.assertEqual(data['requests'][5]['status'], "Open")
  816. self.assertEqual(data['requests'][0]['title'], "merged pullrequest by user pingou on repo test2")
  817. self.assertEqual(data['requests'][1]['title'], "merged pullrequest by user pingou on repo test")
  818. self.assertEqual(data['requests'][2]['title'], "closed pullrequest by user pingou on repo test2")
  819. self.assertEqual(data['requests'][3]['title'], "closed pullrequest by user pingou on repo test")
  820. self.assertEqual(data['requests'][4]['title'], "open pullrequest by user pingou on repo test2")
  821. self.assertEqual(data['requests'][5]['title'], "open pullrequest by user pingou on repo test")
  822. self.assertEqual(data['args']['status'], "all")
  823. self.assertEqual(data['args']['page'], 1)
  824. # Test page 2 with the status parameter set to `all`.
  825. output = self.app.get(
  826. '/api/0/user/pingou/requests/filed?status=all&page=2')
  827. self.assertEqual(output.status_code, 200)
  828. data = json.loads(output.get_data(as_text=True))
  829. self.assertEqual(len(data['requests']), 0)
  830. self.assertEqual(
  831. sorted(data.keys()),
  832. [u'args', u'pagination', u'requests', u'total_requests'])
  833. self.assertEqual(data['args']['page'], 2)
  834. @patch('pagure.lib.notify.send_email')
  835. def test_api_view_user_requests_actionable(self, mockemail):
  836. """ Test the api_view_user_requests_actionable method of the flask user
  837. api """
  838. # First we test without the status parameter. It should default to `open`
  839. output = self.app.get(
  840. '/api/0/user/pingou/requests/actionable')
  841. self.assertEqual(output.status_code, 200)
  842. data = json.loads(output.get_data(as_text=True))
  843. self.assertEqual(len(data['requests']), 2)
  844. self.assertEqual(
  845. sorted(data.keys()),
  846. [u'args', u'pagination', u'requests', u'total_requests'])
  847. self.assertEqual(data['requests'][0]['user']['name'], "foo")
  848. self.assertEqual(data['requests'][1]['user']['name'], "foo")
  849. self.assertEqual(data['requests'][0]['status'], "Open")
  850. self.assertEqual(data['requests'][1]['status'], "Open")
  851. self.assertEqual(data['requests'][0]['title'], "open pullrequest by user foo on repo test2")
  852. self.assertEqual(data['requests'][1]['title'], "open pullrequest by user foo on repo test")
  853. self.assertEqual(data['args']['status'], "open")
  854. self.assertEqual(data['args']['page'], 1)
  855. # Next test with the status parameter set to `open`.
  856. output = self.app.get(
  857. '/api/0/user/pingou/requests/actionable?status=open')
  858. self.assertEqual(output.status_code, 200)
  859. data = json.loads(output.get_data(as_text=True))
  860. self.assertEqual(len(data['requests']), 2)
  861. self.assertEqual(
  862. sorted(data.keys()),
  863. [u'args', u'pagination', u'requests', u'total_requests'])
  864. self.assertEqual(data['requests'][0]['user']['name'], "foo")
  865. self.assertEqual(data['requests'][1]['user']['name'], "foo")
  866. self.assertEqual(data['requests'][0]['status'], "Open")
  867. self.assertEqual(data['requests'][1]['status'], "Open")
  868. self.assertEqual(data['requests'][0]['title'], "open pullrequest by user foo on repo test2")
  869. self.assertEqual(data['requests'][1]['title'], "open pullrequest by user foo on repo test")
  870. self.assertEqual(data['args']['status'], "open")
  871. self.assertEqual(data['args']['page'], 1)
  872. # Next test with the status parameter set to `closed`.
  873. output = self.app.get(
  874. '/api/0/user/pingou/requests/actionable?status=closed')
  875. self.assertEqual(output.status_code, 200)
  876. data = json.loads(output.get_data(as_text=True))
  877. self.assertEqual(len(data['requests']), 2)
  878. self.assertEqual(
  879. sorted(data.keys()),
  880. [u'args', u'pagination', u'requests', u'total_requests'])
  881. self.assertEqual(data['requests'][0]['user']['name'], "foo")
  882. self.assertEqual(data['requests'][1]['user']['name'], "foo")
  883. self.assertEqual(data['requests'][0]['status'], "Closed")
  884. self.assertEqual(data['requests'][1]['status'], "Closed")
  885. self.assertEqual(data['requests'][0]['title'], "closed pullrequest by user foo on repo test2")
  886. self.assertEqual(data['requests'][1]['title'], "closed pullrequest by user foo on repo test")
  887. self.assertEqual(data['args']['status'], "closed")
  888. self.assertEqual(data['args']['page'], 1)
  889. # Next test with the status parameter set to `merged`.
  890. output = self.app.get(
  891. '/api/0/user/pingou/requests/actionable?status=merged')
  892. self.assertEqual(output.status_code, 200)
  893. data = json.loads(output.get_data(as_text=True))
  894. self.assertEqual(len(data['requests']), 2)
  895. self.assertEqual(
  896. sorted(data.keys()),
  897. [u'args', u'pagination', u'requests', u'total_requests'])
  898. self.assertEqual(data['requests'][0]['user']['name'], "foo")
  899. self.assertEqual(data['requests'][1]['user']['name'], "foo")
  900. self.assertEqual(data['requests'][0]['status'], "Merged")
  901. self.assertEqual(data['requests'][1]['status'], "Merged")
  902. self.assertEqual(data['requests'][0]['title'], "merged pullrequest by user foo on repo test2")
  903. self.assertEqual(data['requests'][1]['title'], "merged pullrequest by user foo on repo test")
  904. self.assertEqual(data['args']['status'], "merged")
  905. self.assertEqual(data['args']['page'], 1)
  906. # Finally, test with the status parameter set to `all`.
  907. output = self.app.get(
  908. '/api/0/user/pingou/requests/actionable?status=all')
  909. self.assertEqual(output.status_code, 200)
  910. data = json.loads(output.get_data(as_text=True))
  911. self.assertEqual(len(data['requests']), 6)
  912. self.assertEqual(
  913. sorted(data.keys()),
  914. [u'args', u'pagination', u'requests', u'total_requests'])
  915. self.assertEqual(data['requests'][0]['user']['name'], "foo")
  916. self.assertEqual(data['requests'][1]['user']['name'], "foo")
  917. self.assertEqual(data['requests'][2]['user']['name'], "foo")
  918. self.assertEqual(data['requests'][3]['user']['name'], "foo")
  919. self.assertEqual(data['requests'][4]['user']['name'], "foo")
  920. self.assertEqual(data['requests'][5]['user']['name'], "foo")
  921. self.assertEqual(data['requests'][0]['status'], "Merged")
  922. self.assertEqual(data['requests'][1]['status'], "Merged")
  923. self.assertEqual(data['requests'][2]['status'], "Closed")
  924. self.assertEqual(data['requests'][3]['status'], "Closed")
  925. self.assertEqual(data['requests'][4]['status'], "Open")
  926. self.assertEqual(data['requests'][5]['status'], "Open")
  927. self.assertEqual(data['requests'][0]['title'], "merged pullrequest by user foo on repo test2")
  928. self.assertEqual(data['requests'][1]['title'], "merged pullrequest by user foo on repo test")
  929. self.assertEqual(data['requests'][2]['title'], "closed pullrequest by user foo on repo test2")
  930. self.assertEqual(data['requests'][3]['title'], "closed pullrequest by user foo on repo test")
  931. self.assertEqual(data['requests'][4]['title'], "open pullrequest by user foo on repo test2")
  932. self.assertEqual(data['requests'][5]['title'], "open pullrequest by user foo on repo test")
  933. self.assertEqual(data['args']['status'], "all")
  934. self.assertEqual(data['args']['page'], 1)
  935. # Test page 2 with the status parameter set to `all`.
  936. output = self.app.get(
  937. '/api/0/user/pingou/requests/actionable?status=all&page=2')
  938. self.assertEqual(output.status_code, 200)
  939. data = json.loads(output.get_data(as_text=True))
  940. self.assertEqual(len(data['requests']), 0)
  941. self.assertEqual(
  942. sorted(data.keys()),
  943. [u'args', u'pagination', u'requests', u'total_requests'])
  944. self.assertEqual(data['args']['page'], 2)
  945. class PagureFlaskApiUsertestissues(tests.Modeltests):
  946. """ Tests for the user issues endpoints """
  947. maxDiff = None
  948. def setUp(self):
  949. """ Set up the environnment, ran before every tests. """
  950. super(PagureFlaskApiUsertestissues, self).setUp()
  951. pagure.config.config['REQUESTS_FOLDER'] = None
  952. tests.create_projects(self.session)
  953. repo = pagure.lib._get_project(self.session, 'test')
  954. # Create issues to play with
  955. msg = pagure.lib.new_issue(
  956. session=self.session,
  957. repo=repo,
  958. title='Test issue',
  959. content='We should work on this',
  960. user='pingou',
  961. )
  962. self.session.commit()
  963. self.assertEqual(msg.title, 'Test issue')
  964. def test_user_issues_empty(self):
  965. """ Return the list of issues associated with the specified user. """
  966. output = self.app.get('/api/0/user/foo/issues')
  967. self.assertEqual(output.status_code, 200)
  968. data = json.loads(output.get_data(as_text=True))
  969. for k in ['pagination_issues_assigned', 'pagination_issues_created']:
  970. for k2 in ['first', 'last']:
  971. self.assertIsNotNone(data[k][k2])
  972. data[k][k2] = None
  973. self.assertEqual(
  974. data,
  975. {
  976. "args": {
  977. "assignee": True,
  978. "author": True,
  979. "milestones": [],
  980. "no_stones": None,
  981. "order": None,
  982. "order_key": None,
  983. "page": 1,
  984. "since": None,
  985. "status": None,
  986. "tags": []
  987. },
  988. "issues_assigned": [],
  989. "issues_created": [],
  990. 'pagination_issues_assigned': {
  991. 'first': None,
  992. 'last': None,
  993. 'next': None,
  994. 'page': 1,
  995. 'pages': 0,
  996. 'per_page': 20,
  997. 'prev': None},
  998. 'pagination_issues_created': {
  999. 'first': None,
  1000. 'last': None,
  1001. 'next': None,
  1002. 'page': 1,
  1003. 'pages': 0,
  1004. 'per_page': 20,
  1005. 'prev': None},
  1006. "total_issues_assigned": 0,
  1007. "total_issues_assigned_pages": 1,
  1008. "total_issues_created": 0,
  1009. "total_issues_created_pages": 1
  1010. }
  1011. )
  1012. def test_user_issues(self):
  1013. """ Return the list of issues associated with the specified user. """
  1014. output = self.app.get('/api/0/user/pingou/issues')
  1015. self.assertEqual(output.status_code, 200)
  1016. data = json.loads(output.get_data(as_text=True))
  1017. issues = []
  1018. for issue in data['issues_created']:
  1019. issue['date_created'] = '1513111778'
  1020. issue['last_updated'] = '1513111778'
  1021. issue['project']['date_created'] = '1513111778'
  1022. issue['project']['date_modified'] = '1513111778'
  1023. issues.append(issue)
  1024. data['issues_created'] = issues
  1025. for k in ['pagination_issues_assigned', 'pagination_issues_created']:
  1026. for k2 in ['first', 'last']:
  1027. self.assertIsNotNone(data[k][k2])
  1028. data[k][k2] = None
  1029. self.assertEqual(
  1030. data,
  1031. {
  1032. "args": {
  1033. "assignee": True,
  1034. "author": True,
  1035. "milestones": [],
  1036. "no_stones": None,
  1037. "order": None,
  1038. "order_key": None,
  1039. "page": 1,
  1040. "since": None,
  1041. "status": None,
  1042. "tags": []
  1043. },
  1044. "issues_assigned": [],
  1045. "issues_created": [
  1046. {
  1047. "assignee": None,
  1048. "blocks": [],
  1049. "close_status": None,
  1050. "closed_at": None,
  1051. "comments": [],
  1052. "content": "We should work on this",
  1053. "custom_fields": [],
  1054. "date_created": "1513111778",
  1055. "depends": [],
  1056. "id": 1,
  1057. "last_updated": "1513111778",
  1058. "milestone": None,
  1059. "priority": None,
  1060. "private": False,
  1061. "project": {
  1062. "access_groups": {
  1063. "admin": [],
  1064. "commit": [],
  1065. "ticket": []
  1066. },
  1067. "access_users": {
  1068. "admin": [],
  1069. "commit": [],
  1070. "owner": [
  1071. "pingou"
  1072. ],
  1073. "ticket": []
  1074. },
  1075. "close_status": [
  1076. "Invalid",
  1077. "Insufficient data",
  1078. "Fixed",
  1079. "Duplicate"
  1080. ],
  1081. "custom_keys": [],
  1082. "date_created": "1513111778",
  1083. "date_modified": "1513111778",
  1084. "description": "test project #1",
  1085. "fullname": "test",
  1086. "id": 1,
  1087. "milestones": {},
  1088. "name": "test",
  1089. "namespace": None,
  1090. "parent": None,
  1091. "priorities": {},
  1092. "tags": [],
  1093. "url_path": "test",
  1094. "user": {
  1095. "fullname": "PY C",
  1096. "name": "pingou"
  1097. }
  1098. },
  1099. "status": "Open",
  1100. "tags": [],
  1101. "title": "Test issue",
  1102. "user": {
  1103. "fullname": "PY C",
  1104. "name": "pingou"
  1105. }
  1106. }
  1107. ],
  1108. 'pagination_issues_assigned': {
  1109. 'first': None,
  1110. 'last': None,
  1111. 'next': None,
  1112. 'page': 1,
  1113. 'pages': 0,
  1114. 'per_page': 20,
  1115. 'prev': None},
  1116. 'pagination_issues_created': {
  1117. 'first': None,
  1118. 'last': None,
  1119. 'next': None,
  1120. 'page': 1,
  1121. 'pages': 1,
  1122. 'per_page': 20,
  1123. 'prev': None},
  1124. "total_issues_assigned": 0,
  1125. "total_issues_assigned_pages": 1,
  1126. "total_issues_created": 1,
  1127. "total_issues_created_pages": 1
  1128. }
  1129. )
  1130. if __name__ == '__main__':
  1131. unittest.main(verbosity=2)