utils.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. from __future__ import annotations
  2. import json
  3. from flask import url_for, current_app, Response
  4. from sqlalchemy import select
  5. from flexmeasures.data import db
  6. from flexmeasures.data.services.users import find_user_by_email
  7. from flexmeasures.data.models.user import Account
  8. """
  9. Useful things for API testing
  10. """
  11. def get_auth_token(client, user_email, password):
  12. """
  13. Get an auth token for a user via the API (like users need to do in real life).
  14. TODO: if you have the user object (e.g. from DB, you simply get the token via my_user.get_auth_token()!
  15. """
  16. print("Getting auth token for %s ..." % user_email)
  17. auth_data = json.dumps({"email": user_email, "password": password})
  18. auth_response = client.post(
  19. url_for("flexmeasures_api.request_auth_token"),
  20. data=auth_data,
  21. headers={"content-type": "application/json"},
  22. )
  23. if "errors" in auth_response.json:
  24. raise Exception(";".join(auth_response.json["errors"]))
  25. return auth_response.json["auth_token"]
  26. class AccountContext(object):
  27. """
  28. Context manager for a temporary account instance from the DB,
  29. which is expunged from the session at Exit.
  30. Expunging is useful, so that the API call being tested still operates on
  31. a "fresh" session.
  32. While the context is alive, you can collect any useful information, like
  33. the account's assets:
  34. with AccountContext("Supplier") as supplier:
  35. assets = supplier.generic_assets
  36. """
  37. def __init__(self, account_name: str):
  38. self.the_account = db.session.execute(
  39. select(Account).filter(Account.name == account_name)
  40. ).scalar_one_or_none()
  41. def __enter__(self):
  42. return self.the_account
  43. def __exit__(self, type, value, traceback):
  44. db.session.expunge(self.the_account)
  45. class UserContext(object):
  46. """
  47. Context manager for a temporary user instance from the DB,
  48. which is expunged from the session at Exit.
  49. Expunging is useful, so that the API call being tested still operates on
  50. a "fresh" session.
  51. While the context is alive, you can collect any useful information, like
  52. the user's assets:
  53. with UserContext("test_prosumer_user@seita.nl") as prosumer:
  54. user_roles = prosumer.roles
  55. """
  56. def __init__(self, user_email: str):
  57. self.the_user = find_user_by_email(user_email)
  58. def __enter__(self):
  59. return self.the_user
  60. def __exit__(self, type, value, traceback):
  61. db.session.expunge(self.the_user)
  62. def get_task_run(client, task_name: str, token=None):
  63. """Utility for getting task run information"""
  64. headers = {"Authorization": token}
  65. if token is None:
  66. headers["Authorization"] = current_app.config.get(
  67. "FLEXMEASURES_TASK_CHECK_AUTH_TOKEN", ""
  68. )
  69. elif token == "NOAUTH":
  70. headers = {}
  71. return client.get(
  72. url_for("flexmeasures_api_ops.get_task_run"),
  73. query_string={"name": task_name},
  74. headers=headers,
  75. )
  76. def post_task_run(client, task_name: str, status: bool = True):
  77. """Utility for getting task run information"""
  78. return client.post(
  79. url_for("flexmeasures_api_ops.post_task_run"),
  80. data={"name": task_name, "status": status},
  81. headers={
  82. "Authorization": get_auth_token(client, "task_runner@seita.nl", "testtest")
  83. },
  84. )
  85. def check_deprecation(
  86. response: Response,
  87. deprecation: str | None = "Tue, 13 Dec 2022 23:59:59 GMT",
  88. sunset: str | None = "Tue, 31 Jan 2023 23:59:59 GMT",
  89. ):
  90. """Check deprecation and sunset headers.
  91. Also make sure we link to some url for further info.
  92. If deprecation is None, make sure there are *no* deprecation headers.
  93. If sunset is None, make sure there are *no* sunset headers.
  94. """
  95. print(response.headers)
  96. if deprecation:
  97. assert deprecation in response.headers.getlist("Deprecation")
  98. assert any(
  99. 'rel="deprecation"' in link for link in response.headers.getlist("Link")
  100. )
  101. else:
  102. assert deprecation not in response.headers.getlist("Deprecation")
  103. assert all(
  104. 'rel="deprecation"' not in link for link in response.headers.getlist("Link")
  105. )
  106. if sunset:
  107. assert sunset in response.headers.getlist("Sunset")
  108. assert any('rel="sunset"' in link for link in response.headers.getlist("Link"))
  109. else:
  110. assert sunset not in response.headers.getlist("Sunset")
  111. assert all(
  112. 'rel="sunset"' not in link for link in response.headers.getlist("Link")
  113. )