tests.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. import os
  2. from unittest import SkipTest
  3. from django.contrib.staticfiles.testing import StaticLiveServerTestCase
  4. from django.utils.module_loading import import_string
  5. from django.utils.translation import ugettext as _
  6. class AdminSeleniumWebDriverTestCase(StaticLiveServerTestCase):
  7. available_apps = [
  8. 'django.contrib.admin',
  9. 'django.contrib.auth',
  10. 'django.contrib.contenttypes',
  11. 'django.contrib.sessions',
  12. 'django.contrib.sites',
  13. ]
  14. webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
  15. @classmethod
  16. def setUpClass(cls):
  17. if not os.environ.get('DJANGO_SELENIUM_TESTS', False):
  18. raise SkipTest('Selenium tests not requested')
  19. try:
  20. cls.selenium = import_string(cls.webdriver_class)()
  21. except Exception as e:
  22. raise SkipTest('Selenium webdriver "%s" not installed or not '
  23. 'operational: %s' % (cls.webdriver_class, str(e)))
  24. # This has to be last to ensure that resources are cleaned up properly!
  25. super(AdminSeleniumWebDriverTestCase, cls).setUpClass()
  26. @classmethod
  27. def _tearDownClassInternal(cls):
  28. if hasattr(cls, 'selenium'):
  29. cls.selenium.quit()
  30. super(AdminSeleniumWebDriverTestCase, cls)._tearDownClassInternal()
  31. def wait_until(self, callback, timeout=10):
  32. """
  33. Helper function that blocks the execution of the tests until the
  34. specified callback returns a value that is not falsy. This function can
  35. be called, for example, after clicking a link or submitting a form.
  36. See the other public methods that call this function for more details.
  37. """
  38. from selenium.webdriver.support.wait import WebDriverWait
  39. WebDriverWait(self.selenium, timeout).until(callback)
  40. def wait_loaded_tag(self, tag_name, timeout=10):
  41. """
  42. Helper function that blocks until the element with the given tag name
  43. is found on the page.
  44. """
  45. self.wait_for(tag_name, timeout)
  46. def wait_for(self, css_selector, timeout=10):
  47. """
  48. Helper function that blocks until a CSS selector is found on the page.
  49. """
  50. from selenium.webdriver.common.by import By
  51. from selenium.webdriver.support import expected_conditions as ec
  52. self.wait_until(
  53. ec.presence_of_element_located((By.CSS_SELECTOR, css_selector)),
  54. timeout
  55. )
  56. def wait_for_text(self, css_selector, text, timeout=10):
  57. """
  58. Helper function that blocks until the text is found in the CSS selector.
  59. """
  60. from selenium.webdriver.common.by import By
  61. from selenium.webdriver.support import expected_conditions as ec
  62. self.wait_until(
  63. ec.text_to_be_present_in_element(
  64. (By.CSS_SELECTOR, css_selector), text),
  65. timeout
  66. )
  67. def wait_for_value(self, css_selector, text, timeout=10):
  68. """
  69. Helper function that blocks until the value is found in the CSS selector.
  70. """
  71. from selenium.webdriver.common.by import By
  72. from selenium.webdriver.support import expected_conditions as ec
  73. self.wait_until(
  74. ec.text_to_be_present_in_element_value(
  75. (By.CSS_SELECTOR, css_selector), text),
  76. timeout
  77. )
  78. def wait_page_loaded(self):
  79. """
  80. Block until page has started to load.
  81. """
  82. from selenium.common.exceptions import TimeoutException
  83. try:
  84. # Wait for the next page to be loaded
  85. self.wait_loaded_tag('body')
  86. except TimeoutException:
  87. # IE7 occasionally returns an error "Internet Explorer cannot
  88. # display the webpage" and doesn't load the next page. We just
  89. # ignore it.
  90. pass
  91. def admin_login(self, username, password, login_url='/admin/'):
  92. """
  93. Helper function to log into the admin.
  94. """
  95. self.selenium.get('%s%s' % (self.live_server_url, login_url))
  96. username_input = self.selenium.find_element_by_name('username')
  97. username_input.send_keys(username)
  98. password_input = self.selenium.find_element_by_name('password')
  99. password_input.send_keys(password)
  100. login_text = _('Log in')
  101. self.selenium.find_element_by_xpath(
  102. '//input[@value="%s"]' % login_text).click()
  103. self.wait_page_loaded()
  104. def get_css_value(self, selector, attribute):
  105. """
  106. Helper function that returns the value for the CSS attribute of an
  107. DOM element specified by the given selector. Uses the jQuery that ships
  108. with Django.
  109. """
  110. return self.selenium.execute_script(
  111. 'return django.jQuery("%s").css("%s")' % (selector, attribute))
  112. def get_select_option(self, selector, value):
  113. """
  114. Returns the <OPTION> with the value `value` inside the <SELECT> widget
  115. identified by the CSS selector `selector`.
  116. """
  117. from selenium.common.exceptions import NoSuchElementException
  118. options = self.selenium.find_elements_by_css_selector('%s > option' % selector)
  119. for option in options:
  120. if option.get_attribute('value') == value:
  121. return option
  122. raise NoSuchElementException('Option "%s" not found in "%s"' % (value, selector))
  123. def assertSelectOptions(self, selector, values):
  124. """
  125. Asserts that the <SELECT> widget identified by `selector` has the
  126. options with the given `values`.
  127. """
  128. options = self.selenium.find_elements_by_css_selector('%s > option' % selector)
  129. actual_values = []
  130. for option in options:
  131. actual_values.append(option.get_attribute('value'))
  132. self.assertEqual(values, actual_values)
  133. def has_css_class(self, selector, klass):
  134. """
  135. Returns True if the element identified by `selector` has the CSS class
  136. `klass`.
  137. """
  138. return (self.selenium.find_element_by_css_selector(selector)
  139. .get_attribute('class').find(klass) != -1)