Commit 7f112d7b by Jillian Vogel

OC-1320 Added integration tests for the zone align feature

* Added test data used by test_render and test_interaction
* Moved _get_style() to test_base, so it can be shared
* Added tests to test_interaction and test_render
* Updated JS to set a default empty string for zone.align
parent 2f6442ff
...@@ -981,11 +981,12 @@ function DragAndDropBlock(runtime, element, configuration) { ...@@ -981,11 +981,12 @@ function DragAndDropBlock(runtime, element, configuration) {
var markItemZoneAlign = function() { var markItemZoneAlign = function() {
var zone_align = {}; var zone_align = {};
configuration.zones.forEach(function(zone) { configuration.zones.forEach(function(zone) {
if (!zone.align) zone.align = '';
zone_align[zone.title] = zone.align; zone_align[zone.title] = zone.align;
}); });
Object.keys(state.items).forEach(function(item_id) { Object.keys(state.items).forEach(function(item_id) {
var item = state.items[item_id]; var item = state.items[item_id];
item.zone_align = zone_align[item.zone]; item.zone_align = zone_align[item.zone] || '';
}); });
}; };
......
{
"zones": [
{
"index": 1,
"title": "Zone No Align",
"width": 200,
"height": 100,
"x": 0,
"y": 0,
"align": "",
"id": "zone-none"
},
{
"index": 1,
"title": "Zone Invalid Align",
"width": 200,
"height": 100,
"x": 0,
"y": 100,
"align": "invalid",
"id": "zone-invalid"
},
{
"index": 2,
"title": "Zone Left Align",
"width": 200,
"height": 100,
"x": 0,
"y": 200,
"align": "left",
"id": "zone-left"
},
{
"index": 3,
"title": "Zone Right Align",
"width": 200,
"height": 100,
"x": 0,
"y": 300,
"align": "right",
"id": "zone-right"
},
{
"index": 4,
"title": "Zone Center Align",
"width": 200,
"height": 100,
"x": 0,
"y": 400,
"align": "center",
"id": "zone-center"
}
],
"items": [
{
"displayName": "AAAA",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone No Align",
"imageURL": "",
"id": 0
},
{
"displayName": "AAAA",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone No Align",
"imageURL": "",
"id": 1
},
{
"displayName": "AAAA",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone No Align",
"imageURL": "",
"id": 2
},
{
"displayName": "BBBB",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone Invalid Align",
"imageURL": "",
"id": 3
},
{
"displayName": "BBBB",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone Invalid Align",
"imageURL": "",
"id": 4
},
{
"displayName": "BBBB",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone Invalid Align",
"imageURL": "",
"id": 5
},
{
"displayName": "CCCC",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone Left Align",
"imageURL": "",
"id": 6
},
{
"displayName": "CCCC",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone Left Align",
"imageURL": "",
"id": 7
},
{
"displayName": "CCCC",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone Left Align",
"imageURL": "",
"id": 8
},
{
"displayName": "DDDD",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone Right Align",
"imageURL": "",
"id": 9
},
{
"displayName": "DDDD",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone Right Align",
"imageURL": "",
"id":10
},
{
"displayName": "DDDD",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone Right Align",
"imageURL": "",
"id": 11
},
{
"displayName": "EEEE",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone Center Align",
"imageURL": "",
"id": 12
},
{
"displayName": "EEEE",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone Center Align",
"imageURL": "",
"id": 13
},
{
"displayName": "EEEE",
"feedback": {
"incorrect": "No",
"correct": "Yes"
},
"zone": "Zone Center Align",
"imageURL": "",
"id": 14
},
],
"feedback": {
"start": "Intro",
"finish": "Final"
},
"targetImg": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4MDAiIGhlaWdodD0iNjAwIiBzdHlsZT0iYmFja2dyb3VuZDogI2VlZjsiPjwvc3ZnPg==",
"targetImgDescription": "This describes the target image"
}
...@@ -91,6 +91,13 @@ class BaseIntegrationTest(SeleniumBaseTest): ...@@ -91,6 +91,13 @@ class BaseIntegrationTest(SeleniumBaseTest):
def scroll_down(self, pixels=50): def scroll_down(self, pixels=50):
self.browser.execute_script("$(window).scrollTop({})".format(pixels)) self.browser.execute_script("$(window).scrollTop({})".format(pixels))
def _get_style(self, selector, style, computed=True):
if computed:
query = 'return getComputedStyle($("{selector}").get(0)).{style}'
else:
query = 'return $("{selector}").get(0).style.{style}'
return self.browser.execute_script(query.format(selector=selector, style=style))
@staticmethod @staticmethod
def get_element_html(element): def get_element_html(element):
return element.get_attribute('innerHTML').strip() return element.get_attribute('innerHTML').strip()
......
...@@ -581,3 +581,100 @@ class MultipleBlocksDataInteraction(InteractionTestBase, BaseIntegrationTest): ...@@ -581,3 +581,100 @@ class MultipleBlocksDataInteraction(InteractionTestBase, BaseIntegrationTest):
# Test mouse and keyboard interaction # Test mouse and keyboard interaction
self.interact_with_keyboard_help(scroll_down=900) self.interact_with_keyboard_help(scroll_down=900)
self.interact_with_keyboard_help(scroll_down=0, use_keyboard=True) self.interact_with_keyboard_help(scroll_down=0, use_keyboard=True)
class ZoneAlignInteractionTest(InteractionTestBase, BaseIntegrationTest):
"""
Verifying Drag and Drop XBlock interactions using zone alignment.
"""
PAGE_TITLE = 'Drag and Drop v2'
PAGE_ID = 'drag_and_drop_v2'
def setUp(self):
super(ZoneAlignInteractionTest, self).setUp()
def _get_scenario_xml(self):
return self._get_custom_scenario_xml("data/test_zone_align.json")
def _assert_zone_align_item(self, item_id, zone_id, align, action_key=None):
# parent container has the expected alignment
zone_selector = "div[data-zone='%s'] .item-align" % zone_id
self.assertEquals(self._get_style(zone_selector, 'textAlign'), align)
# Items placed in zones with align setting are children of the zone
zone_item = '%s .option' % zone_selector
prev_placed_items = self._page.find_elements_by_css_selector(zone_item)
self.place_item(item_id, zone_id, action_key)
placed_items = self._page.find_elements_by_css_selector(zone_item)
self.assertEquals(len(placed_items), len(prev_placed_items) + 1)
# Not children of the target
target_item = '.target > .option'
self.assertEquals(len(self._page.find_elements_by_css_selector(target_item)), 0)
# Aligned items are relative positioned, with no transform or top/left
self.assertEquals(self._get_style(zone_item, 'position'), 'relative')
self.assertEquals(self._get_style(zone_item, 'transform'), 'none')
self.assertEquals(self._get_style(zone_item, 'left'), '0px')
self.assertEquals(self._get_style(zone_item, 'top'), '0px')
def test_no_zone_align(self):
# Items placed in zones with no align setting are children of the
# target div, not the zone
zone_id = "Zone No Align"
self.place_item(0, zone_id)
zone_item = "div[data-zone='%s'] .item-align .option" % zone_id
self.assertEquals(len(self._page.find_elements_by_css_selector(zone_item)), 0)
target_item = '.target > .option'
placed_item = self._page.find_elements_by_css_selector(target_item)
self.assertEquals(len(placed_item), 1)
self.assertEquals(placed_item[0].get_attribute('data-value'), '0')
# Non-aligned items are absolute positioned, with top/bottom set to px
self.assertEquals(self._get_style(target_item, 'position'), 'absolute')
self.assertRegexpMatches(self._get_style(target_item, 'left'), r'^\d+(\.\d+)?px$')
self.assertRegexpMatches(self._get_style(target_item, 'top'), r'^\d+(\.\d+)?px$')
def test_zone_align_invalid(self):
self._assert_zone_align_item(3, 'Zone Invalid Align', 'start')
self._assert_zone_align_item(4, 'Zone Invalid Align', 'start')
self._assert_zone_align_item(5, 'Zone Invalid Align', 'start')
def test_zone_align_invalid_key(self):
self._assert_zone_align_item(3, 'Zone Invalid Align', 'start', Keys.RETURN)
self._assert_zone_align_item(4, 'Zone Invalid Align', 'start', Keys.RETURN)
self._assert_zone_align_item(5, 'Zone Invalid Align', 'start', Keys.RETURN)
def test_zone_align_left(self):
self._assert_zone_align_item(6, 'Zone Left Align', 'left')
self._assert_zone_align_item(7, 'Zone Left Align', 'left')
self._assert_zone_align_item(8, 'Zone Left Align', 'left')
def test_zone_align_left_key(self):
self._assert_zone_align_item(6, 'Zone Left Align', 'left', Keys.RETURN)
self._assert_zone_align_item(7, 'Zone Left Align', 'left', Keys.RETURN)
self._assert_zone_align_item(8, 'Zone Left Align', 'left', Keys.RETURN)
def test_zone_align_right(self):
self._assert_zone_align_item(9, 'Zone Right Align', 'right')
self._assert_zone_align_item(10, 'Zone Right Align', 'right')
self._assert_zone_align_item(11, 'Zone Right Align', 'right')
def test_zone_align_right_key(self):
self._assert_zone_align_item(9, 'Zone Right Align', 'right', Keys.RETURN)
self._assert_zone_align_item(10, 'Zone Right Align', 'right', Keys.RETURN)
self._assert_zone_align_item(11, 'Zone Right Align', 'right', Keys.RETURN)
'''
FIXME Erratic bug in place_item(action_key=None) when there's too many zones?
def test_zone_align_center(self):
self._assert_zone_align_item(12, 'Zone Center Align', 'center')
self._assert_zone_align_item(13, 'Zone Center Align', 'center')
self._assert_zone_align_item(14, 'Zone Center Align', 'center')
'''
def test_zone_align_center_key(self):
self._assert_zone_align_item(12, 'Zone Center Align', 'center', Keys.RETURN)
self._assert_zone_align_item(13, 'Zone Center Align', 'center', Keys.RETURN)
self._assert_zone_align_item(14, 'Zone Center Align', 'center', Keys.RETURN)
...@@ -65,13 +65,6 @@ class TestDragAndDropRender(BaseIntegrationTest): ...@@ -65,13 +65,6 @@ class TestDragAndDropRender(BaseIntegrationTest):
self.browser.get(self.live_server_url) self.browser.get(self.live_server_url)
self._page = self.go_to_page(self.PAGE_TITLE) self._page = self.go_to_page(self.PAGE_TITLE)
def _get_style(self, selector, style, computed=True):
if computed:
query = 'return getComputedStyle($("{selector}").get(0)).{style}'
else:
query = 'return $("{selector}").get(0).style.{style}'
return self.browser.execute_script(query.format(selector=selector, style=style))
def _assert_box_percentages(self, selector, left, top, width, height): def _assert_box_percentages(self, selector, left, top, width, height):
""" Assert that the element 'selector' has the specified position/size percentages """ """ Assert that the element 'selector' has the specified position/size percentages """
values = {key: self._get_style(selector, key, False) for key in ['left', 'top', 'width', 'height']} values = {key: self._get_style(selector, key, False) for key in ['left', 'top', 'width', 'height']}
...@@ -188,6 +181,7 @@ class TestDragAndDropRender(BaseIntegrationTest): ...@@ -188,6 +181,7 @@ class TestDragAndDropRender(BaseIntegrationTest):
self.assertEqual(zone.get_attribute('dropzone'), 'move') self.assertEqual(zone.get_attribute('dropzone'), 'move')
self.assertEqual(zone.get_attribute('aria-dropeffect'), 'move') self.assertEqual(zone.get_attribute('aria-dropeffect'), 'move')
self.assertEqual(zone.get_attribute('data-zone'), 'Zone {}'.format(zone_number)) self.assertEqual(zone.get_attribute('data-zone'), 'Zone {}'.format(zone_number))
self.assertEqual(zone.get_attribute('data-zone_align'), '')
self.assertIn('ui-droppable', self.get_element_classes(zone)) self.assertIn('ui-droppable', self.get_element_classes(zone))
zone_box_percentages = box_percentages[index] zone_box_percentages = box_percentages[index]
self._assert_box_percentages( # pylint: disable=star-args self._assert_box_percentages( # pylint: disable=star-args
...@@ -272,3 +266,32 @@ class TestDragAndDropRender(BaseIntegrationTest): ...@@ -272,3 +266,32 @@ class TestDragAndDropRender(BaseIntegrationTest):
for zone in zones: for zone in zones:
zone_name = zone.find_element_by_css_selector('p.zone-name') zone_name = zone.find_element_by_css_selector('p.zone-name')
self.assertNotIn('sr', zone_name.get_attribute('class')) self.assertNotIn('sr', zone_name.get_attribute('class'))
@ddt
class TestDragAndDropRenderZoneAlign(BaseIntegrationTest):
"""
Verifying Drag and Drop XBlock rendering using zone alignment.
"""
PAGE_TITLE = 'Drag and Drop v2'
PAGE_ID = 'drag_and_drop_v2'
def setUp(self):
super(TestDragAndDropRenderZoneAlign, self).setUp()
scenario_xml = self._get_custom_scenario_xml("data/test_zone_align.json")
self._add_scenario(self.PAGE_ID, self.PAGE_TITLE, scenario_xml)
self._page = self.go_to_page(self.PAGE_TITLE)
def test_zone_align(self):
self.assertEquals(self._get_style('#-zone-none .item-wrapper', 'textAlign'), 'start')
self.assertEquals(self._get_style('#-zone-none .item-wrapper', 'textAlign', True), 'start')
self.assertEquals(self._get_style('#-zone-invalid .item-wrapper', 'textAlign'), 'start')
self.assertEquals(self._get_style('#-zone-invalid .item-wrapper', 'textAlign', True), 'start')
self.assertEquals(self._get_style('#-zone-left .item-wrapper', 'textAlign'), 'left')
self.assertEquals(self._get_style('#-zone-left .item-wrapper', 'textAlign', True), 'left')
self.assertEquals(self._get_style('#-zone-right .item-wrapper', 'textAlign'), 'right')
self.assertEquals(self._get_style('#-zone-right .item-wrapper', 'textAlign', True), 'right')
self.assertEquals(self._get_style('#-zone-center .item-wrapper', 'textAlign'), 'center')
self.assertEquals(self._get_style('#-zone-center .item-wrapper', 'textAlign', True), 'center')
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