Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added some Selenium tests for the admin's filter_horizontal and filte…

…r_vertical widgets. Ref #13614, #15220.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17579 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit f2de5f4caba819fad10a78bfec47ae6f29cc2c29 1 parent 6daad89
Julien Phalip authored
22  django/contrib/admin/tests.py
@@ -73,15 +73,25 @@ def get_css_value(self, selector, attribute):
73 73
         return self.selenium.execute_script(
74 74
             'return django.jQuery("%s").css("%s")' % (selector, attribute))
75 75
 
76  
-    def select_option(self, selector, value):
  76
+    def get_select_option(self, selector, value):
77 77
         """
78  
-        Helper function to select the <OPTION> that has the value `value` and
79  
-        that is in the <SELECT> widget identified by the CSS selector `selector`.
  78
+        Returns the <OPTION> with the value `value` inside the <SELECT> widget
  79
+        identified by the CSS selector `selector`.
80 80
         """
81 81
         from selenium.common.exceptions import NoSuchElementException
82 82
         options = self.selenium.find_elements_by_css_selector('%s option' % selector)
83 83
         for option in options:
84 84
             if option.get_attribute('value') == value:
85  
-                option.click()
86  
-                return
87  
-        raise NoSuchElementException('Option "%s" not found in "%s"' % (value, selector))
  85
+                return option
  86
+        raise NoSuchElementException('Option "%s" not found in "%s"' % (value, selector))
  87
+
  88
+    def assertSelectOptions(self, selector, values):
  89
+        """
  90
+        Asserts that the <SELECT> widget identified by `selector` has the
  91
+        options with the given `values`.
  92
+        """
  93
+        options = self.selenium.find_elements_by_css_selector('%s option' % selector)
  94
+        actual_values = []
  95
+        for option in options:
  96
+            actual_values.append(option.get_attribute('value'))
  97
+        self.assertEqual(values, actual_values)
10  tests/regressiontests/admin_views/tests.py
@@ -2911,7 +2911,7 @@ def test_basic(self):
2911 2911
 
2912 2912
         # Main form ----------------------------------------------------------
2913 2913
         self.selenium.find_element_by_css_selector('#id_pubdate').send_keys('2012-02-18')
2914  
-        self.select_option('#id_status', 'option two')
  2914
+        self.get_select_option('#id_status', 'option two').click()
2915 2915
         self.selenium.find_element_by_css_selector('#id_name').send_keys(u' this is the mAin nÀMë and it\'s awεšome')
2916 2916
         slug1 = self.selenium.find_element_by_css_selector('#id_slug1').get_attribute('value')
2917 2917
         slug2 = self.selenium.find_element_by_css_selector('#id_slug2').get_attribute('value')
@@ -2921,7 +2921,7 @@ def test_basic(self):
2921 2921
         # Stacked inlines ----------------------------------------------------
2922 2922
         # Initial inline
2923 2923
         self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-pubdate').send_keys('2011-12-17')
2924  
-        self.select_option('#id_relatedprepopulated_set-0-status', 'option one')
  2924
+        self.get_select_option('#id_relatedprepopulated_set-0-status', 'option one').click()
2925 2925
         self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-name').send_keys(u' here is a sŤāÇkeð   inline !  ')
2926 2926
         slug1 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-slug1').get_attribute('value')
2927 2927
         slug2 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-0-slug2').get_attribute('value')
@@ -2931,7 +2931,7 @@ def test_basic(self):
2931 2931
         # Add an inline
2932 2932
         self.selenium.find_element_by_css_selector('#relatedprepopulated_set-group .add-row a').click()
2933 2933
         self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-pubdate').send_keys('1999-01-25')
2934  
-        self.select_option('#id_relatedprepopulated_set-1-status', 'option two')
  2934
+        self.get_select_option('#id_relatedprepopulated_set-1-status', 'option two').click()
2935 2935
         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... ')
2936 2936
         slug1 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-slug1').get_attribute('value')
2937 2937
         slug2 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-1-slug2').get_attribute('value')
@@ -2941,7 +2941,7 @@ def test_basic(self):
2941 2941
         # Tabular inlines ----------------------------------------------------
2942 2942
         # Initial inline
2943 2943
         self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-pubdate').send_keys('1234-12-07')
2944  
-        self.select_option('#id_relatedprepopulated_set-2-0-status', 'option two')
  2944
+        self.get_select_option('#id_relatedprepopulated_set-2-0-status', 'option two').click()
2945 2945
         self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-name').send_keys(u'And now, with a tÃbűlaŘ inline !!!')
2946 2946
         slug1 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-slug1').get_attribute('value')
2947 2947
         slug2 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-0-slug2').get_attribute('value')
@@ -2951,7 +2951,7 @@ def test_basic(self):
2951 2951
         # Add an inline
2952 2952
         self.selenium.find_element_by_css_selector('#relatedprepopulated_set-2-group .add-row a').click()
2953 2953
         self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-pubdate').send_keys('1981-08-22')
2954  
-        self.select_option('#id_relatedprepopulated_set-2-1-status', 'option one')
  2954
+        self.get_select_option('#id_relatedprepopulated_set-2-1-status', 'option one').click()
2955 2955
         self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-name').send_keys(u'a tÃbűlaŘ inline with ignored ;"&*^\%$#@-/`~ characters')
2956 2956
         slug1 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-slug1').get_attribute('value')
2957 2957
         slug2 = self.selenium.find_element_by_css_selector('#id_relatedprepopulated_set-2-1-slug2').get_attribute('value')
18  tests/regressiontests/admin_widgets/models.py
@@ -99,3 +99,21 @@ class Advisor(models.Model):
99 99
     """
100 100
     name = models.CharField(max_length=20)
101 101
     companies = models.ManyToManyField(Company)
  102
+
  103
+
  104
+class Student(models.Model):
  105
+    name = models.CharField(max_length=255)
  106
+
  107
+    def __unicode__(self):
  108
+        return self.name
  109
+
  110
+    class Meta:
  111
+        ordering = ('name',)
  112
+
  113
+class School(models.Model):
  114
+    name = models.CharField(max_length=255)
  115
+    students = models.ManyToManyField(Student, related_name='current_schools')
  116
+    alumni = models.ManyToManyField(Student, related_name='previous_schools')
  117
+
  118
+    def __unicode__(self):
  119
+        return self.name
132  tests/regressiontests/admin_widgets/tests.py
@@ -410,7 +410,8 @@ def test_no_can_add_related(self):
410 410
         self.assertFalse(w.can_add_related)
411 411
 
412 412
 
413  
-class SeleniumFirefoxTests(AdminSeleniumWebDriverTestCase):
  413
+
  414
+class DateTimePickerSeleniumFirefoxTests(AdminSeleniumWebDriverTestCase):
414 415
     webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
415 416
     fixtures = ['admin-widgets-users.xml']
416 417
     urls = "regressiontests.admin_widgets.urls"
@@ -458,5 +459,132 @@ def test_show_hide_date_time_picker_widgets(self):
458 459
         self.assertEqual(
459 460
             self.get_css_value('#clockbox0', 'display'), 'none')
460 461
 
461  
-class SeleniumChromeTests(SeleniumFirefoxTests):
  462
+class DateTimePickerSeleniumChromeTests(DateTimePickerSeleniumFirefoxTests):
  463
+    webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver'
  464
+
  465
+
  466
+class HorizontalVerticalFilterSeleniumFirefoxTests(AdminSeleniumWebDriverTestCase):
  467
+    webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
  468
+    fixtures = ['admin-widgets-users.xml']
  469
+    urls = "regressiontests.admin_widgets.urls"
  470
+
  471
+    def setUp(self):
  472
+        self.lisa = models.Student.objects.create(name='Lisa')
  473
+        self.john = models.Student.objects.create(name='John')
  474
+        self.bob = models.Student.objects.create(name='Bob')
  475
+        self.peter = models.Student.objects.create(name='Peter')
  476
+        self.jenny = models.Student.objects.create(name='Jenny')
  477
+        self.jason = models.Student.objects.create(name='Jason')
  478
+        self.cliff = models.Student.objects.create(name='Cliff')
  479
+        self.arthur = models.Student.objects.create(name='Arthur')
  480
+        self.school = models.School.objects.create(name='School of Awesome')
  481
+        super(HorizontalVerticalFilterSeleniumFirefoxTests, self).setUp()
  482
+
  483
+    def execute_basic_operations(self, field_name, mode):
  484
+        from_box = '#id_%s_from' % field_name
  485
+        to_box = '#id_%s_to' % field_name
  486
+        choose_link = 'id_%s_add_link' % field_name
  487
+        choose_all_link = 'id_%s_add_all_link' % field_name
  488
+        remove_link = 'id_%s_remove_link' % field_name
  489
+        remove_all_link = 'id_%s_remove_all_link' % field_name
  490
+
  491
+        # Initial positions ---------------------------------------------------
  492
+        self.assertSelectOptions(from_box,
  493
+                        [str(self.arthur.id), str(self.bob.id),
  494
+                         str(self.cliff.id), str(self.jason.id),
  495
+                         str(self.jenny.id), str(self.john.id)])
  496
+        self.assertSelectOptions(to_box,
  497
+                        [str(self.lisa.id), str(self.peter.id)])
  498
+
  499
+        # Click 'Choose all' --------------------------------------------------
  500
+        if mode == 'horizontal':
  501
+            self.selenium.find_element_by_id(choose_all_link).click()
  502
+        elif mode == 'vertical':
  503
+            # There 's no 'Choose all' button in vertical mode, so individually
  504
+            # select all options and click 'Choose'.
  505
+            for option in self.selenium.find_elements_by_css_selector(from_box + ' option'):
  506
+                option.click()
  507
+            self.selenium.find_element_by_id(choose_link).click()
  508
+        self.assertSelectOptions(from_box, [])
  509
+        self.assertSelectOptions(to_box,
  510
+                        [str(self.lisa.id), str(self.peter.id),
  511
+                         str(self.arthur.id), str(self.bob.id),
  512
+                         str(self.cliff.id), str(self.jason.id),
  513
+                         str(self.jenny.id), str(self.john.id)])
  514
+
  515
+        # Click 'Remove all' --------------------------------------------------
  516
+        if mode == 'horizontal':
  517
+            self.selenium.find_element_by_id(remove_all_link).click()
  518
+        elif mode == 'vertical':
  519
+            # There 's no 'Remove all' button in vertical mode, so individually
  520
+            # select all options and click 'Remove'.
  521
+            for option in self.selenium.find_elements_by_css_selector(to_box + ' option'):
  522
+                option.click()
  523
+            self.selenium.find_element_by_id(remove_link).click()
  524
+        self.assertSelectOptions(from_box,
  525
+                        [str(self.lisa.id), str(self.peter.id),
  526
+                         str(self.arthur.id), str(self.bob.id),
  527
+                         str(self.cliff.id), str(self.jason.id),
  528
+                         str(self.jenny.id), str(self.john.id)])
  529
+        self.assertSelectOptions(to_box, [])
  530
+
  531
+        # Choose some options ------------------------------------------------
  532
+        self.get_select_option(from_box, str(self.lisa.id)).click()
  533
+        self.get_select_option(from_box, str(self.jason.id)).click()
  534
+        self.get_select_option(from_box, str(self.bob.id)).click()
  535
+        self.get_select_option(from_box, str(self.john.id)).click()
  536
+        self.selenium.find_element_by_id(choose_link).click()
  537
+
  538
+        self.assertSelectOptions(from_box,
  539
+                        [str(self.peter.id), str(self.arthur.id),
  540
+                         str(self.cliff.id), str(self.jenny.id)])
  541
+        self.assertSelectOptions(to_box,
  542
+                        [str(self.lisa.id), str(self.bob.id),
  543
+                         str(self.jason.id), str(self.john.id)])
  544
+
  545
+        # Remove some options -------------------------------------------------
  546
+        self.get_select_option(to_box, str(self.lisa.id)).click()
  547
+        self.get_select_option(to_box, str(self.bob.id)).click()
  548
+        self.selenium.find_element_by_id(remove_link).click()
  549
+
  550
+        self.assertSelectOptions(from_box,
  551
+                        [str(self.peter.id), str(self.arthur.id),
  552
+                         str(self.cliff.id), str(self.jenny.id),
  553
+                         str(self.lisa.id), str(self.bob.id)])
  554
+        self.assertSelectOptions(to_box,
  555
+                        [str(self.jason.id), str(self.john.id)])
  556
+
  557
+        # Choose some more options --------------------------------------------
  558
+        self.get_select_option(from_box, str(self.arthur.id)).click()
  559
+        self.get_select_option(from_box, str(self.cliff.id)).click()
  560
+        self.selenium.find_element_by_id(choose_link).click()
  561
+
  562
+        self.assertSelectOptions(from_box,
  563
+                        [str(self.peter.id), str(self.jenny.id),
  564
+                         str(self.lisa.id), str(self.bob.id)])
  565
+        self.assertSelectOptions(to_box,
  566
+                        [str(self.jason.id), str(self.john.id),
  567
+                         str(self.arthur.id), str(self.cliff.id)])
  568
+
  569
+    def test_basic(self):
  570
+        self.school.students = [self.lisa, self.peter]
  571
+        self.school.alumni = [self.lisa, self.peter]
  572
+        self.school.save()
  573
+
  574
+        self.admin_login(username='super', password='secret', login_url='/')
  575
+        self.selenium.get(
  576
+            '%s%s' % (self.live_server_url, '/admin_widgets/school/%s/' % self.school.id))
  577
+
  578
+        self.execute_basic_operations('students', 'vertical')
  579
+        self.execute_basic_operations('alumni', 'horizontal')
  580
+
  581
+        # Save and check that everything is properly stored in the database ---
  582
+        self.selenium.find_element_by_xpath('//input[@value="Save"]').click()
  583
+        self.school = models.School.objects.get(id=self.school.id) # Reload from database
  584
+        self.assertEqual(list(self.school.students.all()),
  585
+                         [self.arthur, self.cliff, self.jason, self.john])
  586
+        self.assertEqual(list(self.school.alumni.all()),
  587
+                         [self.arthur, self.cliff, self.jason, self.john])
  588
+
  589
+class HorizontalVerticalFilterSeleniumChromeTests(HorizontalVerticalFilterSeleniumFirefoxTests):
462 590
     webdriver_class = 'selenium.webdriver.chrome.webdriver.WebDriver'
7  tests/regressiontests/admin_widgets/widgetadmin.py
@@ -25,6 +25,11 @@ def formfield_for_foreignkey(self, db_field, request, **kwargs):
25 25
 class EventAdmin(admin.ModelAdmin):
26 26
     raw_id_fields = ['band']
27 27
 
  28
+
  29
+class SchoolAdmin(admin.ModelAdmin):
  30
+    filter_vertical = ('students',)
  31
+    filter_horizontal = ('alumni',)
  32
+
28 33
 site = WidgetAdmin(name='widget-admin')
29 34
 
30 35
 site.register(models.User)
@@ -41,3 +46,5 @@ class EventAdmin(admin.ModelAdmin):
41 46
 site.register(models.Bee)
42 47
 
43 48
 site.register(models.Advisor)
  49
+
  50
+site.register(models.School, SchoolAdmin)

0 notes on commit f2de5f4

Please sign in to comment.
Something went wrong with that request. Please try again.