diff --git a/django/contrib/admin/tests.py b/django/contrib/admin/tests.py index c46cc82acc..e569df396b 100644 --- a/django/contrib/admin/tests.py +++ b/django/contrib/admin/tests.py @@ -147,28 +147,35 @@ class AdminSeleniumTestCase(SeleniumTestCase, StaticLiveServerTestCase): return option raise NoSuchElementException('Option "%s" not found in "%s"' % (value, selector)) + 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( + lambda driver: len(driver.find_elements_by_css_selector(options_selector)) == 0 + ) + def assertSelectOptions(self, selector, values): """ Asserts that the widget identified by `selector` has the selected options with the given `values`. """ - options = self.selenium.find_elements_by_css_selector('%s > option' % selector) - actual_values = [] - for option in options: - if option.get_attribute('selected'): - actual_values.append(option.get_attribute('value')) - self.assertEqual(values, actual_values) + self._assertOptionsValues("%s > option:checked" % selector, values) def has_css_class(self, selector, klass): """ diff --git a/django/test/selenium.py b/django/test/selenium.py index 0f9296f7a9..ae8e603a58 100644 --- a/django/test/selenium.py +++ b/django/test/selenium.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import sys import unittest +from contextlib import contextmanager from django.test import LiveServerTestCase, tag from django.utils.module_loading import import_string @@ -56,11 +57,12 @@ class SeleniumTestCaseBase(type(LiveServerTestCase)): @tag('selenium') class SeleniumTestCase(with_metaclass(SeleniumTestCaseBase, LiveServerTestCase)): + implicit_wait = 10 @classmethod def setUpClass(cls): cls.selenium = cls.create_webdriver() - cls.selenium.implicitly_wait(10) + cls.selenium.implicitly_wait(cls.implicit_wait) super(SeleniumTestCase, cls).setUpClass() @classmethod @@ -71,3 +73,12 @@ class SeleniumTestCase(with_metaclass(SeleniumTestCaseBase, LiveServerTestCase)) if hasattr(cls, 'selenium'): cls.selenium.quit() super(SeleniumTestCase, cls)._tearDownClassInternal() + + @contextmanager + def disable_implicit_wait(self): + """Context manager that disables the default implicit wait.""" + self.selenium.implicitly_wait(0) + try: + yield + finally: + self.selenium.implicitly_wait(self.implicit_wait)