Funktionierender Prototyp des Serious Games zur Vermittlung von Wissen zu Software-Engineering-Arbeitsmodellen.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tests.py 8.3KB

1 year ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. from contextlib import contextmanager
  2. from django.contrib.staticfiles.testing import StaticLiveServerTestCase
  3. from django.test import modify_settings
  4. from django.test.selenium import SeleniumTestCase
  5. from django.utils.deprecation import MiddlewareMixin
  6. from django.utils.translation import gettext as _
  7. class CSPMiddleware(MiddlewareMixin):
  8. """The admin's JavaScript should be compatible with CSP."""
  9. def process_response(self, request, response):
  10. response.headers["Content-Security-Policy"] = "default-src 'self'"
  11. return response
  12. @modify_settings(MIDDLEWARE={"append": "django.contrib.admin.tests.CSPMiddleware"})
  13. class AdminSeleniumTestCase(SeleniumTestCase, StaticLiveServerTestCase):
  14. available_apps = [
  15. "django.contrib.admin",
  16. "django.contrib.auth",
  17. "django.contrib.contenttypes",
  18. "django.contrib.sessions",
  19. "django.contrib.sites",
  20. ]
  21. def wait_until(self, callback, timeout=10):
  22. """
  23. Block the execution of the tests until the specified callback returns a
  24. value that is not falsy. This method can be called, for example, after
  25. clicking a link or submitting a form. See the other public methods that
  26. call this function for more details.
  27. """
  28. from selenium.webdriver.support.wait import WebDriverWait
  29. WebDriverWait(self.selenium, timeout).until(callback)
  30. def wait_for_and_switch_to_popup(self, num_windows=2, timeout=10):
  31. """
  32. Block until `num_windows` are present and are ready (usually 2, but can
  33. be overridden in the case of pop-ups opening other pop-ups). Switch the
  34. current window to the new pop-up.
  35. """
  36. self.wait_until(lambda d: len(d.window_handles) == num_windows, timeout)
  37. self.selenium.switch_to.window(self.selenium.window_handles[-1])
  38. self.wait_page_ready()
  39. def wait_for(self, css_selector, timeout=10):
  40. """
  41. Block until a CSS selector is found on the page.
  42. """
  43. from selenium.webdriver.common.by import By
  44. from selenium.webdriver.support import expected_conditions as ec
  45. self.wait_until(
  46. ec.presence_of_element_located((By.CSS_SELECTOR, css_selector)), timeout
  47. )
  48. def wait_for_text(self, css_selector, text, timeout=10):
  49. """
  50. Block until the text is found in the CSS selector.
  51. """
  52. from selenium.webdriver.common.by import By
  53. from selenium.webdriver.support import expected_conditions as ec
  54. self.wait_until(
  55. ec.text_to_be_present_in_element((By.CSS_SELECTOR, css_selector), text),
  56. timeout,
  57. )
  58. def wait_for_value(self, css_selector, text, timeout=10):
  59. """
  60. Block until the value is found in the CSS selector.
  61. """
  62. from selenium.webdriver.common.by import By
  63. from selenium.webdriver.support import expected_conditions as ec
  64. self.wait_until(
  65. ec.text_to_be_present_in_element_value(
  66. (By.CSS_SELECTOR, css_selector), text
  67. ),
  68. timeout,
  69. )
  70. def wait_until_visible(self, css_selector, timeout=10):
  71. """
  72. Block until the element described by the CSS selector is visible.
  73. """
  74. from selenium.webdriver.common.by import By
  75. from selenium.webdriver.support import expected_conditions as ec
  76. self.wait_until(
  77. ec.visibility_of_element_located((By.CSS_SELECTOR, css_selector)), timeout
  78. )
  79. def wait_until_invisible(self, css_selector, timeout=10):
  80. """
  81. Block until the element described by the CSS selector is invisible.
  82. """
  83. from selenium.webdriver.common.by import By
  84. from selenium.webdriver.support import expected_conditions as ec
  85. self.wait_until(
  86. ec.invisibility_of_element_located((By.CSS_SELECTOR, css_selector)), timeout
  87. )
  88. def wait_page_ready(self, timeout=10):
  89. """
  90. Block until the page is ready.
  91. """
  92. self.wait_until(
  93. lambda driver: driver.execute_script("return document.readyState;")
  94. == "complete",
  95. timeout,
  96. )
  97. @contextmanager
  98. def wait_page_loaded(self, timeout=10):
  99. """
  100. Block until a new page has loaded and is ready.
  101. """
  102. from selenium.webdriver.common.by import By
  103. from selenium.webdriver.support import expected_conditions as ec
  104. old_page = self.selenium.find_element(By.TAG_NAME, "html")
  105. yield
  106. # Wait for the next page to be loaded
  107. self.wait_until(ec.staleness_of(old_page), timeout=timeout)
  108. self.wait_page_ready(timeout=timeout)
  109. def admin_login(self, username, password, login_url="/admin/"):
  110. """
  111. Log in to the admin.
  112. """
  113. from selenium.webdriver.common.by import By
  114. self.selenium.get("%s%s" % (self.live_server_url, login_url))
  115. username_input = self.selenium.find_element(By.NAME, "username")
  116. username_input.send_keys(username)
  117. password_input = self.selenium.find_element(By.NAME, "password")
  118. password_input.send_keys(password)
  119. login_text = _("Log in")
  120. with self.wait_page_loaded():
  121. self.selenium.find_element(
  122. By.XPATH, '//input[@value="%s"]' % login_text
  123. ).click()
  124. def select_option(self, selector, value):
  125. """
  126. Select the <OPTION> with the value `value` inside the <SELECT> widget
  127. identified by the CSS selector `selector`.
  128. """
  129. from selenium.webdriver.common.by import By
  130. from selenium.webdriver.support.ui import Select
  131. select = Select(self.selenium.find_element(By.CSS_SELECTOR, selector))
  132. select.select_by_value(value)
  133. def deselect_option(self, selector, value):
  134. """
  135. Deselect the <OPTION> with the value `value` inside the <SELECT> widget
  136. identified by the CSS selector `selector`.
  137. """
  138. from selenium.webdriver.common.by import By
  139. from selenium.webdriver.support.ui import Select
  140. select = Select(self.selenium.find_element(By.CSS_SELECTOR, selector))
  141. select.deselect_by_value(value)
  142. def assertCountSeleniumElements(self, selector, count, root_element=None):
  143. """
  144. Assert number of matches for a CSS selector.
  145. `root_element` allow restriction to a pre-selected node.
  146. """
  147. from selenium.webdriver.common.by import By
  148. root_element = root_element or self.selenium
  149. self.assertEqual(
  150. len(root_element.find_elements(By.CSS_SELECTOR, selector)), count
  151. )
  152. def _assertOptionsValues(self, options_selector, values):
  153. from selenium.webdriver.common.by import By
  154. if values:
  155. options = self.selenium.find_elements(By.CSS_SELECTOR, options_selector)
  156. actual_values = []
  157. for option in options:
  158. actual_values.append(option.get_attribute("value"))
  159. self.assertEqual(values, actual_values)
  160. else:
  161. # Prevent the `find_elements(By.CSS_SELECTOR, …)` call from blocking
  162. # if the selector doesn't match any options as we expect it
  163. # to be the case.
  164. with self.disable_implicit_wait():
  165. self.wait_until(
  166. lambda driver: not driver.find_elements(
  167. By.CSS_SELECTOR, options_selector
  168. )
  169. )
  170. def assertSelectOptions(self, selector, values):
  171. """
  172. Assert that the <SELECT> widget identified by `selector` has the
  173. options with the given `values`.
  174. """
  175. self._assertOptionsValues("%s > option" % selector, values)
  176. def assertSelectedOptions(self, selector, values):
  177. """
  178. Assert that the <SELECT> widget identified by `selector` has the
  179. selected options with the given `values`.
  180. """
  181. self._assertOptionsValues("%s > option:checked" % selector, values)
  182. def has_css_class(self, selector, klass):
  183. """
  184. Return True if the element identified by `selector` has the CSS class
  185. `klass`.
  186. """
  187. from selenium.webdriver.common.by import By
  188. return (
  189. self.selenium.find_element(
  190. By.CSS_SELECTOR,
  191. selector,
  192. )
  193. .get_attribute("class")
  194. .find(klass)
  195. != -1
  196. )