Commit 99929eae by Tim Krones

Add tests for keyboard a11y.

parent 238bbe21
...@@ -14,8 +14,9 @@ TOP_ZONE_DESCRIPTION = _("Use this zone to associate an item with the top layer ...@@ -14,8 +14,9 @@ TOP_ZONE_DESCRIPTION = _("Use this zone to associate an item with the top layer
MIDDLE_ZONE_DESCRIPTION = _("Use this zone to associate an item with the middle layer of the triangle.") MIDDLE_ZONE_DESCRIPTION = _("Use this zone to associate an item with the middle layer of the triangle.")
BOTTOM_ZONE_DESCRIPTION = _("Use this zone to associate an item with the bottom layer of the triangle.") BOTTOM_ZONE_DESCRIPTION = _("Use this zone to associate an item with the bottom layer of the triangle.")
ITEM_INCORRECT_FEEDBACK = _("No, this item does not belong here. Try again.")
ITEM_CORRECT_FEEDBACK = _("Correct! This one belongs to {zone}.") ITEM_CORRECT_FEEDBACK = _("Correct! This one belongs to {zone}.")
ITEM_INCORRECT_FEEDBACK = _("No, this item does not belong here. Try again.")
ITEM_NO_ZONE_FEEDBACK = _("You silly, there are no zones for this one.")
START_FEEDBACK = _("Drag the items onto the image above.") START_FEEDBACK = _("Drag the items onto the image above.")
FINISH_FEEDBACK = _("Good work! You have completed this drag and drop exercise.") FINISH_FEEDBACK = _("Good work! You have completed this drag and drop exercise.")
...@@ -88,7 +89,7 @@ DEFAULT_DATA = { ...@@ -88,7 +89,7 @@ DEFAULT_DATA = {
{ {
"displayName": _("I don't belong anywhere"), "displayName": _("I don't belong anywhere"),
"feedback": { "feedback": {
"incorrect": _("You silly, there are no zones for this one."), "incorrect": ITEM_NO_ZONE_FEEDBACK,
"correct": "" "correct": ""
}, },
"zone": "none", "zone": "none",
......
...@@ -91,7 +91,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -91,7 +91,7 @@ function DragAndDropBlock(runtime, element, configuration) {
}; };
var focusModalButton = function() { var focusModalButton = function() {
$root.find('.keyboard-help-dialog .dismiss-modal-button ').focus(); $root.find('.keyboard-help-dialog .modal-dismiss-button ').focus();
}; };
var showKeyboardHelp = function(evt) { var showKeyboardHelp = function(evt) {
...@@ -108,7 +108,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -108,7 +108,7 @@ function DragAndDropBlock(runtime, element, configuration) {
// Set up event handlers // Set up event handlers
$(document).on('keydown', keyboardEventDispatcher); $(document).on('keydown', keyboardEventDispatcher);
$keyboardHelpDialog.find('.dismiss-modal-button').on('click', hideKeyboardHelp); $keyboardHelpDialog.find('.modal-dismiss-button').on('click', hideKeyboardHelp);
}; };
var hideKeyboardHelp = function(evt) { var hideKeyboardHelp = function(evt) {
...@@ -124,7 +124,7 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -124,7 +124,7 @@ function DragAndDropBlock(runtime, element, configuration) {
// Remove event handlers // Remove event handlers
$(document).off('keydown', keyboardEventDispatcher); $(document).off('keydown', keyboardEventDispatcher);
$keyboardHelpDialog.find('.dismiss-modal-button').off(); $keyboardHelpDialog.find('.modal-dismiss-button').off();
}; };
/** Asynchronously load the main background image used for this block. */ /** Asynchronously load the main background image used for this block. */
......
...@@ -164,6 +164,8 @@ ...@@ -164,6 +164,8 @@
var dialog_attributes = { role: 'dialog', 'aria-labelledby': 'modal-window-title' }; var dialog_attributes = { role: 'dialog', 'aria-labelledby': 'modal-window-title' };
var dialog_style = {}; var dialog_style = {};
return ( return (
h('section.keyboard-help', [
h('a.keyboard-help-button', { attributes: { tabindex: 0 } }, gettext('Keyboard Help')),
h('div.keyboard-help-dialog', [ h('div.keyboard-help-dialog', [
h('div.modal-window-overlay'), h('div.modal-window-overlay'),
h('div.modal-window', { attributes: dialog_attributes, style: dialog_style }, [ h('div.modal-window', { attributes: dialog_attributes, style: dialog_style }, [
...@@ -181,8 +183,8 @@ ...@@ -181,8 +183,8 @@
]) ])
]), ]),
h('div.modal-actions', [ h('div.modal-actions', [
h('h3.sr', gettext('Actions')), h('button.modal-dismiss-button', gettext("OK"))
h('button.dismiss-modal-button', gettext("OK")) ])
]) ])
]) ])
]) ])
...@@ -223,9 +225,6 @@ ...@@ -223,9 +225,6 @@
renderCollection(itemTemplate, items_placed, ctx), renderCollection(itemTemplate, items_placed, ctx),
]), ]),
]), ]),
h('section.keyboard-help', [
h('a.keyboard-help-button', { attributes: { tabindex: 0 } }, gettext('Keyboard Help'))
]),
keyboardHelpTemplate(ctx), keyboardHelpTemplate(ctx),
feedbackTemplate(ctx), feedbackTemplate(ctx),
]) ])
......
...@@ -57,6 +57,21 @@ class BaseIntegrationTest(SeleniumBaseTest): ...@@ -57,6 +57,21 @@ class BaseIntegrationTest(SeleniumBaseTest):
def _get_zones(self): def _get_zones(self):
return self._page.find_elements_by_css_selector(".drag-container .zone") return self._page.find_elements_by_css_selector(".drag-container .zone")
def _get_popup(self):
return self._page.find_element_by_css_selector(".popup")
def _get_popup_content(self):
return self._page.find_element_by_css_selector(".popup .popup-content")
def _get_keyboard_help(self):
return self._page.find_element_by_css_selector(".keyboard-help")
def _get_keyboard_help_button(self):
return self._page.find_element_by_css_selector(".keyboard-help .keyboard-help-button")
def _get_keyboard_help_dialog(self):
return self._page.find_element_by_css_selector(".keyboard-help .keyboard-help-dialog")
def _get_feedback(self): def _get_feedback(self):
return self._page.find_element_by_css_selector(".feedback") return self._page.find_element_by_css_selector(".feedback")
......
from ddt import ddt, data
from selenium.common.exceptions import NoSuchElementException
from selenium.webdriver import ActionChains from selenium.webdriver import ActionChains
from selenium.webdriver.common.keys import Keys
from drag_and_drop_v2.default_data import START_FEEDBACK, FINISH_FEEDBACK from drag_and_drop_v2.default_data import (
TOP_ZONE_TITLE, MIDDLE_ZONE_TITLE, BOTTOM_ZONE_TITLE,
ITEM_CORRECT_FEEDBACK, ITEM_INCORRECT_FEEDBACK, ITEM_NO_ZONE_FEEDBACK,
START_FEEDBACK, FINISH_FEEDBACK
)
from .test_base import BaseIntegrationTest from .test_base import BaseIntegrationTest
from ..utils import load_resource from ..utils import load_resource
ZONES_MAP = {
0: TOP_ZONE_TITLE,
1: MIDDLE_ZONE_TITLE,
2: BOTTOM_ZONE_TITLE,
}
class ItemDefinition(object): class ItemDefinition(object):
def __init__(self, item_id, zone_id, feedback_positive, feedback_negative, input_value=None): def __init__(self, item_id, zone_id, feedback_positive, feedback_negative, input_value=None):
self.feedback_negative = feedback_negative self.feedback_negative = feedback_negative
...@@ -37,6 +52,10 @@ class InteractionTestBase(object): ...@@ -37,6 +52,10 @@ class InteractionTestBase(object):
items_container = self._page.find_element_by_css_selector('.item-bank') items_container = self._page.find_element_by_css_selector('.item-bank')
return items_container.find_elements_by_xpath("//div[@data-value='{item_id}']".format(item_id=item_value))[0] return items_container.find_elements_by_xpath("//div[@data-value='{item_id}']".format(item_id=item_value))[0]
def _get_placed_item_by_value(self, item_value):
items_container = self._page.find_element_by_css_selector('.target')
return items_container.find_elements_by_xpath("//div[@data-value='{item_id}']".format(item_id=item_value))[0]
def _get_zone_by_id(self, zone_id): def _get_zone_by_id(self, zone_id):
zones_container = self._page.find_element_by_css_selector('.target') zones_container = self._page.find_element_by_css_selector('.target')
return zones_container.find_elements_by_xpath("//div[@data-zone='{zone_id}']".format(zone_id=zone_id))[0] return zones_container.find_elements_by_xpath("//div[@data-zone='{zone_id}']".format(zone_id=zone_id))[0]
...@@ -63,28 +82,98 @@ class InteractionTestBase(object): ...@@ -63,28 +82,98 @@ class InteractionTestBase(object):
action_chains = ActionChains(self.browser) action_chains = ActionChains(self.browser)
action_chains.drag_and_drop(element, target).perform() action_chains.drag_and_drop(element, target).perform()
def parameterized_item_positive_feedback_on_good_move(self, items_map, scroll_down=100): def move_item_to_zone(self, item_value, zone_id, action_key):
# Get item position
item_position = item_value
# Get zone position
zone_position = self.get_zone_position(zone_id)
self.focus_item(0)
focused_item = self._get_item_by_value(0)
for i in range(item_position):
focused_item.send_keys(Keys.TAB)
focused_item = self._get_item_by_value(i+1)
focused_item.send_keys(action_key) # Focus is on first *zone* now
focused_zone = self._get_zone_by_id(ZONES_MAP[0])
for i in range(zone_position):
focused_zone.send_keys(Keys.TAB)
focused_zone = self._get_zone_by_id(ZONES_MAP[i+1])
focused_zone.send_keys(action_key)
def get_zone_position(self, zone_id):
return self.browser.execute_script(
'return $("div[data-zone=\'{zone_id}\']").prevAll(".zone").length'.format(zone_id=zone_id)
)
def focus_item(self, item_position):
self.browser.execute_script("$('.option:nth-child({n})').focus()".format(n=item_position+1))
def assert_placed_item(self, item_value, zone_id):
item = self._get_placed_item_by_value(item_value)
item_content = item.find_element_by_css_selector('.item-content')
item_description = item.find_element_by_css_selector('.sr')
item_description_id = 'item-{}-description'.format(item_value)
self.assertIsNone(item.get_attribute('tabindex'))
self.assertEqual(item.get_attribute('aria-grabbed'), 'false')
self.assertEqual(item.get_attribute('data-drag-disabled'), 'true')
self.assertEqual(item_content.get_attribute('aria-describedby'), item_description_id)
self.assertEqual(item_description.get_attribute('id'), item_description_id)
self.assertEqual(item_description.text, 'Correctly placed in: {}'.format(zone_id))
def assert_reverted_item(self, item_value):
item = self._get_item_by_value(item_value)
item_content = item.find_element_by_css_selector('.item-content')
self.assertEqual(item.get_attribute('tabindex'), '0')
self.assertEqual(item.get_attribute('draggable'), 'true')
self.assertEqual(item.get_attribute('aria-grabbed'), 'false')
self.assertEqual(item.get_attribute('data-drag-disabled'), 'false')
self.assertIsNone(item_content.get_attribute('aria-describedby'))
try:
item.find_element_by_css_selector('.sr')
except NoSuchElementException:
pass
else:
self.fail('Reverted item should not have .sr description.')
def parameterized_item_positive_feedback_on_good_move(
self, items_map, scroll_down=100, use_keyboard=False, action_key=Keys.RETURN
):
# Scroll drop zones into view to make sure Selenium can successfully drop items # Scroll drop zones into view to make sure Selenium can successfully drop items
self.scroll_down(pixels=scroll_down) self.scroll_down(pixels=scroll_down)
for definition in self._get_correct_item_for_zone(items_map).values(): for definition in self._get_correct_item_for_zone(items_map).values():
if not definition.input: if not definition.input:
if use_keyboard:
self.move_item_to_zone(definition.item_id, definition.zone_id, action_key)
else:
self.drag_item_to_zone(definition.item_id, definition.zone_id) self.drag_item_to_zone(definition.item_id, definition.zone_id)
feedback_popup = self.get_feedback_popup() feedback_popup = self.get_feedback_popup()
self.wait_until_html_in(definition.feedback_positive, feedback_popup) self.wait_until_html_in(definition.feedback_positive, feedback_popup)
self.assert_placed_item(definition.item_id, definition.zone_id)
def parameterized_item_positive_feedback_on_good_input(self, items_map, scroll_down=100): def parameterized_item_positive_feedback_on_good_input(
self, items_map, scroll_down=100, use_keyboard=False, action_key=Keys.RETURN
):
self.scroll_down(pixels=scroll_down) self.scroll_down(pixels=scroll_down)
feedback_popup = self.get_feedback_popup() feedback_popup = self.get_feedback_popup()
for definition in self._get_correct_item_for_zone(items_map).values(): for definition in self._get_correct_item_for_zone(items_map).values():
if definition.input: if definition.input:
if use_keyboard:
self.move_item_to_zone(definition.item_id, definition.zone_id, action_key)
else:
self.drag_item_to_zone(definition.item_id, definition.zone_id) self.drag_item_to_zone(definition.item_id, definition.zone_id)
self._send_input(definition.item_id, definition.input) self._send_input(definition.item_id, definition.input)
input_div = self._get_input_div_by_value(definition.item_id) input_div = self._get_input_div_by_value(definition.item_id)
self.wait_until_has_class('correct', input_div) self.wait_until_has_class('correct', input_div)
self.wait_until_html_in(definition.feedback_positive, feedback_popup) self.wait_until_html_in(definition.feedback_positive, feedback_popup)
self.assert_placed_item(definition.item_id, definition.zone_id)
def parameterized_item_negative_feedback_on_bad_move(self, items_map, all_zones, scroll_down=100): def parameterized_item_negative_feedback_on_bad_move(
self, items_map, all_zones, scroll_down=100, use_keyboard=False, action_key=Keys.RETURN
):
feedback_popup = self.get_feedback_popup() feedback_popup = self.get_feedback_popup()
# Scroll drop zones into view to make sure Selenium can successfully drop items # Scroll drop zones into view to make sure Selenium can successfully drop items
...@@ -94,10 +183,16 @@ class InteractionTestBase(object): ...@@ -94,10 +183,16 @@ class InteractionTestBase(object):
for zone in all_zones: for zone in all_zones:
if zone == definition.zone_id: if zone == definition.zone_id:
continue continue
if use_keyboard:
self.move_item_to_zone(definition.item_id, zone, action_key)
else:
self.drag_item_to_zone(definition.item_id, zone) self.drag_item_to_zone(definition.item_id, zone)
self.wait_until_html_in(definition.feedback_negative, feedback_popup) self.wait_until_html_in(definition.feedback_negative, feedback_popup)
self.assert_reverted_item(definition.item_id)
def parameterized_item_positive_feedback_on_bad_input(self, items_map, scroll_down=100): def parameterized_item_negative_feedback_on_bad_input(
self, items_map, scroll_down=100, use_keyboard=False, action_key=Keys.RETURN
):
feedback_popup = self.get_feedback_popup() feedback_popup = self.get_feedback_popup()
# Scroll drop zones into view to make sure Selenium can successfully drop items # Scroll drop zones into view to make sure Selenium can successfully drop items
...@@ -105,13 +200,19 @@ class InteractionTestBase(object): ...@@ -105,13 +200,19 @@ class InteractionTestBase(object):
for definition in self._get_correct_item_for_zone(items_map).values(): for definition in self._get_correct_item_for_zone(items_map).values():
if definition.input: if definition.input:
if use_keyboard:
self.move_item_to_zone(definition.item_id, definition.zone_id, action_key)
else:
self.drag_item_to_zone(definition.item_id, definition.zone_id) self.drag_item_to_zone(definition.item_id, definition.zone_id)
self._send_input(definition.item_id, '1999999') self._send_input(definition.item_id, '1999999')
input_div = self._get_input_div_by_value(definition.item_id) input_div = self._get_input_div_by_value(definition.item_id)
self.wait_until_has_class('incorrect', input_div) self.wait_until_has_class('incorrect', input_div)
self.wait_until_html_in(definition.feedback_negative, feedback_popup) self.wait_until_html_in(definition.feedback_negative, feedback_popup)
self.assert_placed_item(definition.item_id, definition.zone_id)
def parameterized_final_feedback_and_reset(self, items_map, feedback, scroll_down=100): def parameterized_final_feedback_and_reset(
self, items_map, feedback, scroll_down=100, use_keyboard=False, action_key=Keys.RETURN
):
feedback_message = self._get_feedback_message() feedback_message = self._get_feedback_message()
self.assertEqual(self.get_element_html(feedback_message), feedback['intro']) # precondition check self.assertEqual(self.get_element_html(feedback_message), feedback['intro']) # precondition check
...@@ -126,11 +227,15 @@ class InteractionTestBase(object): ...@@ -126,11 +227,15 @@ class InteractionTestBase(object):
self.scroll_down(pixels=scroll_down) self.scroll_down(pixels=scroll_down)
for item_key, definition in items.items(): for item_key, definition in items.items():
self.drag_item_to_zone(item_key, definition.zone_id) if use_keyboard:
self.move_item_to_zone(definition.item_id, definition.zone_id, action_key)
else:
self.drag_item_to_zone(definition.item_id, definition.zone_id)
if definition.input: if definition.input:
self._send_input(item_key, definition.input) self._send_input(item_key, definition.input)
input_div = self._get_input_div_by_value(item_key) input_div = self._get_input_div_by_value(item_key)
self.wait_until_has_class('correct', input_div) self.wait_until_has_class('correct', input_div)
self.assert_placed_item(definition.item_id, definition.zone_id)
self.wait_until_html_in(feedback['final'], self._get_feedback_message()) self.wait_until_html_in(feedback['final'], self._get_feedback_message())
...@@ -138,6 +243,9 @@ class InteractionTestBase(object): ...@@ -138,6 +243,9 @@ class InteractionTestBase(object):
self.scroll_down(pixels=scroll_down+150) self.scroll_down(pixels=scroll_down+150)
reset = self.get_reset_button() reset = self.get_reset_button()
if use_keyboard:
reset.send_keys(Keys.RETURN)
else:
reset.click() reset.click()
self.wait_until_html_in(feedback['intro'], self._get_feedback_message()) self.wait_until_html_in(feedback['intro'], self._get_feedback_message())
...@@ -145,22 +253,56 @@ class InteractionTestBase(object): ...@@ -145,22 +253,56 @@ class InteractionTestBase(object):
locations_after_reset = get_locations() locations_after_reset = get_locations()
for item_key in items.keys(): for item_key in items.keys():
self.assertDictEqual(locations_after_reset[item_key], initial_locations[item_key]) self.assertDictEqual(locations_after_reset[item_key], initial_locations[item_key])
self.assert_reverted_item(item_key)
def interact_with_keyboard_help(self, scroll_down=250, use_keyboard=False):
keyboard_help_button = self._get_keyboard_help_button()
keyboard_help_dialog = self._get_keyboard_help_dialog()
dialog_modal_overlay = keyboard_help_dialog.find_element_by_css_selector('.modal-window-overlay')
dialog_modal = keyboard_help_dialog.find_element_by_css_selector('.modal-window')
dialog_dismiss_button = dialog_modal.find_element_by_css_selector('.modal-dismiss-button')
# Scroll "Keyboard help" button into view to make sure Selenium can successfully click it
self.scroll_down(pixels=scroll_down)
if use_keyboard:
keyboard_help_button.send_keys(Keys.RETURN)
else:
keyboard_help_button.click()
self.assertTrue(dialog_modal_overlay.is_displayed())
self.assertTrue(dialog_modal.is_displayed())
if use_keyboard:
dialog_dismiss_button.send_keys(Keys.RETURN)
else:
dialog_dismiss_button.click()
self.assertFalse(dialog_modal_overlay.is_displayed())
self.assertFalse(dialog_modal.is_displayed())
class BasicInteractionTest(InteractionTestBase): class BasicInteractionTest(InteractionTestBase):
""" """
Verifying Drag and Drop XBlock rendering against default data - if default data changes this will probably break. Testing interactions with Drag and Drop XBlock against default data. If default data changes this will break.
""" """
PAGE_TITLE = 'Drag and Drop v2' PAGE_TITLE = 'Drag and Drop v2'
PAGE_ID = 'drag_and_drop_v2' PAGE_ID = 'drag_and_drop_v2'
items_map = { items_map = {
0: ItemDefinition(0, 'Zone 1', "Yes, it's a 1", "No, 1 does not belong here"), 0: ItemDefinition(
1: ItemDefinition(1, 'Zone 2', "Yes, it's a 2", "No, 2 does not belong here"), 0, TOP_ZONE_TITLE, ITEM_CORRECT_FEEDBACK.format(zone=TOP_ZONE_TITLE), ITEM_INCORRECT_FEEDBACK
2: ItemDefinition(2, None, "", "You silly, there are no zones for X") ),
1: ItemDefinition(
1, MIDDLE_ZONE_TITLE, ITEM_CORRECT_FEEDBACK.format(zone=MIDDLE_ZONE_TITLE), ITEM_INCORRECT_FEEDBACK
),
2: ItemDefinition(
2, BOTTOM_ZONE_TITLE, ITEM_CORRECT_FEEDBACK.format(zone=BOTTOM_ZONE_TITLE), ITEM_INCORRECT_FEEDBACK
),
3: ItemDefinition(3, None, "", ITEM_NO_ZONE_FEEDBACK),
} }
all_zones = ['Zone 1', 'Zone 2'] all_zones = [TOP_ZONE_TITLE, MIDDLE_ZONE_TITLE, BOTTOM_ZONE_TITLE]
feedback = { feedback = {
"intro": START_FEEDBACK, "intro": START_FEEDBACK,
...@@ -179,12 +321,51 @@ class BasicInteractionTest(InteractionTestBase): ...@@ -179,12 +321,51 @@ class BasicInteractionTest(InteractionTestBase):
def test_item_negative_feedback_on_bad_move(self): def test_item_negative_feedback_on_bad_move(self):
self.parameterized_item_negative_feedback_on_bad_move(self.items_map, self.all_zones) self.parameterized_item_negative_feedback_on_bad_move(self.items_map, self.all_zones)
def test_item_positive_feedback_on_bad_input(self): def test_item_negative_feedback_on_bad_input(self):
self.parameterized_item_positive_feedback_on_bad_input(self.items_map) self.parameterized_item_negative_feedback_on_bad_input(self.items_map)
def test_final_feedback_and_reset(self): def test_final_feedback_and_reset(self):
self.parameterized_final_feedback_and_reset(self.items_map, self.feedback) self.parameterized_final_feedback_and_reset(self.items_map, self.feedback)
def test_keyboard_help(self):
self.interact_with_keyboard_help()
@ddt
class KeyboardInteractionTest(BasicInteractionTest, BaseIntegrationTest):
@data(Keys.RETURN, Keys.SPACE)
def test_item_positive_feedback_on_good_move(self, action_key):
self.parameterized_item_positive_feedback_on_good_move(
self.items_map, use_keyboard=True, action_key=action_key
)
@data(Keys.RETURN, Keys.SPACE)
def test_item_positive_feedback_on_good_input(self, action_key):
self.parameterized_item_positive_feedback_on_good_input(
self.items_map, use_keyboard=True, action_key=action_key
)
@data(Keys.RETURN, Keys.SPACE)
def test_item_negative_feedback_on_bad_move(self, action_key):
self.parameterized_item_negative_feedback_on_bad_move(
self.items_map, self.all_zones, use_keyboard=True, action_key=action_key
)
@data(Keys.RETURN, Keys.SPACE)
def test_item_negative_feedback_on_bad_input(self, action_key):
self.parameterized_item_negative_feedback_on_bad_input(
self.items_map, use_keyboard=True, action_key=action_key
)
@data(Keys.RETURN, Keys.SPACE)
def test_final_feedback_and_reset(self, action_key):
self.parameterized_final_feedback_and_reset(
self.items_map, self.feedback, use_keyboard=True, action_key=action_key
)
def test_keyboard_help(self, use_keyboard=True):
self.interact_with_keyboard_help()
class CustomDataInteractionTest(BasicInteractionTest, BaseIntegrationTest): class CustomDataInteractionTest(BasicInteractionTest, BaseIntegrationTest):
items_map = { items_map = {
...@@ -284,11 +465,11 @@ class MultipleBlocksDataInteraction(InteractionTestBase, BaseIntegrationTest): ...@@ -284,11 +465,11 @@ class MultipleBlocksDataInteraction(InteractionTestBase, BaseIntegrationTest):
self.item_maps['block2'], self.all_zones['block2'], scroll_down=900 self.item_maps['block2'], self.all_zones['block2'], scroll_down=900
) )
def test_item_positive_feedback_on_bad_input(self): def test_item_negative_feedback_on_bad_input(self):
self._switch_to_block(0) self._switch_to_block(0)
self.parameterized_item_positive_feedback_on_bad_input(self.item_maps['block1']) self.parameterized_item_negative_feedback_on_bad_input(self.item_maps['block1'])
self._switch_to_block(1) self._switch_to_block(1)
self.parameterized_item_positive_feedback_on_bad_input(self.item_maps['block2'], scroll_down=900) self.parameterized_item_negative_feedback_on_bad_input(self.item_maps['block2'], scroll_down=900)
def test_final_feedback_and_reset(self): def test_final_feedback_and_reset(self):
self._switch_to_block(0) self._switch_to_block(0)
......
...@@ -179,6 +179,30 @@ class TestDragAndDropRender(BaseIntegrationTest): ...@@ -179,6 +179,30 @@ class TestDragAndDropRender(BaseIntegrationTest):
# Zone description should only be visible to screen readers: # Zone description should only be visible to screen readers:
self.assertEqual(zone_description.get_attribute('class'), 'zone-description sr') self.assertEqual(zone_description.get_attribute('class'), 'zone-description sr')
def test_popup(self):
self.load_scenario()
popup = self._get_popup()
popup_content = self._get_popup_content()
self.assertFalse(popup.is_displayed())
self.assertEqual(popup.get_attribute('aria-live'), 'polite')
self.assertEqual(popup_content.text, "")
def test_keyboard_help(self):
self.load_scenario()
self._get_keyboard_help()
keyboard_help_button = self._get_keyboard_help_button()
keyboard_help_dialog = self._get_keyboard_help_dialog()
dialog_modal_overlay = keyboard_help_dialog.find_element_by_css_selector('.modal-window-overlay')
dialog_modal = keyboard_help_dialog.find_element_by_css_selector('.modal-window')
self.assertEqual(keyboard_help_button.get_attribute('tabindex'), '0')
self.assertFalse(dialog_modal_overlay.is_displayed())
self.assertFalse(dialog_modal.is_displayed())
self.assertEqual(dialog_modal.get_attribute('role'), 'dialog')
self.assertEqual(dialog_modal.get_attribute('aria-labelledby'), 'modal-window-title')
def test_feedback(self): def test_feedback(self):
self.load_scenario() self.load_scenario()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment