test_volunteer.py 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  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. result = session.execute(
  73. select(Volunteer).where(Volunteer.project_id == default_project_id)
  74. )
  75. volunteers = result.scalars().all()
  76. assert len(volunteers) > 1
  77. # test invalid payload
  78. del payload["name"]
  79. response = await client.post(
  80. app.url_path_for("create_volunteer", project_id=default_project_id),
  81. json=payload,
  82. headers=default_user_headers,
  83. )
  84. assert response.status_code == 422
  85. async def test_update_volunteer(
  86. client: AsyncClient,
  87. default_public_project: Project,
  88. default_user_headers: dict,
  89. session: Session,
  90. ):
  91. # Test without autentication
  92. response = await client.post(
  93. app.url_path_for(
  94. "update_volunteer",
  95. project_id=default_project_id,
  96. volunteer_id=default_volunteer_id,
  97. )
  98. )
  99. assert response.status_code == 401
  100. payload = {
  101. "name": "Lancelot",
  102. "email": "lancelot@dulac.fr",
  103. "phone_number": "03 14 15 92 65",
  104. "automatic_sms": False,
  105. }
  106. # test invalid project_id
  107. response = await client.post(
  108. app.url_path_for(
  109. "update_volunteer",
  110. project_id=uuid.uuid4(),
  111. volunteer_id=default_volunteer_id,
  112. ),
  113. json=payload,
  114. headers=default_user_headers,
  115. )
  116. assert response.status_code == 404
  117. # test invalid volunteer_id
  118. response = await client.post(
  119. app.url_path_for(
  120. "update_volunteer",
  121. project_id=default_project_id,
  122. volunteer_id=uuid.uuid4(),
  123. ),
  124. json=payload,
  125. headers=default_user_headers,
  126. )
  127. assert response.status_code == 404
  128. # Test normal payload
  129. for k, v in payload.items():
  130. response = await client.post(
  131. app.url_path_for(
  132. "update_volunteer",
  133. project_id=default_project_id,
  134. volunteer_id=default_volunteer_id,
  135. ),
  136. json={k: v},
  137. headers=default_user_headers,
  138. )
  139. assert response.status_code == 200
  140. assert response.json()["id"] == default_volunteer_id
  141. assert response.json()[k] == v
  142. async def test_update_volunteer_slots(
  143. client: AsyncClient,
  144. default_public_project: Project,
  145. default_user_headers: dict,
  146. session: Session,
  147. ):
  148. response = await client.post(
  149. app.url_path_for(
  150. "update_volunteer",
  151. project_id=default_project_id,
  152. volunteer_id=default_volunteer_id,
  153. ),
  154. json={"slots": []},
  155. headers=default_user_headers,
  156. )
  157. assert response.status_code == 200
  158. result = session.execute(select(Slot).where(Slot.id == default_slot_id))
  159. slot = result.scalars().first()
  160. assert slot is not None
  161. assert slot.volunteers_id == []
  162. response = await client.post(
  163. app.url_path_for(
  164. "update_volunteer",
  165. project_id=default_project_id,
  166. volunteer_id=default_volunteer_id,
  167. ),
  168. json={"slots": [default_slot_id]},
  169. headers=default_user_headers,
  170. )
  171. assert response.status_code == 200
  172. session.refresh(slot)
  173. assert slot is not None
  174. assert slot.volunteers_id == [default_volunteer_id]
  175. # An invalid slot list
  176. response = await client.post(
  177. app.url_path_for(
  178. "update_volunteer",
  179. project_id=default_project_id,
  180. volunteer_id=default_volunteer_id,
  181. ),
  182. json={"slots": [str(uuid.uuid4())]},
  183. headers=default_user_headers,
  184. )
  185. assert response.status_code == 400
  186. # An invalid slot list
  187. response = await client.post(
  188. app.url_path_for(
  189. "update_volunteer",
  190. project_id=default_project_id,
  191. volunteer_id=default_volunteer_id,
  192. ),
  193. json={"slots": ["not uuid str"]},
  194. headers=default_user_headers,
  195. )
  196. assert response.status_code == 422
  197. async def test_delete_volunteer(
  198. client: AsyncClient,
  199. default_user_headers: dict,
  200. session: Session,
  201. default_public_project: Project,
  202. ):
  203. # Fail deleting the project due to not logged in
  204. response = await client.delete(
  205. app.url_path_for(
  206. "delete_volunteer",
  207. project_id=default_project_id,
  208. volunteer_id=default_volunteer_id,
  209. )
  210. )
  211. assert response.status_code == 401
  212. result = session.execute(
  213. select(Volunteer).where(Volunteer.id == default_volunteer_id)
  214. )
  215. volunteer = result.scalars().first()
  216. assert volunteer is not None
  217. # Proper deletion
  218. response = await client.delete(
  219. app.url_path_for(
  220. "delete_volunteer",
  221. project_id=default_project_id,
  222. volunteer_id=default_volunteer_id,
  223. ),
  224. headers=default_user_headers,
  225. )
  226. assert response.status_code == 200
  227. result = session.execute(
  228. select(Volunteer).where(Volunteer.id == default_volunteer_id)
  229. )
  230. volunteer = result.scalars().first()
  231. assert volunteer is None
  232. # check deletion is cascaded to slots
  233. result = session.execute(select(Slot).where(Slot.id == default_slot_id))
  234. slot: Slot | None = result.scalars().first()
  235. assert default_volunteer_id not in slot.volunteers_id
  236. # Idempotence test
  237. response = await client.delete(
  238. app.url_path_for(
  239. "delete_volunteer",
  240. project_id=default_project_id,
  241. volunteer_id=default_volunteer_id,
  242. ),
  243. headers=default_user_headers,
  244. )
  245. assert response.status_code == 200
  246. # can delete random uuid
  247. response = await client.delete(
  248. app.url_path_for(
  249. "delete_volunteer", project_id=default_project_id, volunteer_id=uuid.uuid4()
  250. ),
  251. headers=default_user_headers,
  252. )
  253. assert response.status_code == 200
  254. # Cannot delete non uuid string
  255. response = await client.delete(
  256. app.url_path_for(
  257. "delete_volunteer", project_id=default_project_id, volunteer_id="not uidstr"
  258. ),
  259. headers=default_user_headers,
  260. )
  261. assert response.status_code == 422