test_pagure_flask_api_user.py 73 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927
  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, absolute_import
  8. import datetime
  9. import os
  10. import pytz
  11. import shutil
  12. import sys
  13. import unittest
  14. import json
  15. from mock import patch
  16. sys.path.insert(
  17. 0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")
  18. )
  19. import pagure.api
  20. import pagure.config
  21. import pagure.lib.model as model
  22. import pagure.lib.query
  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(
  38. sorted(data.keys()), ["mention", "total_users", "users"]
  39. )
  40. self.assertEqual(data["total_users"], 2)
  41. output = self.app.get("/api/0/users?pattern=p")
  42. self.assertEqual(output.status_code, 200)
  43. data = json.loads(output.get_data(as_text=True))
  44. self.assertEqual(data["users"], ["pingou"])
  45. self.assertEqual(
  46. sorted(data.keys()), ["mention", "total_users", "users"]
  47. )
  48. self.assertEqual(data["total_users"], 1)
  49. def test_api_view_user(self):
  50. """
  51. Test the api_view_user method of the flask api
  52. The tested user has no project or forks.
  53. """
  54. output = self.app.get("/api/0/user/pingou")
  55. self.assertEqual(output.status_code, 200)
  56. exp = {
  57. "forks": [],
  58. "forks_pagination": {
  59. "first": "http://localhost...",
  60. "last": "http://localhost...",
  61. "next": None,
  62. "forkpage": 1,
  63. "pages": 0,
  64. "per_page": 20,
  65. "prev": None,
  66. },
  67. "repos": [],
  68. "repos_pagination": {
  69. "first": "http://localhost...",
  70. "last": "http://localhost...",
  71. "next": None,
  72. "repopage": 1,
  73. "pages": 0,
  74. "per_page": 20,
  75. "prev": None,
  76. },
  77. "user": {
  78. "fullname": "PY C",
  79. "name": "pingou",
  80. "url_path": "user/pingou",
  81. "full_url": "http://localhost.localdomain/user/pingou",
  82. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  83. },
  84. }
  85. data = json.loads(output.get_data(as_text=True))
  86. data["user"]["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  87. for k in ["forks_pagination", "repos_pagination"]:
  88. for k2 in ["first", "last"]:
  89. self.assertIsNotNone(data[k][k2])
  90. data[k][k2] = "http://localhost..."
  91. self.assertEqual(data, exp)
  92. def test_api_view_user_with_project(self):
  93. """
  94. Test the api_view_user method of the flask api,
  95. this time the user has some project defined.
  96. """
  97. tests.create_projects(self.session)
  98. output = self.app.get("/api/0/user/pingou")
  99. self.assertEqual(output.status_code, 200)
  100. data = json.loads(output.get_data(as_text=True))
  101. data["repos"][0]["date_created"] = "1490272832"
  102. data["repos"][0]["date_modified"] = "1490272832"
  103. data["repos"][1]["date_created"] = "1490272832"
  104. data["repos"][1]["date_modified"] = "1490272832"
  105. data["repos"][2]["date_created"] = "1490272832"
  106. data["repos"][2]["date_modified"] = "1490272832"
  107. for k in ["forks_pagination", "repos_pagination"]:
  108. for k2 in ["first", "last"]:
  109. self.assertIsNotNone(data[k][k2])
  110. data[k][k2] = "http://localhost..."
  111. expected_data = {
  112. "forks": [],
  113. "forks_pagination": {
  114. "first": "http://localhost...",
  115. "last": "http://localhost...",
  116. "next": None,
  117. "forkpage": 1,
  118. "pages": 0,
  119. "per_page": 20,
  120. "prev": None,
  121. },
  122. "repos": [
  123. {
  124. "access_groups": {
  125. "admin": [],
  126. "collaborator": [],
  127. "commit": [],
  128. "ticket": [],
  129. },
  130. "access_users": {
  131. "admin": [],
  132. "collaborator": [],
  133. "commit": [],
  134. "owner": ["pingou"],
  135. "ticket": [],
  136. },
  137. "close_status": [
  138. "Invalid",
  139. "Insufficient data",
  140. "Fixed",
  141. "Duplicate",
  142. ],
  143. "custom_keys": [],
  144. "date_created": "1490272832",
  145. "date_modified": "1490272832",
  146. "description": "test project #1",
  147. "fullname": "test",
  148. "url_path": "test",
  149. "full_url": "http://localhost.localdomain/test",
  150. "id": 1,
  151. "milestones": {},
  152. "name": "test",
  153. "namespace": None,
  154. "parent": None,
  155. "priorities": {},
  156. "tags": [],
  157. "user": {
  158. "fullname": "PY C",
  159. "name": "pingou",
  160. "url_path": "user/pingou",
  161. "full_url": "http://localhost.localdomain/user/pingou",
  162. },
  163. },
  164. {
  165. "access_groups": {
  166. "admin": [],
  167. "collaborator": [],
  168. "commit": [],
  169. "ticket": [],
  170. },
  171. "access_users": {
  172. "admin": [],
  173. "collaborator": [],
  174. "commit": [],
  175. "owner": ["pingou"],
  176. "ticket": [],
  177. },
  178. "close_status": [
  179. "Invalid",
  180. "Insufficient data",
  181. "Fixed",
  182. "Duplicate",
  183. ],
  184. "custom_keys": [],
  185. "date_created": "1490272832",
  186. "date_modified": "1490272832",
  187. "description": "test project #2",
  188. "full_url": "http://localhost.localdomain/test2",
  189. "fullname": "test2",
  190. "url_path": "test2",
  191. "id": 2,
  192. "milestones": {},
  193. "name": "test2",
  194. "namespace": None,
  195. "parent": None,
  196. "priorities": {},
  197. "tags": [],
  198. "user": {
  199. "fullname": "PY C",
  200. "name": "pingou",
  201. "url_path": "user/pingou",
  202. "full_url": "http://localhost.localdomain/user/pingou",
  203. },
  204. },
  205. {
  206. "access_groups": {
  207. "admin": [],
  208. "collaborator": [],
  209. "commit": [],
  210. "ticket": [],
  211. },
  212. "access_users": {
  213. "admin": [],
  214. "collaborator": [],
  215. "commit": [],
  216. "owner": ["pingou"],
  217. "ticket": [],
  218. },
  219. "close_status": [
  220. "Invalid",
  221. "Insufficient data",
  222. "Fixed",
  223. "Duplicate",
  224. ],
  225. "custom_keys": [],
  226. "date_created": "1490272832",
  227. "date_modified": "1490272832",
  228. "description": "namespaced test project",
  229. "fullname": "somenamespace/test3",
  230. "url_path": "somenamespace/test3",
  231. "full_url": "http://localhost.localdomain/somenamespace/test3",
  232. "id": 3,
  233. "milestones": {},
  234. "name": "test3",
  235. "namespace": "somenamespace",
  236. "parent": None,
  237. "priorities": {},
  238. "tags": [],
  239. "user": {
  240. "fullname": "PY C",
  241. "full_url": "http://localhost.localdomain/user/pingou",
  242. "name": "pingou",
  243. "url_path": "user/pingou",
  244. },
  245. },
  246. ],
  247. "repos_pagination": {
  248. "first": "http://localhost...",
  249. "last": "http://localhost...",
  250. "next": None,
  251. "repopage": 1,
  252. "pages": 1,
  253. "per_page": 20,
  254. "prev": None,
  255. },
  256. "user": {
  257. "fullname": "PY C",
  258. "name": "pingou",
  259. "url_path": "user/pingou",
  260. "full_url": "http://localhost.localdomain/user/pingou",
  261. "avatar_url": "https://seccdn.libravatar.org/avatar/...",
  262. },
  263. }
  264. data["user"]["avatar_url"] = "https://seccdn.libravatar.org/avatar/..."
  265. self.assertEqual(data, expected_data)
  266. @patch("pagure.lib.notify.send_email")
  267. def test_api_view_user_activity_stats(self, mockemail):
  268. """Test the api_view_user_activity_stats method of the flask user
  269. api."""
  270. mockemail.return_value = True
  271. tests.create_projects(self.session)
  272. tests.create_tokens(self.session)
  273. tests.create_tokens_acl(self.session)
  274. headers = {"Authorization": "token aaabbbcccddd"}
  275. # Create a pull-request
  276. repo = pagure.lib.query._get_project(self.session, "test")
  277. forked_repo = pagure.lib.query._get_project(self.session, "test")
  278. req = pagure.lib.query.new_pull_request(
  279. session=self.session,
  280. repo_from=forked_repo,
  281. branch_from="master",
  282. repo_to=repo,
  283. branch_to="master",
  284. title="test pull-request",
  285. user="pingou",
  286. )
  287. self.session.commit()
  288. self.assertEqual(req.id, 1)
  289. self.assertEqual(req.title, "test pull-request")
  290. # Check comments before
  291. self.session.commit()
  292. request = pagure.lib.query.search_pull_requests(
  293. self.session, project_id=1, requestid=1
  294. )
  295. self.assertEqual(len(request.comments), 0)
  296. data = {"comment": "This is a very interesting question"}
  297. # Valid request
  298. output = self.app.post(
  299. "/api/0/test/pull-request/1/comment", data=data, headers=headers
  300. )
  301. self.assertEqual(output.status_code, 200)
  302. data = json.loads(output.get_data(as_text=True))
  303. self.assertDictEqual(data, {"message": "Comment added"})
  304. # One comment added
  305. self.session.commit()
  306. request = pagure.lib.query.search_pull_requests(
  307. self.session, project_id=1, requestid=1
  308. )
  309. self.assertEqual(len(request.comments), 1)
  310. # Close PR
  311. output = self.app.post(
  312. "/api/0/test/pull-request/1/close", headers=headers
  313. )
  314. self.assertEqual(output.status_code, 200)
  315. data = json.loads(output.get_data(as_text=True))
  316. self.assertDictEqual(data, {"message": "Pull-request closed!"})
  317. # PR closed
  318. self.session.commit()
  319. request = pagure.lib.query.search_pull_requests(
  320. self.session, project_id=1, requestid=1
  321. )
  322. self.assertEqual(request.status, "Closed")
  323. # Finally retrieve the user's logs
  324. output = self.app.get("/api/0/user/pingou/activity/stats")
  325. self.assertEqual(output.status_code, 200)
  326. data = json.loads(output.get_data(as_text=True))
  327. date = datetime.datetime.utcnow().date().strftime("%Y-%m-%d")
  328. self.assertDictEqual(data, {date: 4})
  329. @patch("pagure.lib.notify.send_email")
  330. def test_api_view_user_activity_date(self, mockemail):
  331. """Test the api_view_user_activity_date method of the flask user
  332. api."""
  333. self.test_api_view_user_activity_stats()
  334. # Invalid date
  335. output = self.app.get("/api/0/user/pingou/activity/AABB")
  336. self.assertEqual(output.status_code, 400)
  337. # Invalid date, arrow >= 0.15 throws an exception,
  338. # previous versions parsed it
  339. output = self.app.get("/api/0/user/pingou/activity/2016asd")
  340. arrow_version = self.get_arrow_version()
  341. if arrow_version >= (0, 15, 6):
  342. self.assertEqual(output.status_code, 400)
  343. exp = {
  344. "error": "Could not match input '2016asd' to any of the following formats: "
  345. "YYYY-MM-DD, YYYY-M-DD, YYYY-M-D, YYYY/MM/DD, YYYY/M/DD, YYYY/M/D, "
  346. "YYYY.MM.DD, YYYY.M.DD, YYYY.M.D, YYYYMMDD, YYYY-DDDD, YYYYDDDD, "
  347. "YYYY-MM, YYYY/MM, YYYY.MM, YYYY, W",
  348. "error_code": "ENOCODE",
  349. }
  350. self.assertEqual(json.loads(output.get_data(as_text=True)), exp)
  351. elif arrow_version >= (0, 15):
  352. self.assertEqual(output.status_code, 400)
  353. exp = {
  354. "error": "Could not match input '2016asd' to any of the following formats: "
  355. "YYYY-MM-DD, YYYY-M-DD, YYYY-M-D, YYYY/MM/DD, YYYY/M/DD, YYYY/M/D, "
  356. "YYYY.MM.DD, YYYY.M.DD, YYYY.M.D, YYYYMMDD, YYYY-DDDD, YYYYDDDD, "
  357. "YYYY-MM, YYYY/MM, YYYY.MM, YYYY",
  358. "error_code": "ENOCODE",
  359. }
  360. self.assertEqual(json.loads(output.get_data(as_text=True)), exp)
  361. else:
  362. self.assertEqual(output.status_code, 200)
  363. exp = {"activities": [], "date": "2016-01-01"}
  364. self.assertEqual(json.loads(output.get_data(as_text=True)), exp)
  365. # Invalid date, arrow => throws an exception,
  366. # previous versions parsed it just not really as expected
  367. output = self.app.get("/api/0/user/pingou/activity/20161245")
  368. if self.get_arrow_version() >= (0, 15):
  369. self.assertEqual(output.status_code, 400)
  370. exp = {
  371. "error": "day is out of range for month",
  372. "error_code": "ENOCODE",
  373. }
  374. self.assertEqual(json.loads(output.get_data(as_text=True)), exp)
  375. else:
  376. self.assertEqual(output.status_code, 200)
  377. exp = {"activities": [], "date": "1970-08-22"}
  378. self.assertEqual(json.loads(output.get_data(as_text=True)), exp)
  379. date = datetime.datetime.utcnow().date().strftime("%Y-%m-%d")
  380. # Retrieve the user's logs for today
  381. output = self.app.get("/api/0/user/pingou/activity/%s" % date)
  382. self.assertEqual(output.status_code, 200)
  383. data = json.loads(output.get_data(as_text=True))
  384. exp = {
  385. "activities": [
  386. {
  387. "date": date,
  388. "date_created": "1477558752",
  389. "type": "pull-request",
  390. "description_mk": '<div class="markdown"><p>pingou created PR <a href="/test/pull-request/1" title="[Closed] test pull-request">test#1</a></p></div>',
  391. "id": 1,
  392. "ref_id": "1",
  393. "type": "created",
  394. "user": {
  395. "fullname": "PY C",
  396. "full_url": "http://localhost.localdomain/user/pingou",
  397. "name": "pingou",
  398. "url_path": "user/pingou",
  399. },
  400. },
  401. {
  402. "date": date,
  403. "date_created": "1477558752",
  404. "type": "pull-request",
  405. "description_mk": '<div class="markdown"><p>pingou commented on PR <a href="/test/pull-request/1" title="[Closed] test pull-request">test#1</a></p></div>',
  406. "id": 2,
  407. "ref_id": "1",
  408. "type": "commented",
  409. "user": {
  410. "fullname": "PY C",
  411. "full_url": "http://localhost.localdomain/user/pingou",
  412. "name": "pingou",
  413. "url_path": "user/pingou",
  414. },
  415. },
  416. {
  417. "date": date,
  418. "date_created": "1477558752",
  419. "type": "pull-request",
  420. "description_mk": '<div class="markdown"><p>pingou closed PR <a href="/test/pull-request/1" title="[Closed] test pull-request">test#1</a></p></div>',
  421. "id": 3,
  422. "ref_id": "1",
  423. "type": "closed",
  424. "user": {
  425. "fullname": "PY C",
  426. "full_url": "http://localhost.localdomain/user/pingou",
  427. "name": "pingou",
  428. "url_path": "user/pingou",
  429. },
  430. },
  431. {
  432. "date": date,
  433. "date_created": "1477558752",
  434. "type": "pull-request",
  435. "description_mk": '<div class="markdown"><p>pingou commented on PR <a href="/test/pull-request/1" title="[Closed] test pull-request">test#1</a></p></div>',
  436. "id": 4,
  437. "ref_id": "1",
  438. "type": "commented",
  439. "user": {
  440. "fullname": "PY C",
  441. "full_url": "http://localhost.localdomain/user/pingou",
  442. "name": "pingou",
  443. "url_path": "user/pingou",
  444. },
  445. },
  446. ],
  447. "date": date,
  448. }
  449. for idx, act in enumerate(data["activities"]):
  450. act["date_created"] = "1477558752"
  451. data["activities"][idx] = act
  452. self.assertEqual(data, exp)
  453. @patch("pagure.lib.notify.send_email")
  454. def test_api_view_user_activity_date_1_activity(self, mockemail):
  455. """Test the api_view_user_activity_date method of the flask user
  456. api when the user only did one action."""
  457. tests.create_projects(self.session)
  458. repo = pagure.lib.query._get_project(self.session, "test")
  459. now = datetime.datetime.utcnow()
  460. date = now.date().strftime("%Y-%m-%d")
  461. # Create a single commit log
  462. log = model.PagureLog(
  463. user_id=1,
  464. user_email="foo@bar.com",
  465. project_id=1,
  466. log_type="committed",
  467. ref_id="githash",
  468. date=now.date(),
  469. date_created=now,
  470. )
  471. self.session.add(log)
  472. self.session.commit()
  473. # Retrieve the user's logs for today
  474. output = self.app.get(
  475. "/api/0/user/pingou/activity/%s?grouped=1" % date
  476. )
  477. self.assertEqual(output.status_code, 200)
  478. data = json.loads(output.get_data(as_text=True))
  479. exp = {
  480. "activities": [
  481. {
  482. "description_mk": '<div class="markdown"><p>pingou committed on test#githash</p></div>'
  483. }
  484. ],
  485. "date": date,
  486. }
  487. self.assertEqual(data, exp)
  488. @patch("pagure.lib.notify.send_email")
  489. def test_api_view_user_activity_timezone_negative(self, mockemail):
  490. """Test api_view_user_activity{_stats,_date} with the America/
  491. New York timezone, which is 5 hours behind UTC in winter and
  492. 4 hours behind UTC in summer (daylight savings). The events
  493. will occur on XXXX-02-15 in UTC, but on XXXX-02-14 local.
  494. """
  495. tests.create_projects(self.session)
  496. today = datetime.datetime.utcnow()
  497. # stats/activty returns data for now()-1year time range, so alter
  498. # year as needed to select 15th feb of current or previous year
  499. if today < datetime.datetime(today.year, 2, 15, 3, 30):
  500. year = today.year - 1
  501. else:
  502. year = today.year
  503. dateobj = datetime.datetime(year, 2, 15, 3, 30)
  504. utcdate = "%s-02-15" % year
  505. # the Unix timestamp for YYYY-02-15 12:00 UTC
  506. utcts = str(
  507. int(
  508. (
  509. datetime.datetime(year, 2, 15, 12, 0, tzinfo=pytz.UTC)
  510. - datetime.datetime(1970, 1, 1, tzinfo=pytz.UTC)
  511. ).total_seconds()
  512. )
  513. )
  514. localdate = "%s-02-14" % year
  515. # the Unix timestamp for YYYY-02-15 18:00 America/New_York
  516. localts = str(
  517. int(
  518. (
  519. datetime.datetime(
  520. year,
  521. 2,
  522. 14,
  523. 17,
  524. 0,
  525. tzinfo=pytz.timezone("America/New_York"),
  526. )
  527. - datetime.datetime(
  528. 1970, 1, 1, tzinfo=pytz.timezone("America/New_York")
  529. )
  530. ).total_seconds()
  531. )
  532. )
  533. # Create a single commit log
  534. log = model.PagureLog(
  535. user_id=1,
  536. user_email="foo@bar.com",
  537. project_id=1,
  538. log_type="committed",
  539. ref_id="githash",
  540. date=dateobj.date(),
  541. date_created=dateobj,
  542. )
  543. self.session.add(log)
  544. self.session.commit()
  545. # Retrieve the user's stats with no timezone specified (==UTC)
  546. output = self.app.get("/api/0/user/pingou/activity/stats")
  547. self.assertEqual(output.status_code, 200)
  548. data = json.loads(output.get_data(as_text=True))
  549. # date in output should be UTC date
  550. self.assertDictEqual(data, {utcdate: 1})
  551. # Now in timestamp format...
  552. output = self.app.get(
  553. "/api/0/user/pingou/activity/stats?format=timestamp"
  554. )
  555. self.assertEqual(output.status_code, 200)
  556. data = json.loads(output.get_data(as_text=True))
  557. # timestamp in output should be UTC ts
  558. self.assertDictEqual(data, {utcts: 1})
  559. # Retrieve the user's stats with local timezone specified
  560. output = self.app.get(
  561. "/api/0/user/pingou/activity/stats?tz=America/New_York"
  562. )
  563. self.assertEqual(output.status_code, 200)
  564. data = json.loads(output.get_data(as_text=True))
  565. # date in output should be local date
  566. self.assertDictEqual(data, {localdate: 1})
  567. # Now in timestamp format...
  568. output = self.app.get(
  569. "/api/0/user/pingou/activity/stats?format=timestamp&tz=America/New_York"
  570. )
  571. self.assertEqual(output.status_code, 200)
  572. data = json.loads(output.get_data(as_text=True))
  573. # timestamp in output should be local ts
  574. self.assertDictEqual(data, {localts: 1})
  575. # Retrieve the user's logs for 2018-02-15 with no timezone
  576. output = self.app.get(
  577. "/api/0/user/pingou/activity/%s?grouped=1" % utcdate
  578. )
  579. self.assertEqual(output.status_code, 200)
  580. data = json.loads(output.get_data(as_text=True))
  581. exp = {
  582. "activities": [
  583. {
  584. "description_mk": '<div class="markdown"><p>pingou committed on test#githash</p></div>'
  585. }
  586. ],
  587. "date": utcdate,
  588. }
  589. self.assertEqual(data, exp)
  590. # Now retrieve the user's logs for 2018-02-14 with local time
  591. output = self.app.get(
  592. "/api/0/user/pingou/activity/%s?grouped=1&tz=America/New_York"
  593. % localdate
  594. )
  595. self.assertEqual(output.status_code, 200)
  596. data = json.loads(output.get_data(as_text=True))
  597. exp["date"] = localdate
  598. self.assertEqual(data, exp)
  599. @patch("pagure.lib.notify.send_email")
  600. def test_api_view_user_activity_timezone_positive(self, mockemail):
  601. """Test api_view_user_activity{_stats,_date} with the Asia/
  602. Dubai timezone, which is 4 hours ahead of UTC. The events will
  603. occur on XXXX-02-15 in UTC, but on XXXX-02-16 in local time.
  604. """
  605. tests.create_projects(self.session)
  606. today = datetime.datetime.utcnow()
  607. # stats/activty returns data for now()-1year time range, so alter
  608. # year as needed to select 15th feb of current or previous year
  609. if today < datetime.datetime(today.year, 2, 15, 3, 30):
  610. year = today.year - 1
  611. else:
  612. year = today.year
  613. dateobj = datetime.datetime(year, 2, 15, 22, 30)
  614. utcdate = "%s-02-15" % year
  615. # the Unix timestamp for YYYY-02-15 12:00 UTC
  616. utcts = str(
  617. int(
  618. (
  619. datetime.datetime(year, 2, 15, 12, 0, tzinfo=pytz.UTC)
  620. - datetime.datetime(1970, 1, 1, tzinfo=pytz.UTC)
  621. ).total_seconds()
  622. )
  623. )
  624. localdate = "%s-02-16" % year
  625. # the Unix timestamp for YYYY-02-16 9:00 Asia/Dubai
  626. localts = str(
  627. int(
  628. (
  629. datetime.datetime(
  630. year, 2, 16, 8, 0, tzinfo=pytz.timezone("Asia/Dubai")
  631. )
  632. - datetime.datetime(
  633. 1970, 1, 1, tzinfo=pytz.timezone("Asia/Dubai")
  634. )
  635. ).total_seconds()
  636. )
  637. )
  638. # Create a single commit log
  639. log = model.PagureLog(
  640. user_id=1,
  641. user_email="foo@bar.com",
  642. project_id=1,
  643. log_type="committed",
  644. ref_id="githash",
  645. date=dateobj.date(),
  646. date_created=dateobj,
  647. )
  648. self.session.add(log)
  649. self.session.commit()
  650. # Retrieve the user's stats with no timezone specified (==UTC)
  651. output = self.app.get("/api/0/user/pingou/activity/stats")
  652. self.assertEqual(output.status_code, 200)
  653. data = json.loads(output.get_data(as_text=True))
  654. # date in output should be UTC date
  655. self.assertDictEqual(data, {utcdate: 1})
  656. # Now in timestamp format...
  657. output = self.app.get(
  658. "/api/0/user/pingou/activity/stats?format=timestamp"
  659. )
  660. self.assertEqual(output.status_code, 200)
  661. data = json.loads(output.get_data(as_text=True))
  662. # timestamp in output should be UTC ts
  663. self.assertDictEqual(data, {utcts: 1})
  664. # Retrieve the user's stats with local timezone specified
  665. output = self.app.get(
  666. "/api/0/user/pingou/activity/stats?tz=Asia/Dubai"
  667. )
  668. self.assertEqual(output.status_code, 200)
  669. data = json.loads(output.get_data(as_text=True))
  670. # date in output should be local date
  671. self.assertDictEqual(data, {localdate: 1})
  672. # Now in timestamp format...
  673. output = self.app.get(
  674. "/api/0/user/pingou/activity/stats?format=timestamp&tz=Asia/Dubai"
  675. )
  676. self.assertEqual(output.status_code, 200)
  677. data = json.loads(output.get_data(as_text=True))
  678. # timestamp in output should be local ts
  679. self.assertDictEqual(data, {localts: 1})
  680. # Retrieve the user's logs for 2018-02-15 with no timezone
  681. output = self.app.get(
  682. "/api/0/user/pingou/activity/%s?grouped=1" % utcdate
  683. )
  684. self.assertEqual(output.status_code, 200)
  685. data = json.loads(output.get_data(as_text=True))
  686. exp = {
  687. "activities": [
  688. {
  689. "description_mk": '<div class="markdown"><p>pingou committed on test#githash</p></div>'
  690. }
  691. ],
  692. "date": utcdate,
  693. }
  694. self.assertEqual(data, exp)
  695. # Now retrieve the user's logs for 2018-02-16 with local time
  696. output = self.app.get(
  697. "/api/0/user/pingou/activity/%s?grouped=1&tz=Asia/Dubai"
  698. % localdate
  699. )
  700. self.assertEqual(output.status_code, 200)
  701. data = json.loads(output.get_data(as_text=True))
  702. exp["date"] = localdate
  703. self.assertEqual(data, exp)
  704. class PagureFlaskApiUsertestrequests(tests.Modeltests):
  705. """ Tests for the user requests endpoints """
  706. maxDiff = None
  707. def setUp(self):
  708. """ Set up the environnment, ran before every tests. """
  709. super(PagureFlaskApiUsertestrequests, self).setUp()
  710. pagure.config.config["REQUESTS_FOLDER"] = None
  711. tests.create_projects(self.session)
  712. # Create few pull-requests
  713. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  714. forked_repo = pagure.lib.query.get_authorized_project(
  715. self.session, "test"
  716. )
  717. pagure.lib.query.new_pull_request(
  718. session=self.session,
  719. repo_from=forked_repo,
  720. branch_from="master",
  721. repo_to=repo,
  722. branch_to="master",
  723. title="open pullrequest by user foo on repo test",
  724. user="foo",
  725. )
  726. repo = pagure.lib.query.get_authorized_project(self.session, "test2")
  727. forked_repo = pagure.lib.query.get_authorized_project(
  728. self.session, "test2"
  729. )
  730. pagure.lib.query.new_pull_request(
  731. session=self.session,
  732. repo_from=forked_repo,
  733. branch_from="master",
  734. repo_to=repo,
  735. branch_to="master",
  736. title="open pullrequest by user foo on repo test2",
  737. user="foo",
  738. )
  739. self.session.commit()
  740. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  741. forked_repo = pagure.lib.query.get_authorized_project(
  742. self.session, "test"
  743. )
  744. pagure.lib.query.new_pull_request(
  745. session=self.session,
  746. repo_from=forked_repo,
  747. branch_from="master",
  748. repo_to=repo,
  749. branch_to="master",
  750. title="closed pullrequest by user foo on repo test",
  751. user="foo",
  752. status="Closed",
  753. )
  754. repo = pagure.lib.query.get_authorized_project(self.session, "test2")
  755. forked_repo = pagure.lib.query.get_authorized_project(
  756. self.session, "test2"
  757. )
  758. pagure.lib.query.new_pull_request(
  759. session=self.session,
  760. repo_from=forked_repo,
  761. branch_from="master",
  762. repo_to=repo,
  763. branch_to="master",
  764. title="closed pullrequest by user foo on repo test2",
  765. user="foo",
  766. status="Closed",
  767. )
  768. self.session.commit()
  769. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  770. forked_repo = pagure.lib.query.get_authorized_project(
  771. self.session, "test"
  772. )
  773. pagure.lib.query.new_pull_request(
  774. session=self.session,
  775. repo_from=forked_repo,
  776. branch_from="master",
  777. repo_to=repo,
  778. branch_to="master",
  779. title="merged pullrequest by user foo on repo test",
  780. user="foo",
  781. status="Merged",
  782. )
  783. repo = pagure.lib.query.get_authorized_project(self.session, "test2")
  784. forked_repo = pagure.lib.query.get_authorized_project(
  785. self.session, "test2"
  786. )
  787. pagure.lib.query.new_pull_request(
  788. session=self.session,
  789. repo_from=forked_repo,
  790. branch_from="master",
  791. repo_to=repo,
  792. branch_to="master",
  793. title="merged pullrequest by user foo on repo test2",
  794. user="foo",
  795. status="Merged",
  796. )
  797. self.session.commit()
  798. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  799. forked_repo = pagure.lib.query.get_authorized_project(
  800. self.session, "test"
  801. )
  802. pagure.lib.query.new_pull_request(
  803. session=self.session,
  804. repo_from=forked_repo,
  805. branch_from="master",
  806. repo_to=repo,
  807. branch_to="master",
  808. title="open pullrequest by user pingou on repo test",
  809. user="pingou",
  810. )
  811. self.session.commit()
  812. repo = pagure.lib.query.get_authorized_project(self.session, "test2")
  813. forked_repo = pagure.lib.query.get_authorized_project(
  814. self.session, "test2"
  815. )
  816. pagure.lib.query.new_pull_request(
  817. session=self.session,
  818. repo_from=forked_repo,
  819. branch_from="master",
  820. repo_to=repo,
  821. branch_to="master",
  822. title="open pullrequest by user pingou on repo test2",
  823. user="pingou",
  824. )
  825. self.session.commit()
  826. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  827. forked_repo = pagure.lib.query.get_authorized_project(
  828. self.session, "test"
  829. )
  830. pagure.lib.query.new_pull_request(
  831. session=self.session,
  832. repo_from=forked_repo,
  833. branch_from="master",
  834. repo_to=repo,
  835. branch_to="master",
  836. title="closed pullrequest by user pingou on repo test",
  837. user="pingou",
  838. status="Closed",
  839. )
  840. self.session.commit()
  841. repo = pagure.lib.query.get_authorized_project(self.session, "test2")
  842. forked_repo = pagure.lib.query.get_authorized_project(
  843. self.session, "test2"
  844. )
  845. pagure.lib.query.new_pull_request(
  846. session=self.session,
  847. repo_from=forked_repo,
  848. branch_from="master",
  849. repo_to=repo,
  850. branch_to="master",
  851. title="closed pullrequest by user pingou on repo test2",
  852. user="pingou",
  853. status="Closed",
  854. )
  855. self.session.commit()
  856. repo = pagure.lib.query.get_authorized_project(self.session, "test")
  857. forked_repo = pagure.lib.query.get_authorized_project(
  858. self.session, "test"
  859. )
  860. pagure.lib.query.new_pull_request(
  861. session=self.session,
  862. repo_from=forked_repo,
  863. branch_from="master",
  864. repo_to=repo,
  865. branch_to="master",
  866. title="merged pullrequest by user pingou on repo test",
  867. user="pingou",
  868. status="Merged",
  869. )
  870. self.session.commit()
  871. repo = pagure.lib.query.get_authorized_project(self.session, "test2")
  872. forked_repo = pagure.lib.query.get_authorized_project(
  873. self.session, "test2"
  874. )
  875. pagure.lib.query.new_pull_request(
  876. session=self.session,
  877. repo_from=forked_repo,
  878. branch_from="master",
  879. repo_to=repo,
  880. branch_to="master",
  881. title="merged pullrequest by user pingou on repo test2",
  882. user="pingou",
  883. status="Merged",
  884. )
  885. self.session.commit()
  886. @patch("pagure.lib.notify.send_email")
  887. def test_api_view_user_requests_filed(self, mockemail):
  888. """Test the api_view_user_requests_filed method of the flask user
  889. api"""
  890. # First we test without the status parameter. It should default to `open`
  891. output = self.app.get("/api/0/user/pingou/requests/filed")
  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. ["args", "pagination", "requests", "total_requests"],
  898. )
  899. self.assertEqual(data["requests"][0]["user"]["name"], "pingou")
  900. self.assertEqual(data["requests"][1]["user"]["name"], "pingou")
  901. self.assertEqual(data["requests"][0]["status"], "Open")
  902. self.assertEqual(data["requests"][1]["status"], "Open")
  903. self.assertEqual(
  904. data["requests"][0]["title"],
  905. "open pullrequest by user pingou on repo test2",
  906. )
  907. self.assertEqual(
  908. data["requests"][1]["title"],
  909. "open pullrequest by user pingou on repo test",
  910. )
  911. self.assertEqual(data["args"]["status"], "open")
  912. self.assertEqual(data["args"]["page"], 1)
  913. # Next test with the status parameter set to `open`.
  914. output = self.app.get("/api/0/user/pingou/requests/filed?status=open")
  915. self.assertEqual(output.status_code, 200)
  916. data = json.loads(output.get_data(as_text=True))
  917. self.assertEqual(len(data["requests"]), 2)
  918. self.assertEqual(
  919. sorted(data.keys()),
  920. ["args", "pagination", "requests", "total_requests"],
  921. )
  922. self.assertEqual(data["requests"][0]["user"]["name"], "pingou")
  923. self.assertEqual(data["requests"][1]["user"]["name"], "pingou")
  924. self.assertEqual(data["requests"][0]["status"], "Open")
  925. self.assertEqual(data["requests"][1]["status"], "Open")
  926. self.assertEqual(
  927. data["requests"][0]["title"],
  928. "open pullrequest by user pingou on repo test2",
  929. )
  930. self.assertEqual(
  931. data["requests"][1]["title"],
  932. "open pullrequest by user pingou on repo test",
  933. )
  934. self.assertEqual(data["args"]["status"], "open")
  935. self.assertEqual(data["args"]["page"], 1)
  936. # Next test with the status parameter set to `closed`.
  937. output = self.app.get(
  938. "/api/0/user/pingou/requests/filed?status=closed"
  939. )
  940. self.assertEqual(output.status_code, 200)
  941. data = json.loads(output.get_data(as_text=True))
  942. self.assertEqual(len(data["requests"]), 2)
  943. self.assertEqual(
  944. sorted(data.keys()),
  945. ["args", "pagination", "requests", "total_requests"],
  946. )
  947. self.assertEqual(data["requests"][0]["user"]["name"], "pingou")
  948. self.assertEqual(data["requests"][1]["user"]["name"], "pingou")
  949. self.assertEqual(data["requests"][0]["status"], "Closed")
  950. self.assertEqual(data["requests"][1]["status"], "Closed")
  951. self.assertEqual(
  952. data["requests"][0]["title"],
  953. "closed pullrequest by user pingou on repo test2",
  954. )
  955. self.assertEqual(
  956. data["requests"][1]["title"],
  957. "closed pullrequest by user pingou on repo test",
  958. )
  959. self.assertEqual(data["args"]["status"], "closed")
  960. self.assertEqual(data["args"]["page"], 1)
  961. # Next test with the status parameter set to `merged`.
  962. output = self.app.get(
  963. "/api/0/user/pingou/requests/filed?status=merged"
  964. )
  965. self.assertEqual(output.status_code, 200)
  966. data = json.loads(output.get_data(as_text=True))
  967. self.assertEqual(len(data["requests"]), 2)
  968. self.assertEqual(
  969. sorted(data.keys()),
  970. ["args", "pagination", "requests", "total_requests"],
  971. )
  972. self.assertEqual(data["requests"][0]["user"]["name"], "pingou")
  973. self.assertEqual(data["requests"][1]["user"]["name"], "pingou")
  974. self.assertEqual(data["requests"][0]["status"], "Merged")
  975. self.assertEqual(data["requests"][1]["status"], "Merged")
  976. self.assertEqual(
  977. data["requests"][0]["title"],
  978. "merged pullrequest by user pingou on repo test2",
  979. )
  980. self.assertEqual(
  981. data["requests"][1]["title"],
  982. "merged pullrequest by user pingou on repo test",
  983. )
  984. self.assertEqual(data["args"]["status"], "merged")
  985. self.assertEqual(data["args"]["page"], 1)
  986. # Finally, test with the status parameter set to `all`.
  987. output = self.app.get("/api/0/user/pingou/requests/filed?status=all")
  988. self.assertEqual(output.status_code, 200)
  989. data = json.loads(output.get_data(as_text=True))
  990. self.assertEqual(len(data["requests"]), 6)
  991. self.assertEqual(
  992. sorted(data.keys()),
  993. ["args", "pagination", "requests", "total_requests"],
  994. )
  995. self.assertEqual(data["requests"][0]["user"]["name"], "pingou")
  996. self.assertEqual(data["requests"][1]["user"]["name"], "pingou")
  997. self.assertEqual(data["requests"][2]["user"]["name"], "pingou")
  998. self.assertEqual(data["requests"][3]["user"]["name"], "pingou")
  999. self.assertEqual(data["requests"][4]["user"]["name"], "pingou")
  1000. self.assertEqual(data["requests"][5]["user"]["name"], "pingou")
  1001. self.assertEqual(data["requests"][0]["status"], "Merged")
  1002. self.assertEqual(data["requests"][1]["status"], "Merged")
  1003. self.assertEqual(data["requests"][2]["status"], "Closed")
  1004. self.assertEqual(data["requests"][3]["status"], "Closed")
  1005. self.assertEqual(data["requests"][4]["status"], "Open")
  1006. self.assertEqual(data["requests"][5]["status"], "Open")
  1007. self.assertEqual(
  1008. data["requests"][0]["title"],
  1009. "merged pullrequest by user pingou on repo test2",
  1010. )
  1011. self.assertEqual(
  1012. data["requests"][1]["title"],
  1013. "merged pullrequest by user pingou on repo test",
  1014. )
  1015. self.assertEqual(
  1016. data["requests"][2]["title"],
  1017. "closed pullrequest by user pingou on repo test2",
  1018. )
  1019. self.assertEqual(
  1020. data["requests"][3]["title"],
  1021. "closed pullrequest by user pingou on repo test",
  1022. )
  1023. self.assertEqual(
  1024. data["requests"][4]["title"],
  1025. "open pullrequest by user pingou on repo test2",
  1026. )
  1027. self.assertEqual(
  1028. data["requests"][5]["title"],
  1029. "open pullrequest by user pingou on repo test",
  1030. )
  1031. self.assertEqual(data["args"]["status"], "all")
  1032. self.assertEqual(data["args"]["page"], 1)
  1033. # Test page 2 with the status parameter set to `all`.
  1034. output = self.app.get(
  1035. "/api/0/user/pingou/requests/filed?status=all&page=2"
  1036. )
  1037. self.assertEqual(output.status_code, 200)
  1038. data = json.loads(output.get_data(as_text=True))
  1039. self.assertEqual(len(data["requests"]), 0)
  1040. self.assertEqual(
  1041. sorted(data.keys()),
  1042. ["args", "pagination", "requests", "total_requests"],
  1043. )
  1044. self.assertEqual(data["args"]["page"], 2)
  1045. @patch("pagure.lib.notify.send_email")
  1046. def test_api_view_user_requests_filed_created(self, mockemail):
  1047. """Test the api_view_user_requests_filed method of the flask user
  1048. api with the created parameter"""
  1049. today = datetime.datetime.utcnow().date()
  1050. output = self.app.get(
  1051. "/api/0/user/pingou/requests/filed?status=all&created=%s"
  1052. % (today.isoformat())
  1053. )
  1054. self.assertEqual(output.status_code, 200)
  1055. data = json.loads(output.get_data(as_text=True))
  1056. self.assertEqual(len(data["requests"]), 6)
  1057. yesterday = today - datetime.timedelta(days=1)
  1058. output = self.app.get(
  1059. "/api/0/user/pingou/requests/filed?status=all&created=%s"
  1060. % (yesterday.isoformat())
  1061. )
  1062. self.assertEqual(output.status_code, 200)
  1063. data = json.loads(output.get_data(as_text=True))
  1064. self.assertEqual(len(data["requests"]), 6)
  1065. tomorrow = today + datetime.timedelta(days=1)
  1066. output = self.app.get(
  1067. "/api/0/user/pingou/requests/filed?status=all&created=%s"
  1068. % (tomorrow.isoformat())
  1069. )
  1070. self.assertEqual(output.status_code, 200)
  1071. data = json.loads(output.get_data(as_text=True))
  1072. self.assertEqual(len(data["requests"]), 0)
  1073. output = self.app.get(
  1074. "/api/0/user/pingou/requests/filed?status=all&created=..%s"
  1075. % (today.isoformat())
  1076. )
  1077. self.assertEqual(output.status_code, 200)
  1078. data = json.loads(output.get_data(as_text=True))
  1079. self.assertEqual(len(data["requests"]), 0)
  1080. output = self.app.get(
  1081. "/api/0/user/pingou/requests/filed?status=all&created=..%s"
  1082. % (yesterday.isoformat())
  1083. )
  1084. self.assertEqual(output.status_code, 200)
  1085. data = json.loads(output.get_data(as_text=True))
  1086. self.assertEqual(len(data["requests"]), 0)
  1087. thedaybefore = today - datetime.timedelta(days=1)
  1088. output = self.app.get(
  1089. "/api/0/user/pingou/requests/filed?status=all&created=..%s"
  1090. % (thedaybefore.isoformat())
  1091. )
  1092. self.assertEqual(output.status_code, 200)
  1093. data = json.loads(output.get_data(as_text=True))
  1094. self.assertEqual(len(data["requests"]), 0)
  1095. output = self.app.get(
  1096. "/api/0/user/pingou/requests/filed?status=all&created=..%s"
  1097. % (tomorrow.isoformat())
  1098. )
  1099. self.assertEqual(output.status_code, 200)
  1100. data = json.loads(output.get_data(as_text=True))
  1101. self.assertEqual(len(data["requests"]), 6)
  1102. output = self.app.get(
  1103. "/api/0/user/pingou/requests/filed?status=all&created=%s..%s"
  1104. % (thedaybefore.isoformat(), tomorrow.isoformat())
  1105. )
  1106. self.assertEqual(output.status_code, 200)
  1107. data = json.loads(output.get_data(as_text=True))
  1108. self.assertEqual(len(data["requests"]), 6)
  1109. @patch("pagure.lib.notify.send_email")
  1110. def test_api_view_user_requests_filed_updated(self, mockemail):
  1111. """Test the api_view_user_requests_filed method of the flask user
  1112. api with the created parameter"""
  1113. today = datetime.datetime.utcnow().date()
  1114. output = self.app.get(
  1115. "/api/0/user/pingou/requests/filed?status=all&updated=%s"
  1116. % (today.isoformat())
  1117. )
  1118. self.assertEqual(output.status_code, 200)
  1119. data = json.loads(output.get_data(as_text=True))
  1120. self.assertEqual(len(data["requests"]), 0)
  1121. yesterday = today - datetime.timedelta(days=1)
  1122. output = self.app.get(
  1123. "/api/0/user/pingou/requests/filed?status=all&updated=%s"
  1124. % (yesterday.isoformat())
  1125. )
  1126. self.assertEqual(output.status_code, 200)
  1127. data = json.loads(output.get_data(as_text=True))
  1128. self.assertEqual(len(data["requests"]), 0)
  1129. tomorrow = today + datetime.timedelta(days=1)
  1130. output = self.app.get(
  1131. "/api/0/user/pingou/requests/filed?status=all&updated=%s"
  1132. % (tomorrow.isoformat())
  1133. )
  1134. self.assertEqual(output.status_code, 200)
  1135. data = json.loads(output.get_data(as_text=True))
  1136. self.assertEqual(len(data["requests"]), 6)
  1137. @patch("pagure.lib.notify.send_email")
  1138. def test_api_view_user_requests_filed_closed(self, mockemail):
  1139. """Test the api_view_user_requests_filed method of the flask user
  1140. api with the created parameter"""
  1141. today = datetime.datetime.utcnow().date()
  1142. output = self.app.get(
  1143. "/api/0/user/pingou/requests/filed?status=all&closed=%s"
  1144. % (today.isoformat())
  1145. )
  1146. self.assertEqual(output.status_code, 200)
  1147. data = json.loads(output.get_data(as_text=True))
  1148. self.assertEqual(len(data["requests"]), 0)
  1149. yesterday = today - datetime.timedelta(days=1)
  1150. output = self.app.get(
  1151. "/api/0/user/pingou/requests/filed?status=all&closed=%s"
  1152. % (yesterday.isoformat())
  1153. )
  1154. self.assertEqual(output.status_code, 200)
  1155. data = json.loads(output.get_data(as_text=True))
  1156. self.assertEqual(len(data["requests"]), 0)
  1157. tomorrow = today + datetime.timedelta(days=1)
  1158. output = self.app.get(
  1159. "/api/0/user/pingou/requests/filed?status=all&closed=%s"
  1160. % (tomorrow.isoformat())
  1161. )
  1162. self.assertEqual(output.status_code, 200)
  1163. data = json.loads(output.get_data(as_text=True))
  1164. self.assertEqual(len(data["requests"]), 0)
  1165. @patch("pagure.lib.notify.send_email")
  1166. def test_api_view_user_requests_filed_foo(self, mockemail):
  1167. """Test the api_view_user_requests_filed method of the flask user
  1168. api"""
  1169. # Default data returned
  1170. output = self.app.get(
  1171. "/api/0/user/foo/requests/filed?status=all&per_page=6"
  1172. )
  1173. self.assertEqual(output.status_code, 200)
  1174. data = json.loads(output.get_data(as_text=True))
  1175. self.assertEqual(len(data["requests"]), 6)
  1176. self.assertEqual(
  1177. sorted(data.keys()),
  1178. ["args", "pagination", "requests", "total_requests"],
  1179. )
  1180. # There are 6 PRs, that's 1 page at 6 results per page
  1181. self.assertEqual(data["pagination"]["pages"], 1)
  1182. @patch("pagure.lib.notify.send_email")
  1183. def test_api_view_user_requests_filed_foo_grp_access(self, mockemail):
  1184. """ Test when the user has accessed to some PRs via a group. """
  1185. # Add the user to a group
  1186. msg = pagure.lib.query.add_group(
  1187. self.session,
  1188. group_name="some_group",
  1189. display_name="Some Group",
  1190. description=None,
  1191. group_type="bar",
  1192. user="pingou",
  1193. is_admin=False,
  1194. blacklist=[],
  1195. )
  1196. self.session.commit()
  1197. # Add the group to the project `test2`
  1198. project = pagure.lib.query._get_project(self.session, "test2")
  1199. msg = pagure.lib.query.add_group_to_project(
  1200. session=self.session,
  1201. project=project,
  1202. new_group="some_group",
  1203. user="pingou",
  1204. )
  1205. self.session.commit()
  1206. self.assertEqual(msg, "Group added")
  1207. # Add foo to the group
  1208. group = pagure.lib.query.search_groups(
  1209. self.session, group_name="some_group"
  1210. )
  1211. result = pagure.lib.query.add_user_to_group(
  1212. self.session, "foo", group, "pingou", True
  1213. )
  1214. self.session.commit()
  1215. self.assertEqual(result, "User `foo` added to the group `some_group`.")
  1216. # Query the API for foo's filed PRs
  1217. output = self.app.get(
  1218. "/api/0/user/foo/requests/filed?status=all&per_page=6"
  1219. )
  1220. self.assertEqual(output.status_code, 200)
  1221. data = json.loads(output.get_data(as_text=True))
  1222. self.assertEqual(len(data["requests"]), 6)
  1223. self.assertEqual(
  1224. sorted(data.keys()),
  1225. ["args", "pagination", "requests", "total_requests"],
  1226. )
  1227. # There are 6 PRs, that's 1 page at 6 results per page
  1228. self.assertEqual(data["pagination"]["pages"], 1)
  1229. @patch("pagure.lib.notify.send_email")
  1230. def test_api_view_user_requests_actionable(self, mockemail):
  1231. """Test the api_view_user_requests_actionable method of the flask user
  1232. api"""
  1233. # First we test without the status parameter. It should default to `open`
  1234. output = self.app.get("/api/0/user/pingou/requests/actionable")
  1235. self.assertEqual(output.status_code, 200)
  1236. data = json.loads(output.get_data(as_text=True))
  1237. self.assertEqual(len(data["requests"]), 2)
  1238. self.assertEqual(
  1239. sorted(data.keys()),
  1240. ["args", "pagination", "requests", "total_requests"],
  1241. )
  1242. self.assertEqual(data["requests"][0]["user"]["name"], "foo")
  1243. self.assertEqual(data["requests"][1]["user"]["name"], "foo")
  1244. self.assertEqual(data["requests"][0]["status"], "Open")
  1245. self.assertEqual(data["requests"][1]["status"], "Open")
  1246. self.assertEqual(
  1247. data["requests"][0]["title"],
  1248. "open pullrequest by user foo on repo test2",
  1249. )
  1250. self.assertEqual(
  1251. data["requests"][1]["title"],
  1252. "open pullrequest by user foo on repo test",
  1253. )
  1254. self.assertEqual(data["args"]["status"], "open")
  1255. self.assertEqual(data["args"]["page"], 1)
  1256. # Next test with the status parameter set to `open`.
  1257. output = self.app.get(
  1258. "/api/0/user/pingou/requests/actionable?status=open"
  1259. )
  1260. self.assertEqual(output.status_code, 200)
  1261. data = json.loads(output.get_data(as_text=True))
  1262. self.assertEqual(len(data["requests"]), 2)
  1263. self.assertEqual(
  1264. sorted(data.keys()),
  1265. ["args", "pagination", "requests", "total_requests"],
  1266. )
  1267. self.assertEqual(data["requests"][0]["user"]["name"], "foo")
  1268. self.assertEqual(data["requests"][1]["user"]["name"], "foo")
  1269. self.assertEqual(data["requests"][0]["status"], "Open")
  1270. self.assertEqual(data["requests"][1]["status"], "Open")
  1271. self.assertEqual(
  1272. data["requests"][0]["title"],
  1273. "open pullrequest by user foo on repo test2",
  1274. )
  1275. self.assertEqual(
  1276. data["requests"][1]["title"],
  1277. "open pullrequest by user foo on repo test",
  1278. )
  1279. self.assertEqual(data["args"]["status"], "open")
  1280. self.assertEqual(data["args"]["page"], 1)
  1281. # Next test with the status parameter set to `closed`.
  1282. output = self.app.get(
  1283. "/api/0/user/pingou/requests/actionable?status=closed"
  1284. )
  1285. self.assertEqual(output.status_code, 200)
  1286. data = json.loads(output.get_data(as_text=True))
  1287. self.assertEqual(len(data["requests"]), 2)
  1288. self.assertEqual(
  1289. sorted(data.keys()),
  1290. ["args", "pagination", "requests", "total_requests"],
  1291. )
  1292. self.assertEqual(data["requests"][0]["user"]["name"], "foo")
  1293. self.assertEqual(data["requests"][1]["user"]["name"], "foo")
  1294. self.assertEqual(data["requests"][0]["status"], "Closed")
  1295. self.assertEqual(data["requests"][1]["status"], "Closed")
  1296. self.assertEqual(
  1297. data["requests"][0]["title"],
  1298. "closed pullrequest by user foo on repo test2",
  1299. )
  1300. self.assertEqual(
  1301. data["requests"][1]["title"],
  1302. "closed pullrequest by user foo on repo test",
  1303. )
  1304. self.assertEqual(data["args"]["status"], "closed")
  1305. self.assertEqual(data["args"]["page"], 1)
  1306. # Next test with the status parameter set to `merged`.
  1307. output = self.app.get(
  1308. "/api/0/user/pingou/requests/actionable?status=merged"
  1309. )
  1310. self.assertEqual(output.status_code, 200)
  1311. data = json.loads(output.get_data(as_text=True))
  1312. self.assertEqual(len(data["requests"]), 2)
  1313. self.assertEqual(
  1314. sorted(data.keys()),
  1315. ["args", "pagination", "requests", "total_requests"],
  1316. )
  1317. self.assertEqual(data["requests"][0]["user"]["name"], "foo")
  1318. self.assertEqual(data["requests"][1]["user"]["name"], "foo")
  1319. self.assertEqual(data["requests"][0]["status"], "Merged")
  1320. self.assertEqual(data["requests"][1]["status"], "Merged")
  1321. self.assertEqual(
  1322. data["requests"][0]["title"],
  1323. "merged pullrequest by user foo on repo test2",
  1324. )
  1325. self.assertEqual(
  1326. data["requests"][1]["title"],
  1327. "merged pullrequest by user foo on repo test",
  1328. )
  1329. self.assertEqual(data["args"]["status"], "merged")
  1330. self.assertEqual(data["args"]["page"], 1)
  1331. # Finally, test with the status parameter set to `all`.
  1332. output = self.app.get(
  1333. "/api/0/user/pingou/requests/actionable?status=all"
  1334. )
  1335. self.assertEqual(output.status_code, 200)
  1336. data = json.loads(output.get_data(as_text=True))
  1337. self.assertEqual(len(data["requests"]), 6)
  1338. self.assertEqual(
  1339. sorted(data.keys()),
  1340. ["args", "pagination", "requests", "total_requests"],
  1341. )
  1342. self.assertEqual(data["requests"][0]["user"]["name"], "foo")
  1343. self.assertEqual(data["requests"][1]["user"]["name"], "foo")
  1344. self.assertEqual(data["requests"][2]["user"]["name"], "foo")
  1345. self.assertEqual(data["requests"][3]["user"]["name"], "foo")
  1346. self.assertEqual(data["requests"][4]["user"]["name"], "foo")
  1347. self.assertEqual(data["requests"][5]["user"]["name"], "foo")
  1348. self.assertEqual(data["requests"][0]["status"], "Merged")
  1349. self.assertEqual(data["requests"][1]["status"], "Merged")
  1350. self.assertEqual(data["requests"][2]["status"], "Closed")
  1351. self.assertEqual(data["requests"][3]["status"], "Closed")
  1352. self.assertEqual(data["requests"][4]["status"], "Open")
  1353. self.assertEqual(data["requests"][5]["status"], "Open")
  1354. self.assertEqual(
  1355. data["requests"][0]["title"],
  1356. "merged pullrequest by user foo on repo test2",
  1357. )
  1358. self.assertEqual(
  1359. data["requests"][1]["title"],
  1360. "merged pullrequest by user foo on repo test",
  1361. )
  1362. self.assertEqual(
  1363. data["requests"][2]["title"],
  1364. "closed pullrequest by user foo on repo test2",
  1365. )
  1366. self.assertEqual(
  1367. data["requests"][3]["title"],
  1368. "closed pullrequest by user foo on repo test",
  1369. )
  1370. self.assertEqual(
  1371. data["requests"][4]["title"],
  1372. "open pullrequest by user foo on repo test2",
  1373. )
  1374. self.assertEqual(
  1375. data["requests"][5]["title"],
  1376. "open pullrequest by user foo on repo test",
  1377. )
  1378. self.assertEqual(data["args"]["status"], "all")
  1379. self.assertEqual(data["args"]["page"], 1)
  1380. # Test page 2 with the status parameter set to `all`.
  1381. output = self.app.get(
  1382. "/api/0/user/pingou/requests/actionable?status=all&page=2"
  1383. )
  1384. self.assertEqual(output.status_code, 200)
  1385. data = json.loads(output.get_data(as_text=True))
  1386. self.assertEqual(len(data["requests"]), 0)
  1387. self.assertEqual(
  1388. sorted(data.keys()),
  1389. ["args", "pagination", "requests", "total_requests"],
  1390. )
  1391. self.assertEqual(data["args"]["page"], 2)
  1392. @patch("pagure.lib.notify.send_email")
  1393. def test_api_view_user_requests_actionable_created(self, mockemail):
  1394. """Test the api_view_user_requests_filed method of the flask user
  1395. api with the created parameter"""
  1396. today = datetime.datetime.utcnow().date()
  1397. output = self.app.get(
  1398. "/api/0/user/pingou/requests/actionable?status=all&created=%s"
  1399. % (today.isoformat())
  1400. )
  1401. self.assertEqual(output.status_code, 200)
  1402. data = json.loads(output.get_data(as_text=True))
  1403. self.assertEqual(len(data["requests"]), 6)
  1404. yesterday = today - datetime.timedelta(days=1)
  1405. output = self.app.get(
  1406. "/api/0/user/pingou/requests/actionable?status=all&created=%s"
  1407. % (yesterday.isoformat())
  1408. )
  1409. self.assertEqual(output.status_code, 200)
  1410. data = json.loads(output.get_data(as_text=True))
  1411. self.assertEqual(len(data["requests"]), 6)
  1412. tomorrow = today + datetime.timedelta(days=1)
  1413. output = self.app.get(
  1414. "/api/0/user/pingou/requests/actionable?status=all&created=%s"
  1415. % (tomorrow.isoformat())
  1416. )
  1417. self.assertEqual(output.status_code, 200)
  1418. data = json.loads(output.get_data(as_text=True))
  1419. self.assertEqual(len(data["requests"]), 0)
  1420. output = self.app.get(
  1421. "/api/0/user/pingou/requests/actionable?status=all&created=..%s"
  1422. % (today.isoformat())
  1423. )
  1424. self.assertEqual(output.status_code, 200)
  1425. data = json.loads(output.get_data(as_text=True))
  1426. self.assertEqual(len(data["requests"]), 0)
  1427. output = self.app.get(
  1428. "/api/0/user/pingou/requests/actionable?status=all&created=..%s"
  1429. % (yesterday.isoformat())
  1430. )
  1431. self.assertEqual(output.status_code, 200)
  1432. data = json.loads(output.get_data(as_text=True))
  1433. self.assertEqual(len(data["requests"]), 0)
  1434. thedaybefore = today - datetime.timedelta(days=1)
  1435. output = self.app.get(
  1436. "/api/0/user/pingou/requests/actionable?status=all&created=..%s"
  1437. % (thedaybefore.isoformat())
  1438. )
  1439. self.assertEqual(output.status_code, 200)
  1440. data = json.loads(output.get_data(as_text=True))
  1441. self.assertEqual(len(data["requests"]), 0)
  1442. output = self.app.get(
  1443. "/api/0/user/pingou/requests/actionable?status=all&created=..%s"
  1444. % (tomorrow.isoformat())
  1445. )
  1446. self.assertEqual(output.status_code, 200)
  1447. data = json.loads(output.get_data(as_text=True))
  1448. self.assertEqual(len(data["requests"]), 6)
  1449. output = self.app.get(
  1450. "/api/0/user/pingou/requests/actionable?status=all&created=%s..%s"
  1451. % (thedaybefore.isoformat(), tomorrow.isoformat())
  1452. )
  1453. self.assertEqual(output.status_code, 200)
  1454. data = json.loads(output.get_data(as_text=True))
  1455. self.assertEqual(len(data["requests"]), 6)
  1456. @patch("pagure.lib.notify.send_email")
  1457. def test_api_view_user_requests_actionable_updated(self, mockemail):
  1458. """Test the api_view_user_requests_filed method of the flask user
  1459. api with the created parameter"""
  1460. today = datetime.datetime.utcnow().date()
  1461. output = self.app.get(
  1462. "/api/0/user/pingou/requests/actionable?status=all&updated=%s"
  1463. % (today.isoformat())
  1464. )
  1465. self.assertEqual(output.status_code, 200)
  1466. data = json.loads(output.get_data(as_text=True))
  1467. self.assertEqual(len(data["requests"]), 0)
  1468. yesterday = today - datetime.timedelta(days=1)
  1469. output = self.app.get(
  1470. "/api/0/user/pingou/requests/actionable?status=all&updated=%s"
  1471. % (yesterday.isoformat())
  1472. )
  1473. self.assertEqual(output.status_code, 200)
  1474. data = json.loads(output.get_data(as_text=True))
  1475. self.assertEqual(len(data["requests"]), 0)
  1476. tomorrow = today + datetime.timedelta(days=1)
  1477. output = self.app.get(
  1478. "/api/0/user/pingou/requests/actionable?status=all&updated=%s"
  1479. % (tomorrow.isoformat())
  1480. )
  1481. self.assertEqual(output.status_code, 200)
  1482. data = json.loads(output.get_data(as_text=True))
  1483. self.assertEqual(len(data["requests"]), 6)
  1484. @patch("pagure.lib.notify.send_email")
  1485. def test_api_view_user_requests_actionable_closed(self, mockemail):
  1486. """Test the api_view_user_requests_filed method of the flask user
  1487. api with the created parameter"""
  1488. today = datetime.datetime.utcnow().date()
  1489. output = self.app.get(
  1490. "/api/0/user/pingou/requests/actionable?status=all&closed=%s"
  1491. % (today.isoformat())
  1492. )
  1493. self.assertEqual(output.status_code, 200)
  1494. data = json.loads(output.get_data(as_text=True))
  1495. self.assertEqual(len(data["requests"]), 0)
  1496. yesterday = today - datetime.timedelta(days=1)
  1497. output = self.app.get(
  1498. "/api/0/user/pingou/requests/actionable?status=all&closed=%s"
  1499. % (yesterday.isoformat())
  1500. )
  1501. self.assertEqual(output.status_code, 200)
  1502. data = json.loads(output.get_data(as_text=True))
  1503. self.assertEqual(len(data["requests"]), 0)
  1504. tomorrow = today + datetime.timedelta(days=1)
  1505. output = self.app.get(
  1506. "/api/0/user/pingou/requests/actionable?status=all&closed=%s"
  1507. % (tomorrow.isoformat())
  1508. )
  1509. self.assertEqual(output.status_code, 200)
  1510. data = json.loads(output.get_data(as_text=True))
  1511. self.assertEqual(len(data["requests"]), 0)
  1512. class PagureFlaskApiUsertestissues(tests.Modeltests):
  1513. """ Tests for the user issues endpoints """
  1514. maxDiff = None
  1515. def setUp(self):
  1516. """ Set up the environnment, ran before every tests. """
  1517. super(PagureFlaskApiUsertestissues, self).setUp()
  1518. pagure.config.config["REQUESTS_FOLDER"] = None
  1519. tests.create_projects(self.session)
  1520. repo = pagure.lib.query._get_project(self.session, "test")
  1521. # Create issues to play with
  1522. msg = pagure.lib.query.new_issue(
  1523. session=self.session,
  1524. repo=repo,
  1525. title="Test issue",
  1526. content="We should work on this",
  1527. user="pingou",
  1528. )
  1529. self.session.commit()
  1530. self.assertEqual(msg.title, "Test issue")
  1531. def test_user_issues_empty(self):
  1532. """ Return the list of issues associated with the specified user. """
  1533. output = self.app.get("/api/0/user/foo/issues")
  1534. self.assertEqual(output.status_code, 200)
  1535. data = json.loads(output.get_data(as_text=True))
  1536. for k in ["pagination_issues_assigned", "pagination_issues_created"]:
  1537. for k2 in ["first", "last"]:
  1538. self.assertIsNotNone(data[k][k2])
  1539. data[k][k2] = None
  1540. self.assertEqual(
  1541. data,
  1542. {
  1543. "args": {
  1544. "assignee": True,
  1545. "author": True,
  1546. "closed": None,
  1547. "created": None,
  1548. "milestones": [],
  1549. "no_stones": None,
  1550. "order": None,
  1551. "order_key": None,
  1552. "page": 1,
  1553. "since": None,
  1554. "status": None,
  1555. "tags": [],
  1556. "updated": None,
  1557. },
  1558. "issues_assigned": [],
  1559. "issues_created": [],
  1560. "pagination_issues_assigned": {
  1561. "first": None,
  1562. "last": None,
  1563. "next": None,
  1564. "page": 1,
  1565. "pages": 0,
  1566. "per_page": 20,
  1567. "prev": None,
  1568. },
  1569. "pagination_issues_created": {
  1570. "first": None,
  1571. "last": None,
  1572. "next": None,
  1573. "page": 1,
  1574. "pages": 0,
  1575. "per_page": 20,
  1576. "prev": None,
  1577. },
  1578. "total_issues_assigned": 0,
  1579. "total_issues_assigned_pages": 1,
  1580. "total_issues_created": 0,
  1581. "total_issues_created_pages": 1,
  1582. },
  1583. )
  1584. def test_user_issues(self):
  1585. """ Return the list of issues associated with the specified user. """
  1586. output = self.app.get("/api/0/user/pingou/issues")
  1587. self.assertEqual(output.status_code, 200)
  1588. data = json.loads(output.get_data(as_text=True))
  1589. issues = []
  1590. for issue in data["issues_created"]:
  1591. issue["date_created"] = "1513111778"
  1592. issue["last_updated"] = "1513111778"
  1593. issue["project"]["date_created"] = "1513111778"
  1594. issue["project"]["date_modified"] = "1513111778"
  1595. issues.append(issue)
  1596. data["issues_created"] = issues
  1597. for k in ["pagination_issues_assigned", "pagination_issues_created"]:
  1598. for k2 in ["first", "last"]:
  1599. self.assertIsNotNone(data[k][k2])
  1600. data[k][k2] = None
  1601. self.assertEqual(
  1602. data,
  1603. {
  1604. "args": {
  1605. "assignee": True,
  1606. "author": True,
  1607. "closed": None,
  1608. "created": None,
  1609. "milestones": [],
  1610. "no_stones": None,
  1611. "order": None,
  1612. "order_key": None,
  1613. "page": 1,
  1614. "since": None,
  1615. "status": None,
  1616. "tags": [],
  1617. "updated": None,
  1618. },
  1619. "issues_assigned": [],
  1620. "issues_created": [
  1621. {
  1622. "assignee": None,
  1623. "blocks": [],
  1624. "close_status": None,
  1625. "closed_at": None,
  1626. "closed_by": None,
  1627. "comments": [],
  1628. "content": "We should work on this",
  1629. "custom_fields": [],
  1630. "date_created": "1513111778",
  1631. "full_url": "http://localhost.localdomain/test/issue/1",
  1632. "depends": [],
  1633. "id": 1,
  1634. "last_updated": "1513111778",
  1635. "milestone": None,
  1636. "priority": None,
  1637. "private": False,
  1638. "project": {
  1639. "access_groups": {
  1640. "admin": [],
  1641. "collaborator": [],
  1642. "commit": [],
  1643. "ticket": [],
  1644. },
  1645. "access_users": {
  1646. "admin": [],
  1647. "collaborator": [],
  1648. "commit": [],
  1649. "owner": ["pingou"],
  1650. "ticket": [],
  1651. },
  1652. "close_status": [
  1653. "Invalid",
  1654. "Insufficient data",
  1655. "Fixed",
  1656. "Duplicate",
  1657. ],
  1658. "custom_keys": [],
  1659. "date_created": "1513111778",
  1660. "date_modified": "1513111778",
  1661. "description": "test project #1",
  1662. "full_url": "http://localhost.localdomain/test",
  1663. "fullname": "test",
  1664. "id": 1,
  1665. "milestones": {},
  1666. "name": "test",
  1667. "namespace": None,
  1668. "parent": None,
  1669. "priorities": {},
  1670. "tags": [],
  1671. "url_path": "test",
  1672. "user": {
  1673. "fullname": "PY C",
  1674. "full_url": "http://localhost.localdomain/user/pingou",
  1675. "name": "pingou",
  1676. "url_path": "user/pingou",
  1677. },
  1678. },
  1679. "related_prs": [],
  1680. "status": "Open",
  1681. "tags": [],
  1682. "title": "Test issue",
  1683. "user": {
  1684. "fullname": "PY C",
  1685. "full_url": "http://localhost.localdomain/user/pingou",
  1686. "name": "pingou",
  1687. "url_path": "user/pingou",
  1688. },
  1689. }
  1690. ],
  1691. "pagination_issues_assigned": {
  1692. "first": None,
  1693. "last": None,
  1694. "next": None,
  1695. "page": 1,
  1696. "pages": 0,
  1697. "per_page": 20,
  1698. "prev": None,
  1699. },
  1700. "pagination_issues_created": {
  1701. "first": None,
  1702. "last": None,
  1703. "next": None,
  1704. "page": 1,
  1705. "pages": 1,
  1706. "per_page": 20,
  1707. "prev": None,
  1708. },
  1709. "total_issues_assigned": 0,
  1710. "total_issues_assigned_pages": 1,
  1711. "total_issues_created": 1,
  1712. "total_issues_created_pages": 1,
  1713. },
  1714. )
  1715. def test_user_issues_created(self):
  1716. """Return the list of issues associated with the specified user
  1717. and play with the created filter."""
  1718. today = datetime.datetime.utcnow().date()
  1719. output = self.app.get(
  1720. "/api/0/user/pingou/issues?created=%s" % (today.isoformat())
  1721. )
  1722. self.assertEqual(output.status_code, 200)
  1723. data = json.loads(output.get_data(as_text=True))
  1724. self.assertEqual(data["total_issues_assigned"], 0)
  1725. self.assertEqual(data["total_issues_created"], 1)
  1726. yesterday = today - datetime.timedelta(days=1)
  1727. output = self.app.get(
  1728. "/api/0/user/pingou/issues?created=%s" % (yesterday.isoformat())
  1729. )
  1730. self.assertEqual(output.status_code, 200)
  1731. data = json.loads(output.get_data(as_text=True))
  1732. self.assertEqual(data["total_issues_assigned"], 0)
  1733. self.assertEqual(data["total_issues_created"], 1)
  1734. tomorrow = today + datetime.timedelta(days=1)
  1735. output = self.app.get(
  1736. "/api/0/user/pingou/issues?created=%s" % (tomorrow.isoformat())
  1737. )
  1738. self.assertEqual(output.status_code, 200)
  1739. data = json.loads(output.get_data(as_text=True))
  1740. self.assertEqual(data["total_issues_assigned"], 0)
  1741. self.assertEqual(data["total_issues_created"], 0)
  1742. output = self.app.get(
  1743. "/api/0/user/pingou/issues?created=..%s" % (yesterday.isoformat())
  1744. )
  1745. self.assertEqual(output.status_code, 200)
  1746. data = json.loads(output.get_data(as_text=True))
  1747. self.assertEqual(data["total_issues_assigned"], 0)
  1748. self.assertEqual(data["total_issues_created"], 0)
  1749. output = self.app.get(
  1750. "/api/0/user/pingou/issues?created=%s..%s"
  1751. % (yesterday.isoformat(), today.isoformat())
  1752. )
  1753. self.assertEqual(output.status_code, 200)
  1754. data = json.loads(output.get_data(as_text=True))
  1755. self.assertEqual(data["total_issues_assigned"], 0)
  1756. self.assertEqual(data["total_issues_created"], 0)
  1757. output = self.app.get(
  1758. "/api/0/user/pingou/issues?created=%s..%s"
  1759. % (yesterday.isoformat(), tomorrow.isoformat())
  1760. )
  1761. self.assertEqual(output.status_code, 200)
  1762. data = json.loads(output.get_data(as_text=True))
  1763. self.assertEqual(data["total_issues_assigned"], 0)
  1764. self.assertEqual(data["total_issues_created"], 1)
  1765. if __name__ == "__main__":
  1766. unittest.main(verbosity=2)