2019-11-27 21:36:26 +08:00
|
|
|
from contextlib import contextmanager
|
|
|
|
|
2014-08-28 14:44:26 +08:00
|
|
|
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
|
2016-02-07 10:24:36 +08:00
|
|
|
from django.test import modify_settings
|
|
|
|
from django.test.selenium import SeleniumTestCase
|
2015-11-07 23:12:37 +08:00
|
|
|
from django.utils.deprecation import MiddlewareMixin
|
2017-01-27 03:58:33 +08:00
|
|
|
from django.utils.translation import gettext as _
|
Fixed #2879 -- Added support for the integration with Selenium and other in-browser testing frameworks. Also added the first Selenium tests for `contrib.admin`. Many thanks to everyone for their contributions and feedback: Mikeal Rogers, Dirk Datzert, mir, Simon G., Almad, Russell Keith-Magee, Denis Golomazov, devin, robertrv, andrewbadr, Idan Gazit, voidspace, Tom Christie, hjwp2, Adam Nelson, Jannis Leidel, Anssi Kääriäinen, Preston Holmes, Bruno Renié and Jacob Kaplan-Moss.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17241 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2011-12-22 16:33:58 +08:00
|
|
|
|
2013-06-04 14:09:29 +08:00
|
|
|
|
2015-11-07 23:12:37 +08:00
|
|
|
class CSPMiddleware(MiddlewareMixin):
|
2015-11-23 18:46:19 +08:00
|
|
|
"""The admin's JavaScript should be compatible with CSP."""
|
|
|
|
def process_response(self, request, response):
|
2020-07-14 19:32:24 +08:00
|
|
|
response.headers['Content-Security-Policy'] = "default-src 'self'"
|
2015-11-23 18:46:19 +08:00
|
|
|
return response
|
|
|
|
|
|
|
|
|
2015-11-07 23:12:37 +08:00
|
|
|
@modify_settings(MIDDLEWARE={'append': 'django.contrib.admin.tests.CSPMiddleware'})
|
2016-02-07 10:24:36 +08:00
|
|
|
class AdminSeleniumTestCase(SeleniumTestCase, StaticLiveServerTestCase):
|
2013-06-04 14:09:29 +08:00
|
|
|
|
|
|
|
available_apps = [
|
|
|
|
'django.contrib.admin',
|
|
|
|
'django.contrib.auth',
|
|
|
|
'django.contrib.contenttypes',
|
|
|
|
'django.contrib.sessions',
|
|
|
|
'django.contrib.sites',
|
|
|
|
]
|
Fixed #2879 -- Added support for the integration with Selenium and other in-browser testing frameworks. Also added the first Selenium tests for `contrib.admin`. Many thanks to everyone for their contributions and feedback: Mikeal Rogers, Dirk Datzert, mir, Simon G., Almad, Russell Keith-Magee, Denis Golomazov, devin, robertrv, andrewbadr, Idan Gazit, voidspace, Tom Christie, hjwp2, Adam Nelson, Jannis Leidel, Anssi Kääriäinen, Preston Holmes, Bruno Renié and Jacob Kaplan-Moss.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17241 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2011-12-22 16:33:58 +08:00
|
|
|
|
2011-12-29 06:20:30 +08:00
|
|
|
def wait_until(self, callback, timeout=10):
|
|
|
|
"""
|
2017-01-25 04:31:57 +08:00
|
|
|
Block the execution of the tests until the specified callback returns a
|
|
|
|
value that is not falsy. This method can be called, for example, after
|
|
|
|
clicking a link or submitting a form. See the other public methods that
|
|
|
|
call this function for more details.
|
2011-12-29 06:20:30 +08:00
|
|
|
"""
|
|
|
|
from selenium.webdriver.support.wait import WebDriverWait
|
|
|
|
WebDriverWait(self.selenium, timeout).until(callback)
|
|
|
|
|
2019-11-29 12:06:42 +08:00
|
|
|
def wait_for_and_switch_to_popup(self, num_windows=2, timeout=10):
|
2015-08-20 08:43:27 +08:00
|
|
|
"""
|
2019-11-29 12:06:42 +08:00
|
|
|
Block until `num_windows` are present and are ready (usually 2, but can
|
|
|
|
be overridden in the case of pop-ups opening other pop-ups). Switch the
|
|
|
|
current window to the new pop-up.
|
2015-08-20 08:43:27 +08:00
|
|
|
"""
|
|
|
|
self.wait_until(lambda d: len(d.window_handles) == num_windows, timeout)
|
2019-11-29 12:06:42 +08:00
|
|
|
self.selenium.switch_to.window(self.selenium.window_handles[-1])
|
|
|
|
self.wait_page_ready()
|
2015-08-20 08:43:27 +08:00
|
|
|
|
2014-01-03 07:31:53 +08:00
|
|
|
def wait_for(self, css_selector, timeout=10):
|
|
|
|
"""
|
2017-01-25 04:31:57 +08:00
|
|
|
Block until a CSS selector is found on the page.
|
2014-01-03 07:31:53 +08:00
|
|
|
"""
|
|
|
|
from selenium.webdriver.common.by import By
|
|
|
|
from selenium.webdriver.support import expected_conditions as ec
|
|
|
|
self.wait_until(
|
|
|
|
ec.presence_of_element_located((By.CSS_SELECTOR, css_selector)),
|
|
|
|
timeout
|
|
|
|
)
|
|
|
|
|
|
|
|
def wait_for_text(self, css_selector, text, timeout=10):
|
|
|
|
"""
|
2017-01-25 04:31:57 +08:00
|
|
|
Block until the text is found in the CSS selector.
|
2014-01-03 07:31:53 +08:00
|
|
|
"""
|
|
|
|
from selenium.webdriver.common.by import By
|
2014-01-03 18:25:24 +08:00
|
|
|
from selenium.webdriver.support import expected_conditions as ec
|
|
|
|
self.wait_until(
|
|
|
|
ec.text_to_be_present_in_element(
|
|
|
|
(By.CSS_SELECTOR, css_selector), text),
|
|
|
|
timeout
|
|
|
|
)
|
|
|
|
|
|
|
|
def wait_for_value(self, css_selector, text, timeout=10):
|
|
|
|
"""
|
2017-01-25 04:31:57 +08:00
|
|
|
Block until the value is found in the CSS selector.
|
2014-01-03 18:25:24 +08:00
|
|
|
"""
|
|
|
|
from selenium.webdriver.common.by import By
|
2014-01-03 07:31:53 +08:00
|
|
|
from selenium.webdriver.support import expected_conditions as ec
|
2011-12-29 06:20:30 +08:00
|
|
|
self.wait_until(
|
2014-01-03 07:31:53 +08:00
|
|
|
ec.text_to_be_present_in_element_value(
|
|
|
|
(By.CSS_SELECTOR, css_selector), text),
|
2011-12-29 06:20:30 +08:00
|
|
|
timeout
|
|
|
|
)
|
|
|
|
|
2016-01-12 01:25:56 +08:00
|
|
|
def wait_until_visible(self, css_selector, timeout=10):
|
|
|
|
"""
|
|
|
|
Block until the element described by the CSS selector is visible.
|
|
|
|
"""
|
|
|
|
from selenium.webdriver.common.by import By
|
|
|
|
from selenium.webdriver.support import expected_conditions as ec
|
|
|
|
self.wait_until(
|
|
|
|
ec.visibility_of_element_located((By.CSS_SELECTOR, css_selector)),
|
|
|
|
timeout
|
|
|
|
)
|
|
|
|
|
|
|
|
def wait_until_invisible(self, css_selector, timeout=10):
|
|
|
|
"""
|
|
|
|
Block until the element described by the CSS selector is invisible.
|
|
|
|
"""
|
|
|
|
from selenium.webdriver.common.by import By
|
|
|
|
from selenium.webdriver.support import expected_conditions as ec
|
|
|
|
self.wait_until(
|
|
|
|
ec.invisibility_of_element_located((By.CSS_SELECTOR, css_selector)),
|
|
|
|
timeout
|
|
|
|
)
|
|
|
|
|
2019-11-27 21:36:26 +08:00
|
|
|
def wait_page_ready(self, timeout=10):
|
2013-02-20 09:08:55 +08:00
|
|
|
"""
|
2019-11-27 21:36:26 +08:00
|
|
|
Block until the page is ready.
|
2013-02-20 09:08:55 +08:00
|
|
|
"""
|
2019-11-27 21:36:26 +08:00
|
|
|
self.wait_until(
|
|
|
|
lambda driver: driver.execute_script('return document.readyState;') == 'complete',
|
|
|
|
timeout,
|
|
|
|
)
|
|
|
|
|
|
|
|
@contextmanager
|
|
|
|
def wait_page_loaded(self, timeout=10):
|
|
|
|
"""
|
|
|
|
Block until a new page has loaded and is ready.
|
|
|
|
"""
|
|
|
|
from selenium.webdriver.support import expected_conditions as ec
|
|
|
|
old_page = self.selenium.find_element_by_tag_name('html')
|
|
|
|
yield
|
|
|
|
# Wait for the next page to be loaded
|
|
|
|
self.wait_until(ec.staleness_of(old_page), timeout=timeout)
|
|
|
|
self.wait_page_ready(timeout=timeout)
|
2013-02-20 09:08:55 +08:00
|
|
|
|
Fixed #2879 -- Added support for the integration with Selenium and other in-browser testing frameworks. Also added the first Selenium tests for `contrib.admin`. Many thanks to everyone for their contributions and feedback: Mikeal Rogers, Dirk Datzert, mir, Simon G., Almad, Russell Keith-Magee, Denis Golomazov, devin, robertrv, andrewbadr, Idan Gazit, voidspace, Tom Christie, hjwp2, Adam Nelson, Jannis Leidel, Anssi Kääriäinen, Preston Holmes, Bruno Renié and Jacob Kaplan-Moss.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17241 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2011-12-22 16:33:58 +08:00
|
|
|
def admin_login(self, username, password, login_url='/admin/'):
|
|
|
|
"""
|
2017-01-25 04:31:57 +08:00
|
|
|
Log in to the admin.
|
Fixed #2879 -- Added support for the integration with Selenium and other in-browser testing frameworks. Also added the first Selenium tests for `contrib.admin`. Many thanks to everyone for their contributions and feedback: Mikeal Rogers, Dirk Datzert, mir, Simon G., Almad, Russell Keith-Magee, Denis Golomazov, devin, robertrv, andrewbadr, Idan Gazit, voidspace, Tom Christie, hjwp2, Adam Nelson, Jannis Leidel, Anssi Kääriäinen, Preston Holmes, Bruno Renié and Jacob Kaplan-Moss.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17241 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2011-12-22 16:33:58 +08:00
|
|
|
"""
|
|
|
|
self.selenium.get('%s%s' % (self.live_server_url, login_url))
|
|
|
|
username_input = self.selenium.find_element_by_name('username')
|
|
|
|
username_input.send_keys(username)
|
|
|
|
password_input = self.selenium.find_element_by_name('password')
|
|
|
|
password_input.send_keys(password)
|
|
|
|
login_text = _('Log in')
|
2019-11-27 21:36:26 +08:00
|
|
|
with self.wait_page_loaded():
|
|
|
|
self.selenium.find_element_by_xpath('//input[@value="%s"]' % login_text).click()
|
Fixed #2879 -- Added support for the integration with Selenium and other in-browser testing frameworks. Also added the first Selenium tests for `contrib.admin`. Many thanks to everyone for their contributions and feedback: Mikeal Rogers, Dirk Datzert, mir, Simon G., Almad, Russell Keith-Magee, Denis Golomazov, devin, robertrv, andrewbadr, Idan Gazit, voidspace, Tom Christie, hjwp2, Adam Nelson, Jannis Leidel, Anssi Kääriäinen, Preston Holmes, Bruno Renié and Jacob Kaplan-Moss.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@17241 bcc190cf-cafb-0310-a4f2-bffc1f526a37
2011-12-22 16:33:58 +08:00
|
|
|
|
2019-11-27 23:34:07 +08:00
|
|
|
def select_option(self, selector, value):
|
2012-02-20 00:42:12 +08:00
|
|
|
"""
|
2019-11-27 23:34:07 +08:00
|
|
|
Select the <OPTION> with the value `value` inside the <SELECT> widget
|
2012-02-23 16:07:07 +08:00
|
|
|
identified by the CSS selector `selector`.
|
2012-02-20 00:42:12 +08:00
|
|
|
"""
|
2019-11-27 23:34:07 +08:00
|
|
|
from selenium.webdriver.support.ui import Select
|
|
|
|
select = Select(self.selenium.find_element_by_css_selector(selector))
|
|
|
|
select.select_by_value(value)
|
|
|
|
|
|
|
|
def deselect_option(self, selector, value):
|
|
|
|
"""
|
|
|
|
Deselect the <OPTION> with the value `value` inside the <SELECT> widget
|
|
|
|
identified by the CSS selector `selector`.
|
|
|
|
"""
|
|
|
|
from selenium.webdriver.support.ui import Select
|
|
|
|
select = Select(self.selenium.find_element_by_css_selector(selector))
|
|
|
|
select.deselect_by_value(value)
|
2012-02-23 16:07:07 +08:00
|
|
|
|
2021-10-20 20:36:13 +08:00
|
|
|
def assertCountSeleniumElements(self, selector, count, root_element=None):
|
|
|
|
"""
|
|
|
|
Assert number of matches for a CSS selector.
|
|
|
|
|
|
|
|
`root_element` allow restriction to a pre-selected node.
|
|
|
|
"""
|
|
|
|
root_element = root_element or self.selenium
|
|
|
|
self.assertEqual(len(root_element.find_elements_by_css_selector(selector)), count)
|
|
|
|
|
2016-05-04 11:19:24 +08:00
|
|
|
def _assertOptionsValues(self, options_selector, values):
|
|
|
|
if values:
|
|
|
|
options = self.selenium.find_elements_by_css_selector(options_selector)
|
|
|
|
actual_values = []
|
|
|
|
for option in options:
|
|
|
|
actual_values.append(option.get_attribute('value'))
|
|
|
|
self.assertEqual(values, actual_values)
|
|
|
|
else:
|
|
|
|
# Prevent the `find_elements_by_css_selector` call from blocking
|
|
|
|
# if the selector doesn't match any options as we expect it
|
|
|
|
# to be the case.
|
|
|
|
with self.disable_implicit_wait():
|
|
|
|
self.wait_until(
|
2017-11-30 00:54:34 +08:00
|
|
|
lambda driver: not driver.find_elements_by_css_selector(options_selector)
|
2016-05-04 11:19:24 +08:00
|
|
|
)
|
|
|
|
|
2012-02-23 16:07:07 +08:00
|
|
|
def assertSelectOptions(self, selector, values):
|
|
|
|
"""
|
2017-01-25 04:31:57 +08:00
|
|
|
Assert that the <SELECT> widget identified by `selector` has the
|
2012-02-23 16:07:07 +08:00
|
|
|
options with the given `values`.
|
|
|
|
"""
|
2016-05-04 11:19:24 +08:00
|
|
|
self._assertOptionsValues("%s > option" % selector, values)
|
2012-03-04 09:20:03 +08:00
|
|
|
|
2016-05-04 01:09:07 +08:00
|
|
|
def assertSelectedOptions(self, selector, values):
|
|
|
|
"""
|
2017-01-25 04:31:57 +08:00
|
|
|
Assert that the <SELECT> widget identified by `selector` has the
|
2016-05-04 01:09:07 +08:00
|
|
|
selected options with the given `values`.
|
|
|
|
"""
|
2016-05-04 11:19:24 +08:00
|
|
|
self._assertOptionsValues("%s > option:checked" % selector, values)
|
2016-05-04 01:09:07 +08:00
|
|
|
|
2012-03-04 09:20:03 +08:00
|
|
|
def has_css_class(self, selector, klass):
|
|
|
|
"""
|
2017-01-25 04:31:57 +08:00
|
|
|
Return True if the element identified by `selector` has the CSS class
|
2012-03-04 09:20:03 +08:00
|
|
|
`klass`.
|
|
|
|
"""
|
|
|
|
return (self.selenium.find_element_by_css_selector(selector)
|
2012-10-04 18:45:22 +08:00
|
|
|
.get_attribute('class').find(klass) != -1)
|