test_volunteer.py 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. import uuid
  2. from httpx import AsyncClient
  3. from sqlalchemy import false, select
  4. from sqlalchemy.orm import Session
  5. from app.main import app
  6. from app.models import Project, Slot, Sms, User, Volunteer
  7. from app.tests.conftest import (
  8. default_project_id,
  9. default_volunteer_id,
  10. default_slot_id,
  11. )
  12. async def test_read_list_project_volunteers(
  13. client: AsyncClient, default_user_headers: dict, default_public_project: Project
  14. ):
  15. response = await client.get(
  16. app.url_path_for("list_project_volunteers", project_id=default_project_id),
  17. )
  18. assert response.status_code == 401
  19. response = await client.get(
  20. app.url_path_for("list_project_volunteers", project_id=uuid.uuid4()),
  21. headers=default_user_headers,
  22. )
  23. assert response.status_code == 404
  24. response = await client.get(
  25. app.url_path_for("list_project_volunteers", project_id="pas un uuid valid"),
  26. headers=default_user_headers,
  27. )
  28. assert response.status_code == 422
  29. response = await client.get(
  30. app.url_path_for("list_project_volunteers", project_id=default_project_id),
  31. headers=default_user_headers,
  32. )
  33. assert response.status_code == 200
  34. data = response.json()
  35. assert len(data) == 1
  36. volunteer_response = data[0]
  37. assert volunteer_response["name"] == "Arthur"
  38. assert volunteer_response["id"] == default_volunteer_id
  39. assert "created_at" in volunteer_response
  40. async def test_create_volunteer(
  41. client: AsyncClient,
  42. default_public_project: Project,
  43. default_user_headers: dict,
  44. session: Session,
  45. ):
  46. # Test without autentication
  47. response = await client.post(
  48. app.url_path_for("create_volunteer", project_id=default_project_id)
  49. )
  50. assert response.status_code == 401
  51. payload = {
  52. "name": "Lancelot",
  53. "email": "lancelot@dulac.fr",
  54. "phone_number": "03 14 15 92 65",
  55. }
  56. # test invalid project_id
  57. response = await client.post(
  58. app.url_path_for("create_volunteer", project_id=uuid.uuid4()),
  59. json=payload,
  60. headers=default_user_headers,
  61. )
  62. assert response.status_code == 404
  63. # Test normal payload
  64. response = await client.post(
  65. app.url_path_for("create_volunteer", project_id=default_project_id),
  66. json=payload,
  67. headers=default_user_headers,
  68. )
  69. assert response.status_code == 200
  70. assert response.json()["id"] != default_project_id
  71. assert response.json()["name"] == "Lancelot"
  72. assert response.json()["comment"] == ""
  73. result = session.execute(
  74. select(Volunteer).where(Volunteer.project_id == default_project_id)
  75. )
  76. volunteers = result.scalars().all()
  77. assert len(volunteers) > 1
  78. # test invalid payload
  79. del payload["name"]
  80. response = await client.post(
  81. app.url_path_for("create_volunteer", project_id=default_project_id),
  82. json=payload,
  83. headers=default_user_headers,
  84. )
  85. assert response.status_code == 422
  86. async def test_create_volunteer_comment(
  87. client: AsyncClient,
  88. default_public_project: Project,
  89. default_user_headers: dict,
  90. session: Session,
  91. ):
  92. payload = {
  93. "name": "Lancelot",
  94. "email": "lancelot@dulac.fr",
  95. "phone_number": "03 14 15 92 65",
  96. "comment": "it's a knight",
  97. }
  98. # Test normal payload
  99. response = await client.post(
  100. app.url_path_for("create_volunteer", project_id=default_project_id),
  101. json=payload,
  102. headers=default_user_headers,
  103. )
  104. assert response.status_code == 200
  105. assert response.json()["id"] != default_project_id
  106. assert response.json()["name"] == "Lancelot"
  107. assert response.json()["comment"] != ""
  108. new_id = response.json()["id"]
  109. result = session.execute(select(Volunteer).where(Volunteer.id == new_id))
  110. volunteer = result.scalar_one_or_none()
  111. assert volunteer is not None
  112. assert volunteer.comment == "it's a knight"
  113. async def test_update_volunteer(
  114. client: AsyncClient,
  115. default_public_project: Project,
  116. default_user_headers: dict,
  117. session: Session,
  118. ):
  119. # Test without autentication
  120. response = await client.post(
  121. app.url_path_for(
  122. "update_volunteer",
  123. project_id=default_project_id,
  124. volunteer_id=default_volunteer_id,
  125. )
  126. )
  127. assert response.status_code == 401
  128. payload = {
  129. "name": "Lancelot",
  130. "email": "lancelot@dulac.fr",
  131. "phone_number": "03 14 15 92 65",
  132. "automatic_sms": False,
  133. "comment": "new comment",
  134. }
  135. # test invalid project_id
  136. response = await client.post(
  137. app.url_path_for(
  138. "update_volunteer",
  139. project_id=uuid.uuid4(),
  140. volunteer_id=default_volunteer_id,
  141. ),
  142. json=payload,
  143. headers=default_user_headers,
  144. )
  145. assert response.status_code == 404
  146. # test invalid volunteer_id
  147. response = await client.post(
  148. app.url_path_for(
  149. "update_volunteer",
  150. project_id=default_project_id,
  151. volunteer_id=uuid.uuid4(),
  152. ),
  153. json=payload,
  154. headers=default_user_headers,
  155. )
  156. assert response.status_code == 404
  157. # Test normal payload
  158. for k, v in payload.items():
  159. response = await client.post(
  160. app.url_path_for(
  161. "update_volunteer",
  162. project_id=default_project_id,
  163. volunteer_id=default_volunteer_id,
  164. ),
  165. json={k: v},
  166. headers=default_user_headers,
  167. )
  168. assert response.status_code == 200
  169. assert response.json()["id"] == default_volunteer_id
  170. assert response.json()[k] == v
  171. async def test_update_volunteer_slots(
  172. client: AsyncClient,
  173. default_public_project: Project,
  174. default_user_headers: dict,
  175. session: Session,
  176. ):
  177. response = await client.post(
  178. app.url_path_for(
  179. "update_volunteer",
  180. project_id=default_project_id,
  181. volunteer_id=default_volunteer_id,
  182. ),
  183. json={"slots": []},
  184. headers=default_user_headers,
  185. )
  186. assert response.status_code == 200
  187. result = session.execute(select(Slot).where(Slot.id == default_slot_id))
  188. slot = result.scalars().first()
  189. assert slot is not None
  190. assert slot.volunteers_id == []
  191. response = await client.post(
  192. app.url_path_for(
  193. "update_volunteer",
  194. project_id=default_project_id,
  195. volunteer_id=default_volunteer_id,
  196. ),
  197. json={"slots": [default_slot_id]},
  198. headers=default_user_headers,
  199. )
  200. assert response.status_code == 200
  201. session.refresh(slot)
  202. assert slot is not None
  203. assert slot.volunteers_id == [default_volunteer_id]
  204. # An invalid slot list
  205. response = await client.post(
  206. app.url_path_for(
  207. "update_volunteer",
  208. project_id=default_project_id,
  209. volunteer_id=default_volunteer_id,
  210. ),
  211. json={"slots": [str(uuid.uuid4())]},
  212. headers=default_user_headers,
  213. )
  214. assert response.status_code == 400
  215. # An invalid slot list
  216. response = await client.post(
  217. app.url_path_for(
  218. "update_volunteer",
  219. project_id=default_project_id,
  220. volunteer_id=default_volunteer_id,
  221. ),
  222. json={"slots": ["not uuid str"]},
  223. headers=default_user_headers,
  224. )
  225. assert response.status_code == 422
  226. async def test_delete_volunteer(
  227. client: AsyncClient,
  228. default_user_headers: dict,
  229. session: Session,
  230. default_public_project: Project,
  231. ):
  232. # Fail deleting the project due to not logged in
  233. response = await client.delete(
  234. app.url_path_for(
  235. "delete_volunteer",
  236. project_id=default_project_id,
  237. volunteer_id=default_volunteer_id,
  238. )
  239. )
  240. assert response.status_code == 401
  241. result = session.execute(
  242. select(Volunteer).where(Volunteer.id == default_volunteer_id)
  243. )
  244. volunteer = result.scalars().first()
  245. assert volunteer is not None
  246. # Proper deletion
  247. response = await client.delete(
  248. app.url_path_for(
  249. "delete_volunteer",
  250. project_id=default_project_id,
  251. volunteer_id=default_volunteer_id,
  252. ),
  253. headers=default_user_headers,
  254. )
  255. assert response.status_code == 200
  256. result = session.execute(
  257. select(Volunteer).where(Volunteer.id == default_volunteer_id)
  258. )
  259. volunteer = result.scalars().first()
  260. assert volunteer is None
  261. # check deletion is cascaded to slots
  262. result = session.execute(select(Slot).where(Slot.id == default_slot_id))
  263. slot: Slot | None = result.scalar_one_or_none()
  264. assert slot is not None
  265. assert default_volunteer_id not in slot.volunteers_id
  266. # Idempotence test
  267. response = await client.delete(
  268. app.url_path_for(
  269. "delete_volunteer",
  270. project_id=default_project_id,
  271. volunteer_id=default_volunteer_id,
  272. ),
  273. headers=default_user_headers,
  274. )
  275. assert response.status_code == 200
  276. # can delete random uuid
  277. response = await client.delete(
  278. app.url_path_for(
  279. "delete_volunteer", project_id=default_project_id, volunteer_id=uuid.uuid4()
  280. ),
  281. headers=default_user_headers,
  282. )
  283. assert response.status_code == 200
  284. # Cannot delete non uuid string
  285. response = await client.delete(
  286. app.url_path_for(
  287. "delete_volunteer", project_id=default_project_id, volunteer_id="not uidstr"
  288. ),
  289. headers=default_user_headers,
  290. )
  291. assert response.status_code == 422