test_user.py 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  1. # -*- coding: utf-8 -*-
  2. """
  3. Tests for /api/v2/users subpath endpoints.
  4. """
  5. from time import sleep
  6. import transaction
  7. from tracim import models
  8. from tracim.lib.core.content import ContentApi
  9. from tracim.lib.core.user import UserApi
  10. from tracim.lib.core.workspace import WorkspaceApi
  11. from tracim.models import get_tm_session
  12. from tracim.models.contents import ContentTypeLegacy as ContentType
  13. from tracim.models.revision_protection import new_revision
  14. from tracim.tests import FunctionalTest
  15. from tracim.fixtures.content import Content as ContentFixtures
  16. from tracim.fixtures.users_and_groups import Base as BaseFixture
  17. class TestUserRecentlyActiveContentEndpoint(FunctionalTest):
  18. """
  19. Tests for /api/v2/users/{user_id}/workspaces/{workspace_id}/contents/recently_active # nopep8
  20. """
  21. fixtures = [BaseFixture]
  22. def test_api__get_recently_active_content__ok__200__nominal_case(self):
  23. # init DB
  24. dbsession = get_tm_session(self.session_factory, transaction.manager)
  25. admin = dbsession.query(models.User) \
  26. .filter(models.User.email == 'admin@admin.admin') \
  27. .one()
  28. workspace_api = WorkspaceApi(
  29. current_user=admin,
  30. session=dbsession,
  31. config=self.app_config
  32. )
  33. workspace = WorkspaceApi(
  34. current_user=admin,
  35. session=dbsession,
  36. config=self.app_config,
  37. ).create_workspace(
  38. 'test workspace',
  39. save_now=True
  40. )
  41. workspace2 = WorkspaceApi(
  42. current_user=admin,
  43. session=dbsession,
  44. config=self.app_config,
  45. ).create_workspace(
  46. 'test workspace2',
  47. save_now=True
  48. )
  49. api = ContentApi(
  50. current_user=admin,
  51. session=dbsession,
  52. config=self.app_config,
  53. )
  54. main_folder_workspace2 = api.create(ContentType.Folder, workspace2, None, 'Hepla', '', True) # nopep8
  55. main_folder = api.create(ContentType.Folder, workspace, None, 'this is randomized folder', '', True) # nopep8
  56. # creation order test
  57. firstly_created = api.create(ContentType.Page, workspace, main_folder, 'creation_order_test', '', True) # nopep8
  58. secondly_created = api.create(ContentType.Page, workspace, main_folder, 'another creation_order_test', '', True) # nopep8
  59. # update order test
  60. firstly_created_but_recently_updated = api.create(ContentType.Page, workspace, main_folder, 'update_order_test', '', True) # nopep8
  61. secondly_created_but_not_updated = api.create(ContentType.Page, workspace, main_folder, 'another update_order_test', '', True) # nopep8
  62. with new_revision(
  63. session=dbsession,
  64. tm=transaction.manager,
  65. content=firstly_created_but_recently_updated,
  66. ):
  67. firstly_created_but_recently_updated.description = 'Just an update'
  68. api.save(firstly_created_but_recently_updated)
  69. # comment change order
  70. firstly_created_but_recently_commented = api.create(ContentType.Page, workspace, main_folder, 'this is randomized label content', '', True) # nopep8
  71. secondly_created_but_not_commented = api.create(ContentType.Page, workspace, main_folder, 'this is another randomized label content', '', True) # nopep8
  72. comments = api.create_comment(workspace, firstly_created_but_recently_commented, 'juste a super comment', True) # nopep8
  73. content_workspace_2 = api.create(ContentType.Page, workspace2,main_folder_workspace2, 'content_workspace_2', '',True) # nopep8
  74. dbsession.flush()
  75. transaction.commit()
  76. self.testapp.authorization = (
  77. 'Basic',
  78. (
  79. 'admin@admin.admin',
  80. 'admin@admin.admin'
  81. )
  82. )
  83. res = self.testapp.get('/api/v2/users/1/workspaces/{}/contents/recently_active'.format(workspace.workspace_id), status=200) # nopep8
  84. res = res.json_body
  85. assert len(res) == 7
  86. for elem in res:
  87. assert isinstance(elem['content_id'], int)
  88. assert isinstance(elem['content_type'], str)
  89. assert elem['content_type'] != 'comments'
  90. assert isinstance(elem['is_archived'], bool)
  91. assert isinstance(elem['is_deleted'], bool)
  92. assert isinstance(elem['label'], str)
  93. assert isinstance(elem['parent_id'], int) or elem['parent_id'] is None
  94. assert isinstance(elem['show_in_ui'], bool)
  95. assert isinstance(elem['slug'], str)
  96. assert isinstance(elem['status'], str)
  97. assert isinstance(elem['sub_content_types'], list)
  98. for sub_content_type in elem['sub_content_types']:
  99. assert isinstance(sub_content_type, str)
  100. assert isinstance(elem['workspace_id'], int)
  101. # comment is newest than page2
  102. assert res[0]['content_id'] == firstly_created_but_recently_commented.content_id
  103. assert res[1]['content_id'] == secondly_created_but_not_commented.content_id
  104. # last updated content is newer than other one despite creation
  105. # of the other is more recent
  106. assert res[2]['content_id'] == firstly_created_but_recently_updated.content_id
  107. assert res[3]['content_id'] == secondly_created_but_not_updated.content_id
  108. # creation order is inverted here as last created is last active
  109. assert res[4]['content_id'] == secondly_created.content_id
  110. assert res[5]['content_id'] == firstly_created.content_id
  111. # folder subcontent modification does not change folder order
  112. assert res[6]['content_id'] == main_folder.content_id
  113. def test_api__get_recently_active_content__ok__200__limit_2_multiple(self):
  114. # TODO - G.M - 2018-07-20 - Better fix for this test, do not use sleep()
  115. # anymore to fix datetime lack of precision.
  116. # init DB
  117. dbsession = get_tm_session(self.session_factory, transaction.manager)
  118. admin = dbsession.query(models.User) \
  119. .filter(models.User.email == 'admin@admin.admin') \
  120. .one()
  121. workspace_api = WorkspaceApi(
  122. current_user=admin,
  123. session=dbsession,
  124. config=self.app_config
  125. )
  126. workspace = WorkspaceApi(
  127. current_user=admin,
  128. session=dbsession,
  129. config=self.app_config,
  130. ).create_workspace(
  131. 'test workspace',
  132. save_now=True
  133. )
  134. workspace2 = WorkspaceApi(
  135. current_user=admin,
  136. session=dbsession,
  137. config=self.app_config,
  138. ).create_workspace(
  139. 'test workspace2',
  140. save_now=True
  141. )
  142. api = ContentApi(
  143. current_user=admin,
  144. session=dbsession,
  145. config=self.app_config,
  146. )
  147. main_folder_workspace2 = api.create(ContentType.Folder, workspace2, None, 'Hepla', '', True) # nopep8
  148. sleep(1)
  149. main_folder = api.create(ContentType.Folder, workspace, None, 'this is randomized folder', '', True) # nopep8
  150. # creation order test
  151. firstly_created = api.create(ContentType.Page, workspace, main_folder, 'creation_order_test', '', True) # nopep8
  152. sleep(1)
  153. secondly_created = api.create(ContentType.Page, workspace, main_folder, 'another creation_order_test', '', True) # nopep8
  154. # update order test
  155. firstly_created_but_recently_updated = api.create(ContentType.Page, workspace, main_folder, 'update_order_test', '', True) # nopep8
  156. sleep(1)
  157. secondly_created_but_not_updated = api.create(ContentType.Page, workspace, main_folder, 'another update_order_test', '', True) # nopep8
  158. sleep(1)
  159. with new_revision(
  160. session=dbsession,
  161. tm=transaction.manager,
  162. content=firstly_created_but_recently_updated,
  163. ):
  164. firstly_created_but_recently_updated.description = 'Just an update'
  165. api.save(firstly_created_but_recently_updated)
  166. # comment change order
  167. firstly_created_but_recently_commented = api.create(ContentType.Page, workspace, main_folder, 'this is randomized label content', '', True) # nopep8
  168. sleep(1)
  169. secondly_created_but_not_commented = api.create(ContentType.Page, workspace, main_folder, 'this is another randomized label content', '', True) # nopep8
  170. sleep(1)
  171. comments = api.create_comment(workspace, firstly_created_but_recently_commented, 'juste a super comment', True) # nopep8
  172. sleep(1)
  173. content_workspace_2 = api.create(ContentType.Page, workspace2,main_folder_workspace2, 'content_workspace_2', '',True) # nopep8
  174. dbsession.flush()
  175. transaction.commit()
  176. self.testapp.authorization = (
  177. 'Basic',
  178. (
  179. 'admin@admin.admin',
  180. 'admin@admin.admin'
  181. )
  182. )
  183. params = {
  184. 'limit': 2,
  185. }
  186. res = self.testapp.get(
  187. '/api/v2/users/1/workspaces/{}/contents/recently_active'.format(workspace.workspace_id), # nopep8
  188. status=200,
  189. params=params
  190. ) # nopep8
  191. res = res.json_body
  192. assert len(res) == 2
  193. for elem in res:
  194. assert isinstance(elem['content_id'], int)
  195. assert isinstance(elem['content_type'], str)
  196. assert elem['content_type'] != 'comments'
  197. assert isinstance(elem['is_archived'], bool)
  198. assert isinstance(elem['is_deleted'], bool)
  199. assert isinstance(elem['label'], str)
  200. assert isinstance(elem['parent_id'], int) or elem['parent_id'] is None
  201. assert isinstance(elem['show_in_ui'], bool)
  202. assert isinstance(elem['slug'], str)
  203. assert isinstance(elem['status'], str)
  204. assert isinstance(elem['sub_content_types'], list)
  205. for sub_content_type in elem['sub_content_types']:
  206. assert isinstance(sub_content_type, str)
  207. assert isinstance(elem['workspace_id'], int)
  208. # comment is newest than page2
  209. assert res[0]['content_id'] == firstly_created_but_recently_commented.content_id
  210. assert res[1]['content_id'] == secondly_created_but_not_commented.content_id
  211. params = {
  212. 'limit': 2,
  213. 'before_datetime': secondly_created_but_not_commented.get_last_activity_date().strftime('%Y-%m-%dT%H:%M:%SZ'), # nopep8
  214. }
  215. res = self.testapp.get(
  216. '/api/v2/users/1/workspaces/{}/contents/recently_active'.format(workspace.workspace_id), # nopep8
  217. status=200,
  218. params=params
  219. )
  220. res = res.json_body
  221. assert len(res) == 2
  222. # last updated content is newer than other one despite creation
  223. # of the other is more recent
  224. assert res[0]['content_id'] == firstly_created_but_recently_updated.content_id
  225. assert res[1]['content_id'] == secondly_created_but_not_updated.content_id
  226. class TestUserWorkspaceEndpoint(FunctionalTest):
  227. """
  228. Tests for /api/v2/users/{user_id}/workspaces
  229. """
  230. fixtures = [BaseFixture, ContentFixtures]
  231. def test_api__get_user_workspaces__ok_200__nominal_case(self):
  232. """
  233. Check obtain all workspaces reachables for user with user auth.
  234. """
  235. self.testapp.authorization = (
  236. 'Basic',
  237. (
  238. 'admin@admin.admin',
  239. 'admin@admin.admin'
  240. )
  241. )
  242. res = self.testapp.get('/api/v2/users/1/workspaces', status=200)
  243. res = res.json_body
  244. workspace = res[0]
  245. assert workspace['workspace_id'] == 1
  246. assert workspace['label'] == 'Business'
  247. assert workspace['slug'] == 'business'
  248. assert len(workspace['sidebar_entries']) == 7
  249. sidebar_entry = workspace['sidebar_entries'][0]
  250. assert sidebar_entry['slug'] == 'dashboard'
  251. assert sidebar_entry['label'] == 'Dashboard'
  252. assert sidebar_entry['route'] == '/#/workspaces/1/dashboard' # nopep8
  253. assert sidebar_entry['hexcolor'] == "#252525"
  254. assert sidebar_entry['fa_icon'] == "signal"
  255. sidebar_entry = workspace['sidebar_entries'][1]
  256. assert sidebar_entry['slug'] == 'contents/all'
  257. assert sidebar_entry['label'] == 'All Contents'
  258. assert sidebar_entry['route'] == "/#/workspaces/1/contents" # nopep8
  259. assert sidebar_entry['hexcolor'] == "#fdfdfd"
  260. assert sidebar_entry['fa_icon'] == "th"
  261. sidebar_entry = workspace['sidebar_entries'][2]
  262. assert sidebar_entry['slug'] == 'contents/html-documents'
  263. assert sidebar_entry['label'] == 'Text Documents'
  264. assert sidebar_entry['route'] == '/#/workspaces/1/contents?type=html-documents' # nopep8
  265. assert sidebar_entry['hexcolor'] == "#3f52e3"
  266. assert sidebar_entry['fa_icon'] == "file-text-o"
  267. sidebar_entry = workspace['sidebar_entries'][3]
  268. assert sidebar_entry['slug'] == 'contents/markdownpluspage'
  269. assert sidebar_entry['label'] == 'Markdown Plus Documents'
  270. assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=markdownpluspage" # nopep8
  271. assert sidebar_entry['hexcolor'] == "#f12d2d"
  272. assert sidebar_entry['fa_icon'] == "file-code-o"
  273. sidebar_entry = workspace['sidebar_entries'][4]
  274. assert sidebar_entry['slug'] == 'contents/files'
  275. assert sidebar_entry['label'] == 'Files'
  276. assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=file" # nopep8
  277. assert sidebar_entry['hexcolor'] == "#FF9900"
  278. assert sidebar_entry['fa_icon'] == "paperclip"
  279. sidebar_entry = workspace['sidebar_entries'][5]
  280. assert sidebar_entry['slug'] == 'contents/threads'
  281. assert sidebar_entry['label'] == 'Threads'
  282. assert sidebar_entry['route'] == "/#/workspaces/1/contents?type=thread" # nopep8
  283. assert sidebar_entry['hexcolor'] == "#ad4cf9"
  284. assert sidebar_entry['fa_icon'] == "comments-o"
  285. sidebar_entry = workspace['sidebar_entries'][6]
  286. assert sidebar_entry['slug'] == 'calendar'
  287. assert sidebar_entry['label'] == 'Calendar'
  288. assert sidebar_entry['route'] == "/#/workspaces/1/calendar" # nopep8
  289. assert sidebar_entry['hexcolor'] == "#757575"
  290. assert sidebar_entry['fa_icon'] == "calendar"
  291. def test_api__get_user_workspaces__err_403__unallowed_user(self):
  292. """
  293. Check obtain all workspaces reachables for one user
  294. with another non-admin user auth.
  295. """
  296. self.testapp.authorization = (
  297. 'Basic',
  298. (
  299. 'lawrence-not-real-email@fsf.local',
  300. 'foobarbaz'
  301. )
  302. )
  303. res = self.testapp.get('/api/v2/users/1/workspaces', status=403)
  304. assert isinstance(res.json, dict)
  305. assert 'code' in res.json.keys()
  306. assert 'message' in res.json.keys()
  307. assert 'details' in res.json.keys()
  308. def test_api__get_user_workspaces__err_401__unregistered_user(self):
  309. """
  310. Check obtain all workspaces reachables for one user
  311. without correct user auth (user unregistered).
  312. """
  313. self.testapp.authorization = (
  314. 'Basic',
  315. (
  316. 'john@doe.doe',
  317. 'lapin'
  318. )
  319. )
  320. res = self.testapp.get('/api/v2/users/1/workspaces', status=401)
  321. assert isinstance(res.json, dict)
  322. assert 'code' in res.json.keys()
  323. assert 'message' in res.json.keys()
  324. assert 'details' in res.json.keys()
  325. def test_api__get_user_workspaces__err_400__user_does_not_exist(self):
  326. """
  327. Check obtain all workspaces reachables for one user who does
  328. not exist
  329. with a correct user auth.
  330. """
  331. self.testapp.authorization = (
  332. 'Basic',
  333. (
  334. 'admin@admin.admin',
  335. 'admin@admin.admin'
  336. )
  337. )
  338. res = self.testapp.get('/api/v2/users/5/workspaces', status=400)
  339. assert isinstance(res.json, dict)
  340. assert 'code' in res.json.keys()
  341. assert 'message' in res.json.keys()
  342. assert 'details' in res.json.keys()