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.