Ticket #2879: 2879.selenium-support.5.diff
File 2879.selenium-support.5.diff, 27.3 KB (added by , 13 years ago) |
---|
-
django/conf/global_settings.py
diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 6b09be2..86924c4 100644
a b DEFAULT_EXCEPTION_REPORTER_FILTER = 'django.views.debug.SafeExceptionReporterFil 560 560 # The name of the class to use to run the test suite 561 561 TEST_RUNNER = 'django.test.simple.DjangoTestSuiteRunner' 562 562 563 # For the live test server (e.g. used for running Selenium tests) 564 LIVE_TEST_SERVER_HOST = 'localhost' 565 LIVE_TEST_SERVER_PORT = 8081 566 567 # For Selenium RC 568 SELENIUM_RC_HOST = 'localhost' 569 SELENIUM_RC_PORT = 4444 570 SELENIUM_RC_BROWSER = '*firefox' 571 563 572 ############ 564 573 # FIXTURES # 565 574 ############ -
django/test/__init__.py
diff --git a/django/test/__init__.py b/django/test/__init__.py index a3a03e3..21a4841 100644
a b Django Unit Test and Doctest framework. 4 4 5 5 from django.test.client import Client, RequestFactory 6 6 from django.test.testcases import (TestCase, TransactionTestCase, 7 SimpleTestCase, skipIfDBFeature, skipUnlessDBFeature) 7 SimpleTestCase, LiveServerTestCase, skipIfDBFeature, 8 skipUnlessDBFeature) 8 9 from django.test.utils import Approximate -
django/test/testcases.py
diff --git a/django/test/testcases.py b/django/test/testcases.py index ee22ac2..176f1b8 100644
a b import sys 5 5 from functools import wraps 6 6 from urlparse import urlsplit, urlunsplit 7 7 from xml.dom.minidom import parseString, Node 8 import select 9 import socket 10 import threading 8 11 9 12 from django.conf import settings 13 from django.contrib.staticfiles.handlers import StaticFilesHandler 10 14 from django.core import mail 11 15 from django.core.exceptions import ValidationError 16 from django.core.handlers.wsgi import WSGIHandler 12 17 from django.core.management import call_command 13 18 from django.core.signals import request_started 19 from django.core.servers.basehttp import (WSGIRequestHandler, WSGIServer, 20 WSGIServerException) 14 21 from django.core.urlresolvers import clear_url_caches 15 22 from django.core.validators import EMPTY_VALUES 16 23 from django.db import (transaction, connection, connections, DEFAULT_DB_ALIAS, … … class TransactionTestCase(SimpleTestCase): 364 371 for db in databases: 365 372 call_command('flush', verbosity=0, interactive=False, database=db) 366 373 367 if hasattr(self, 'fixtures'):374 if getattr(self, 'fixtures', None): 368 375 # We have to use this slightly awkward syntax due to the fact 369 376 # that we're using *args and **kwargs together. 370 377 call_command('loaddata', *self.fixtures, … … class TestCase(TransactionTestCase): 679 686 Site.objects.clear_cache() 680 687 681 688 for db in databases: 682 if hasattr(self, 'fixtures'):689 if getattr(self, 'fixtures', None): 683 690 call_command('loaddata', *self.fixtures, 684 691 **{ 685 692 'verbosity': 0, … … def skipUnlessDBFeature(feature): 732 739 """ 733 740 return _deferredSkip(lambda: not getattr(connection.features, feature), 734 741 "Database doesn't support feature %s" % feature) 742 743 class QuietWSGIRequestHandler(WSGIRequestHandler): 744 """ 745 Just a regular WSGIRequestHandler except it doesn't log to the standard 746 output any of the requests received, so as to not clutter the output for 747 the tests' results. 748 """ 749 def log_message(*args): 750 pass 751 752 class StoppableWSGIServer(WSGIServer): 753 """ 754 The code in this class is borrowed from the `SocketServer.BaseServer` class 755 in Python 2.6. The important functionality here is that the server is non- 756 blocking and that it can be shut down at any moment. This is made possible 757 by the server regularly polling the socket and checking if it has been 758 asked to stop. 759 Note for the future: Once Django stops supporting Python 2.5, this class 760 can be removed as `WSGIServer` will have this ability to shutdown on 761 demand. 762 """ 763 764 def __init__(self, *args, **kwargs): 765 super(StoppableWSGIServer, self).__init__(*args, **kwargs) 766 self.__is_shut_down = threading.Event() 767 self.__serving = False 768 769 def serve_forever(self, poll_interval=0.5): 770 """Handle one request at a time until shutdown. 771 772 Polls for shutdown every poll_interval seconds. 773 """ 774 self.__serving = True 775 self.__is_shut_down.clear() 776 while self.__serving: 777 r, w, e = select.select([self], [], [], poll_interval) 778 if r: 779 self._handle_request_noblock() 780 self.__is_shut_down.set() 781 782 def shutdown(self): 783 """Stops the serve_forever loop. 784 785 Blocks until the loop has finished. This must be called while 786 serve_forever() is running in another thread, or it will 787 deadlock. 788 """ 789 self.__serving = False 790 self.__is_shut_down.wait() 791 792 def handle_request(self): 793 """Handle one request, possibly blocking. 794 """ 795 fd_sets = select.select([self], [], [], None) 796 if not fd_sets[0]: 797 return 798 self._handle_request_noblock() 799 800 def _handle_request_noblock(self): 801 """Handle one request, without blocking. 802 803 I assume that select.select has returned that the socket is 804 readable before this function was called, so there should be 805 no risk of blocking in get_request(). 806 """ 807 try: 808 request, client_address = self.get_request() 809 except socket.error: 810 return 811 if self.verify_request(request, client_address): 812 try: 813 self.process_request(request, client_address) 814 except Exception: 815 self.handle_error(request, client_address) 816 self.close_request(request) 817 818 class LiveServerThread(threading.Thread): 819 """ 820 Thread for running a live http server while the tests are running. 821 """ 822 823 def __init__(self, address, port, fixtures): 824 self.address = address 825 self.port = port 826 self.fixtures = fixtures 827 self.is_ready = threading.Event() 828 self.error = None 829 super(LiveServerThread, self).__init__() 830 831 def run(self): 832 """ 833 Sets up live server and database and loops over handling http requests. 834 """ 835 try: 836 # Instantiate and start the server 837 self.httpd = StoppableWSGIServer( 838 (self.address, self.port), QuietWSGIRequestHandler) 839 handler = StaticFilesHandler(WSGIHandler()) 840 self.httpd.set_app(handler) 841 842 # If the database is in memory we must reload the data in this new 843 # thread. 844 if (settings.DATABASES['default']['ENGINE'] == 'django.db.backends.sqlite3' or 845 settings.DATABASES['default']['TEST_NAME']): 846 connection.creation.create_test_db(0) 847 # Import the fixtures into the test database 848 if getattr(self, 'fixtures', None): 849 call_command('loaddata', *self.fixtures, 850 **{'verbosity': 0}) 851 self.is_ready.set() 852 self.httpd.serve_forever() 853 except WSGIServerException, e: 854 self.error = e 855 self.is_ready.set() 856 857 def join(self, timeout=None): 858 self.httpd.shutdown() 859 self.httpd.server_close() 860 super(LiveServerThread, self).join(timeout) 861 862 class LiveServerTestCase(TestCase): 863 """ 864 Does basically the same as TestCase but also launches a live http server in 865 a separate thread so that the tests may use another testing framework, such 866 as Selenium for example, instead of the built-in dummy client. 867 """ 868 869 fixtures = [] 870 871 @property 872 def live_test_server_url(self): 873 return 'http://%s:%s' % (settings.LIVE_TEST_SERVER_HOST, 874 settings.LIVE_TEST_SERVER_PORT) 875 876 def setUp(self): 877 # Launch the Django live server's thread 878 self.server_thread = LiveServerThread( 879 settings.LIVE_TEST_SERVER_HOST, 880 int(settings.LIVE_TEST_SERVER_PORT), 881 fixtures=self.fixtures) 882 self.server_thread.start() 883 884 # Wait for the Django server to be ready 885 self.server_thread.is_ready.wait() 886 if self.server_thread.error: 887 raise self.server_thread.error 888 889 super(LiveServerTestCase, self).setUp() 890 891 def tearDown(self): 892 # Terminate the Django server's thread 893 self.server_thread.join() 894 super(LiveServerTestCase, self).tearDown() -
docs/internals/contributing/writing-code/unit-tests.txt
diff --git a/docs/internals/contributing/writing-code/unit-tests.txt b/docs/internals/contributing/writing-code/unit-tests.txt index 5ec09fe..cec408c 100644
a b Going beyond that, you can specify an individual test method like this: 122 122 123 123 ./runtests.py --settings=path.to.settings i18n.TranslationTests.test_lazy_objects 124 124 125 Running the Selenium tests 126 ~~~~~~~~~~~~~~~~~~~~~~~~~~ 127 128 Some admin tests require Selenium to work via a real Web browser. To allow 129 those tests to run and not be skipped, you must install the selenium_ package 130 into your Python path and download the `Selenium server (>2.12.0)`_. The 131 Selenium server must then be started with the following command: 132 133 .. code-block:: bash 134 135 java -jar selenium-server-standalone-2.12.0.jar 136 137 If you're using linux, you may also run the tests in headless mode (i.e. with a 138 virtual display) using with the following command instead: 139 140 .. code-block:: bash 141 142 Xvfb :99 -ac & && DISPLAY=:99 java -jar selenium-server-standalone-2.12.0.jar 143 144 Then, run the tests normally, for example: 145 146 .. code-block:: bash 147 148 ./runtests.py --settings=test_sqlite admin_inlines 149 125 150 Running all the tests 126 151 ~~~~~~~~~~~~~~~~~~~~~ 127 152 … … dependencies: 135 160 * setuptools_ 136 161 * memcached_, plus a :ref:`supported Python binding <memcached>` 137 162 * gettext_ (:ref:`gettext_on_windows`) 163 * selenium_ plus the `Selenium server (>2.12.0)`_ 138 164 139 165 If you want to test the memcached cache backend, you'll also need to define 140 166 a :setting:`CACHES` setting that points at your memcached instance. … … associated tests will be skipped. 149 175 .. _setuptools: http://pypi.python.org/pypi/setuptools/ 150 176 .. _memcached: http://www.danga.com/memcached/ 151 177 .. _gettext: http://www.gnu.org/software/gettext/manual/gettext.html 178 .. _selenium: http://pypi.python.org/pypi/selenium 179 .. _Selenium server (>2.12.0): http://seleniumhq.org/download/ 152 180 153 181 .. _contrib-apps: 154 182 -
docs/ref/settings.txt
diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index 20366e3..aaaa48c 100644
a b all cache keys used by the Django server. 195 195 196 196 See the :ref:`cache documentation <cache_key_prefixing>` for more information. 197 197 198 .. setting:: LIVE_TEST_SERVER_HOST 199 200 LIVE_TEST_SERVER_HOST 201 ~~~~~~~~~~~~~~~~~~~~~ 202 203 Default: ``'localhost'`` 204 205 Controls the host address at which the live test server gets started when using 206 a :class:`~django.test.LiveServerTestCase`. 207 208 See also: :setting:`LIVE_TEST_SERVER_PORT` 209 210 .. setting:: LIVE_TEST_SERVER_PORT 211 212 LIVE_TEST_SERVER_PORT 213 ~~~~~~~~~~~~~~~~~~~~~ 214 215 Default: ``8080`` 216 217 Controls the port at which the live test server gets started when using 218 a :class:`~django.test.LiveServerTestCase`. 219 220 See also: :setting:`LIVE_TEST_SERVER_HOST` 221 198 222 .. setting:: CACHES-LOCATION 199 223 200 224 LOCATION … … Default: ``''`` (Empty string) 496 520 The port to use when connecting to the database. An empty string means the 497 521 default port. Not used with SQLite. 498 522 523 .. setting:: SELENIUM_RC_HOST 524 525 SELENIUM_RC_HOST 526 ~~~~~~~~~~~~~~~~~~~~ 527 528 Default: ``localhost`` 529 530 Host address where the Selenium server can be accessed. 531 532 .. setting:: SELENIUM_RC_PORT 533 534 SELENIUM_RC_PORT 535 ~~~~~~~~~~~~~~~~~~~~ 536 537 Default: ``4444`` 538 539 Port where the Selenium server can be accessed. 540 541 .. setting:: SELENIUM_RC_BROWSER 542 543 SELENIUM_RC_BROWSER 544 ~~~~~~~~~~~~~~~~~~~ 545 546 Default: ``'*firefox'`` 547 548 Browser to be used when running Selenium tests. Note that the prefixing star 549 ('``*``') is required. Possible values include: 550 551 * ``'*firefox'`` 552 * ``'*googlechrome'`` 553 * ``'*safari'`` 554 * ``'*mock'`` 555 * ``'*firefoxproxy'`` 556 * ``'*pifirefox'`` 557 * ``'*chrome'`` 558 * ``'*iexploreproxy'`` 559 * ``'*iexplore'`` 560 * ``'*safariproxy'`` 561 * ``'*konqueror'`` 562 * ``'*firefox2'`` 563 * ``'*firefox3'`` 564 * ``'*firefoxchrome'`` 565 * ``'*piiexplore'`` 566 * ``'*opera'`` 567 * ``'*iehta'`` 568 * ``'*custom'`` 569 499 570 .. setting:: USER 500 571 501 572 USER -
docs/topics/testing.txt
diff --git a/docs/topics/testing.txt b/docs/topics/testing.txt index dc5bf7e..a25b0af 100644
a b Some of the things you can do with the test client are: 580 580 * Test that a given request is rendered by a given Django template, with 581 581 a template context that contains certain values. 582 582 583 Note that the test client is not intended to be a replacement for Twill_,583 Note that the test client is not intended to be a replacement for Windmill_, 584 584 Selenium_, or other "in-browser" frameworks. Django's test client has 585 585 a different focus. In short: 586 586 587 587 * Use Django's test client to establish that the correct view is being 588 588 called and that the view is collecting the correct context data. 589 589 590 * Use in-browser frameworks such as Twill and Selenium to test *rendered* 591 HTML and the *behavior* of Web pages, namely JavaScript functionality. 590 * Use in-browser frameworks such as Windmill_ and Selenium_ to test *rendered* 591 HTML and the *behavior* of Web pages, namely JavaScript functionality. Django 592 also provides special support for those frameworks; see the sections on 593 :class:`~django.test.testcases.LiveServerTestCase` and 594 :class:`~django.test.testcases.SeleniumRCTestCase`. 592 595 593 596 A comprehensive test suite should use a combination of both test types. 594 597 595 .. _Twill: http://twill.idyll.org/596 .. _Selenium: http://seleniumhq.org/597 598 598 Overview and a quick example 599 599 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 600 600 … … set up, execute and tear down the test suite. 1828 1828 those options will be added to the list of command-line options that 1829 1829 the :djadmin:`test` command can use. 1830 1830 1831 Live test server 1832 ---------------- 1833 1834 .. currentmodule:: django.test 1835 1836 .. versionadded::1.4 1837 1838 .. class:: LiveServerTestCase() 1839 1840 ``LiveServerTestCase`` does basically the same as 1841 :class:`~django.test.TestCase` with one extra thing: it launches a live Django 1842 server in the background on setup, and shuts it down on teardown. This allows 1843 to use other automated test clients than the 1844 :ref:`Django dummy client <test-client>` such as, for example, the Selenium_ or 1845 Windmill_ clients. 1846 1847 You may control which host and port the live server will run at with 1848 respectively the :setting:`LIVE_TEST_SERVER_HOST` and 1849 :setting:`LIVE_TEST_SERVER_PORT` settings. 1850 1851 Fixtures defined with the :attr:`~TestCase.fixtures` class attribute will get 1852 loaded at the beginning of each test if you require some initial data to be 1853 present. 1854 1855 See the section on :class:`SeleniumRCTestCase` for a concrete example of how 1856 ``LiveServerTestCase`` can be used. 1857 1858 Selenium tests 1859 -------------- 1860 1861 .. versionadded::1.4 1862 1863 .. class:: SeleniumRCTestCase() 1864 1865 Django provides out-of-the box support for Selenium_ tests with the 1866 ``SeleniumRCTestCase`` class. Django itself uses it in its own test suite for 1867 some ``contrib.admin`` tests. 1868 1869 ``SeleniumRCTestCase`` inherits from :class:`LiveServerTestCase`, which means 1870 that a live server is available for the duration of each test. That live server 1871 can then be accessed by the Selenium client to execute a series of functional 1872 tests inside a browser, simulating a real user's actions. 1873 1874 To get started with Selenium tests, your environment needs to satisfy a number 1875 of requirements: 1876 1877 * You must install the `selenium package`_ into your Python path: 1878 1879 .. code-block:: bash 1880 1881 pip install selenium 1882 1883 * You must download the `Selenium server (>2.12.0)`_, and then start it with 1884 the following command: 1885 1886 .. code-block:: bash 1887 1888 java -jar selenium-server-standalone-2.12.0.jar 1889 1890 If you'd like to run the selenium server at a different port than the 1891 standard one (i.e. 4444) you may do so as follows: 1892 1893 .. code-block:: bash 1894 1895 java -jar selenium-server-standalone-2.12.0.jar -port 1234 1896 1897 * If the selenium server isn't running at the standard host address or port, 1898 you need to provide the exact details using respectively the 1899 :setting:`SELENIUM_RC_HOST` and :setting:`SELENIUM_RC_PORT` 1900 settings. 1901 1902 If those requirements are not satisfied, then the tests will be skipped. 1903 1904 By the default, the tests are run in Firefox_. If you do not have Firefox 1905 installed or simply wish to run the tests in another browser, you may do so by 1906 changing the :setting:`SELENIUM_RC_BROWSER` setting. 1907 1908 Once your environment is set up, you may start writing your Selenium tests. 1909 Here's an example of how to control the Selenium client (accessible via 1910 ``self.selenium``): 1911 1912 .. code-block:: python 1913 1914 from django.contrib.selenium import SeleniumRCTestCase 1915 1916 class MySeleniumTests(SeleniumRCTestCase): 1917 1918 fixtures = ['user-data.json'] 1919 1920 def test_login(self): 1921 self.selenium.open('/login/') 1922 self.selenium.type('username', username) 1923 self.selenium.type('password', password) 1924 self.selenium.click("//input[@value='Log in']") 1925 1926 This is just a tiny fraction of what the Selenium client can do. Check out the 1927 `full reference`_ for more details. 1928 1929 .. _Windmill: http://www.getwindmill.com/ 1930 .. _Selenium: http://seleniumhq.org/ 1931 .. _selenium package: http://pypi.python.org/pypi/selenium 1932 .. _Selenium server (>2.12.0): http://seleniumhq.org/download/ 1933 .. _full reference: http://selenium.googlecode.com/svn/trunk/docs/api/py/selenium/selenium.selenium.html 1934 .. _Firefox: http://www.mozilla.com/firefox/ 1831 1935 1832 1936 Attributes 1833 1937 ~~~~~~~~~~ 1834 1938 1835 1836 1939 .. attribute:: DjangoTestSuiteRunner.option_list 1837 1940 1838 1941 .. versionadded:: 1.4 -
tests/regressiontests/admin_inlines/tests.py
diff --git a/tests/regressiontests/admin_inlines/tests.py b/tests/regressiontests/admin_inlines/tests.py index c2e3bbc..33da854 100644
a b from __future__ import absolute_import 3 3 from django.contrib.admin.helpers import InlineAdminForm 4 4 from django.contrib.auth.models import User, Permission 5 5 from django.contrib.contenttypes.models import ContentType 6 from django.contrib.selenium import SeleniumRCTestCase 6 7 from django.test import TestCase 7 8 8 9 # local test models … … class TestInlinePermissions(TestCase): 380 381 self.assertContains(response, 'value="4" id="id_inner2_set-TOTAL_FORMS"') 381 382 self.assertContains(response, '<input type="hidden" name="inner2_set-0-id" value="%i"' % self.inner2_id) 382 383 self.assertContains(response, 'id="id_inner2_set-0-DELETE"') 384 385 386 class SeleniumTests(SeleniumRCTestCase): 387 fixtures = ['admin-views-users.xml'] 388 urls = "regressiontests.admin_inlines.urls" 389 390 def admin_login(self, username, password): 391 """ 392 Helper function to log into the admin. 393 """ 394 self.selenium.open('/admin/') 395 self.selenium.type('username', username) 396 self.selenium.type('password', password) 397 self.selenium.click("//input[@value='Log in']") 398 self.selenium.wait_for_page_to_load(3000) 399 400 def test_add_inlines(self): 401 """ 402 Ensure that the "Add another XXX" link correctly adds items to the 403 inline form. 404 """ 405 self.admin_login(username='super', password='secret') 406 self.selenium.open('/admin/admin_inlines/titlecollection/add/') 407 408 # Check that there's only one inline to start with and that it has the 409 # correct ID. 410 self.failUnlessEqual(self.selenium.get_css_count( 411 'css=#title_set-group table tr.dynamic-title_set'), 1) 412 self.failUnless(self.selenium.get_attribute( 413 'css=.dynamic-title_set:nth-of-type(1)@id'), 'title_set-0') 414 self.failUnless(self.selenium.is_element_present( 415 'css=form#titlecollection_form tr.dynamic-title_set#title_set-0 input[name=title_set-0-title1]')) 416 self.failUnless(self.selenium.is_element_present( 417 'css=form#titlecollection_form tr.dynamic-title_set#title_set-0 input[name=title_set-0-title2]')) 418 419 # Add an inline 420 self.selenium.click("link=Add another Title") 421 422 # Check that the inline has been added, that it has the right id, and 423 # that it contains the right fields. 424 self.failUnlessEqual(self.selenium.get_css_count( 425 'css=#title_set-group table tr.dynamic-title_set'), 2) 426 self.failUnless(self.selenium.get_attribute( 427 'css=.dynamic-title_set:nth-of-type(2)@id'), 'title_set-1') 428 self.failUnless(self.selenium.is_element_present( 429 'css=form#titlecollection_form tr.dynamic-title_set#title_set-1 input[name=title_set-1-title1]')) 430 self.failUnless(self.selenium.is_element_present( 431 'css=form#titlecollection_form tr.dynamic-title_set#title_set-1 input[name=title_set-1-title2]')) 432 433 # Let's add another one to be sure 434 self.selenium.click("link=Add another Title") 435 self.failUnlessEqual(self.selenium.get_css_count( 436 'css=#title_set-group table tr.dynamic-title_set'), 3) 437 self.failUnless(self.selenium.get_attribute( 438 'css=.dynamic-title_set:nth-of-type(3)@id'), 'title_set-2') 439 self.failUnless(self.selenium.is_element_present( 440 'css=form#titlecollection_form tr.dynamic-title_set#title_set-2 input[name=title_set-2-title1]')) 441 self.failUnless(self.selenium.is_element_present( 442 'css=form#titlecollection_form tr.dynamic-title_set#title_set-2 input[name=title_set-2-title2]')) 443 444 def test_delete_inlines(self): 445 self.admin_login(username='super', password='secret') 446 self.selenium.open('/admin/admin_inlines/titlecollection/add/') 447 448 # Add a few inlines 449 self.selenium.click("link=Add another Title") 450 self.selenium.click("link=Add another Title") 451 self.selenium.click("link=Add another Title") 452 self.selenium.click("link=Add another Title") 453 self.failUnlessEqual(self.selenium.get_css_count( 454 'css=#title_set-group table tr.dynamic-title_set'), 5) 455 self.failUnless(self.selenium.is_element_present( 456 'css=form#titlecollection_form tr.dynamic-title_set#title_set-0')) 457 self.failUnless(self.selenium.is_element_present( 458 'css=form#titlecollection_form tr.dynamic-title_set#title_set-1')) 459 self.failUnless(self.selenium.is_element_present( 460 'css=form#titlecollection_form tr.dynamic-title_set#title_set-2')) 461 self.failUnless(self.selenium.is_element_present( 462 'css=form#titlecollection_form tr.dynamic-title_set#title_set-3')) 463 self.failUnless(self.selenium.is_element_present( 464 'css=form#titlecollection_form tr.dynamic-title_set#title_set-4')) 465 466 # Click on a few delete buttons 467 self.selenium.click( 468 'css=form#titlecollection_form tr.dynamic-title_set#title_set-1 td.delete a') 469 self.selenium.click( 470 'css=form#titlecollection_form tr.dynamic-title_set#title_set-2 td.delete a') 471 # Verify that they're gone and that the IDs have been re-sequenced 472 self.failUnlessEqual(self.selenium.get_css_count( 473 'css=#title_set-group table tr.dynamic-title_set'), 3) 474 self.failUnless(self.selenium.is_element_present( 475 'css=form#titlecollection_form tr.dynamic-title_set#title_set-0')) 476 self.failUnless(self.selenium.is_element_present( 477 'css=form#titlecollection_form tr.dynamic-title_set#title_set-1')) 478 self.failUnless(self.selenium.is_element_present( 479 'css=form#titlecollection_form tr.dynamic-title_set#title_set-2')) -
tests/regressiontests/admin_widgets/tests.py
diff --git a/tests/regressiontests/admin_widgets/tests.py b/tests/regressiontests/admin_widgets/tests.py index 08a1a59..0d22710 100644
a b from django.core.files.storage import default_storage 11 11 from django.core.files.uploadedfile import SimpleUploadedFile 12 12 from django.db.models import DateField 13 13 from django.test import TestCase as DjangoTestCase 14 from django.contrib.selenium import SeleniumRCTestCase 14 15 from django.utils import translation 15 16 from django.utils.html import conditional_escape 16 17 from django.utils.unittest import TestCase … … class RelatedFieldWidgetWrapperTests(DjangoTestCase): 372 373 # Used to fail with a name error. 373 374 w = widgets.RelatedFieldWidgetWrapper(w, rel, widget_admin_site) 374 375 self.assertFalse(w.can_add_related) 376 377 378 class SeleniumTests(SeleniumRCTestCase): 379 fixtures = ['admin-widgets-users.xml'] 380 urls = "regressiontests.admin_widgets.urls" 381 382 def admin_login(self, username, password): 383 """ 384 Helper function to log into the admin. 385 """ 386 self.selenium.open('/') 387 self.selenium.type('username', username) 388 self.selenium.type('password', password) 389 self.selenium.click("//input[@value='Log in']") 390 self.selenium.wait_for_page_to_load(3000) 391 392 def get_css_value(self, selector, attribute): 393 """ 394 Helper function that returns the value for the CSS attribute of an 395 DOM element specified by the given selector. 396 """ 397 return self.selenium.get_eval( 398 'selenium.browserbot.getCurrentWindow().django' 399 '.jQuery("%s").css("%s")' % (selector, attribute)) 400 401 def test_show_hide_date_time_picker_widgets(self): 402 """ 403 Ensure that pressing the ESC key closes the date and time picker 404 widgets. 405 Refs #17064. 406 """ 407 self.admin_login(username='super', password='secret') 408 # Open a page that has a date and time picker widgets 409 self.selenium.open('/admin_widgets/member/add/') 410 411 # First, with the date picker widget --------------------------------- 412 # Check that the date picker is hidden 413 self.assertEqual( 414 self.get_css_value('#calendarbox0', 'display'), 'none') 415 # Click the calendar icon 416 self.selenium.click('id=calendarlink0') 417 # Check that the date picker is visible 418 self.assertEqual( 419 self.get_css_value('#calendarbox0', 'display'), 'block') 420 # Press the ESC key 421 self.selenium.key_up('css=html', '27') 422 # Check that the date picker is hidden again 423 self.assertEqual( 424 self.get_css_value('#calendarbox0', 'display'), 'none') 425 426 # Then, with the time picker widget ---------------------------------- 427 # Check that the time picker is hidden 428 self.assertEqual( 429 self.get_css_value('#clockbox0', 'display'), 'none') 430 # Click the time icon 431 self.selenium.click('id=clocklink0') 432 # Check that the time picker is visible 433 self.assertEqual( 434 self.get_css_value('#clockbox0', 'display'), 'block') 435 # Press the ESC key 436 self.selenium.key_up('css=html', '27') 437 # Check that the time picker is hidden again 438 self.assertEqual( 439 self.get_css_value('#clockbox0', 'display'), 'none')