diff --git a/django/contrib/admin/static/admin/css/responsive.css b/django/contrib/admin/static/admin/css/responsive.css index 932e824c1c..7d296b150f 100644 --- a/django/contrib/admin/static/admin/css/responsive.css +++ b/django/contrib/admin/static/admin/css/responsive.css @@ -299,7 +299,7 @@ input[type="submit"], button { background-position: 0 -80px; } - a.selector-chooseall, a.selector-clearall { + .selector-chooseall, .selector-clearall { align-self: center; } @@ -649,6 +649,7 @@ input[type="submit"], button { .related-widget-wrapper .selector { order: 1; + flex: 1 0 auto; } .related-widget-wrapper > a { diff --git a/django/contrib/admin/static/admin/css/rtl.css b/django/contrib/admin/static/admin/css/rtl.css index b8f60e0a34..5b55b63013 100644 --- a/django/contrib/admin/static/admin/css/rtl.css +++ b/django/contrib/admin/static/admin/css/rtl.css @@ -235,19 +235,19 @@ fieldset .fieldBox { background-position: 0 -112px; } -a.selector-chooseall { +.selector-chooseall { background: url(../img/selector-icons.svg) right -128px no-repeat; } -a.active.selector-chooseall:focus, a.active.selector-chooseall:hover { +.active.selector-chooseall:focus, .active.selector-chooseall:hover { background-position: 100% -144px; } -a.selector-clearall { +.selector-clearall { background: url(../img/selector-icons.svg) 0 -160px no-repeat; } -a.active.selector-clearall:focus, a.active.selector-clearall:hover { +.active.selector-clearall:focus, .active.selector-clearall:hover { background-position: 0 -176px; } diff --git a/django/contrib/admin/static/admin/css/widgets.css b/django/contrib/admin/static/admin/css/widgets.css index cc64811a2b..c8bf90b3b2 100644 --- a/django/contrib/admin/static/admin/css/widgets.css +++ b/django/contrib/admin/static/admin/css/widgets.css @@ -2,7 +2,7 @@ .selector { display: flex; - flex-grow: 1; + flex: 1; gap: 0 10px; } @@ -14,17 +14,20 @@ } .selector-available, .selector-chosen { - text-align: center; display: flex; flex-direction: column; flex: 1 1; } -.selector-available h2, .selector-chosen h2 { +.selector-available-title, .selector-chosen-title { border: 1px solid var(--border-color); border-radius: 4px 4px 0 0; } +.selector .helptext { + font-size: 0.6875rem; +} + .selector-chosen .list-footer-display { border: 1px solid var(--border-color); border-top: none; @@ -40,14 +43,20 @@ color: var(--breadcrumbs-fg); } -.selector-chosen h2 { +.selector-chosen-title { background: var(--secondary); color: var(--header-link-color); + padding: 8px; +} + +.selector-chosen-title label { + color: var(--header-link-color); } -.selector .selector-available h2 { +.selector-available-title { background: var(--darkened-bg); color: var(--body-quiet-color); + padding: 8px; } .selector .selector-filter { @@ -121,6 +130,7 @@ overflow: hidden; cursor: default; opacity: 0.55; + border: none; } .active.selector-add, .active.selector-remove { @@ -147,7 +157,7 @@ background-position: 0 -80px; } -a.selector-chooseall, a.selector-clearall { +.selector-chooseall, .selector-clearall { display: inline-block; height: 16px; text-align: left; @@ -158,38 +168,39 @@ a.selector-chooseall, a.selector-clearall { color: var(--body-quiet-color); text-decoration: none; opacity: 0.55; + border: none; } -a.active.selector-chooseall:focus, a.active.selector-clearall:focus, -a.active.selector-chooseall:hover, a.active.selector-clearall:hover { +.active.selector-chooseall:focus, .active.selector-clearall:focus, +.active.selector-chooseall:hover, .active.selector-clearall:hover { color: var(--link-fg); } -a.active.selector-chooseall, a.active.selector-clearall { +.active.selector-chooseall, .active.selector-clearall { opacity: 1; } -a.active.selector-chooseall:hover, a.active.selector-clearall:hover { +.active.selector-chooseall:hover, .active.selector-clearall:hover { cursor: pointer; } -a.selector-chooseall { +.selector-chooseall { padding: 0 18px 0 0; background: url(../img/selector-icons.svg) right -160px no-repeat; cursor: default; } -a.active.selector-chooseall:focus, a.active.selector-chooseall:hover { +.active.selector-chooseall:focus, .active.selector-chooseall:hover { background-position: 100% -176px; } -a.selector-clearall { +.selector-clearall { padding: 0 0 0 18px; background: url(../img/selector-icons.svg) 0 -128px no-repeat; cursor: default; } -a.active.selector-clearall:focus, a.active.selector-clearall:hover { +.active.selector-clearall:focus, .active.selector-clearall:hover { background-position: 0 -144px; } diff --git a/django/contrib/admin/static/admin/js/SelectFilter2.js b/django/contrib/admin/static/admin/js/SelectFilter2.js index 133d809d52..7f0cfef8c9 100644 --- a/django/contrib/admin/static/admin/js/SelectFilter2.js +++ b/django/contrib/admin/static/admin/js/SelectFilter2.js @@ -15,6 +15,7 @@ Requires core.js and SelectBox.js. const from_box = document.getElementById(field_id); from_box.id += '_from'; // change its ID from_box.className = 'filtered'; + from_box.setAttribute('aria-labelledby', field_id + '_from_title'); for (const p of from_box.parentNode.getElementsByTagName('p')) { if (p.classList.contains("info")) { @@ -38,18 +39,15 @@ Requires core.js and SelectBox.js. // <div class="selector-available"> const selector_available = quickElement('div', selector_div); selector_available.className = 'selector-available'; - const title_available = quickElement('h2', selector_available, interpolate(gettext('Available %s') + ' ', [field_name])); + const selector_available_title = quickElement('div', selector_available); + selector_available_title.id = field_id + '_from_title'; + selector_available_title.className = 'selector-available-title'; + quickElement('label', selector_available_title, interpolate(gettext('Available %s') + ' ', [field_name]), 'for', field_id + '_from'); quickElement( - 'span', title_available, '', - 'class', 'help help-tooltip help-icon', - 'title', interpolate( - gettext( - 'This is the list of available %s. You may choose some by ' + - 'selecting them in the box below and then clicking the ' + - '"Choose" arrow between the two boxes.' - ), - [field_name] - ) + 'p', + selector_available_title, + interpolate(gettext('Choose %s by selecting them and then select the "Choose" arrow button.'), [field_name]), + 'class', 'helptext' ); const filter_p = quickElement('p', selector_available, '', 'id', field_id + '_filter'); @@ -60,7 +58,7 @@ Requires core.js and SelectBox.js. quickElement( 'span', search_filter_label, '', 'class', 'help-tooltip search-label-icon', - 'title', interpolate(gettext("Type into this box to filter down the list of available %s."), [field_name]) + 'aria-label', interpolate(gettext("Type into this box to filter down the list of available %s."), [field_name]) ); filter_p.appendChild(document.createTextNode(' ')); @@ -69,32 +67,44 @@ Requires core.js and SelectBox.js. filter_input.id = field_id + '_input'; selector_available.appendChild(from_box); - const choose_all = quickElement('a', selector_available, gettext('Choose all'), 'title', interpolate(gettext('Click to choose all %s at once.'), [field_name]), 'href', '#', 'id', field_id + '_add_all_link'); - choose_all.className = 'selector-chooseall'; + const choose_all = quickElement( + 'button', + selector_available, + interpolate(gettext('Choose all %s'), [field_name]), + 'id', field_id + '_add_all', + 'class', 'selector-chooseall' + ); // <ul class="selector-chooser"> const selector_chooser = quickElement('ul', selector_div); selector_chooser.className = 'selector-chooser'; - const add_link = quickElement('a', quickElement('li', selector_chooser), gettext('Choose'), 'title', gettext('Choose'), 'href', '#', 'id', field_id + '_add_link'); - add_link.className = 'selector-add'; - const remove_link = quickElement('a', quickElement('li', selector_chooser), gettext('Remove'), 'title', gettext('Remove'), 'href', '#', 'id', field_id + '_remove_link'); - remove_link.className = 'selector-remove'; + const add_button = quickElement( + 'button', + quickElement('li', selector_chooser), + interpolate(gettext('Choose selected %s'), [field_name]), + 'id', field_id + '_add', + 'class', 'selector-add' + ); + const remove_button = quickElement( + 'button', + quickElement('li', selector_chooser), + interpolate(gettext('Remove selected chosen %s'), [field_name]), + 'id', field_id + '_remove', + 'class', 'selector-remove' + ); // <div class="selector-chosen"> const selector_chosen = quickElement('div', selector_div, '', 'id', field_id + '_selector_chosen'); selector_chosen.className = 'selector-chosen'; - const title_chosen = quickElement('h2', selector_chosen, interpolate(gettext('Chosen %s') + ' ', [field_name])); + const selector_chosen_title = quickElement('div', selector_chosen); + selector_chosen_title.className = 'selector-chosen-title'; + selector_chosen_title.id = field_id + '_to_title'; + quickElement('label', selector_chosen_title, interpolate(gettext('Chosen %s') + ' ', [field_name]), 'for', field_id + '_to'); quickElement( - 'span', title_chosen, '', - 'class', 'help help-tooltip help-icon', - 'title', interpolate( - gettext( - 'This is the list of chosen %s. You may remove some by ' + - 'selecting them in the box below and then clicking the ' + - '"Remove" arrow between the two boxes.' - ), - [field_name] - ) + 'p', + selector_chosen_title, + interpolate(gettext('Remove %s by selecting them and then select the "Remove" arrow button.'), [field_name]), + 'class', 'helptext' ); const filter_selected_p = quickElement('p', selector_chosen, '', 'id', field_id + '_filter_selected'); @@ -105,7 +115,7 @@ Requires core.js and SelectBox.js. quickElement( 'span', search_filter_selected_label, '', 'class', 'help-tooltip search-label-icon', - 'title', interpolate(gettext("Type into this box to filter down the list of selected %s."), [field_name]) + 'aria-label', interpolate(gettext("Type into this box to filter down the list of selected %s."), [field_name]) ); filter_selected_p.appendChild(document.createTextNode(' ')); @@ -113,15 +123,27 @@ Requires core.js and SelectBox.js. const filter_selected_input = quickElement('input', filter_selected_p, '', 'type', 'text', 'placeholder', gettext("Filter")); filter_selected_input.id = field_id + '_selected_input'; - const to_box = quickElement('select', selector_chosen, '', 'id', field_id + '_to', 'multiple', '', 'size', from_box.size, 'name', from_box.name); - to_box.className = 'filtered'; - + quickElement( + 'select', + selector_chosen, + '', + 'id', field_id + '_to', + 'multiple', '', + 'size', from_box.size, + 'name', from_box.name, + 'aria-labelledby', field_id + '_to_title', + 'class', 'filtered' + ); const warning_footer = quickElement('div', selector_chosen, '', 'class', 'list-footer-display'); quickElement('span', warning_footer, '', 'id', field_id + '_list-footer-display-text'); quickElement('span', warning_footer, ' ' + gettext('(click to clear)'), 'class', 'list-footer-display__clear'); - - const clear_all = quickElement('a', selector_chosen, gettext('Remove all'), 'title', interpolate(gettext('Click to remove all chosen %s at once.'), [field_name]), 'href', '#', 'id', field_id + '_remove_all_link'); - clear_all.className = 'selector-clearall'; + const clear_all = quickElement( + 'button', + selector_chosen, + interpolate(gettext('Remove all %s'), [field_name]), + 'id', field_id + '_remove_all', + 'class', 'selector-clearall' + ); from_box.name = from_box.name + '_old'; @@ -138,10 +160,10 @@ Requires core.js and SelectBox.js. choose_all.addEventListener('click', function(e) { move_selection(e, this, SelectBox.move_all, field_id + '_from', field_id + '_to'); }); - add_link.addEventListener('click', function(e) { + add_button.addEventListener('click', function(e) { move_selection(e, this, SelectBox.move, field_id + '_from', field_id + '_to'); }); - remove_link.addEventListener('click', function(e) { + remove_button.addEventListener('click', function(e) { move_selection(e, this, SelectBox.move, field_id + '_to', field_id + '_from'); }); clear_all.addEventListener('click', function(e) { @@ -227,11 +249,11 @@ Requires core.js and SelectBox.js. const from = document.getElementById(field_id + '_from'); const to = document.getElementById(field_id + '_to'); // Active if at least one item is selected - document.getElementById(field_id + '_add_link').classList.toggle('active', SelectFilter.any_selected(from)); - document.getElementById(field_id + '_remove_link').classList.toggle('active', SelectFilter.any_selected(to)); + document.getElementById(field_id + '_add').classList.toggle('active', SelectFilter.any_selected(from)); + document.getElementById(field_id + '_remove').classList.toggle('active', SelectFilter.any_selected(to)); // Active if the corresponding box isn't empty - document.getElementById(field_id + '_add_all_link').classList.toggle('active', from.querySelector('option')); - document.getElementById(field_id + '_remove_all_link').classList.toggle('active', to.querySelector('option')); + document.getElementById(field_id + '_add_all').classList.toggle('active', from.querySelector('option')); + document.getElementById(field_id + '_remove_all').classList.toggle('active', to.querySelector('option')); SelectFilter.refresh_filtered_warning(field_id); }, filter_key_press: function(event, field_id, source, target) { diff --git a/js_tests/admin/SelectFilter2.test.js b/js_tests/admin/SelectFilter2.test.js index 0b1317cff5..af227c0c1e 100644 --- a/js_tests/admin/SelectFilter2.test.js +++ b/js_tests/admin/SelectFilter2.test.js @@ -12,13 +12,25 @@ QUnit.test('init', function(assert) { SelectFilter.init('id', 'things', 0); assert.equal($('#test').children().first().prop("tagName"), "DIV"); assert.equal($('#test').children().first().attr("class"), "selector"); - assert.equal($('.selector-available h2').text().trim(), "Available things"); - assert.equal($('.selector-chosen h2').text().trim(), "Chosen things"); + assert.equal($('.selector-available label').text().trim(), "Available things"); + assert.equal($('.selector-chosen label').text().trim(), "Chosen things"); assert.equal($('.selector-chosen select')[0].getAttribute('multiple'), ''); - assert.equal($('.selector-chooseall').text(), "Choose all"); - assert.equal($('.selector-add').text(), "Choose"); - assert.equal($('.selector-remove').text(), "Remove"); - assert.equal($('.selector-clearall').text(), "Remove all"); + assert.equal($('.selector-chooseall').text(), "Choose all things"); + assert.equal($('.selector-chooseall').prop("tagName"), "BUTTON"); + assert.equal($('.selector-add').text(), "Choose selected things"); + assert.equal($('.selector-add').prop("tagName"), "BUTTON"); + assert.equal($('.selector-remove').text(), "Remove selected chosen things"); + assert.equal($('.selector-remove').prop("tagName"), "BUTTON"); + assert.equal($('.selector-clearall').text(), "Remove all things"); + assert.equal($('.selector-clearall').prop("tagName"), "BUTTON"); + assert.equal($('.selector-available .filtered').attr("aria-labelledby"), "id_from_title"); + assert.equal($('.selector-available .selector-available-title label').text(), "Available things "); + assert.equal($('.selector-available .selector-available-title .helptext').text(), 'Choose things by selecting them and then select the "Choose" arrow button.'); + assert.equal($('.selector-chosen .filtered').attr("aria-labelledby"), "id_to_title"); + assert.equal($('.selector-chosen .selector-chosen-title label').text(), "Chosen things "); + assert.equal($('.selector-chosen .selector-chosen-title .helptext').text(), 'Remove things by selecting them and then select the "Remove" arrow button.'); + assert.equal($('.selector-filter label .help-tooltip')[0].getAttribute("aria-label"), "Type into this box to filter down the list of available things."); + assert.equal($('.selector-filter label .help-tooltip')[1].getAttribute("aria-label"), "Type into this box to filter down the list of selected things."); }); QUnit.test('filtering available options', function(assert) { diff --git a/tests/admin_inlines/tests.py b/tests/admin_inlines/tests.py index 9c32f6fb8e..b08ab3a52a 100644 --- a/tests/admin_inlines/tests.py +++ b/tests/admin_inlines/tests.py @@ -2420,31 +2420,43 @@ class SeleniumTests(AdminSeleniumTestCase): "admin:admin_inlines_courseproxy1_add", "admin:admin_inlines_courseproxy2_add", ] - css_selector = ".dynamic-class_set#class_set-%s h2" + css_available_selector = ( + ".dynamic-class_set#class_set-%s .selector-available-title" + ) + css_chosen_selector = ".dynamic-class_set#class_set-%s .selector-chosen-title" for url_name in tests: with self.subTest(url=url_name): self.selenium.get(self.live_server_url + reverse(url_name)) # First inline shows the verbose_name. - available, chosen = self.selenium.find_elements( - By.CSS_SELECTOR, css_selector % 0 + available = self.selenium.find_element( + By.CSS_SELECTOR, css_available_selector % 0 ) - self.assertEqual(available.text, "AVAILABLE ATTENDANT") - self.assertEqual(chosen.text, "CHOSEN ATTENDANT") + chosen = self.selenium.find_element( + By.CSS_SELECTOR, css_chosen_selector % 0 + ) + self.assertIn("Available attendant", available.text) + self.assertIn("Chosen attendant", chosen.text) # Added inline should also have the correct verbose_name. self.selenium.find_element(By.LINK_TEXT, "Add another Class").click() - available, chosen = self.selenium.find_elements( - By.CSS_SELECTOR, css_selector % 1 + available = self.selenium.find_element( + By.CSS_SELECTOR, css_available_selector % 1 ) - self.assertEqual(available.text, "AVAILABLE ATTENDANT") - self.assertEqual(chosen.text, "CHOSEN ATTENDANT") + chosen = self.selenium.find_element( + By.CSS_SELECTOR, css_chosen_selector % 1 + ) + self.assertIn("Available attendant", available.text) + self.assertIn("Chosen attendant", chosen.text) # Third inline should also have the correct verbose_name. self.selenium.find_element(By.LINK_TEXT, "Add another Class").click() - available, chosen = self.selenium.find_elements( - By.CSS_SELECTOR, css_selector % 2 + available = self.selenium.find_element( + By.CSS_SELECTOR, css_available_selector % 2 ) - self.assertEqual(available.text, "AVAILABLE ATTENDANT") - self.assertEqual(chosen.text, "CHOSEN ATTENDANT") + chosen = self.selenium.find_element( + By.CSS_SELECTOR, css_chosen_selector % 2 + ) + self.assertIn("Available attendant", available.text) + self.assertIn("Chosen attendant", chosen.text) def test_tabular_inline_layout(self): from selenium.webdriver.common.by import By diff --git a/tests/admin_views/test_related_object_lookups.py b/tests/admin_views/test_related_object_lookups.py index 4b2171a09f..b591117460 100644 --- a/tests/admin_views/test_related_object_lookups.py +++ b/tests/admin_views/test_related_object_lookups.py @@ -162,7 +162,7 @@ class SeleniumTests(AdminSeleniumTestCase): # Move the new value to the from box. self.selenium.find_element(By.XPATH, "//*[@id='id_m2m_to']/option").click() - self.selenium.find_element(By.XPATH, "//*[@id='id_m2m_remove_link']").click() + self.selenium.find_element(By.XPATH, "//*[@id='id_m2m_remove']").click() self.assertHTMLEqual( m2m_box.get_attribute("innerHTML"), @@ -172,7 +172,7 @@ class SeleniumTests(AdminSeleniumTestCase): # Move the new value to the to box. self.selenium.find_element(By.XPATH, "//*[@id='id_m2m_from']/option").click() - self.selenium.find_element(By.XPATH, "//*[@id='id_m2m_add_link']").click() + self.selenium.find_element(By.XPATH, "//*[@id='id_m2m_add']").click() self.assertHTMLEqual(m2m_box.get_attribute("innerHTML"), "") self.assertHTMLEqual( diff --git a/tests/admin_views/tests.py b/tests/admin_views/tests.py index 3f106f6814..1ff29fc3db 100644 --- a/tests/admin_views/tests.py +++ b/tests/admin_views/tests.py @@ -6225,9 +6225,7 @@ class SeleniumTests(AdminSeleniumTestCase): self.take_screenshot("selectbox-available-perms-some-selected") # Move permissions to the "Chosen" list, but none is selected yet. - self.selenium.find_element( - By.CSS_SELECTOR, "#id_user_permissions_add_link" - ).click() + self.selenium.find_element(By.CSS_SELECTOR, "#id_user_permissions_add").click() self.take_screenshot("selectbox-chosen-perms-none-selected") # Select some permissions from the "Chosen" list. diff --git a/tests/admin_widgets/tests.py b/tests/admin_widgets/tests.py index 5da4adf8c9..a81f5802d1 100644 --- a/tests/admin_widgets/tests.py +++ b/tests/admin_widgets/tests.py @@ -1257,15 +1257,19 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase): def assertActiveButtons( self, mode, field_name, choose, remove, choose_all=None, remove_all=None ): - 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 - self.assertEqual(self.has_css_class(choose_link, "active"), choose) - self.assertEqual(self.has_css_class(remove_link, "active"), remove) + choose_button = "#id_%s_add" % field_name + choose_all_button = "#id_%s_add_all" % field_name + remove_button = "#id_%s_remove" % field_name + remove_all_button = "#id_%s_remove_all" % field_name + self.assertEqual(self.has_css_class(choose_button, "active"), choose) + self.assertEqual(self.has_css_class(remove_button, "active"), remove) if mode == "horizontal": - self.assertEqual(self.has_css_class(choose_all_link, "active"), choose_all) - self.assertEqual(self.has_css_class(remove_all_link, "active"), remove_all) + self.assertEqual( + self.has_css_class(choose_all_button, "active"), choose_all + ) + self.assertEqual( + self.has_css_class(remove_all_button, "active"), remove_all + ) def execute_basic_operations(self, mode, field_name): from selenium.webdriver.common.by import By @@ -1274,10 +1278,10 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase): 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 + choose_button = "id_%s_add" % field_name + choose_all_button = "id_%s_add_all" % field_name + remove_button = "id_%s_remove" % field_name + remove_all_button = "id_%s_remove_all" % field_name # Initial positions --------------------------------------------------- self.assertSelectOptions( @@ -1296,7 +1300,7 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase): # Click 'Choose all' -------------------------------------------------- if mode == "horizontal": - self.selenium.find_element(By.ID, choose_all_link).click() + self.selenium.find_element(By.ID, choose_all_button).click() elif mode == "vertical": # There 's no 'Choose all' button in vertical mode, so individually # select all options and click 'Choose'. @@ -1304,7 +1308,7 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase): By.CSS_SELECTOR, from_box + " > option" ): option.click() - self.selenium.find_element(By.ID, choose_link).click() + self.selenium.find_element(By.ID, choose_button).click() self.assertSelectOptions(from_box, []) self.assertSelectOptions( to_box, @@ -1323,7 +1327,7 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase): # Click 'Remove all' -------------------------------------------------- if mode == "horizontal": - self.selenium.find_element(By.ID, remove_all_link).click() + self.selenium.find_element(By.ID, remove_all_button).click() elif mode == "vertical": # There 's no 'Remove all' button in vertical mode, so individually # select all options and click 'Remove'. @@ -1331,7 +1335,7 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase): By.CSS_SELECTOR, to_box + " > option" ): option.click() - self.selenium.find_element(By.ID, remove_link).click() + self.selenium.find_element(By.ID, remove_button).click() self.assertSelectOptions( from_box, [ @@ -1364,7 +1368,7 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase): self.select_option(from_box, str(self.bob.id)) self.select_option(from_box, str(self.john.id)) self.assertActiveButtons(mode, field_name, True, False, True, False) - self.selenium.find_element(By.ID, choose_link).click() + self.selenium.find_element(By.ID, choose_button).click() self.assertActiveButtons(mode, field_name, False, False, True, True) self.assertSelectOptions( @@ -1399,7 +1403,7 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase): self.select_option(to_box, str(self.lisa.id)) self.select_option(to_box, str(self.bob.id)) self.assertActiveButtons(mode, field_name, False, True, True, True) - self.selenium.find_element(By.ID, remove_link).click() + self.selenium.find_element(By.ID, remove_button).click() self.assertActiveButtons(mode, field_name, False, False, True, True) self.assertSelectOptions( @@ -1418,7 +1422,7 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase): # Choose some more options -------------------------------------------- self.select_option(from_box, str(self.arthur.id)) self.select_option(from_box, str(self.cliff.id)) - self.selenium.find_element(By.ID, choose_link).click() + self.selenium.find_element(By.ID, choose_button).click() self.assertSelectOptions( from_box, @@ -1445,7 +1449,7 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase): # Confirm they're selected after clicking inactive buttons: ticket #26575 self.assertSelectedOptions(from_box, [str(self.peter.id), str(self.lisa.id)]) - self.selenium.find_element(By.ID, remove_link).click() + self.selenium.find_element(By.ID, remove_button).click() self.assertSelectedOptions(from_box, [str(self.peter.id), str(self.lisa.id)]) # Unselect the options ------------------------------------------------ @@ -1458,7 +1462,7 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase): # Confirm they're selected after clicking inactive buttons: ticket #26575 self.assertSelectedOptions(to_box, [str(self.jason.id), str(self.john.id)]) - self.selenium.find_element(By.ID, choose_link).click() + self.selenium.find_element(By.ID, choose_button).click() self.assertSelectedOptions(to_box, [str(self.jason.id), str(self.john.id)]) # Unselect the options ------------------------------------------------ @@ -1520,8 +1524,8 @@ class HorizontalVerticalFilterSeleniumTests(AdminWidgetSeleniumTestCase): for field_name in ["students", "alumni"]: from_box = "#id_%s_from" % field_name to_box = "#id_%s_to" % field_name - choose_link = "id_%s_add_link" % field_name - remove_link = "id_%s_remove_link" % field_name + choose_link = "id_%s_add" % field_name + remove_link = "id_%s_remove" % field_name input = self.selenium.find_element(By.ID, "id_%s_input" % field_name) # Initial values. self.assertSelectOptions(