test_sms.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. from datetime import datetime, timezone
  2. import uuid
  3. from httpx import AsyncClient
  4. from sqlalchemy import select
  5. from sqlalchemy.orm import Session
  6. from app.main import app
  7. from app.models import Project, Sms, Sms, Volunteer
  8. from app.tests.conftest import default_project_id, default_volunteer_id, default_sms_id
  9. async def test_read_list_project_sms(
  10. client: AsyncClient, default_user_headers: dict, default_public_project: Project
  11. ):
  12. response = await client.get(
  13. app.url_path_for("list_project_sms", project_id=default_project_id),
  14. )
  15. assert response.status_code == 401
  16. response = await client.get(
  17. app.url_path_for("list_project_sms", project_id=uuid.uuid4()),
  18. headers=default_user_headers,
  19. )
  20. assert response.status_code == 404
  21. response = await client.get(
  22. app.url_path_for("list_project_sms", project_id="pas un uuid valid"),
  23. headers=default_user_headers,
  24. )
  25. assert response.status_code == 422
  26. response = await client.get(
  27. app.url_path_for("list_project_sms", project_id=default_project_id),
  28. headers=default_user_headers,
  29. )
  30. assert response.status_code == 200
  31. data = response.json()
  32. assert len(data) == 1
  33. assert data[0]["id"] == default_sms_id
  34. async def test_create_sms(
  35. client: AsyncClient,
  36. default_public_project: Project,
  37. default_user_headers: dict,
  38. session: Session,
  39. ):
  40. # Test without autentication
  41. response = await client.post(app.url_path_for("create_sms", project_id=default_project_id))
  42. assert response.status_code == 401
  43. starting_time = datetime(1900, 1, 1)
  44. payload = {"phone_number": "06 75 75 75 75 ", "content": "sms_content"}
  45. # test invalid project_id
  46. response = await client.post(
  47. app.url_path_for("create_sms", project_id=uuid.uuid4()),
  48. json=payload,
  49. headers=default_user_headers,
  50. )
  51. assert response.status_code == 404
  52. # Test normal payload
  53. before_creation_time = datetime.now(timezone.utc)
  54. response = await client.post(
  55. app.url_path_for("create_sms", project_id=default_project_id),
  56. json=payload,
  57. headers=default_user_headers,
  58. )
  59. assert response.status_code == 200
  60. assert response.json()["content"] == "sms_content"
  61. result = session.execute(
  62. select(Sms).where((Sms.project_id == default_project_id) & (Sms.id != default_sms_id))
  63. )
  64. sms = result.scalars().first()
  65. assert sms is not None
  66. assert sms.content == "sms_content"
  67. assert before_creation_time < sms.sending_time
  68. assert sms.sending_time < datetime.now(timezone.utc)
  69. # test invalid payload
  70. del payload["content"]
  71. response = await client.post(
  72. app.url_path_for("create_sms", project_id=default_project_id),
  73. json=payload,
  74. headers=default_user_headers,
  75. )
  76. assert response.status_code == 422
  77. async def test_update_sms(
  78. client: AsyncClient,
  79. default_public_project: Project,
  80. default_user_headers: dict,
  81. session: Session,
  82. ):
  83. # Test without autentication
  84. response = await client.post(
  85. app.url_path_for(
  86. "update_sms",
  87. project_id=default_project_id,
  88. sms_id=default_sms_id,
  89. )
  90. )
  91. assert response.status_code == 401
  92. # Test invalid payload
  93. response = await client.post(
  94. app.url_path_for(
  95. "update_sms",
  96. project_id=default_project_id,
  97. sms_id=default_sms_id,
  98. ),
  99. json={"volunteer_id": True},
  100. headers=default_user_headers,
  101. )
  102. assert response.status_code == 422
  103. payload = {
  104. "volunteer_id": default_volunteer_id,
  105. "phone_number": "06 75 75 75 75 ",
  106. "content": "sms_content",
  107. "sending_time": datetime(2024, 5, 17, tzinfo=timezone.utc).isoformat(),
  108. }
  109. # test invalid project_id
  110. response = await client.post(
  111. app.url_path_for(
  112. "update_sms",
  113. project_id=uuid.uuid4(),
  114. sms_id=default_sms_id,
  115. ),
  116. json=payload,
  117. headers=default_user_headers,
  118. )
  119. assert response.status_code == 404
  120. # test invalid sms_id
  121. response = await client.post(
  122. app.url_path_for(
  123. "update_sms",
  124. project_id=default_project_id,
  125. sms_id=uuid.uuid4(),
  126. ),
  127. json=payload,
  128. headers=default_user_headers,
  129. )
  130. assert response.status_code == 404
  131. # Test normal payload
  132. for k, v in payload.items():
  133. response = await client.post(
  134. app.url_path_for(
  135. "update_sms",
  136. project_id=default_project_id,
  137. sms_id=default_sms_id,
  138. ),
  139. json={k: v},
  140. headers=default_user_headers,
  141. )
  142. assert response.status_code == 200
  143. assert response.json()["id"] == default_sms_id
  144. if "time" in k:
  145. parsed_time = datetime.fromisoformat(response.json()[k])
  146. assert parsed_time == datetime.fromisoformat(v)
  147. else:
  148. assert response.json()[k] == v
  149. async def test_delete_sms(
  150. client: AsyncClient,
  151. default_user_headers: dict,
  152. session: Session,
  153. default_public_project: Project,
  154. ):
  155. # Fail deleting the project due to not logged in
  156. response = await client.delete(
  157. app.url_path_for(
  158. "delete_sms",
  159. project_id=default_project_id,
  160. sms_id=default_sms_id,
  161. )
  162. )
  163. assert response.status_code == 401
  164. result = session.execute(select(Sms).where(Sms.id == default_sms_id))
  165. sms = result.scalars().first()
  166. assert sms is not None
  167. # Proper deletion
  168. response = await client.delete(
  169. app.url_path_for(
  170. "delete_sms",
  171. project_id=default_project_id,
  172. sms_id=default_sms_id,
  173. ),
  174. headers=default_user_headers,
  175. )
  176. assert response.status_code == 200
  177. result = session.execute(select(Sms).where(Sms.id == default_sms_id))
  178. sms = result.scalars().first()
  179. assert sms is None
  180. # Idempotence test
  181. response = await client.delete(
  182. app.url_path_for(
  183. "delete_sms",
  184. project_id=default_project_id,
  185. sms_id=default_sms_id,
  186. ),
  187. headers=default_user_headers,
  188. )
  189. assert response.status_code == 200
  190. # can delete random uuid
  191. response = await client.delete(
  192. app.url_path_for("delete_sms", project_id=default_project_id, sms_id=uuid.uuid4()),
  193. headers=default_user_headers,
  194. )
  195. assert response.status_code == 200
  196. # Cannot delete non uuid string
  197. response = await client.delete(
  198. app.url_path_for("delete_sms", project_id=default_project_id, sms_id="not uidstr"),
  199. headers=default_user_headers,
  200. )
  201. assert response.status_code == 422
  202. async def test_delete_sms_with_volunteer(
  203. client: AsyncClient,
  204. default_user_headers: dict,
  205. session: Session,
  206. default_public_project: Project,
  207. ):
  208. result = session.execute(select(Volunteer).where(Volunteer.id == default_volunteer_id))
  209. volunteer = result.scalars().first()
  210. assert volunteer is not None
  211. assert len(volunteer.sms) == 0
  212. result = session.execute(select(Sms).where(Sms.id == default_sms_id))
  213. sms = result.scalars().first()
  214. assert sms is not None
  215. sms.volunteer_id = default_volunteer_id
  216. session.commit()
  217. session.refresh(volunteer)
  218. assert len(volunteer.sms) == 1, "Sms not added to volunteer"
  219. response = await client.delete(
  220. app.url_path_for(
  221. "delete_sms",
  222. project_id=default_project_id,
  223. sms_id=default_sms_id,
  224. ),
  225. headers=default_user_headers,
  226. )
  227. assert response.status_code == 200
  228. result = session.execute(select(Sms).where(Sms.id == default_sms_id))
  229. assert result.scalars().first() is None
  230. session.refresh(volunteer)
  231. assert len(volunteer.sms) == 0, "Sms should be deleted"
  232. result = session.execute(select(Volunteer).where(Volunteer.id == default_volunteer_id))
  233. volunteer_result = result.scalars().first()
  234. assert volunteer_result is not None, "Volunteer should not be deleted"
  235. assert len(volunteer_result.sms) == 0, "No more sms associated to volunteer"