Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
X
xblock-drag-and-drop-v2
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
OpenEdx
xblock-drag-and-drop-v2
Commits
698f404d
Commit
698f404d
authored
Feb 08, 2016
by
Braden MacDonald
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Identify zones by UID, not by title.
Fixes bugs when zones had numeric titles. Backwards compatible.
parent
4c066e7a
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
205 additions
and
167 deletions
+205
-167
drag_and_drop_v2/default_data.py
+10
-9
drag_and_drop_v2/drag_and_drop_v2.py
+34
-2
drag_and_drop_v2/public/js/drag_and_drop.js
+16
-5
drag_and_drop_v2/public/js/drag_and_drop_edit.js
+50
-50
drag_and_drop_v2/templates/html/js_templates.html
+10
-9
pylintrc
+1
-0
tests/integration/data/test_data.json
+4
-6
tests/integration/data/test_data_a11y.json
+1
-4
tests/integration/data/test_data_other.json
+4
-6
tests/integration/data/test_html_data.json
+4
-6
tests/integration/data/test_sizing_template.json
+6
-6
tests/integration/test_interaction.py
+36
-30
tests/integration/test_render.py
+4
-4
tests/unit/data/html/config_out.json
+2
-4
tests/unit/data/old/config_out.json
+2
-4
tests/unit/data/plain/config_out.json
+2
-4
tests/unit/data/plain/data.json
+4
-6
tests/unit/test_advanced.py
+5
-2
tests/unit/test_basics.py
+10
-10
No files found.
drag_and_drop_v2/default_data.py
View file @
698f404d
...
@@ -6,6 +6,10 @@ TARGET_IMG_DESCRIPTION = _(
...
@@ -6,6 +6,10 @@ TARGET_IMG_DESCRIPTION = _(
"and the narrowest layer is located at the top."
"and the narrowest layer is located at the top."
)
)
TOP_ZONE_ID
=
"top"
MIDDLE_ZONE_ID
=
"middle"
BOTTOM_ZONE_ID
=
"bottom"
TOP_ZONE_TITLE
=
_
(
"The Top Zone"
)
TOP_ZONE_TITLE
=
_
(
"The Top Zone"
)
MIDDLE_ZONE_TITLE
=
_
(
"The Middle Zone"
)
MIDDLE_ZONE_TITLE
=
_
(
"The Middle Zone"
)
BOTTOM_ZONE_TITLE
=
_
(
"The Bottom Zone"
)
BOTTOM_ZONE_TITLE
=
_
(
"The Bottom Zone"
)
...
@@ -25,8 +29,7 @@ DEFAULT_DATA = {
...
@@ -25,8 +29,7 @@ DEFAULT_DATA = {
"targetImgDescription"
:
TARGET_IMG_DESCRIPTION
,
"targetImgDescription"
:
TARGET_IMG_DESCRIPTION
,
"zones"
:
[
"zones"
:
[
{
{
"index"
:
1
,
"uid"
:
TOP_ZONE_ID
,
"id"
:
"zone-1"
,
"title"
:
TOP_ZONE_TITLE
,
"title"
:
TOP_ZONE_TITLE
,
"description"
:
TOP_ZONE_DESCRIPTION
,
"description"
:
TOP_ZONE_DESCRIPTION
,
"x"
:
160
,
"x"
:
160
,
...
@@ -35,8 +38,7 @@ DEFAULT_DATA = {
...
@@ -35,8 +38,7 @@ DEFAULT_DATA = {
"height"
:
178
,
"height"
:
178
,
},
},
{
{
"index"
:
2
,
"uid"
:
MIDDLE_ZONE_ID
,
"id"
:
"zone-2"
,
"title"
:
MIDDLE_ZONE_TITLE
,
"title"
:
MIDDLE_ZONE_TITLE
,
"description"
:
MIDDLE_ZONE_DESCRIPTION
,
"description"
:
MIDDLE_ZONE_DESCRIPTION
,
"x"
:
86
,
"x"
:
86
,
...
@@ -45,8 +47,7 @@ DEFAULT_DATA = {
...
@@ -45,8 +47,7 @@ DEFAULT_DATA = {
"height"
:
138
,
"height"
:
138
,
},
},
{
{
"index"
:
3
,
"uid"
:
BOTTOM_ZONE_ID
,
"id"
:
"zone-3"
,
"title"
:
BOTTOM_ZONE_TITLE
,
"title"
:
BOTTOM_ZONE_TITLE
,
"description"
:
BOTTOM_ZONE_DESCRIPTION
,
"description"
:
BOTTOM_ZONE_DESCRIPTION
,
"x"
:
15
,
"x"
:
15
,
...
@@ -62,7 +63,7 @@ DEFAULT_DATA = {
...
@@ -62,7 +63,7 @@ DEFAULT_DATA = {
"incorrect"
:
ITEM_INCORRECT_FEEDBACK
,
"incorrect"
:
ITEM_INCORRECT_FEEDBACK
,
"correct"
:
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
TOP_ZONE_TITLE
)
"correct"
:
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
TOP_ZONE_TITLE
)
},
},
"zone"
:
TOP_ZONE_
TITLE
,
"zone"
:
TOP_ZONE_
ID
,
"imageURL"
:
""
,
"imageURL"
:
""
,
"id"
:
0
,
"id"
:
0
,
},
},
...
@@ -72,7 +73,7 @@ DEFAULT_DATA = {
...
@@ -72,7 +73,7 @@ DEFAULT_DATA = {
"incorrect"
:
ITEM_INCORRECT_FEEDBACK
,
"incorrect"
:
ITEM_INCORRECT_FEEDBACK
,
"correct"
:
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
MIDDLE_ZONE_TITLE
)
"correct"
:
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
MIDDLE_ZONE_TITLE
)
},
},
"zone"
:
MIDDLE_ZONE_
TITLE
,
"zone"
:
MIDDLE_ZONE_
ID
,
"imageURL"
:
""
,
"imageURL"
:
""
,
"id"
:
1
,
"id"
:
1
,
},
},
...
@@ -82,7 +83,7 @@ DEFAULT_DATA = {
...
@@ -82,7 +83,7 @@ DEFAULT_DATA = {
"incorrect"
:
ITEM_INCORRECT_FEEDBACK
,
"incorrect"
:
ITEM_INCORRECT_FEEDBACK
,
"correct"
:
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
BOTTOM_ZONE_TITLE
)
"correct"
:
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
BOTTOM_ZONE_TITLE
)
},
},
"zone"
:
BOTTOM_ZONE_
TITLE
,
"zone"
:
BOTTOM_ZONE_
ID
,
"imageURL"
:
""
,
"imageURL"
:
""
,
"id"
:
2
,
"id"
:
2
,
},
},
...
...
drag_and_drop_v2/drag_and_drop_v2.py
View file @
698f404d
...
@@ -9,6 +9,7 @@ import copy
...
@@ -9,6 +9,7 @@ import copy
import
urllib
import
urllib
from
xblock.core
import
XBlock
from
xblock.core
import
XBlock
from
xblock.exceptions
import
JsonHandlerError
from
xblock.fields
import
Scope
,
String
,
Dict
,
Float
,
Boolean
from
xblock.fields
import
Scope
,
String
,
Dict
,
Float
,
Boolean
from
xblock.fragment
import
Fragment
from
xblock.fragment
import
Fragment
from
xblockutils.resources
import
ResourceLoader
from
xblockutils.resources
import
ResourceLoader
...
@@ -154,7 +155,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
...
@@ -154,7 +155,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
return
items
return
items
return
{
return
{
"zones"
:
self
.
data
.
get
(
'zones'
,
[]
),
"zones"
:
self
.
_get_zones
(
),
# SDK doesn't supply url_name.
# SDK doesn't supply url_name.
"url_name"
:
getattr
(
self
,
'url_name'
,
''
),
"url_name"
:
getattr
(
self
,
'url_name'
,
''
),
"display_zone_labels"
:
self
.
data
.
get
(
'displayLabels'
,
False
),
"display_zone_labels"
:
self
.
data
.
get
(
'displayLabels'
,
False
),
...
@@ -234,6 +235,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
...
@@ -234,6 +235,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
item
=
self
.
_get_item_definition
(
attempt
[
'val'
])
item
=
self
.
_get_item_definition
(
attempt
[
'val'
])
state
=
None
state
=
None
zone
=
None
feedback
=
item
[
'feedback'
][
'incorrect'
]
feedback
=
item
[
'feedback'
][
'incorrect'
]
overall_feedback
=
None
overall_feedback
=
None
is_correct
=
False
is_correct
=
False
...
@@ -268,6 +270,11 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
...
@@ -268,6 +270,11 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
if
state
:
if
state
:
self
.
item_state
[
str
(
item
[
'id'
])]
=
state
self
.
item_state
[
str
(
item
[
'id'
])]
=
state
zone
=
self
.
_get_zone_by_uid
(
state
[
'zone'
])
else
:
zone
=
self
.
_get_zone_by_uid
(
attempt
[
'zone'
])
if
not
zone
:
raise
JsonHandlerError
(
400
,
"Item zone data invalid."
)
if
self
.
_is_finished
():
if
self
.
_is_finished
():
overall_feedback
=
self
.
data
[
'feedback'
][
'finish'
]
overall_feedback
=
self
.
data
[
'feedback'
][
'finish'
]
...
@@ -288,7 +295,8 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
...
@@ -288,7 +295,8 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
self
.
runtime
.
publish
(
self
,
'edx.drag_and_drop_v2.item.dropped'
,
{
self
.
runtime
.
publish
(
self
,
'edx.drag_and_drop_v2.item.dropped'
,
{
'item_id'
:
item
[
'id'
],
'item_id'
:
item
[
'id'
],
'location'
:
attempt
.
get
(
'zone'
),
'location'
:
zone
.
get
(
"title"
),
'location_id'
:
zone
.
get
(
"uid"
),
'input'
:
attempt
.
get
(
'input'
),
'input'
:
attempt
.
get
(
'input'
),
'is_correct_location'
:
is_correct_location
,
'is_correct_location'
:
is_correct_location
,
'is_correct'
:
is_correct
,
'is_correct'
:
is_correct
,
...
@@ -395,6 +403,30 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
...
@@ -395,6 +403,30 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
"""
"""
return
next
(
i
for
i
in
self
.
data
[
'items'
]
if
i
[
'id'
]
==
item_id
)
return
next
(
i
for
i
in
self
.
data
[
'items'
]
if
i
[
'id'
]
==
item_id
)
def
_get_zones
(
self
):
"""
Get drop zone data, defined by the author.
"""
# Convert zone data from old to new format if necessary
zones
=
[]
for
zone
in
self
.
data
.
get
(
'zones'
,
[]):
zone
=
zone
.
copy
()
if
"uid"
not
in
zone
:
zone
[
"uid"
]
=
zone
.
get
(
"title"
)
# Older versions used title as the zone UID
# Remove old, now-unused zone attributes, if present:
zone
.
pop
(
"id"
,
None
)
zone
.
pop
(
"index"
,
None
)
zones
.
append
(
zone
)
return
zones
def
_get_zone_by_uid
(
self
,
uid
):
"""
Given a zone UID, return that zone, or None.
"""
for
zone
in
self
.
_get_zones
():
if
zone
[
"uid"
]
==
uid
:
return
zone
def
_get_grade
(
self
):
def
_get_grade
(
self
):
"""
"""
Returns the student's grade for this block.
Returns the student's grade for this block.
...
...
drag_and_drop_v2/public/js/drag_and_drop.js
View file @
698f404d
...
@@ -52,6 +52,16 @@ function DragNDropTemplates(url_name) {
...
@@ -52,6 +52,16 @@ function DragNDropTemplates(url_name) {
);
);
};
};
var
getZoneTitle
=
function
(
zoneUID
,
ctx
)
{
// Given the context and a zone UID, return the zone's title
for
(
var
i
=
0
;
i
<
ctx
.
zones
.
length
;
i
++
)
{
if
(
ctx
.
zones
[
i
].
uid
===
zoneUID
)
{
return
ctx
.
zones
[
i
].
title
;
}
}
return
"Unknown Zone"
;
// This title should never be seen, so does not need i18n
}
var
itemTemplate
=
function
(
item
,
ctx
)
{
var
itemTemplate
=
function
(
item
,
ctx
)
{
// Define properties
// Define properties
var
className
=
(
item
.
class_name
)
?
item
.
class_name
:
""
;
var
className
=
(
item
.
class_name
)
?
item
.
class_name
:
""
;
...
@@ -119,7 +129,7 @@ function DragNDropTemplates(url_name) {
...
@@ -119,7 +129,7 @@ function DragNDropTemplates(url_name) {
var
item_description
=
h
(
var
item_description
=
h
(
'div'
,
'div'
,
{
id
:
item_description_id
,
className
:
'sr'
},
{
id
:
item_description_id
,
className
:
'sr'
},
gettext
(
'Correctly placed in: '
)
+
item
.
zone
gettext
(
'Correctly placed in: '
)
+
getZoneTitle
(
item
.
zone
,
ctx
)
);
);
children
.
splice
(
1
,
0
,
item_description
);
children
.
splice
(
1
,
0
,
item_description
);
}
}
...
@@ -147,12 +157,12 @@ function DragNDropTemplates(url_name) {
...
@@ -147,12 +157,12 @@ function DragNDropTemplates(url_name) {
h
(
h
(
selector
,
selector
,
{
{
id
:
zone
.
id
,
id
:
zone
.
prefixed_u
id
,
attributes
:
{
attributes
:
{
'tabindex'
:
0
,
'tabindex'
:
0
,
'dropzone'
:
'move'
,
'dropzone'
:
'move'
,
'aria-dropeffect'
:
'move'
,
'aria-dropeffect'
:
'move'
,
'data-
zone'
:
zone
.
title
,
'data-
uid'
:
zone
.
uid
,
'role'
:
'button'
,
'role'
:
'button'
,
},
},
style
:
{
style
:
{
...
@@ -449,7 +459,8 @@ function DragAndDropBlock(runtime, element, configuration) {
...
@@ -449,7 +459,8 @@ function DragAndDropBlock(runtime, element, configuration) {
delete
zone
.
width
;
delete
zone
.
width
;
zone
.
height_percent
=
(
+
zone
.
height
)
/
bg_image_height
*
100
;
zone
.
height_percent
=
(
+
zone
.
height
)
/
bg_image_height
*
100
;
delete
zone
.
height
;
delete
zone
.
height
;
zone
.
id
=
configuration
.
url_name
+
'-'
+
zone
.
id
;
// Generate an HTML ID value that's unique within the DOM and not containing spaces etc:
zone
.
prefixed_uid
=
configuration
.
url_name
+
'-'
+
zone
.
uid
.
replace
(
/
([^\w\-])
/g
,
"_"
);
}
}
};
};
...
@@ -582,7 +593,7 @@ function DragAndDropBlock(runtime, element, configuration) {
...
@@ -582,7 +593,7 @@ function DragAndDropBlock(runtime, element, configuration) {
// so use relevant properties of *zone* when calculating new position below.
// so use relevant properties of *zone* when calculating new position below.
$anchor
=
$zone
;
$anchor
=
$zone
;
}
}
var
zone
=
$zone
.
data
(
'zone'
);
var
zone
=
String
(
$zone
.
data
(
'uid'
)
);
var
$target_img
=
$root
.
find
(
'.target-img'
);
var
$target_img
=
$root
.
find
(
'.target-img'
);
// Calculate the position of the item to place relative to the image.
// Calculate the position of the item to place relative to the image.
...
...
drag_and_drop_v2/public/js/drag_and_drop_edit.js
View file @
698f404d
...
@@ -205,34 +205,28 @@ function DragAndDropEditBlock(runtime, element, params) {
...
@@ -205,34 +205,28 @@ function DragAndDropEditBlock(runtime, element, params) {
},
},
form
:
{
form
:
{
zone
:
{
zone
:
{
count
:
0
,
totalZonesCreated
:
0
,
// This counter is used for HTML IDs. Never decremented.
formCount
:
0
,
zoneObjects
:
[],
zoneObjects
:
[],
get
ObjByIndex
:
function
(
num
)
{
get
ZoneObjByUID
:
function
(
uid
)
{
for
(
var
i
=
0
;
i
<
_fn
.
build
.
form
.
zone
.
zoneObjects
.
length
;
i
++
)
{
for
(
var
i
=
0
;
i
<
_fn
.
build
.
form
.
zone
.
zoneObjects
.
length
;
i
++
)
{
if
(
_fn
.
build
.
form
.
zone
.
zoneObjects
[
i
].
index
==
num
)
if
(
_fn
.
build
.
form
.
zone
.
zoneObjects
[
i
].
uid
==
uid
)
{
return
_fn
.
build
.
form
.
zone
.
zoneObjects
[
i
];
return
_fn
.
build
.
form
.
zone
.
zoneObjects
[
i
];
}
}
}
},
},
add
:
function
(
oldZone
)
{
add
:
function
(
oldZone
)
{
var
inputTemplate
=
_fn
.
tpl
.
zoneInput
,
name
=
'zone-'
,
$elements
=
_fn
.
build
.
$el
,
num
;
if
(
!
oldZone
)
oldZone
=
{};
if
(
!
oldZone
)
oldZone
=
{};
var
num
=
_fn
.
build
.
form
.
zone
.
zoneObjects
.
length
+
1
;
_fn
.
build
.
form
.
zone
.
count
++
;
_fn
.
build
.
form
.
zone
.
formCount
++
;
num
=
_fn
.
build
.
form
.
zone
.
count
;
name
+=
num
;
// Update zone obj
// Update zone obj
var
zoneObj
=
{
var
zoneObj
=
{
title
:
oldZone
.
title
||
'Zone '
+
num
,
title
:
oldZone
.
title
||
'Zone '
+
num
,
description
:
oldZone
.
description
,
description
:
oldZone
.
description
,
id
:
name
,
// uid: unique ID for this zone. For backwards compatibility,
index
:
num
,
// this field cannot be called "id" and must inherit the "title"
// property if no 'uid' value is present, since old versions of
// this block used the title as the primary identifier.
uid
:
oldZone
.
uid
||
oldZone
.
title
||
_fn
.
build
.
form
.
zone
.
generateUID
(),
width
:
oldZone
.
width
||
200
,
width
:
oldZone
.
width
||
200
,
height
:
oldZone
.
height
||
100
,
height
:
oldZone
.
height
||
100
,
x
:
oldZone
.
x
||
0
,
x
:
oldZone
.
x
||
0
,
...
@@ -241,45 +235,55 @@ function DragAndDropEditBlock(runtime, element, params) {
...
@@ -241,45 +235,55 @@ function DragAndDropEditBlock(runtime, element, params) {
_fn
.
build
.
form
.
zone
.
zoneObjects
.
push
(
zoneObj
);
_fn
.
build
.
form
.
zone
.
zoneObjects
.
push
(
zoneObj
);
// Add fields to zone position form
// Add fields to zone form
$zoneNode
=
$
(
inputTemplate
(
zoneObj
));
$zoneNode
=
$
(
_fn
.
tpl
.
zoneInput
({
$zoneNode
.
data
(
'index'
,
num
);
zone
:
zoneObj
,
$elements
.
zones
.
form
.
append
(
$zoneNode
);
index
:
_fn
.
build
.
form
.
zone
.
totalZonesCreated
++
,
}));
_fn
.
build
.
$el
.
zones
.
form
.
append
(
$zoneNode
);
_fn
.
build
.
form
.
zone
.
enableDelete
();
_fn
.
build
.
form
.
zone
.
enableDelete
();
// Add zone div to target
// Add zone div to target
_fn
.
build
.
form
.
zone
.
renderZonesPreview
();
_fn
.
build
.
form
.
zone
.
renderZonesPreview
();
},
},
generateUID
:
function
()
{
// Generate a unique ID for a new zone.
for
(
var
i
=
1
;
true
;
i
++
)
{
var
uid
=
"zone-"
+
i
;
if
(
!
_fn
.
build
.
form
.
zone
.
getZoneObjByUID
(
uid
))
{
return
uid
;
}
}
},
remove
:
function
(
e
)
{
remove
:
function
(
e
)
{
var
$el
=
$
(
e
.
currentTarget
).
closest
(
'.zone-row'
),
var
$el
=
$
(
e
.
currentTarget
).
closest
(
'.zone-row'
),
classes
=
$el
.
attr
(
'class'
),
classes
=
$el
.
attr
(
'class'
),
id
=
classes
.
slice
(
classes
.
indexOf
(
'zone-row'
)
+
9
),
id
=
classes
.
slice
(
classes
.
indexOf
(
'zone-row'
)
+
9
),
index
=
$el
.
data
(
'index'
),
uid
=
String
(
$el
.
data
(
'uid'
)),
// cast to string since UID must be string but .data() converts data-uid="5" to 5
array_index
;
array_index
;
e
.
preventDefault
();
e
.
preventDefault
();
$el
.
detach
();
$el
.
detach
();
// Find the
index
of the zone in the array and remove it.
// Find the
uid
of the zone in the array and remove it.
for
(
array_index
=
0
;
array_index
<
_fn
.
build
.
form
.
zone
.
zoneObjects
.
length
;
for
(
array_index
=
0
;
array_index
<
_fn
.
build
.
form
.
zone
.
zoneObjects
.
length
;
array_index
++
)
{
array_index
++
)
{
if
(
_fn
.
build
.
form
.
zone
.
zoneObjects
[
array_index
].
index
==
index
)
break
;
if
(
_fn
.
build
.
form
.
zone
.
zoneObjects
[
array_index
].
uid
==
uid
)
break
;
}
}
_fn
.
build
.
form
.
zone
.
zoneObjects
.
splice
(
array_index
,
1
);
_fn
.
build
.
form
.
zone
.
zoneObjects
.
splice
(
array_index
,
1
);
_fn
.
build
.
form
.
zone
.
renderZonesPreview
();
_fn
.
build
.
form
.
zone
.
renderZonesPreview
();
_fn
.
build
.
form
.
zone
.
formCount
--
;
_fn
.
build
.
form
.
zone
.
disableDelete
();
_fn
.
build
.
form
.
zone
.
disableDelete
();
},
},
enableDelete
:
function
()
{
enableDelete
:
function
()
{
if
(
_fn
.
build
.
form
.
zone
.
formCount
>
1
)
{
if
(
_fn
.
build
.
form
.
zone
.
zoneObjects
.
length
>
1
)
{
_fn
.
build
.
$el
.
zones
.
form
.
find
(
'.remove-zone'
).
removeClass
(
'hidden'
);
_fn
.
build
.
$el
.
zones
.
form
.
find
(
'.remove-zone'
).
removeClass
(
'hidden'
);
}
}
},
},
disableDelete
:
function
()
{
disableDelete
:
function
()
{
if
(
_fn
.
build
.
form
.
zone
.
formCount
===
1
)
{
if
(
_fn
.
build
.
form
.
zone
.
zoneObjects
.
length
===
1
)
{
_fn
.
build
.
$el
.
zones
.
form
.
find
(
'.remove-zone'
).
addClass
(
'hidden'
);
_fn
.
build
.
$el
.
zones
.
form
.
find
(
'.remove-zone'
).
addClass
(
'hidden'
);
}
}
},
},
...
@@ -296,7 +300,7 @@ function DragAndDropEditBlock(runtime, element, params) {
...
@@ -296,7 +300,7 @@ function DragAndDropEditBlock(runtime, element, params) {
this
.
zoneObjects
.
forEach
(
function
(
zoneObj
)
{
this
.
zoneObjects
.
forEach
(
function
(
zoneObj
)
{
_fn
.
build
.
$el
.
zonesPreview
.
append
(
_fn
.
build
.
$el
.
zonesPreview
.
append
(
_fn
.
tpl
.
zoneElement
({
_fn
.
tpl
.
zoneElement
({
id
:
zoneObj
.
id
,
uid
:
zoneObj
.
u
id
,
title
:
zoneObj
.
title
,
title
:
zoneObj
.
title
,
description
:
zoneObj
.
description
,
description
:
zoneObj
.
description
,
x_percent
:
(
+
zoneObj
.
x
)
/
imgWidth
*
100
,
x_percent
:
(
+
zoneObj
.
x
)
/
imgWidth
*
100
,
...
@@ -307,23 +311,11 @@ function DragAndDropEditBlock(runtime, element, params) {
...
@@ -307,23 +311,11 @@ function DragAndDropEditBlock(runtime, element, params) {
);
);
});
});
},
},
getZoneNames
:
function
()
{
var
zoneNames
=
[];
var
$form
=
_fn
.
build
.
$el
.
zones
.
form
.
find
(
'.title'
);
$form
.
each
(
function
(
i
,
el
)
{
var
val
=
$
(
el
).
val
();
if
(
val
.
length
>
0
)
{
zoneNames
.
push
(
val
);
}
});
return
zoneNames
;
},
changedInputHandler
:
function
(
ev
)
{
changedInputHandler
:
function
(
ev
)
{
// Called when any of the inputs have changed.
// Called when any of the inputs have changed.
var
$changedInput
=
$
(
ev
.
currentTarget
);
var
$changedInput
=
$
(
ev
.
currentTarget
);
var
$row
=
$changedInput
.
closest
(
'.zone-row'
);
var
$row
=
$changedInput
.
closest
(
'.zone-row'
);
var
record
=
_fn
.
build
.
form
.
zone
.
get
ObjByIndex
(
$row
.
data
(
'index'
));
var
record
=
_fn
.
build
.
form
.
zone
.
get
ZoneObjByUID
(
String
(
$row
.
data
(
'uid'
)
));
if
(
$changedInput
.
hasClass
(
'title'
))
{
if
(
$changedInput
.
hasClass
(
'title'
))
{
record
.
title
=
$changedInput
.
val
();
record
.
title
=
$changedInput
.
val
();
}
else
if
(
$changedInput
.
hasClass
(
'width'
))
{
}
else
if
(
$changedInput
.
hasClass
(
'width'
))
{
...
@@ -344,18 +336,26 @@ function DragAndDropEditBlock(runtime, element, params) {
...
@@ -344,18 +336,26 @@ function DragAndDropEditBlock(runtime, element, params) {
_fn
.
build
.
form
.
zone
.
renderZonesPreview
();
_fn
.
build
.
form
.
zone
.
renderZonesPreview
();
},
},
},
},
createDropdown
:
function
(
selected
)
{
createDropdown
:
function
(
selectedUID
)
{
var
tpl
=
_fn
.
tpl
.
zoneDropdown
,
var
template
=
_fn
.
tpl
.
zoneDropdown
;
dropdown
=
[],
var
dropdown
=
[];
html
,
var
zoneObjects
=
_fn
.
build
.
form
.
zone
.
zoneObjects
;
dropdown_items
=
_fn
.
build
.
form
.
zone
.
getZoneNames
().
concat
(
'none'
);
zoneObjects
.
forEach
(
function
(
zoneObj
)
{
dropdown
.
push
(
template
({
uid
:
zoneObj
.
uid
,
title
:
zoneObj
.
title
,
selected
:
(
zoneObj
.
uid
==
selectedUID
)
?
'selected'
:
''
,
}));
});
for
(
var
i
=
0
;
i
<
dropdown_items
.
length
;
i
++
)
{
dropdown
.
push
(
template
({
var
is_sel
=
(
dropdown_items
[
i
]
==
selected
)
?
'selected'
:
''
;
uid
:
"none"
,
dropdown
.
push
(
tpl
({
value
:
dropdown_items
[
i
],
selected
:
is_sel
}));
title
:
window
.
gettext
(
"None"
),
}
selected
:
(
selectedUID
===
"none"
)
?
'selected'
:
''
,
}));
html
=
dropdown
.
join
(
''
);
var
html
=
dropdown
.
join
(
''
);
return
new
Handlebars
.
SafeString
(
html
);
return
new
Handlebars
.
SafeString
(
html
);
},
},
feedback
:
function
(
$form
)
{
feedback
:
function
(
$form
)
{
...
...
drag_and_drop_v2/templates/html/js_templates.html
View file @
698f404d
<script
id=
"zone-element-tpl"
type=
"text/html"
>
<script
id=
"zone-element-tpl"
type=
"text/html"
>
<
div
id
=
"{{ id }}"
class
=
"zone"
data
-
zone
=
"{{ title
}}"
style
=
"
<
div
class
=
"zone"
data
-
zone
=
"{{ uid
}}"
style
=
"
top:{{ y_percent }}%;
top:{{ y_percent }}%;
left:{{ x_percent }}%;
left:{{ x_percent }}%;
width:{{ width_percent }}%;
width:{{ width_percent }}%;
...
@@ -10,12 +10,13 @@
...
@@ -10,12 +10,13 @@
</script>
</script>
<script
id=
"zone-input-tpl"
type=
"text/html"
>
<script
id=
"zone-input-tpl"
type=
"text/html"
>
<
div
class
=
"zone-row {{ id }}"
data
-
index
=
"{{index}}"
>
<
div
class
=
"zone-row"
data
-
uid
=
"{{zone.uid}}"
>
<!--
uid
values
from
old
versions
of
the
block
may
contain
spaces
and
other
characters
,
so
we
use
'index'
as
an
alternate
unique
ID
here
.
-->
<
label
for
=
"zone-{{index}}-title"
>
{{
i18n
"Text"
}}
<
/label
>
<
label
for
=
"zone-{{index}}-title"
>
{{
i18n
"Text"
}}
<
/label
>
<
input
type
=
"text"
<
input
type
=
"text"
id
=
"zone-{{index}}-title"
id
=
"zone-{{index}}-title"
class
=
"title"
class
=
"title"
value
=
"{{ title }}"
value
=
"{{
zone.
title }}"
required
/>
required
/>
<
a
href
=
"#"
class
=
"remove-zone hidden"
>
<
a
href
=
"#"
class
=
"remove-zone hidden"
>
<
div
class
=
"icon remove"
><
/div
>
<
div
class
=
"icon remove"
><
/div
>
...
@@ -24,7 +25,7 @@
...
@@ -24,7 +25,7 @@
<
input
type
=
"text"
<
input
type
=
"text"
id
=
"zone-{{index}}-description"
id
=
"zone-{{index}}-description"
class
=
"description"
class
=
"description"
value
=
"{{ description }}"
value
=
"{{
zone.
description }}"
placeholder
=
"{{i18n 'Describe this zone to non-visual users'}}"
placeholder
=
"{{i18n 'Describe this zone to non-visual users'}}"
required
/>
required
/>
<
div
class
=
"layout"
>
<
div
class
=
"layout"
>
...
@@ -32,29 +33,29 @@
...
@@ -32,29 +33,29 @@
<
input
type
=
"text"
<
input
type
=
"text"
id
=
"zone-{{index}}-width"
id
=
"zone-{{index}}-width"
class
=
"size width"
class
=
"size width"
value
=
"{{ width }}"
/>
value
=
"{{
zone.
width }}"
/>
<
label
for
=
"zone-{{index}}-height"
>
{{
i18n
"height"
}}
<
/label
>
<
label
for
=
"zone-{{index}}-height"
>
{{
i18n
"height"
}}
<
/label
>
<
input
type
=
"text"
<
input
type
=
"text"
id
=
"zone-{{index}}-height"
id
=
"zone-{{index}}-height"
class
=
"size height"
class
=
"size height"
value
=
"{{ height }}"
/>
value
=
"{{
zone.
height }}"
/>
<
br
/>
<
br
/>
<
label
for
=
"zone-{{index}}-x"
>
x
<
/label
>
<
label
for
=
"zone-{{index}}-x"
>
x
<
/label
>
<
input
type
=
"text"
<
input
type
=
"text"
id
=
"zone-{{index}}-x"
id
=
"zone-{{index}}-x"
class
=
"coord x"
class
=
"coord x"
value
=
"{{ x }}"
/>
value
=
"{{
zone.
x }}"
/>
<
label
for
=
"zone-{{index}}-y"
>
y
<
/label
>
<
label
for
=
"zone-{{index}}-y"
>
y
<
/label
>
<
input
type
=
"text"
<
input
type
=
"text"
id
=
"zone-{{index}}-y"
id
=
"zone-{{index}}-y"
class
=
"coord y"
class
=
"coord y"
value
=
"{{ y }}"
/>
value
=
"{{
zone.
y }}"
/>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
</script>
</script>
<script
id=
"zone-dropdown-tpl"
type=
"text/html"
>
<script
id=
"zone-dropdown-tpl"
type=
"text/html"
>
<
option
value
=
"{{
value }}"
{{
selected
}}
>
{{
valu
e
}}
<
/option
>
<
option
value
=
"{{
uid }}"
{{
selected
}}
>
{{
titl
e
}}
<
/option
>
</script>
</script>
<script
id=
"item-input-tpl"
type=
"text/html"
>
<script
id=
"item-input-tpl"
type=
"text/html"
>
...
...
pylintrc
View file @
698f404d
...
@@ -11,6 +11,7 @@ disable=
...
@@ -11,6 +11,7 @@ disable=
missing-docstring,
missing-docstring,
too-many-ancestors,
too-many-ancestors,
too-many-arguments,
too-many-arguments,
too-many-branches,
too-many-instance-attributes,
too-many-instance-attributes,
too-few-public-methods,
too-few-public-methods,
too-many-public-methods,
too-many-public-methods,
...
...
tests/integration/data/test_data.json
View file @
698f404d
{
{
"zones"
:
[
"zones"
:
[
{
{
"index"
:
1
,
"width"
:
200
,
"width"
:
200
,
"title"
:
"Zone 1"
,
"title"
:
"Zone 1"
,
"height"
:
100
,
"height"
:
100
,
"y"
:
"200"
,
"y"
:
"200"
,
"x"
:
"100"
,
"x"
:
"100"
,
"id"
:
"zone-1"
"
u
id"
:
"zone-1"
},
},
{
{
"index"
:
2
,
"width"
:
200
,
"width"
:
200
,
"title"
:
"Zone 2"
,
"title"
:
"Zone 2"
,
"height"
:
100
,
"height"
:
100
,
"y"
:
0
,
"y"
:
0
,
"x"
:
0
,
"x"
:
0
,
"id"
:
"zone-2"
"
u
id"
:
"zone-2"
}
}
],
],
"items"
:
[
"items"
:
[
...
@@ -26,7 +24,7 @@
...
@@ -26,7 +24,7 @@
"incorrect"
:
"No 1"
,
"incorrect"
:
"No 1"
,
"correct"
:
"Yes 1"
"correct"
:
"Yes 1"
},
},
"zone"
:
"
Zone
1"
,
"zone"
:
"
zone-
1"
,
"imageURL"
:
""
,
"imageURL"
:
""
,
"id"
:
0
"id"
:
0
},
},
...
@@ -36,7 +34,7 @@
...
@@ -36,7 +34,7 @@
"incorrect"
:
"No 2"
,
"incorrect"
:
"No 2"
,
"correct"
:
"Yes 2"
"correct"
:
"Yes 2"
},
},
"zone"
:
"
Zone
2"
,
"zone"
:
"
zone-
2"
,
"imageURL"
:
""
,
"imageURL"
:
""
,
"id"
:
1
,
"id"
:
1
,
"inputOptions"
:
{
"inputOptions"
:
{
...
...
tests/integration/data/test_data_a11y.json
View file @
698f404d
{
{
"zones"
:
[
"zones"
:
[
{
{
"index"
:
1
,
"title"
:
"Zone 1"
,
"title"
:
"Zone 1"
,
"description"
:
"This describes zone 1"
,
"description"
:
"This describes zone 1"
,
"height"
:
178
,
"height"
:
178
,
"width"
:
196
,
"width"
:
196
,
"y"
:
"30"
,
"y"
:
"30"
,
"x"
:
"160"
,
"x"
:
"160"
,
"id"
:
"
zone-1
"
"id"
:
"
the deprecated id attribute is ignored.
"
},
},
{
{
"index"
:
2
,
"title"
:
"Zone 2"
,
"title"
:
"Zone 2"
,
"description"
:
"This describes zone 2"
,
"description"
:
"This describes zone 2"
,
"height"
:
140
,
"height"
:
140
,
"width"
:
340
,
"width"
:
340
,
"y"
:
"210"
,
"y"
:
"210"
,
"x"
:
"86"
,
"x"
:
"86"
,
"id"
:
"zone-2"
}
}
],
],
"items"
:
[
"items"
:
[
...
...
tests/integration/data/test_data_other.json
View file @
698f404d
{
{
"zones"
:
[
"zones"
:
[
{
{
"index"
:
1
,
"width"
:
200
,
"width"
:
200
,
"title"
:
"Zone 51"
,
"title"
:
"Zone 51"
,
"height"
:
100
,
"height"
:
100
,
"y"
:
"400"
,
"y"
:
"400"
,
"x"
:
"200"
,
"x"
:
"200"
,
"id"
:
"zone-51"
"
u
id"
:
"zone-51"
},
},
{
{
"index"
:
2
,
"width"
:
200
,
"width"
:
200
,
"title"
:
"Zone 52"
,
"title"
:
"Zone 52"
,
"height"
:
100
,
"height"
:
100
,
"y"
:
"200"
,
"y"
:
"200"
,
"x"
:
"100"
,
"x"
:
"100"
,
"id"
:
"zone-52"
"
u
id"
:
"zone-52"
}
}
],
],
"items"
:
[
"items"
:
[
...
@@ -26,7 +24,7 @@
...
@@ -26,7 +24,7 @@
"incorrect"
:
"Incorrect 1"
,
"incorrect"
:
"Incorrect 1"
,
"correct"
:
"Correct 1"
"correct"
:
"Correct 1"
},
},
"zone"
:
"
Zone
51"
,
"zone"
:
"
zone-
51"
,
"imageURL"
:
""
,
"imageURL"
:
""
,
"id"
:
10
"id"
:
10
},
},
...
@@ -36,7 +34,7 @@
...
@@ -36,7 +34,7 @@
"incorrect"
:
"Incorrect 2"
,
"incorrect"
:
"Incorrect 2"
,
"correct"
:
"Correct 2"
"correct"
:
"Correct 2"
},
},
"zone"
:
"
Zone
52"
,
"zone"
:
"
zone-
52"
,
"imageURL"
:
""
,
"imageURL"
:
""
,
"id"
:
20
,
"id"
:
20
,
"inputOptions"
:
{
"inputOptions"
:
{
...
...
tests/integration/data/test_html_data.json
View file @
698f404d
{
{
"zones"
:
[
"zones"
:
[
{
{
"index"
:
1
,
"width"
:
200
,
"width"
:
200
,
"title"
:
"Zone <i>1</i>"
,
"title"
:
"Zone <i>1</i>"
,
"height"
:
100
,
"height"
:
100
,
"y"
:
200
,
"y"
:
200
,
"x"
:
100
,
"x"
:
100
,
"id"
:
"zone-1"
"
u
id"
:
"zone-1"
},
},
{
{
"index"
:
2
,
"width"
:
200
,
"width"
:
200
,
"title"
:
"Zone <b>2</b>"
,
"title"
:
"Zone <b>2</b>"
,
"height"
:
100
,
"height"
:
100
,
"y"
:
0
,
"y"
:
0
,
"x"
:
0
,
"x"
:
0
,
"id"
:
"zone-2"
"
u
id"
:
"zone-2"
}
}
],
],
"items"
:
[
"items"
:
[
...
@@ -26,7 +24,7 @@
...
@@ -26,7 +24,7 @@
"incorrect"
:
"No <b>1</b>"
,
"incorrect"
:
"No <b>1</b>"
,
"correct"
:
"Yes <b>1</b>"
"correct"
:
"Yes <b>1</b>"
},
},
"zone"
:
"
Zone <i>1</i>
"
,
"zone"
:
"
zone-1
"
,
"imageURL"
:
""
,
"imageURL"
:
""
,
"id"
:
0
"id"
:
0
},
},
...
@@ -36,7 +34,7 @@
...
@@ -36,7 +34,7 @@
"incorrect"
:
"No <i>2</i>"
,
"incorrect"
:
"No <i>2</i>"
,
"correct"
:
"Yes <i>2</i>"
"correct"
:
"Yes <i>2</i>"
},
},
"zone"
:
"
Zone <b>2</b>
"
,
"zone"
:
"
zone-2
"
,
"imageURL"
:
""
,
"imageURL"
:
""
,
"id"
:
1
,
"id"
:
1
,
"inputOptions"
:
{
"inputOptions"
:
{
...
...
tests/integration/data/test_sizing_template.json
View file @
698f404d
...
@@ -2,16 +2,16 @@
...
@@ -2,16 +2,16 @@
{
%
if
img
==
"wide"
%
}
{
%
if
img
==
"wide"
%
}
"targetImg"
:
"{{img_wide_url}}"
,
"targetImg"
:
"{{img_wide_url}}"
,
"zones"
:
[
"zones"
:
[
{
"
index"
:
1
,
"title"
:
"Zone 1/3"
,
"width"
:
533
,
"height"
:
200
,
"x"
:
"0"
,
"y"
:
"0"
,
"id"
:
"zone-1
"
},
{
"
title"
:
"Zone 1/3"
,
"width"
:
533
,
"height"
:
200
,
"x"
:
"0"
,
"y"
:
"0
"
},
{
"
index"
:
2
,
"title"
:
"Zone 50%"
,
"width"
:
800
,
"height"
:
200
,
"x"
:
"0"
,
"y"
:
"350"
,
"id"
:
"zone-2
"
},
{
"
title"
:
"Zone 50%"
,
"width"
:
800
,
"height"
:
200
,
"x"
:
"0"
,
"y"
:
"350
"
},
{
"
index"
:
3
,
"title"
:
"Zone 75%"
,
"width"
:
1200
,
"height"
:
200
,
"x"
:
"0"
,
"y"
:
"700"
,
"id"
:
"zone-3
"
}
{
"
title"
:
"Zone 75%"
,
"width"
:
1200
,
"height"
:
200
,
"x"
:
"0"
,
"y"
:
"700
"
}
],
],
{
%
else
%
}
{
%
else
%
}
"targetImg"
:
"{{img_square_url}}"
,
"targetImg"
:
"{{img_square_url}}"
,
"zones"
:
[
"zones"
:
[
{
"
index"
:
1
,
"title"
:
"Zone 1/3"
,
"width"
:
166
,
"height"
:
100
,
"x"
:
"0"
,
"y"
:
"0"
,
"id"
:
"zone-1
"
},
{
"
title"
:
"Zone 1/3"
,
"width"
:
166
,
"height"
:
100
,
"x"
:
"0"
,
"y"
:
"0
"
},
{
"
index"
:
2
,
"title"
:
"Zone 50%"
,
"width"
:
250
,
"height"
:
100
,
"x"
:
"0"
,
"y"
:
"200"
,
"id"
:
"zone-2
"
},
{
"
title"
:
"Zone 50%"
,
"width"
:
250
,
"height"
:
100
,
"x"
:
"0"
,
"y"
:
"200
"
},
{
"
index"
:
3
,
"title"
:
"Zone 75%"
,
"width"
:
375
,
"height"
:
100
,
"x"
:
"0"
,
"y"
:
"400"
,
"id"
:
"zone-3
"
}
{
"
title"
:
"Zone 75%"
,
"width"
:
375
,
"height"
:
100
,
"x"
:
"0"
,
"y"
:
"400
"
}
],
],
{
%
endif
%
}
{
%
endif
%
}
"displayBorders"
:
true
,
"displayBorders"
:
true
,
...
...
tests/integration/test_interaction.py
View file @
698f404d
...
@@ -11,6 +11,7 @@ from workbench.runtime import WorkbenchRuntime
...
@@ -11,6 +11,7 @@ from workbench.runtime import WorkbenchRuntime
from
xblockutils.resources
import
ResourceLoader
from
xblockutils.resources
import
ResourceLoader
from
drag_and_drop_v2.default_data
import
(
from
drag_and_drop_v2.default_data
import
(
TOP_ZONE_ID
,
MIDDLE_ZONE_ID
,
BOTTOM_ZONE_ID
,
TOP_ZONE_TITLE
,
MIDDLE_ZONE_TITLE
,
BOTTOM_ZONE_TITLE
,
TOP_ZONE_TITLE
,
MIDDLE_ZONE_TITLE
,
BOTTOM_ZONE_TITLE
,
ITEM_CORRECT_FEEDBACK
,
ITEM_INCORRECT_FEEDBACK
,
ITEM_NO_ZONE_FEEDBACK
,
ITEM_CORRECT_FEEDBACK
,
ITEM_INCORRECT_FEEDBACK
,
ITEM_NO_ZONE_FEEDBACK
,
START_FEEDBACK
,
FINISH_FEEDBACK
START_FEEDBACK
,
FINISH_FEEDBACK
...
@@ -26,10 +27,11 @@ loader = ResourceLoader(__name__)
...
@@ -26,10 +27,11 @@ loader = ResourceLoader(__name__)
# Classes ###########################################################
# Classes ###########################################################
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
,
zone_title
,
feedback_positive
,
feedback_negative
,
input_value
=
None
):
self
.
feedback_negative
=
feedback_negative
self
.
feedback_negative
=
feedback_negative
self
.
feedback_positive
=
feedback_positive
self
.
feedback_positive
=
feedback_positive
self
.
zone_id
=
zone_id
self
.
zone_id
=
zone_id
self
.
zone_title
=
zone_title
self
.
item_id
=
item_id
self
.
item_id
=
item_id
self
.
input
=
input_value
self
.
input
=
input_value
...
@@ -73,7 +75,7 @@ class InteractionTestBase(object):
...
@@ -73,7 +75,7 @@ class InteractionTestBase(object):
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-
uid
='{zone_id}']"
.
format
(
zone_id
=
zone_id
))[
0
]
def
_get_input_div_by_value
(
self
,
item_value
):
def
_get_input_div_by_value
(
self
,
item_value
):
element
=
self
.
_get_item_by_value
(
item_value
)
element
=
self
.
_get_item_by_value
(
item_value
)
...
@@ -89,7 +91,7 @@ class InteractionTestBase(object):
...
@@ -89,7 +91,7 @@ class InteractionTestBase(object):
def
_get_zone_position
(
self
,
zone_id
):
def
_get_zone_position
(
self
,
zone_id
):
return
self
.
browser
.
execute_script
(
return
self
.
browser
.
execute_script
(
'return $("div[data-
zone
=
\'
{zone_id}
\'
]").prevAll(".zone").length'
.
format
(
zone_id
=
zone_id
)
'return $("div[data-
uid
=
\'
{zone_id}
\'
]").prevAll(".zone").length'
.
format
(
zone_id
=
zone_id
)
)
)
def
place_item
(
self
,
item_value
,
zone_id
,
action_key
=
None
):
def
place_item
(
self
,
item_value
,
zone_id
,
action_key
=
None
):
...
@@ -126,7 +128,7 @@ class InteractionTestBase(object):
...
@@ -126,7 +128,7 @@ class InteractionTestBase(object):
def
assert_grabbed_item
(
self
,
item
):
def
assert_grabbed_item
(
self
,
item
):
self
.
assertEqual
(
item
.
get_attribute
(
'aria-grabbed'
),
'true'
)
self
.
assertEqual
(
item
.
get_attribute
(
'aria-grabbed'
),
'true'
)
def
assert_placed_item
(
self
,
item_value
,
zone_
id
):
def
assert_placed_item
(
self
,
item_value
,
zone_
title
):
item
=
self
.
_get_placed_item_by_value
(
item_value
)
item
=
self
.
_get_placed_item_by_value
(
item_value
)
self
.
wait_until_visible
(
item
)
self
.
wait_until_visible
(
item
)
item_content
=
item
.
find_element_by_css_selector
(
'.item-content'
)
item_content
=
item
.
find_element_by_css_selector
(
'.item-content'
)
...
@@ -138,7 +140,7 @@ class InteractionTestBase(object):
...
@@ -138,7 +140,7 @@ class InteractionTestBase(object):
self
.
assertEqual
(
item
.
get_attribute
(
'data-drag-disabled'
),
'true'
)
self
.
assertEqual
(
item
.
get_attribute
(
'data-drag-disabled'
),
'true'
)
self
.
assertEqual
(
item_content
.
get_attribute
(
'aria-describedby'
),
item_description_id
)
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
.
get_attribute
(
'id'
),
item_description_id
)
self
.
assertEqual
(
item_description
.
text
,
'Correctly placed in: {}'
.
format
(
zone_
id
))
self
.
assertEqual
(
item_description
.
text
,
'Correctly placed in: {}'
.
format
(
zone_
title
))
def
assert_reverted_item
(
self
,
item_value
):
def
assert_reverted_item
(
self
,
item_value
):
item
=
self
.
_get_item_by_value
(
item_value
)
item
=
self
.
_get_item_by_value
(
item_value
)
...
@@ -180,7 +182,7 @@ class InteractionTestBase(object):
...
@@ -180,7 +182,7 @@ class InteractionTestBase(object):
self
.
place_item
(
definition
.
item_id
,
definition
.
zone_id
,
action_key
)
self
.
place_item
(
definition
.
item_id
,
definition
.
zone_id
,
action_key
)
self
.
wait_until_html_in
(
definition
.
feedback_positive
,
feedback_popup_content
)
self
.
wait_until_html_in
(
definition
.
feedback_positive
,
feedback_popup_content
)
self
.
assertEqual
(
popup
.
get_attribute
(
'class'
),
'popup'
)
self
.
assertEqual
(
popup
.
get_attribute
(
'class'
),
'popup'
)
self
.
assert_placed_item
(
definition
.
item_id
,
definition
.
zone_
id
)
self
.
assert_placed_item
(
definition
.
item_id
,
definition
.
zone_
title
)
def
parameterized_item_positive_feedback_on_good_input
(
self
,
items_map
,
scroll_down
=
100
,
action_key
=
None
):
def
parameterized_item_positive_feedback_on_good_input
(
self
,
items_map
,
scroll_down
=
100
,
action_key
=
None
):
popup
=
self
.
_get_popup
()
popup
=
self
.
_get_popup
()
...
@@ -195,7 +197,7 @@ class InteractionTestBase(object):
...
@@ -195,7 +197,7 @@ class InteractionTestBase(object):
self
.
send_input
(
definition
.
item_id
,
definition
.
input
)
self
.
send_input
(
definition
.
item_id
,
definition
.
input
)
self
.
wait_until_html_in
(
definition
.
feedback_positive
,
feedback_popup_content
)
self
.
wait_until_html_in
(
definition
.
feedback_positive
,
feedback_popup_content
)
self
.
assertEqual
(
popup
.
get_attribute
(
'class'
),
'popup'
)
self
.
assertEqual
(
popup
.
get_attribute
(
'class'
),
'popup'
)
self
.
assert_placed_item
(
definition
.
item_id
,
definition
.
zone_
id
)
self
.
assert_placed_item
(
definition
.
item_id
,
definition
.
zone_
title
)
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
)
...
@@ -228,7 +230,7 @@ class InteractionTestBase(object):
...
@@ -228,7 +230,7 @@ class InteractionTestBase(object):
self
.
send_input
(
definition
.
item_id
,
'1999999'
)
self
.
send_input
(
definition
.
item_id
,
'1999999'
)
self
.
wait_until_html_in
(
definition
.
feedback_negative
,
feedback_popup_content
)
self
.
wait_until_html_in
(
definition
.
feedback_negative
,
feedback_popup_content
)
self
.
assertEqual
(
popup
.
get_attribute
(
'class'
),
'popup popup-incorrect'
)
self
.
assertEqual
(
popup
.
get_attribute
(
'class'
),
'popup popup-incorrect'
)
self
.
assert_placed_item
(
definition
.
item_id
,
definition
.
zone_
id
)
self
.
assert_placed_item
(
definition
.
item_id
,
definition
.
zone_
title
)
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
)
...
@@ -252,7 +254,7 @@ class InteractionTestBase(object):
...
@@ -252,7 +254,7 @@ class InteractionTestBase(object):
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
.
assert_placed_item
(
definition
.
item_id
,
definition
.
zone_
title
)
self
.
wait_until_html_in
(
feedback
[
'final'
],
self
.
_get_feedback_message
())
self
.
wait_until_html_in
(
feedback
[
'final'
],
self
.
_get_feedback_message
())
...
@@ -326,18 +328,21 @@ class DefaultDataTestMixin(object):
...
@@ -326,18 +328,21 @@ class DefaultDataTestMixin(object):
items_map
=
{
items_map
=
{
0
:
ItemDefinition
(
0
:
ItemDefinition
(
0
,
TOP_ZONE_TITLE
,
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
TOP_ZONE_TITLE
),
ITEM_INCORRECT_FEEDBACK
0
,
TOP_ZONE_ID
,
TOP_ZONE_TITLE
,
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
TOP_ZONE_TITLE
),
ITEM_INCORRECT_FEEDBACK
),
),
1
:
ItemDefinition
(
1
:
ItemDefinition
(
1
,
MIDDLE_ZONE_TITLE
,
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
MIDDLE_ZONE_TITLE
),
ITEM_INCORRECT_FEEDBACK
1
,
MIDDLE_ZONE_ID
,
MIDDLE_ZONE_TITLE
,
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
MIDDLE_ZONE_TITLE
),
ITEM_INCORRECT_FEEDBACK
),
),
2
:
ItemDefinition
(
2
:
ItemDefinition
(
2
,
BOTTOM_ZONE_TITLE
,
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
BOTTOM_ZONE_TITLE
),
ITEM_INCORRECT_FEEDBACK
2
,
BOTTOM_ZONE_ID
,
BOTTOM_ZONE_TITLE
,
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
BOTTOM_ZONE_TITLE
),
ITEM_INCORRECT_FEEDBACK
),
),
3
:
ItemDefinition
(
3
,
None
,
""
,
ITEM_NO_ZONE_FEEDBACK
),
3
:
ItemDefinition
(
3
,
None
,
None
,
""
,
ITEM_NO_ZONE_FEEDBACK
),
}
}
all_zones
=
[
TOP_ZONE_
TITLE
,
MIDDLE_ZONE_TITLE
,
BOTTOM_ZONE_TITLE
]
all_zones
=
[
TOP_ZONE_
ID
,
MIDDLE_ZONE_ID
,
BOTTOM_ZONE_ID
]
feedback
=
{
feedback
=
{
"intro"
:
START_FEEDBACK
,
"intro"
:
START_FEEDBACK
,
...
@@ -398,6 +403,7 @@ class EventsFiredTest(DefaultDataTestMixin, InteractionTestBase, BaseIntegration
...
@@ -398,6 +403,7 @@ class EventsFiredTest(DefaultDataTestMixin, InteractionTestBase, BaseIntegration
'is_correct_location'
:
True
,
'is_correct_location'
:
True
,
'item_id'
:
0
,
'item_id'
:
0
,
'location'
:
TOP_ZONE_TITLE
,
'location'
:
TOP_ZONE_TITLE
,
'location_id'
:
TOP_ZONE_ID
,
},
},
},
},
{
{
...
@@ -467,12 +473,12 @@ class KeyboardInteractionTest(BasicInteractionTest, BaseIntegrationTest):
...
@@ -467,12 +473,12 @@ class KeyboardInteractionTest(BasicInteractionTest, BaseIntegrationTest):
class
CustomDataInteractionTest
(
BasicInteractionTest
,
BaseIntegrationTest
):
class
CustomDataInteractionTest
(
BasicInteractionTest
,
BaseIntegrationTest
):
items_map
=
{
items_map
=
{
0
:
ItemDefinition
(
0
,
'
Zone 1'
,
"Yes 1"
,
"No 1"
),
0
:
ItemDefinition
(
0
,
'
zone-1'
,
"Zone 1"
,
"Yes 1"
,
"No 1"
),
1
:
ItemDefinition
(
1
,
'
Zone 2'
,
"Yes 2"
,
"No 2"
,
"102"
),
1
:
ItemDefinition
(
1
,
'
zone-2'
,
"Zone 2"
,
"Yes 2"
,
"No 2"
,
"102"
),
2
:
ItemDefinition
(
2
,
None
,
""
,
"No Zone for this"
)
2
:
ItemDefinition
(
2
,
None
,
None
,
""
,
"No Zone for this"
)
}
}
all_zones
=
[
'
Zone 1'
,
'Zone
2'
]
all_zones
=
[
'
zone-1'
,
'zone-
2'
]
feedback
=
{
feedback
=
{
"intro"
:
"Some Intro Feed"
,
"intro"
:
"Some Intro Feed"
,
...
@@ -485,12 +491,12 @@ class CustomDataInteractionTest(BasicInteractionTest, BaseIntegrationTest):
...
@@ -485,12 +491,12 @@ class CustomDataInteractionTest(BasicInteractionTest, BaseIntegrationTest):
class
CustomHtmlDataInteractionTest
(
BasicInteractionTest
,
BaseIntegrationTest
):
class
CustomHtmlDataInteractionTest
(
BasicInteractionTest
,
BaseIntegrationTest
):
items_map
=
{
items_map
=
{
0
:
ItemDefinition
(
0
,
'Zone <i>1</i>'
,
"Yes <b>1</b>"
,
"No <b>1</b>"
),
0
:
ItemDefinition
(
0
,
'
zone-1'
,
'
Zone <i>1</i>'
,
"Yes <b>1</b>"
,
"No <b>1</b>"
),
1
:
ItemDefinition
(
1
,
'Zone <b>2</b>'
,
"Yes <i>2</i>"
,
"No <i>2</i>"
,
"95"
),
1
:
ItemDefinition
(
1
,
'
zone-2'
,
'
Zone <b>2</b>'
,
"Yes <i>2</i>"
,
"No <i>2</i>"
,
"95"
),
2
:
ItemDefinition
(
2
,
None
,
""
,
"No Zone for <i>X</i>"
)
2
:
ItemDefinition
(
2
,
None
,
None
,
""
,
"No Zone for <i>X</i>"
)
}
}
all_zones
=
[
'
Zone <i>1</i>'
,
'Zone <b>2</b>
'
]
all_zones
=
[
'
zone-1'
,
'zone-2
'
]
feedback
=
{
feedback
=
{
"intro"
:
"Intro <i>Feed</i>"
,
"intro"
:
"Intro <i>Feed</i>"
,
...
@@ -510,20 +516,20 @@ class MultipleBlocksDataInteraction(InteractionTestBase, BaseIntegrationTest):
...
@@ -510,20 +516,20 @@ class MultipleBlocksDataInteraction(InteractionTestBase, BaseIntegrationTest):
item_maps
=
{
item_maps
=
{
'block1'
:
{
'block1'
:
{
0
:
ItemDefinition
(
0
,
'Zone 1'
,
"Yes 1"
,
"No 1"
),
0
:
ItemDefinition
(
0
,
'
zone-1'
,
'
Zone 1'
,
"Yes 1"
,
"No 1"
),
1
:
ItemDefinition
(
1
,
'Zone 2'
,
"Yes 2"
,
"No 2"
,
"102"
),
1
:
ItemDefinition
(
1
,
'
zone-2'
,
'
Zone 2'
,
"Yes 2"
,
"No 2"
,
"102"
),
2
:
ItemDefinition
(
2
,
None
,
""
,
"No Zone for this"
)
2
:
ItemDefinition
(
2
,
None
,
None
,
""
,
"No Zone for this"
)
},
},
'block2'
:
{
'block2'
:
{
10
:
ItemDefinition
(
10
,
'Zone 51'
,
"Correct 1"
,
"Incorrect 1"
),
10
:
ItemDefinition
(
10
,
'
zone-51'
,
'
Zone 51'
,
"Correct 1"
,
"Incorrect 1"
),
20
:
ItemDefinition
(
20
,
'Zone 52'
,
"Correct 2"
,
"Incorrect 2"
,
"102"
),
20
:
ItemDefinition
(
20
,
'
zone-52'
,
'
Zone 52'
,
"Correct 2"
,
"Incorrect 2"
,
"102"
),
30
:
ItemDefinition
(
30
,
None
,
""
,
"No Zone for this"
)
30
:
ItemDefinition
(
30
,
None
,
None
,
""
,
"No Zone for this"
)
},
},
}
}
all_zones
=
{
all_zones
=
{
'block1'
:
[
'
Zone 1'
,
'Zone
2'
],
'block1'
:
[
'
zone-1'
,
'zone-
2'
],
'block2'
:
[
'
Zone 51'
,
'Zone
52'
]
'block2'
:
[
'
zone-51'
,
'zone-
52'
]
}
}
feedback
=
{
feedback
=
{
...
...
tests/integration/test_render.py
View file @
698f404d
...
@@ -187,11 +187,11 @@ class TestDragAndDropRender(BaseIntegrationTest):
...
@@ -187,11 +187,11 @@ class TestDragAndDropRender(BaseIntegrationTest):
self
.
assertEqual
(
zone
.
get_attribute
(
'tabindex'
),
'0'
)
self
.
assertEqual
(
zone
.
get_attribute
(
'tabindex'
),
'0'
)
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-
uid
'
),
'Zone {}'
.
format
(
zone_number
))
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
'#-
zone-
{}'
.
format
(
zone_number
),
**
zone_box_percentages
'#-
Zone_
{}'
.
format
(
zone_number
),
**
zone_box_percentages
)
)
zone_name
=
zone
.
find_element_by_css_selector
(
'p.zone-name'
)
zone_name
=
zone
.
find_element_by_css_selector
(
'p.zone-name'
)
self
.
assertEqual
(
zone_name
.
text
,
'Zone {}'
.
format
(
zone_number
))
self
.
assertEqual
(
zone_name
.
text
,
'Zone {}'
.
format
(
zone_number
))
...
@@ -244,7 +244,7 @@ class TestDragAndDropRender(BaseIntegrationTest):
...
@@ -244,7 +244,7 @@ class TestDragAndDropRender(BaseIntegrationTest):
self
.
load_scenario
()
self
.
load_scenario
()
zones
=
self
.
_get_zones
()
zones
=
self
.
_get_zones
()
for
index
,
dummy
in
enumerate
(
zones
,
start
=
1
):
for
index
,
dummy
in
enumerate
(
zones
,
start
=
1
):
zone
=
'#-
zone-
{}'
.
format
(
index
)
zone
=
'#-
Zone_
{}'
.
format
(
index
)
for
side
in
self
.
SIDES
:
for
side
in
self
.
SIDES
:
self
.
assertEqual
(
self
.
_get_style
(
zone
,
'border{}Width'
.
format
(
side
),
True
),
'0px'
)
self
.
assertEqual
(
self
.
_get_style
(
zone
,
'border{}Width'
.
format
(
side
),
True
),
'0px'
)
self
.
assertEqual
(
self
.
_get_style
(
zone
,
'border{}Style'
.
format
(
side
),
True
),
'none'
)
self
.
assertEqual
(
self
.
_get_style
(
zone
,
'border{}Style'
.
format
(
side
),
True
),
'none'
)
...
@@ -253,7 +253,7 @@ class TestDragAndDropRender(BaseIntegrationTest):
...
@@ -253,7 +253,7 @@ class TestDragAndDropRender(BaseIntegrationTest):
self
.
load_scenario
(
zone_borders
=
True
)
self
.
load_scenario
(
zone_borders
=
True
)
zones
=
self
.
_get_zones
()
zones
=
self
.
_get_zones
()
for
index
,
dummy
in
enumerate
(
zones
,
start
=
1
):
for
index
,
dummy
in
enumerate
(
zones
,
start
=
1
):
zone
=
'#-
zone-
{}'
.
format
(
index
)
zone
=
'#-
Zone_
{}'
.
format
(
index
)
for
side
in
self
.
SIDES
:
for
side
in
self
.
SIDES
:
self
.
assertEqual
(
self
.
_get_style
(
zone
,
'border{}Width'
.
format
(
side
),
True
),
'1px'
)
self
.
assertEqual
(
self
.
_get_style
(
zone
,
'border{}Width'
.
format
(
side
),
True
),
'1px'
)
self
.
assertEqual
(
self
.
_get_style
(
zone
,
'border{}Style'
.
format
(
side
),
True
),
'dotted'
)
self
.
assertEqual
(
self
.
_get_style
(
zone
,
'border{}Style'
.
format
(
side
),
True
),
'dotted'
)
...
...
tests/unit/data/html/config_out.json
View file @
698f404d
...
@@ -14,22 +14,20 @@
...
@@ -14,22 +14,20 @@
"zones"
:
[
"zones"
:
[
{
{
"index"
:
1
,
"title"
:
"Zone <i>1</i>"
,
"title"
:
"Zone <i>1</i>"
,
"x"
:
100
,
"x"
:
100
,
"y"
:
200
,
"y"
:
200
,
"width"
:
200
,
"width"
:
200
,
"height"
:
100
,
"height"
:
100
,
"
id"
:
"zone-1
"
"
uid"
:
"Zone <i>1</i>
"
},
},
{
{
"index"
:
2
,
"title"
:
"Zone <b>2</b>"
,
"title"
:
"Zone <b>2</b>"
,
"x"
:
0
,
"x"
:
0
,
"y"
:
0
,
"y"
:
0
,
"width"
:
200
,
"width"
:
200
,
"height"
:
100
,
"height"
:
100
,
"
id"
:
"zone-2
"
"
uid"
:
"Zone <b>2</b>
"
}
}
],
],
...
...
tests/unit/data/old/config_out.json
View file @
698f404d
...
@@ -14,22 +14,20 @@
...
@@ -14,22 +14,20 @@
"zones"
:
[
"zones"
:
[
{
{
"index"
:
1
,
"title"
:
"Zone 1"
,
"title"
:
"Zone 1"
,
"x"
:
"100"
,
"x"
:
"100"
,
"y"
:
"200"
,
"y"
:
"200"
,
"width"
:
200
,
"width"
:
200
,
"height"
:
100
,
"height"
:
100
,
"
id"
:
"zone-
1"
"
uid"
:
"Zone
1"
},
},
{
{
"index"
:
2
,
"title"
:
"Zone 2"
,
"title"
:
"Zone 2"
,
"x"
:
0
,
"x"
:
0
,
"y"
:
0
,
"y"
:
0
,
"width"
:
200
,
"width"
:
200
,
"height"
:
100
,
"height"
:
100
,
"
id"
:
"zone-
2"
"
uid"
:
"Zone
2"
}
}
],
],
...
...
tests/unit/data/plain/config_out.json
View file @
698f404d
...
@@ -14,22 +14,20 @@
...
@@ -14,22 +14,20 @@
"zones"
:
[
"zones"
:
[
{
{
"index"
:
1
,
"title"
:
"Zone 1"
,
"title"
:
"Zone 1"
,
"y"
:
123
,
"y"
:
123
,
"x"
:
234
,
"x"
:
234
,
"width"
:
345
,
"width"
:
345
,
"height"
:
456
,
"height"
:
456
,
"id"
:
"zone-1"
"
u
id"
:
"zone-1"
},
},
{
{
"index"
:
2
,
"title"
:
"Zone 2"
,
"title"
:
"Zone 2"
,
"y"
:
20
,
"y"
:
20
,
"x"
:
10
,
"x"
:
10
,
"width"
:
30
,
"width"
:
30
,
"height"
:
40
,
"height"
:
40
,
"id"
:
"zone-2"
"
u
id"
:
"zone-2"
}
}
],
],
...
...
tests/unit/data/plain/data.json
View file @
698f404d
{
{
"zones"
:
[
"zones"
:
[
{
{
"index"
:
1
,
"title"
:
"Zone 1"
,
"title"
:
"Zone 1"
,
"y"
:
123
,
"y"
:
123
,
"x"
:
234
,
"x"
:
234
,
"width"
:
345
,
"width"
:
345
,
"height"
:
456
,
"height"
:
456
,
"id"
:
"zone-1"
"
u
id"
:
"zone-1"
},
},
{
{
"index"
:
2
,
"title"
:
"Zone 2"
,
"title"
:
"Zone 2"
,
"y"
:
20
,
"y"
:
20
,
"x"
:
10
,
"x"
:
10
,
"width"
:
30
,
"width"
:
30
,
"height"
:
40
,
"height"
:
40
,
"id"
:
"zone-2"
"
u
id"
:
"zone-2"
}
}
],
],
...
@@ -28,7 +26,7 @@
...
@@ -28,7 +26,7 @@
"incorrect"
:
"No 1"
,
"incorrect"
:
"No 1"
,
"correct"
:
"Yes 1"
"correct"
:
"Yes 1"
},
},
"zone"
:
"
Zone
1"
,
"zone"
:
"
zone-
1"
,
"imageURL"
:
""
,
"imageURL"
:
""
,
"id"
:
0
"id"
:
0
},
},
...
@@ -38,7 +36,7 @@
...
@@ -38,7 +36,7 @@
"incorrect"
:
"No 2"
,
"incorrect"
:
"No 2"
,
"correct"
:
"Yes 2"
"correct"
:
"Yes 2"
},
},
"zone"
:
"
Zone
2"
,
"zone"
:
"
zone-
2"
,
"imageURL"
:
""
,
"imageURL"
:
""
,
"id"
:
1
,
"id"
:
1
,
"inputOptions"
:
{
"inputOptions"
:
{
...
...
tests/unit/test_advanced.py
View file @
698f404d
...
@@ -248,8 +248,8 @@ class TestDragAndDropHtmlData(BaseDragAndDropAjaxFixture, unittest.TestCase):
...
@@ -248,8 +248,8 @@ class TestDragAndDropHtmlData(BaseDragAndDropAjaxFixture, unittest.TestCase):
class
TestDragAndDropPlainData
(
BaseDragAndDropAjaxFixture
,
unittest
.
TestCase
):
class
TestDragAndDropPlainData
(
BaseDragAndDropAjaxFixture
,
unittest
.
TestCase
):
FOLDER
=
"plain"
FOLDER
=
"plain"
ZONE_1
=
"
Zone
1"
ZONE_1
=
"
zone-
1"
ZONE_2
=
"
Zone
2"
ZONE_2
=
"
zone-
2"
FEEDBACK
=
{
FEEDBACK
=
{
0
:
{
"correct"
:
"Yes 1"
,
"incorrect"
:
"No 1"
},
0
:
{
"correct"
:
"Yes 1"
,
"incorrect"
:
"No 1"
},
...
@@ -266,3 +266,6 @@ class TestOldDataFormat(TestDragAndDropPlainData):
...
@@ -266,3 +266,6 @@ class TestOldDataFormat(TestDragAndDropPlainData):
"""
"""
FOLDER
=
"old"
FOLDER
=
"old"
FINAL_FEEDBACK
=
"Final Feed"
FINAL_FEEDBACK
=
"Final Feed"
ZONE_1
=
"Zone 1"
ZONE_2
=
"Zone 2"
tests/unit/test_basics.py
View file @
698f404d
import
unittest
import
unittest
from
drag_and_drop_v2.default_data
import
(
from
drag_and_drop_v2.default_data
import
(
TARGET_IMG_DESCRIPTION
,
TOP_ZONE_
TITLE
,
MIDDLE_ZONE_TITLE
,
BOTTOM_ZONE_TITLE
,
TARGET_IMG_DESCRIPTION
,
TOP_ZONE_
ID
,
MIDDLE_ZONE_ID
,
BOTTOM_ZONE_ID
,
START_FEEDBACK
,
FINISH_FEEDBACK
,
DEFAULT_DATA
START_FEEDBACK
,
FINISH_FEEDBACK
,
DEFAULT_DATA
)
)
from
..utils
import
make_block
,
TestCaseMixin
from
..utils
import
make_block
,
TestCaseMixin
...
@@ -65,25 +65,25 @@ class BasicTests(TestCaseMixin, unittest.TestCase):
...
@@ -65,25 +65,25 @@ class BasicTests(TestCaseMixin, unittest.TestCase):
assert_user_state_empty
()
assert_user_state_empty
()
# Drag three items into the correct spot:
# Drag three items into the correct spot:
data
=
{
"val"
:
0
,
"zone"
:
TOP_ZONE_
TITLE
,
"x_percent"
:
"33
%
"
,
"y_percent"
:
"11
%
"
}
data
=
{
"val"
:
0
,
"zone"
:
TOP_ZONE_
ID
,
"x_percent"
:
"33
%
"
,
"y_percent"
:
"11
%
"
}
self
.
call_handler
(
'do_attempt'
,
data
)
self
.
call_handler
(
'do_attempt'
,
data
)
data
=
{
"val"
:
1
,
"zone"
:
MIDDLE_ZONE_
TITLE
,
"x_percent"
:
"67
%
"
,
"y_percent"
:
"80
%
"
}
data
=
{
"val"
:
1
,
"zone"
:
MIDDLE_ZONE_
ID
,
"x_percent"
:
"67
%
"
,
"y_percent"
:
"80
%
"
}
self
.
call_handler
(
'do_attempt'
,
data
)
self
.
call_handler
(
'do_attempt'
,
data
)
data
=
{
"val"
:
2
,
"zone"
:
BOTTOM_ZONE_
TITLE
,
"x_percent"
:
"99
%
"
,
"y_percent"
:
"95
%
"
}
data
=
{
"val"
:
2
,
"zone"
:
BOTTOM_ZONE_
ID
,
"x_percent"
:
"99
%
"
,
"y_percent"
:
"95
%
"
}
self
.
call_handler
(
'do_attempt'
,
data
)
self
.
call_handler
(
'do_attempt'
,
data
)
# Check the result:
# Check the result:
self
.
assertTrue
(
self
.
block
.
completed
)
self
.
assertTrue
(
self
.
block
.
completed
)
self
.
assertEqual
(
self
.
block
.
item_state
,
{
self
.
assertEqual
(
self
.
block
.
item_state
,
{
'0'
:
{
'x_percent'
:
'33
%
'
,
'y_percent'
:
'11
%
'
,
'zone'
:
TOP_ZONE_
TITLE
},
'0'
:
{
'x_percent'
:
'33
%
'
,
'y_percent'
:
'11
%
'
,
'zone'
:
TOP_ZONE_
ID
},
'1'
:
{
'x_percent'
:
'67
%
'
,
'y_percent'
:
'80
%
'
,
'zone'
:
MIDDLE_ZONE_
TITLE
},
'1'
:
{
'x_percent'
:
'67
%
'
,
'y_percent'
:
'80
%
'
,
'zone'
:
MIDDLE_ZONE_
ID
},
'2'
:
{
'x_percent'
:
'99
%
'
,
'y_percent'
:
'95
%
'
,
'zone'
:
BOTTOM_ZONE_
TITLE
},
'2'
:
{
'x_percent'
:
'99
%
'
,
'y_percent'
:
'95
%
'
,
'zone'
:
BOTTOM_ZONE_
ID
},
})
})
self
.
assertEqual
(
self
.
call_handler
(
'get_user_state'
),
{
self
.
assertEqual
(
self
.
call_handler
(
'get_user_state'
),
{
'items'
:
{
'items'
:
{
'0'
:
{
'x_percent'
:
'33
%
'
,
'y_percent'
:
'11
%
'
,
'correct_input'
:
True
,
'zone'
:
TOP_ZONE_
TITLE
},
'0'
:
{
'x_percent'
:
'33
%
'
,
'y_percent'
:
'11
%
'
,
'correct_input'
:
True
,
'zone'
:
TOP_ZONE_
ID
},
'1'
:
{
'x_percent'
:
'67
%
'
,
'y_percent'
:
'80
%
'
,
'correct_input'
:
True
,
'zone'
:
MIDDLE_ZONE_
TITLE
},
'1'
:
{
'x_percent'
:
'67
%
'
,
'y_percent'
:
'80
%
'
,
'correct_input'
:
True
,
'zone'
:
MIDDLE_ZONE_
ID
},
'2'
:
{
'x_percent'
:
'99
%
'
,
'y_percent'
:
'95
%
'
,
'correct_input'
:
True
,
'zone'
:
BOTTOM_ZONE_
TITLE
},
'2'
:
{
'x_percent'
:
'99
%
'
,
'y_percent'
:
'95
%
'
,
'correct_input'
:
True
,
'zone'
:
BOTTOM_ZONE_
ID
},
},
},
'finished'
:
True
,
'finished'
:
True
,
'overall_feedback'
:
FINISH_FEEDBACK
,
'overall_feedback'
:
FINISH_FEEDBACK
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment