Author: julien
Date: 2012-02-23 00:07:07 -0800 (Thu, 23 Feb 2012)
New Revision: 17579

Modified:
   django/trunk/django/contrib/admin/tests.py
   django/trunk/tests/regressiontests/admin_views/tests.py
   django/trunk/tests/regressiontests/admin_widgets/models.py
   django/trunk/tests/regressiontests/admin_widgets/tests.py
   django/trunk/tests/regressiontests/admin_widgets/widgetadmin.py
Log:
Added some Selenium tests for the admin's filter_horizontal and filter_vertical 
widgets. Ref #13614, #15220.

Modified: django/trunk/django/contrib/admin/tests.py
===================================================================
--- django/trunk/django/contrib/admin/tests.py  2012-02-22 21:42:50 UTC (rev 
17578)
+++ django/trunk/django/contrib/admin/tests.py  2012-02-23 08:07:07 UTC (rev 
17579)
@@ -73,15 +73,25 @@
         return self.selenium.execute_script(
             'return django.jQuery("%s").css("%s")' % (selector, attribute))
 
-    def select_option(self, selector, value):
+    def get_select_option(self, selector, value):
         """
-        Helper function to select the <OPTION> that has the value `value` and
-        that is in the <SELECT> widget identified by the CSS selector 
`selector`.
+        Returns the <OPTION> with the value `value` inside the <SELECT> widget
+        identified by the CSS selector `selector`.
         """
         from selenium.common.exceptions import NoSuchElementException
         options = self.selenium.find_elements_by_css_selector('%s option' % 
selector)
         for option in options:
             if option.get_attribute('value') == value:
-                option.click()
-                return
-        raise NoSuchElementException('Option "%s" not found in "%s"' % (value, 
selector))
\ No newline at end of file
+                return option
+        raise NoSuchElementException('Option "%s" not found in "%s"' % (value, 
selector))
+
+    def assertSelectOptions(self, selector, values):
+        """
+        Asserts that the <SELECT> widget identified by `selector` has the
+        options with the given `values`.
+        """
+        options = self.selenium.find_elements_by_css_selector('%s option' % 
selector)
+        actual_values = []
+        for option in options:
+            actual_values.append(option.get_attribute('value'))
+        self.assertEqual(values, actual_values)
\ No newline at end of file

Modified: django/trunk/tests/regressiontests/admin_views/tests.py
===================================================================
--- django/trunk/tests/regressiontests/admin_views/tests.py     2012-02-22 
21:42:50 UTC (rev 17578)
+++ django/trunk/tests/regressiontests/admin_views/tests.py     2012-02-23 
08:07:07 UTC (rev 17579)
@@ -2911,7 +2911,7 @@
 
         # Main form ----------------------------------------------------------
         
self.selenium.find_element_by_css_selector('#id_pubdate').send_keys('2012-02-18')
-        self.select_option('#id_status', 'option two')
+        self.get_select_option('#id_status', 'option two').click()
         self.selenium.find_element_by_css_selector('#id_name').send_keys(u' 
this is the mAin nÀMë and it\'s awεšome')
         slug1 = 
self.selenium.find_element_by_css_selector('#id_slug1').get_attribute('value')
         slug2 = 
self.selenium.find_element_by_css_selector('#id_slug2').get_attribute('value')
@@ -2921,7 +2921,7 @@
         # Stacked inlines ----------------------------------------------------
         # Initial inline
         
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-pubdate').send_keys('2011-12-17')
-        self.select_option('#id_relatedprepopulated_set-0-status', 'option 
one')
+        self.get_select_option('#id_relatedprepopulated_set-0-status', 'option 
one').click()
         
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-name').send_keys(u'
 here is a sŤāÇkeð   inline !  ')
         slug1 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-slug1').get_attribute('value')
         slug2 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-slug2').get_attribute('value')
@@ -2931,7 +2931,7 @@
         # Add an inline
         
self.selenium.find_element_by_css_selector('#relatedprepopulated_set-group 
.add-row a').click()
         
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-pubdate').send_keys('1999-01-25')
-        self.select_option('#id_relatedprepopulated_set-1-status', 'option 
two')
+        self.get_select_option('#id_relatedprepopulated_set-1-status', 'option 
two').click()
         
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-name').send_keys(u'
 now you haVe anöther   sŤāÇkeð  inline with a very ... 
loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooog text... 
')
         slug1 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-slug1').get_attribute('value')
         slug2 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-slug2').get_attribute('value')
@@ -2941,7 +2941,7 @@
         # Tabular inlines ----------------------------------------------------
         # Initial inline
         
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-pubdate').send_keys('1234-12-07')
-        self.select_option('#id_relatedprepopulated_set-2-0-status', 'option 
two')
+        self.get_select_option('#id_relatedprepopulated_set-2-0-status', 
'option two').click()
         
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-name').send_keys(u'And
 now, with a tÃbűlaŘ inline !!!')
         slug1 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-slug1').get_attribute('value')
         slug2 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-slug2').get_attribute('value')
@@ -2951,7 +2951,7 @@
         # Add an inline
         
self.selenium.find_element_by_css_selector('#relatedprepopulated_set-2-group 
.add-row a').click()
         
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-pubdate').send_keys('1981-08-22')
-        self.select_option('#id_relatedprepopulated_set-2-1-status', 'option 
one')
+        self.get_select_option('#id_relatedprepopulated_set-2-1-status', 
'option one').click()
         
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-name').send_keys(u'a
 tÃbűlaŘ inline with ignored ;"&*^\%$#@-/`~ characters')
         slug1 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-slug1').get_attribute('value')
         slug2 = 
self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-slug2').get_attribute('value')

Modified: django/trunk/tests/regressiontests/admin_widgets/models.py
===================================================================
--- django/trunk/tests/regressiontests/admin_widgets/models.py  2012-02-22 
21:42:50 UTC (rev 17578)
+++ django/trunk/tests/regressiontests/admin_widgets/models.py  2012-02-23 
08:07:07 UTC (rev 17579)
@@ -99,3 +99,21 @@
     """
     name = models.CharField(max_length=20)
     companies = models.ManyToManyField(Company)
+
+
+class Student(models.Model):
+    name = models.CharField(max_length=255)
+
+    def __unicode__(self):
+        return self.name
+
+    class Meta:
+        ordering = ('name',)
+
+class School(models.Model):
+    name = models.CharField(max_length=255)
+    students = models.ManyToManyField(Student, related_name='current_schools')
+    alumni = models.ManyToManyField(Student, related_name='previous_schools')
+
+    def __unicode__(self):
+        return self.name
\ No newline at end of file

Modified: django/trunk/tests/regressiontests/admin_widgets/tests.py
===================================================================
--- django/trunk/tests/regressiontests/admin_widgets/tests.py   2012-02-22 
21:42:50 UTC (rev 17578)
+++ django/trunk/tests/regressiontests/admin_widgets/tests.py   2012-02-23 
08:07:07 UTC (rev 17579)
@@ -410,7 +410,8 @@
         self.assertFalse(w.can_add_related)
 
 
-class SeleniumFirefoxTests(AdminSeleniumWebDriverTestCase):
+
+class DateTimePickerSeleniumFirefoxTests(AdminSeleniumWebDriverTestCase):
     webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
     fixtures = ['admin-widgets-users.xml']
     urls = "regressiontests.admin_widgets.urls"
@@ -458,5 +459,132 @@
         self.assertEqual(
             self.get_css_value('#clockbox0', 'display'), 'none')
 
-class SeleniumChromeTests(SeleniumFirefoxTests):
+class DateTimePickerSeleniumChromeTests(DateTimePickerSeleniumFirefoxTests):
+    webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver'
+
+
+class 
HorizontalVerticalFilterSeleniumFirefoxTests(AdminSeleniumWebDriverTestCase):
+    webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
+    fixtures = ['admin-widgets-users.xml']
+    urls = "regressiontests.admin_widgets.urls"
+
+    def setUp(self):
+        self.lisa = models.Student.objects.create(name='Lisa')
+        self.john = models.Student.objects.create(name='John')
+        self.bob = models.Student.objects.create(name='Bob')
+        self.peter = models.Student.objects.create(name='Peter')
+        self.jenny = models.Student.objects.create(name='Jenny')
+        self.jason = models.Student.objects.create(name='Jason')
+        self.cliff = models.Student.objects.create(name='Cliff')
+        self.arthur = models.Student.objects.create(name='Arthur')
+        self.school = models.School.objects.create(name='School of Awesome')
+        super(HorizontalVerticalFilterSeleniumFirefoxTests, self).setUp()
+
+    def execute_basic_operations(self, field_name, mode):
+        from_box = '#id_%s_from' % field_name
+        to_box = '#id_%s_to' % field_name
+        choose_link = 'id_%s_add_link' % field_name
+        choose_all_link = 'id_%s_add_all_link' % field_name
+        remove_link = 'id_%s_remove_link' % field_name
+        remove_all_link = 'id_%s_remove_all_link' % field_name
+
+        # Initial positions ---------------------------------------------------
+        self.assertSelectOptions(from_box,
+                        [str(self.arthur.id), str(self.bob.id),
+                         str(self.cliff.id), str(self.jason.id),
+                         str(self.jenny.id), str(self.john.id)])
+        self.assertSelectOptions(to_box,
+                        [str(self.lisa.id), str(self.peter.id)])
+
+        # Click 'Choose all' --------------------------------------------------
+        if mode == 'horizontal':
+            self.selenium.find_element_by_id(choose_all_link).click()
+        elif mode == 'vertical':
+            # There 's no 'Choose all' button in vertical mode, so individually
+            # select all options and click 'Choose'.
+            for option in self.selenium.find_elements_by_css_selector(from_box 
+ ' option'):
+                option.click()
+            self.selenium.find_element_by_id(choose_link).click()
+        self.assertSelectOptions(from_box, [])
+        self.assertSelectOptions(to_box,
+                        [str(self.lisa.id), str(self.peter.id),
+                         str(self.arthur.id), str(self.bob.id),
+                         str(self.cliff.id), str(self.jason.id),
+                         str(self.jenny.id), str(self.john.id)])
+
+        # Click 'Remove all' --------------------------------------------------
+        if mode == 'horizontal':
+            self.selenium.find_element_by_id(remove_all_link).click()
+        elif mode == 'vertical':
+            # There 's no 'Remove all' button in vertical mode, so individually
+            # select all options and click 'Remove'.
+            for option in self.selenium.find_elements_by_css_selector(to_box + 
' option'):
+                option.click()
+            self.selenium.find_element_by_id(remove_link).click()
+        self.assertSelectOptions(from_box,
+                        [str(self.lisa.id), str(self.peter.id),
+                         str(self.arthur.id), str(self.bob.id),
+                         str(self.cliff.id), str(self.jason.id),
+                         str(self.jenny.id), str(self.john.id)])
+        self.assertSelectOptions(to_box, [])
+
+        # Choose some options ------------------------------------------------
+        self.get_select_option(from_box, str(self.lisa.id)).click()
+        self.get_select_option(from_box, str(self.jason.id)).click()
+        self.get_select_option(from_box, str(self.bob.id)).click()
+        self.get_select_option(from_box, str(self.john.id)).click()
+        self.selenium.find_element_by_id(choose_link).click()
+
+        self.assertSelectOptions(from_box,
+                        [str(self.peter.id), str(self.arthur.id),
+                         str(self.cliff.id), str(self.jenny.id)])
+        self.assertSelectOptions(to_box,
+                        [str(self.lisa.id), str(self.bob.id),
+                         str(self.jason.id), str(self.john.id)])
+
+        # Remove some options -------------------------------------------------
+        self.get_select_option(to_box, str(self.lisa.id)).click()
+        self.get_select_option(to_box, str(self.bob.id)).click()
+        self.selenium.find_element_by_id(remove_link).click()
+
+        self.assertSelectOptions(from_box,
+                        [str(self.peter.id), str(self.arthur.id),
+                         str(self.cliff.id), str(self.jenny.id),
+                         str(self.lisa.id), str(self.bob.id)])
+        self.assertSelectOptions(to_box,
+                        [str(self.jason.id), str(self.john.id)])
+
+        # Choose some more options --------------------------------------------
+        self.get_select_option(from_box, str(self.arthur.id)).click()
+        self.get_select_option(from_box, str(self.cliff.id)).click()
+        self.selenium.find_element_by_id(choose_link).click()
+
+        self.assertSelectOptions(from_box,
+                        [str(self.peter.id), str(self.jenny.id),
+                         str(self.lisa.id), str(self.bob.id)])
+        self.assertSelectOptions(to_box,
+                        [str(self.jason.id), str(self.john.id),
+                         str(self.arthur.id), str(self.cliff.id)])
+
+    def test_basic(self):
+        self.school.students = [self.lisa, self.peter]
+        self.school.alumni = [self.lisa, self.peter]
+        self.school.save()
+
+        self.admin_login(username='super', password='secret', login_url='/')
+        self.selenium.get(
+            '%s%s' % (self.live_server_url, '/admin_widgets/school/%s/' % 
self.school.id))
+
+        self.execute_basic_operations('students', 'vertical')
+        self.execute_basic_operations('alumni', 'horizontal')
+
+        # Save and check that everything is properly stored in the database ---
+        self.selenium.find_element_by_xpath('//input[@value="Save"]').click()
+        self.school = models.School.objects.get(id=self.school.id) # Reload 
from database
+        self.assertEqual(list(self.school.students.all()),
+                         [self.arthur, self.cliff, self.jason, self.john])
+        self.assertEqual(list(self.school.alumni.all()),
+                         [self.arthur, self.cliff, self.jason, self.john])
+
+class 
HorizontalVerticalFilterSeleniumChromeTests(HorizontalVerticalFilterSeleniumFirefoxTests):
     webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver'
\ No newline at end of file

Modified: django/trunk/tests/regressiontests/admin_widgets/widgetadmin.py
===================================================================
--- django/trunk/tests/regressiontests/admin_widgets/widgetadmin.py     
2012-02-22 21:42:50 UTC (rev 17578)
+++ django/trunk/tests/regressiontests/admin_widgets/widgetadmin.py     
2012-02-23 08:07:07 UTC (rev 17579)
@@ -25,6 +25,11 @@
 class EventAdmin(admin.ModelAdmin):
     raw_id_fields = ['band']
 
+
+class SchoolAdmin(admin.ModelAdmin):
+    filter_vertical = ('students',)
+    filter_horizontal = ('alumni',)
+
 site = WidgetAdmin(name='widget-admin')
 
 site.register(models.User)
@@ -41,3 +46,5 @@
 site.register(models.Bee)
 
 site.register(models.Advisor)
+
+site.register(models.School, SchoolAdmin)
\ No newline at end of file

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-updates@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to