test_sms_batch.py 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. from datetime import datetime, timedelta
  2. from httpx import AsyncClient
  3. import pytest
  4. from sqlalchemy import select
  5. from sqlalchemy.orm import Session
  6. from app.main import app
  7. from app.models import Project, Slot, SlotTemplate, Sms, Volunteer
  8. from app.tests.conftest import default_sms_id, default_volunteer_id
  9. def get_arthur(session) -> Volunteer:
  10. result = session.execute(select(Volunteer).where(Volunteer.id == default_volunteer_id))
  11. arthur = result.scalars().first()
  12. assert arthur is not None
  13. return arthur
  14. async def test_create_sms_batch_bad_input(
  15. client: AsyncClient,
  16. default_user_headers: dict,
  17. session: Session,
  18. default_public_project: Project,
  19. ):
  20. response = await client.post(
  21. app.url_path_for("create_sms_batch", project_id=default_public_project.id),
  22. json={"is_public": False},
  23. )
  24. assert response.status_code == 401
  25. async def test_basic(
  26. client: AsyncClient,
  27. default_user_headers: dict,
  28. session: Session,
  29. default_public_project: Project,
  30. ):
  31. slot = Slot(
  32. project_id=default_public_project.id,
  33. title="replanter excalibure",
  34. starting_time=datetime.now() + timedelta(minutes=30),
  35. ending_time=datetime.now() + timedelta(minutes=60),
  36. )
  37. slot.volunteers.append(get_arthur(session))
  38. session.add(slot)
  39. session.commit()
  40. # créer un sms simple
  41. response = await client.post(
  42. app.url_path_for("create_sms_batch", project_id=default_public_project.id),
  43. headers=default_user_headers,
  44. json={"template": "Bonjour {prenom}!\n{titre}"},
  45. )
  46. assert response.status_code == 200
  47. result = session.execute(
  48. select(Sms).where(
  49. (Sms.project_id == default_public_project.id) & (Sms.id != default_sms_id)
  50. )
  51. )
  52. sms = result.scalars().first()
  53. assert sms is not None
  54. assert sms.content == "Bonjour Arthur!\nreplanter excalibure"
  55. async def test_multiple_volunteer(
  56. client: AsyncClient,
  57. default_user_headers: dict,
  58. session: Session,
  59. default_public_project: Project,
  60. ):
  61. slot = Slot(
  62. project_id=default_public_project.id,
  63. title="replanter excalibure",
  64. starting_time=datetime.now() + timedelta(minutes=30),
  65. ending_time=datetime.now() + timedelta(minutes=60),
  66. )
  67. slot.volunteers.append(get_arthur(session))
  68. slot.volunteers.append(
  69. Volunteer(
  70. project_id=default_public_project.id,
  71. name="benevole 2",
  72. surname="echo",
  73. phone_number="t",
  74. email="",
  75. automatic_sms=True,
  76. )
  77. )
  78. session.add(slot)
  79. session.commit()
  80. # créer un sms simple
  81. response = await client.post(
  82. app.url_path_for("create_sms_batch", project_id=default_public_project.id),
  83. headers=default_user_headers,
  84. json={"template": "Bonjour {prenom}!\n{titre}"},
  85. )
  86. assert response.status_code == 200
  87. result = session.execute(
  88. select(Sms).where(
  89. (Sms.project_id == default_public_project.id) & (Sms.id != default_sms_id)
  90. )
  91. )
  92. count_sms = 0
  93. for _ in result.fetchall():
  94. count_sms += 1
  95. assert count_sms == 2
  96. @pytest.mark.parametrize("automatic_sms,expected", [(True, True), (False, False)])
  97. async def test_volunteer_settings(
  98. client: AsyncClient,
  99. default_user_headers: dict,
  100. session: Session,
  101. default_public_project: Project,
  102. automatic_sms: bool,
  103. expected: bool,
  104. ):
  105. slot = Slot(
  106. project_id=default_public_project.id,
  107. title="replanter excalibure",
  108. starting_time=datetime.now() + timedelta(minutes=30),
  109. ending_time=datetime.now() + timedelta(minutes=60),
  110. )
  111. arthur = get_arthur(session)
  112. arthur.automatic_sms = automatic_sms
  113. slot.volunteers.append(arthur)
  114. session.add(slot)
  115. session.commit()
  116. # créer un sms simple
  117. response = await client.post(
  118. app.url_path_for("create_sms_batch", project_id=default_public_project.id),
  119. headers=default_user_headers,
  120. json={"template": "Bonjour {prenom}!\n{titre}"},
  121. )
  122. assert response.status_code == 200
  123. result = session.execute(
  124. select(Sms).where(
  125. (Sms.project_id == default_public_project.id) & (Sms.id != default_sms_id)
  126. )
  127. )
  128. sms = result.scalars().first()
  129. assert (sms is not None) == expected
  130. async def test_only_future_slot(
  131. client: AsyncClient,
  132. default_user_headers: dict,
  133. session: Session,
  134. default_public_project: Project,
  135. ):
  136. # Create a slot starting in the past
  137. # no sms should be issued
  138. slot = Slot(
  139. project_id=default_public_project.id,
  140. title="replanter excalibure",
  141. starting_time=datetime.now() + timedelta(minutes=-30),
  142. ending_time=datetime.now() + timedelta(minutes=60),
  143. )
  144. slot.volunteers.append(get_arthur(session))
  145. session.add(slot)
  146. session.commit()
  147. # créer un sms simple
  148. response = await client.post(
  149. app.url_path_for("create_sms_batch", project_id=default_public_project.id),
  150. headers=default_user_headers,
  151. json={"template": "Bonjour {prenom}!\n{titre}"},
  152. )
  153. assert response.status_code == 200
  154. result = session.execute(
  155. select(Sms).where(
  156. (Sms.project_id == default_public_project.id) & (Sms.id != default_sms_id)
  157. )
  158. )
  159. sms = result.scalars().first()
  160. assert sms is None
  161. @pytest.mark.parametrize("delta_t,expected", [(32, False), (28, True)])
  162. async def test_time_delta(
  163. client: AsyncClient,
  164. default_user_headers: dict,
  165. session: Session,
  166. default_public_project: Project,
  167. delta_t: int,
  168. expected,
  169. ):
  170. # Create a slot starting in the past
  171. # no sms should be issued
  172. slot = Slot(
  173. project_id=default_public_project.id,
  174. title="replanter excalibure",
  175. starting_time=datetime.now() + timedelta(minutes=30),
  176. ending_time=datetime.now() + timedelta(minutes=60),
  177. )
  178. slot.volunteers.append(get_arthur(session))
  179. session.add(slot)
  180. session.commit()
  181. # créer un sms simple
  182. response = await client.post(
  183. app.url_path_for("create_sms_batch", project_id=default_public_project.id),
  184. headers=default_user_headers,
  185. json={"template": "Bonjour {prenom}!\n{titre}", "delta_t": delta_t},
  186. )
  187. assert response.status_code == 200
  188. result = session.execute(
  189. select(Sms).where(
  190. (Sms.project_id == default_public_project.id) & (Sms.id != default_sms_id)
  191. )
  192. )
  193. sms = result.scalars().first()
  194. assert (sms is not None) == expected
  195. starting_time = datetime.now() + timedelta(minutes=30)
  196. @pytest.mark.parametrize(
  197. "template,expected",
  198. [
  199. ("no escape", "no escape"),
  200. ("{titre}", "replanter excalibure"),
  201. ("{prenom}", "Arthur"),
  202. ("{prenom} {nom}", "Arthur Pandragon"),
  203. ("{debut}", starting_time.strftime("%Hh%M")),
  204. (
  205. "{titre} {description}, {respo}",
  206. "replanter excalibure {description}, {respo}",
  207. ),
  208. ],
  209. )
  210. async def test_content_no_template(
  211. client: AsyncClient,
  212. default_user_headers: dict,
  213. session: Session,
  214. default_public_project: Project,
  215. template: str,
  216. expected: str,
  217. ):
  218. # Create a slot starting in the past
  219. # no sms should be issued
  220. slot = Slot(
  221. project_id=default_public_project.id,
  222. title="replanter excalibure",
  223. starting_time=starting_time,
  224. ending_time=datetime.now() + timedelta(minutes=60),
  225. )
  226. slot.volunteers.append(get_arthur(session))
  227. session.add(slot)
  228. session.commit()
  229. # créer un sms simple
  230. response = await client.post(
  231. app.url_path_for("create_sms_batch", project_id=default_public_project.id),
  232. headers=default_user_headers,
  233. json={"template": template},
  234. )
  235. assert response.status_code == 200
  236. result = session.execute(
  237. select(Sms).where(
  238. (Sms.project_id == default_public_project.id) & (Sms.id != default_sms_id)
  239. )
  240. )
  241. sms = result.scalars().first()
  242. assert sms is not None
  243. assert sms.content == expected
  244. @pytest.mark.parametrize(
  245. "template,expected",
  246. [
  247. ("no escape", "no escape"),
  248. ("{titre}", "replanter excalibure"),
  249. ("{prenom}", "Arthur"),
  250. ("{prenom} {nom}", "Arthur Pandragon"),
  251. ("{debut}", starting_time.strftime("%Hh%M")),
  252. (
  253. "{titre} {description}, {respo}",
  254. "replanter excalibure rendre l'épee à son caillou, dieu",
  255. ),
  256. ],
  257. )
  258. async def test_content_with_template(
  259. client: AsyncClient,
  260. default_user_headers: dict,
  261. session: Session,
  262. default_public_project: Project,
  263. template: str,
  264. expected: str,
  265. ):
  266. # Create a slot starting in the past
  267. # no sms should be issued
  268. slot_template = SlotTemplate(
  269. project_id=default_public_project.id,
  270. title="replanter excalibure",
  271. description="rendre l'épee à son caillou",
  272. responsible_contact="dieu",
  273. place="gros caillou",
  274. )
  275. slot = Slot(
  276. project_id=default_public_project.id,
  277. title="replanter excalibure",
  278. starting_time=starting_time,
  279. ending_time=datetime.now() + timedelta(minutes=60),
  280. )
  281. slot.template = slot_template
  282. slot.volunteers.append(get_arthur(session))
  283. session.add(slot_template)
  284. session.add(slot)
  285. session.commit()
  286. # créer un sms simple
  287. response = await client.post(
  288. app.url_path_for("create_sms_batch", project_id=default_public_project.id),
  289. headers=default_user_headers,
  290. json={"template": template},
  291. )
  292. assert response.status_code == 200
  293. result = session.execute(
  294. select(Sms).where(
  295. (Sms.project_id == default_public_project.id) & (Sms.id != default_sms_id)
  296. )
  297. )
  298. sms = result.scalars().first()
  299. assert sms is not None
  300. assert sms.content == expected