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
2ec7da2b
Commit
2ec7da2b
authored
Feb 12, 2016
by
Braden MacDonald
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #54 from open-craft/braden/bugfixes
Various Bug Fixes
parents
7b8b4abb
698f404d
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
207 additions
and
168 deletions
+207
-168
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/drag_and_drop_edit.html
+2
-1
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 @
2ec7da2b
...
...
@@ -6,6 +6,10 @@ TARGET_IMG_DESCRIPTION = _(
"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"
)
MIDDLE_ZONE_TITLE
=
_
(
"The Middle Zone"
)
BOTTOM_ZONE_TITLE
=
_
(
"The Bottom Zone"
)
...
...
@@ -25,8 +29,7 @@ DEFAULT_DATA = {
"targetImgDescription"
:
TARGET_IMG_DESCRIPTION
,
"zones"
:
[
{
"index"
:
1
,
"id"
:
"zone-1"
,
"uid"
:
TOP_ZONE_ID
,
"title"
:
TOP_ZONE_TITLE
,
"description"
:
TOP_ZONE_DESCRIPTION
,
"x"
:
160
,
...
...
@@ -35,8 +38,7 @@ DEFAULT_DATA = {
"height"
:
178
,
},
{
"index"
:
2
,
"id"
:
"zone-2"
,
"uid"
:
MIDDLE_ZONE_ID
,
"title"
:
MIDDLE_ZONE_TITLE
,
"description"
:
MIDDLE_ZONE_DESCRIPTION
,
"x"
:
86
,
...
...
@@ -45,8 +47,7 @@ DEFAULT_DATA = {
"height"
:
138
,
},
{
"index"
:
3
,
"id"
:
"zone-3"
,
"uid"
:
BOTTOM_ZONE_ID
,
"title"
:
BOTTOM_ZONE_TITLE
,
"description"
:
BOTTOM_ZONE_DESCRIPTION
,
"x"
:
15
,
...
...
@@ -62,7 +63,7 @@ DEFAULT_DATA = {
"incorrect"
:
ITEM_INCORRECT_FEEDBACK
,
"correct"
:
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
TOP_ZONE_TITLE
)
},
"zone"
:
TOP_ZONE_
TITLE
,
"zone"
:
TOP_ZONE_
ID
,
"imageURL"
:
""
,
"id"
:
0
,
},
...
...
@@ -72,7 +73,7 @@ DEFAULT_DATA = {
"incorrect"
:
ITEM_INCORRECT_FEEDBACK
,
"correct"
:
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
MIDDLE_ZONE_TITLE
)
},
"zone"
:
MIDDLE_ZONE_
TITLE
,
"zone"
:
MIDDLE_ZONE_
ID
,
"imageURL"
:
""
,
"id"
:
1
,
},
...
...
@@ -82,7 +83,7 @@ DEFAULT_DATA = {
"incorrect"
:
ITEM_INCORRECT_FEEDBACK
,
"correct"
:
ITEM_CORRECT_FEEDBACK
.
format
(
zone
=
BOTTOM_ZONE_TITLE
)
},
"zone"
:
BOTTOM_ZONE_
TITLE
,
"zone"
:
BOTTOM_ZONE_
ID
,
"imageURL"
:
""
,
"id"
:
2
,
},
...
...
drag_and_drop_v2/drag_and_drop_v2.py
View file @
2ec7da2b
...
...
@@ -9,6 +9,7 @@ import copy
import
urllib
from
xblock.core
import
XBlock
from
xblock.exceptions
import
JsonHandlerError
from
xblock.fields
import
Scope
,
String
,
Dict
,
Float
,
Boolean
from
xblock.fragment
import
Fragment
from
xblockutils.resources
import
ResourceLoader
...
...
@@ -154,7 +155,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
return
items
return
{
"zones"
:
self
.
data
.
get
(
'zones'
,
[]
),
"zones"
:
self
.
_get_zones
(
),
# SDK doesn't supply url_name.
"url_name"
:
getattr
(
self
,
'url_name'
,
''
),
"display_zone_labels"
:
self
.
data
.
get
(
'displayLabels'
,
False
),
...
...
@@ -234,6 +235,7 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
item
=
self
.
_get_item_definition
(
attempt
[
'val'
])
state
=
None
zone
=
None
feedback
=
item
[
'feedback'
][
'incorrect'
]
overall_feedback
=
None
is_correct
=
False
...
...
@@ -268,6 +270,11 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
if
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
():
overall_feedback
=
self
.
data
[
'feedback'
][
'finish'
]
...
...
@@ -288,7 +295,8 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
self
.
runtime
.
publish
(
self
,
'edx.drag_and_drop_v2.item.dropped'
,
{
'item_id'
:
item
[
'id'
],
'location'
:
attempt
.
get
(
'zone'
),
'location'
:
zone
.
get
(
"title"
),
'location_id'
:
zone
.
get
(
"uid"
),
'input'
:
attempt
.
get
(
'input'
),
'is_correct_location'
:
is_correct_location
,
'is_correct'
:
is_correct
,
...
...
@@ -395,6 +403,30 @@ class DragAndDropBlock(XBlock, XBlockWithSettingsMixin, ThemableXBlockMixin):
"""
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
):
"""
Returns the student's grade for this block.
...
...
drag_and_drop_v2/public/js/drag_and_drop.js
View file @
2ec7da2b
...
...
@@ -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
)
{
// Define properties
var
className
=
(
item
.
class_name
)
?
item
.
class_name
:
""
;
...
...
@@ -119,7 +129,7 @@ function DragNDropTemplates(url_name) {
var
item_description
=
h
(
'div'
,
{
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
);
}
...
...
@@ -147,12 +157,12 @@ function DragNDropTemplates(url_name) {
h
(
selector
,
{
id
:
zone
.
id
,
id
:
zone
.
prefixed_u
id
,
attributes
:
{
'tabindex'
:
0
,
'dropzone'
:
'move'
,
'aria-dropeffect'
:
'move'
,
'data-
zone'
:
zone
.
title
,
'data-
uid'
:
zone
.
uid
,
'role'
:
'button'
,
},
style
:
{
...
...
@@ -449,7 +459,8 @@ function DragAndDropBlock(runtime, element, configuration) {
delete
zone
.
width
;
zone
.
height_percent
=
(
+
zone
.
height
)
/
bg_image_height
*
100
;
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) {
// so use relevant properties of *zone* when calculating new position below.
$anchor
=
$zone
;
}
var
zone
=
$zone
.
data
(
'zone'
);
var
zone
=
String
(
$zone
.
data
(
'uid'
)
);
var
$target_img
=
$root
.
find
(
'.target-img'
);
// 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 @
2ec7da2b
...
...
@@ -205,34 +205,28 @@ function DragAndDropEditBlock(runtime, element, params) {
},
form
:
{
zone
:
{
count
:
0
,
formCount
:
0
,
totalZonesCreated
:
0
,
// This counter is used for HTML IDs. Never decremented.
zoneObjects
:
[],
get
ObjByIndex
:
function
(
num
)
{
get
ZoneObjByUID
:
function
(
uid
)
{
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
];
}
}
},
add
:
function
(
oldZone
)
{
var
inputTemplate
=
_fn
.
tpl
.
zoneInput
,
name
=
'zone-'
,
$elements
=
_fn
.
build
.
$el
,
num
;
if
(
!
oldZone
)
oldZone
=
{};
_fn
.
build
.
form
.
zone
.
count
++
;
_fn
.
build
.
form
.
zone
.
formCount
++
;
num
=
_fn
.
build
.
form
.
zone
.
count
;
name
+=
num
;
var
num
=
_fn
.
build
.
form
.
zone
.
zoneObjects
.
length
+
1
;
// Update zone obj
var
zoneObj
=
{
title
:
oldZone
.
title
||
'Zone '
+
num
,
description
:
oldZone
.
description
,
id
:
name
,
index
:
num
,
// uid: unique ID for this zone. For backwards compatibility,
// 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
,
height
:
oldZone
.
height
||
100
,
x
:
oldZone
.
x
||
0
,
...
...
@@ -241,45 +235,55 @@ function DragAndDropEditBlock(runtime, element, params) {
_fn
.
build
.
form
.
zone
.
zoneObjects
.
push
(
zoneObj
);
// Add fields to zone position form
$zoneNode
=
$
(
inputTemplate
(
zoneObj
));
$zoneNode
.
data
(
'index'
,
num
);
$elements
.
zones
.
form
.
append
(
$zoneNode
);
// Add fields to zone form
$zoneNode
=
$
(
_fn
.
tpl
.
zoneInput
({
zone
:
zoneObj
,
index
:
_fn
.
build
.
form
.
zone
.
totalZonesCreated
++
,
}));
_fn
.
build
.
$el
.
zones
.
form
.
append
(
$zoneNode
);
_fn
.
build
.
form
.
zone
.
enableDelete
();
// Add zone div to target
_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
)
{
var
$el
=
$
(
e
.
currentTarget
).
closest
(
'.zone-row'
),
classes
=
$el
.
attr
(
'class'
),
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
;
e
.
preventDefault
();
$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
;
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
.
renderZonesPreview
();
_fn
.
build
.
form
.
zone
.
formCount
--
;
_fn
.
build
.
form
.
zone
.
disableDelete
();
},
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'
);
}
},
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'
);
}
},
...
...
@@ -296,7 +300,7 @@ function DragAndDropEditBlock(runtime, element, params) {
this
.
zoneObjects
.
forEach
(
function
(
zoneObj
)
{
_fn
.
build
.
$el
.
zonesPreview
.
append
(
_fn
.
tpl
.
zoneElement
({
id
:
zoneObj
.
id
,
uid
:
zoneObj
.
u
id
,
title
:
zoneObj
.
title
,
description
:
zoneObj
.
description
,
x_percent
:
(
+
zoneObj
.
x
)
/
imgWidth
*
100
,
...
...
@@ -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
)
{
// Called when any of the inputs have changed.
var
$changedInput
=
$
(
ev
.
currentTarget
);
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'
))
{
record
.
title
=
$changedInput
.
val
();
}
else
if
(
$changedInput
.
hasClass
(
'width'
))
{
...
...
@@ -344,18 +336,26 @@ function DragAndDropEditBlock(runtime, element, params) {
_fn
.
build
.
form
.
zone
.
renderZonesPreview
();
},
},
createDropdown
:
function
(
selected
)
{
var
tpl
=
_fn
.
tpl
.
zoneDropdown
,
dropdown
=
[],
html
,
dropdown_items
=
_fn
.
build
.
form
.
zone
.
getZoneNames
().
concat
(
'none'
);
createDropdown
:
function
(
selectedUID
)
{
var
template
=
_fn
.
tpl
.
zoneDropdown
;
var
dropdown
=
[];
var
zoneObjects
=
_fn
.
build
.
form
.
zone
.
zoneObjects
;
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
++
)
{
var
is_sel
=
(
dropdown_items
[
i
]
==
selected
)
?
'selected'
:
''
;
dropdown
.
push
(
tpl
({
value
:
dropdown_items
[
i
],
selected
:
is_sel
}));
}
dropdown
.
push
(
template
({
uid
:
"none"
,
title
:
window
.
gettext
(
"None"
),
selected
:
(
selectedUID
===
"none"
)
?
'selected'
:
''
,
}));
html
=
dropdown
.
join
(
''
);
var
html
=
dropdown
.
join
(
''
);
return
new
Handlebars
.
SafeString
(
html
);
},
feedback
:
function
(
$form
)
{
...
...
drag_and_drop_v2/templates/html/drag_and_drop_edit.html
View file @
2ec7da2b
{% load i18n %}
{% load l10n %}
<div
class=
"xblock--drag-and-drop--editor editor-with-buttons"
>
{{ js_templates|safe }}
...
...
@@ -21,7 +22,7 @@
</label>
<label
class=
"h3"
for=
"weight"
>
{% trans "Maximum score" %}
</label>
<input
id=
"weight"
type=
"number"
step=
"0.1"
value=
"{{ self.weight }}"
/>
<input
id=
"weight"
type=
"number"
step=
"0.1"
value=
"{{ self.weight
|unlocalize
}}"
/>
<label
class=
"h3"
for=
"problem-text"
>
{% trans "Problem text" %}
</label>
<textarea
id=
"problem-text"
>
{{ self.question_text }}
</textarea>
...
...
drag_and_drop_v2/templates/html/js_templates.html
View file @
2ec7da2b
<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 }}%;
left:{{ x_percent }}%;
width:{{ width_percent }}%;
...
...
@@ -10,12 +10,13 @@
</script>
<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
>
<
input
type
=
"text"
id
=
"zone-{{index}}-title"
class
=
"title"
value
=
"{{ title }}"
value
=
"{{
zone.
title }}"
required
/>
<
a
href
=
"#"
class
=
"remove-zone hidden"
>
<
div
class
=
"icon remove"
><
/div
>
...
...
@@ -24,7 +25,7 @@
<
input
type
=
"text"
id
=
"zone-{{index}}-description"
class
=
"description"
value
=
"{{ description }}"
value
=
"{{
zone.
description }}"
placeholder
=
"{{i18n 'Describe this zone to non-visual users'}}"
required
/>
<
div
class
=
"layout"
>
...
...
@@ -32,29 +33,29 @@
<
input
type
=
"text"
id
=
"zone-{{index}}-width"
class
=
"size width"
value
=
"{{ width }}"
/>
value
=
"{{
zone.
width }}"
/>
<
label
for
=
"zone-{{index}}-height"
>
{{
i18n
"height"
}}
<
/label
>
<
input
type
=
"text"
id
=
"zone-{{index}}-height"
class
=
"size height"
value
=
"{{ height }}"
/>
value
=
"{{
zone.
height }}"
/>
<
br
/>
<
label
for
=
"zone-{{index}}-x"
>
x
<
/label
>
<
input
type
=
"text"
id
=
"zone-{{index}}-x"
class
=
"coord x"
value
=
"{{ x }}"
/>
value
=
"{{
zone.
x }}"
/>
<
label
for
=
"zone-{{index}}-y"
>
y
<
/label
>
<
input
type
=
"text"
id
=
"zone-{{index}}-y"
class
=
"coord y"
value
=
"{{ y }}"
/>
value
=
"{{
zone.
y }}"
/>
<
/div
>
<
/div
>
</script>
<script
id=
"zone-dropdown-tpl"
type=
"text/html"
>
<
option
value
=
"{{
value }}"
{{
selected
}}
>
{{
valu
e
}}
<
/option
>
<
option
value
=
"{{
uid }}"
{{
selected
}}
>
{{
titl
e
}}
<
/option
>
</script>
<script
id=
"item-input-tpl"
type=
"text/html"
>
...
...
pylintrc
View file @
2ec7da2b
...
...
@@ -11,6 +11,7 @@ disable=
missing-docstring,
too-many-ancestors,
too-many-arguments,
too-many-branches,
too-many-instance-attributes,
too-few-public-methods,
too-many-public-methods,
...
...
tests/integration/data/test_data.json
View file @
2ec7da2b
{
"zones"
:
[
{
"index"
:
1
,
"width"
:
200
,
"title"
:
"Zone 1"
,
"height"
:
100
,
"y"
:
"200"
,
"x"
:
"100"
,
"id"
:
"zone-1"
"
u
id"
:
"zone-1"
},
{
"index"
:
2
,
"width"
:
200
,
"title"
:
"Zone 2"
,
"height"
:
100
,
"y"
:
0
,
"x"
:
0
,
"id"
:
"zone-2"
"
u
id"
:
"zone-2"
}
],
"items"
:
[
...
...
@@ -26,7 +24,7 @@
"incorrect"
:
"No 1"
,
"correct"
:
"Yes 1"
},
"zone"
:
"
Zone
1"
,
"zone"
:
"
zone-
1"
,
"imageURL"
:
""
,
"id"
:
0
},
...
...
@@ -36,7 +34,7 @@
"incorrect"
:
"No 2"
,
"correct"
:
"Yes 2"
},
"zone"
:
"
Zone
2"
,
"zone"
:
"
zone-
2"
,
"imageURL"
:
""
,
"id"
:
1
,
"inputOptions"
:
{
...
...
tests/integration/data/test_data_a11y.json
View file @
2ec7da2b
{
"zones"
:
[
{
"index"
:
1
,
"title"
:
"Zone 1"
,
"description"
:
"This describes zone 1"
,
"height"
:
178
,
"width"
:
196
,
"y"
:
"30"
,
"x"
:
"160"
,
"id"
:
"
zone-1
"
"id"
:
"
the deprecated id attribute is ignored.
"
},
{
"index"
:
2
,
"title"
:
"Zone 2"
,
"description"
:
"This describes zone 2"
,
"height"
:
140
,
"width"
:
340
,
"y"
:
"210"
,
"x"
:
"86"
,
"id"
:
"zone-2"
}
],
"items"
:
[
...
...
tests/integration/data/test_data_other.json
View file @
2ec7da2b
{
"zones"
:
[
{
"index"
:
1
,
"width"
:
200
,
"title"
:
"Zone 51"
,
"height"
:
100
,
"y"
:
"400"
,
"x"
:
"200"
,
"id"
:
"zone-51"
"
u
id"
:
"zone-51"
},
{
"index"
:
2
,
"width"
:
200
,
"title"
:
"Zone 52"
,
"height"
:
100
,
"y"
:
"200"
,
"x"
:
"100"
,
"id"
:
"zone-52"
"
u
id"
:
"zone-52"
}
],
"items"
:
[
...
...
@@ -26,7 +24,7 @@
"incorrect"
:
"Incorrect 1"
,
"correct"
:
"Correct 1"
},
"zone"
:
"
Zone
51"
,
"zone"
:
"
zone-
51"
,
"imageURL"
:
""
,
"id"
:
10
},
...
...
@@ -36,7 +34,7 @@
"incorrect"
:
"Incorrect 2"
,
"correct"
:
"Correct 2"
},
"zone"
:
"
Zone
52"
,
"zone"
:
"
zone-
52"
,
"imageURL"
:
""
,
"id"
:
20
,
"inputOptions"
:
{
...
...
tests/integration/data/test_html_data.json
View file @
2ec7da2b
{
"zones"
:
[
{
"index"
:
1
,
"width"
:
200
,
"title"
:
"Zone <i>1</i>"
,
"height"
:
100
,
"y"
:
200
,
"x"
:
100
,
"id"
:
"zone-1"
"
u
id"
:
"zone-1"
},
{
"index"
:
2
,
"width"
:
200
,
"title"
:
"Zone <b>2</b>"
,
"height"
:
100
,
"y"
:
0
,
"x"
:
0
,
"id"
:
"zone-2"
"
u
id"
:
"zone-2"
}
],
"items"
:
[
...
...
@@ -26,7 +24,7 @@
"incorrect"
:
"No <b>1</b>"
,
"correct"
:
"Yes <b>1</b>"
},
"zone"
:
"
Zone <i>1</i>
"
,
"zone"
:
"
zone-1
"
,
"imageURL"
:
""
,
"id"
:
0
},
...
...
@@ -36,7 +34,7 @@
"incorrect"
:
"No <i>2</i>"
,
"correct"
:
"Yes <i>2</i>"
},
"zone"
:
"
Zone <b>2</b>
"
,
"zone"
:
"
zone-2
"
,
"imageURL"
:
""
,
"id"
:
1
,
"inputOptions"
:
{
...
...
tests/integration/data/test_sizing_template.json
View file @
2ec7da2b
...
...
@@ -2,16 +2,16 @@
{
%
if
img
==
"wide"
%
}
"targetImg"
:
"{{img_wide_url}}"
,
"zones"
:
[
{
"
index"
:
1
,
"title"
:
"Zone 1/3"
,
"width"
:
533
,
"height"
:
200
,
"x"
:
"0"
,
"y"
:
"0"
,
"id"
:
"zone-1
"
},
{
"
index"
:
2
,
"title"
:
"Zone 50%"
,
"width"
:
800
,
"height"
:
200
,
"x"
:
"0"
,
"y"
:
"350"
,
"id"
:
"zone-2
"
},
{
"
index"
:
3
,
"title"
:
"Zone 75%"
,
"width"
:
1200
,
"height"
:
200
,
"x"
:
"0"
,
"y"
:
"700"
,
"id"
:
"zone-3
"
}
{
"
title"
:
"Zone 1/3"
,
"width"
:
533
,
"height"
:
200
,
"x"
:
"0"
,
"y"
:
"0
"
},
{
"
title"
:
"Zone 50%"
,
"width"
:
800
,
"height"
:
200
,
"x"
:
"0"
,
"y"
:
"350
"
},
{
"
title"
:
"Zone 75%"
,
"width"
:
1200
,
"height"
:
200
,
"x"
:
"0"
,
"y"
:
"700
"
}
],
{
%
else
%
}
"targetImg"
:
"{{img_square_url}}"
,
"zones"
:
[
{
"
index"
:
1
,
"title"
:
"Zone 1/3"
,
"width"
:
166
,
"height"
:
100
,
"x"
:
"0"
,
"y"
:
"0"
,
"id"
:
"zone-1
"
},
{
"
index"
:
2
,
"title"
:
"Zone 50%"
,
"width"
:
250
,
"height"
:
100
,
"x"
:
"0"
,
"y"
:
"200"
,
"id"
:
"zone-2
"
},
{
"
index"
:
3
,
"title"
:
"Zone 75%"
,
"width"
:
375
,
"height"
:
100
,
"x"
:
"0"
,
"y"
:
"400"
,
"id"
:
"zone-3
"
}
{
"
title"
:
"Zone 1/3"
,
"width"
:
166
,
"height"
:
100
,
"x"
:
"0"
,
"y"
:
"0
"
},
{
"
title"
:
"Zone 50%"
,
"width"
:
250
,
"height"
:
100
,
"x"
:
"0"
,
"y"
:
"200
"
},
{
"
title"
:
"Zone 75%"
,
"width"
:
375
,
"height"
:
100
,
"x"
:
"0"
,
"y"
:
"400
"
}
],
{
%
endif
%
}
"displayBorders"
:
true
,
...
...
tests/integration/test_interaction.py
View file @
2ec7da2b
...
...
@@ -11,6 +11,7 @@ from workbench.runtime import WorkbenchRuntime
from
xblockutils.resources
import
ResourceLoader
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
,
ITEM_CORRECT_FEEDBACK
,
ITEM_INCORRECT_FEEDBACK
,
ITEM_NO_ZONE_FEEDBACK
,
START_FEEDBACK
,
FINISH_FEEDBACK
...
...
@@ -26,10 +27,11 @@ loader = ResourceLoader(__name__)
# Classes ###########################################################
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_positive
=
feedback_positive
self
.
zone_id
=
zone_id
self
.
zone_title
=
zone_title
self
.
item_id
=
item_id
self
.
input
=
input_value
...
...
@@ -73,7 +75,7 @@ class InteractionTestBase(object):
def
_get_zone_by_id
(
self
,
zone_id
):
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
):
element
=
self
.
_get_item_by_value
(
item_value
)
...
...
@@ -89,7 +91,7 @@ class InteractionTestBase(object):
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
)
'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
):
...
...
@@ -126,7 +128,7 @@ class InteractionTestBase(object):
def
assert_grabbed_item
(
self
,
item
):
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
)
self
.
wait_until_visible
(
item
)
item_content
=
item
.
find_element_by_css_selector
(
'.item-content'
)
...
...
@@ -138,7 +140,7 @@ class InteractionTestBase(object):
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
))
self
.
assertEqual
(
item_description
.
text
,
'Correctly placed in: {}'
.
format
(
zone_
title
))
def
assert_reverted_item
(
self
,
item_value
):
item
=
self
.
_get_item_by_value
(
item_value
)
...
...
@@ -180,7 +182,7 @@ class InteractionTestBase(object):
self
.
place_item
(
definition
.
item_id
,
definition
.
zone_id
,
action_key
)
self
.
wait_until_html_in
(
definition
.
feedback_positive
,
feedback_popup_content
)
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
):
popup
=
self
.
_get_popup
()
...
...
@@ -195,7 +197,7 @@ class InteractionTestBase(object):
self
.
send_input
(
definition
.
item_id
,
definition
.
input
)
self
.
wait_until_html_in
(
definition
.
feedback_positive
,
feedback_popup_content
)
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
)
self
.
wait_until_has_class
(
'correct'
,
input_div
)
...
...
@@ -228,7 +230,7 @@ class InteractionTestBase(object):
self
.
send_input
(
definition
.
item_id
,
'1999999'
)
self
.
wait_until_html_in
(
definition
.
feedback_negative
,
feedback_popup_content
)
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
)
self
.
wait_until_has_class
(
'incorrect'
,
input_div
)
...
...
@@ -252,7 +254,7 @@ class InteractionTestBase(object):
self
.
send_input
(
item_key
,
definition
.
input
)
input_div
=
self
.
_get_input_div_by_value
(
item_key
)
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
())
...
...
@@ -326,18 +328,21 @@ class DefaultDataTestMixin(object):
items_map
=
{
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
,
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
,
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
=
{
"intro"
:
START_FEEDBACK
,
...
...
@@ -398,6 +403,7 @@ class EventsFiredTest(DefaultDataTestMixin, InteractionTestBase, BaseIntegration
'is_correct_location'
:
True
,
'item_id'
:
0
,
'location'
:
TOP_ZONE_TITLE
,
'location_id'
:
TOP_ZONE_ID
,
},
},
{
...
...
@@ -467,12 +473,12 @@ class KeyboardInteractionTest(BasicInteractionTest, BaseIntegrationTest):
class
CustomDataInteractionTest
(
BasicInteractionTest
,
BaseIntegrationTest
):
items_map
=
{
0
:
ItemDefinition
(
0
,
'
Zone 1'
,
"Yes 1"
,
"No 1"
),
1
:
ItemDefinition
(
1
,
'
Zone 2'
,
"Yes 2"
,
"No 2"
,
"102"
),
2
:
ItemDefinition
(
2
,
None
,
""
,
"No Zone for this"
)
0
:
ItemDefinition
(
0
,
'
zone-1'
,
"Zone 1"
,
"Yes 1"
,
"No 1"
),
1
:
ItemDefinition
(
1
,
'
zone-2'
,
"Zone 2"
,
"Yes 2"
,
"No 2"
,
"102"
),
2
:
ItemDefinition
(
2
,
None
,
None
,
""
,
"No Zone for this"
)
}
all_zones
=
[
'
Zone 1'
,
'Zone
2'
]
all_zones
=
[
'
zone-1'
,
'zone-
2'
]
feedback
=
{
"intro"
:
"Some Intro Feed"
,
...
...
@@ -485,12 +491,12 @@ class CustomDataInteractionTest(BasicInteractionTest, BaseIntegrationTest):
class
CustomHtmlDataInteractionTest
(
BasicInteractionTest
,
BaseIntegrationTest
):
items_map
=
{
0
:
ItemDefinition
(
0
,
'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"
),
2
:
ItemDefinition
(
2
,
None
,
""
,
"No Zone for <i>X</i>"
)
0
:
ItemDefinition
(
0
,
'
zone-1'
,
'
Zone <i>1</i>'
,
"Yes <b>1</b>"
,
"No <b>1</b>"
),
1
:
ItemDefinition
(
1
,
'
zone-2'
,
'
Zone <b>2</b>'
,
"Yes <i>2</i>"
,
"No <i>2</i>"
,
"95"
),
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
=
{
"intro"
:
"Intro <i>Feed</i>"
,
...
...
@@ -510,20 +516,20 @@ class MultipleBlocksDataInteraction(InteractionTestBase, BaseIntegrationTest):
item_maps
=
{
'block1'
:
{
0
:
ItemDefinition
(
0
,
'Zone 1'
,
"Yes 1"
,
"No 1"
),
1
:
ItemDefinition
(
1
,
'Zone 2'
,
"Yes 2"
,
"No 2"
,
"102"
),
2
:
ItemDefinition
(
2
,
None
,
""
,
"No Zone for this"
)
0
:
ItemDefinition
(
0
,
'
zone-1'
,
'
Zone 1'
,
"Yes 1"
,
"No 1"
),
1
:
ItemDefinition
(
1
,
'
zone-2'
,
'
Zone 2'
,
"Yes 2"
,
"No 2"
,
"102"
),
2
:
ItemDefinition
(
2
,
None
,
None
,
""
,
"No Zone for this"
)
},
'block2'
:
{
10
:
ItemDefinition
(
10
,
'Zone 51'
,
"Correct 1"
,
"Incorrect 1"
),
20
:
ItemDefinition
(
20
,
'Zone 52'
,
"Correct 2"
,
"Incorrect 2"
,
"102"
),
30
:
ItemDefinition
(
30
,
None
,
""
,
"No Zone for this"
)
10
:
ItemDefinition
(
10
,
'
zone-51'
,
'
Zone 51'
,
"Correct 1"
,
"Incorrect 1"
),
20
:
ItemDefinition
(
20
,
'
zone-52'
,
'
Zone 52'
,
"Correct 2"
,
"Incorrect 2"
,
"102"
),
30
:
ItemDefinition
(
30
,
None
,
None
,
""
,
"No Zone for this"
)
},
}
all_zones
=
{
'block1'
:
[
'
Zone 1'
,
'Zone
2'
],
'block2'
:
[
'
Zone 51'
,
'Zone
52'
]
'block1'
:
[
'
zone-1'
,
'zone-
2'
],
'block2'
:
[
'
zone-51'
,
'zone-
52'
]
}
feedback
=
{
...
...
tests/integration/test_render.py
View file @
2ec7da2b
...
...
@@ -187,11 +187,11 @@ class TestDragAndDropRender(BaseIntegrationTest):
self
.
assertEqual
(
zone
.
get_attribute
(
'tabindex'
),
'0'
)
self
.
assertEqual
(
zone
.
get_attribute
(
'dropzone'
),
'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
))
zone_box_percentages
=
box_percentages
[
index
]
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'
)
self
.
assertEqual
(
zone_name
.
text
,
'Zone {}'
.
format
(
zone_number
))
...
...
@@ -244,7 +244,7 @@ class TestDragAndDropRender(BaseIntegrationTest):
self
.
load_scenario
()
zones
=
self
.
_get_zones
()
for
index
,
dummy
in
enumerate
(
zones
,
start
=
1
):
zone
=
'#-
zone-
{}'
.
format
(
index
)
zone
=
'#-
Zone_
{}'
.
format
(
index
)
for
side
in
self
.
SIDES
:
self
.
assertEqual
(
self
.
_get_style
(
zone
,
'border{}Width'
.
format
(
side
),
True
),
'0px'
)
self
.
assertEqual
(
self
.
_get_style
(
zone
,
'border{}Style'
.
format
(
side
),
True
),
'none'
)
...
...
@@ -253,7 +253,7 @@ class TestDragAndDropRender(BaseIntegrationTest):
self
.
load_scenario
(
zone_borders
=
True
)
zones
=
self
.
_get_zones
()
for
index
,
dummy
in
enumerate
(
zones
,
start
=
1
):
zone
=
'#-
zone-
{}'
.
format
(
index
)
zone
=
'#-
Zone_
{}'
.
format
(
index
)
for
side
in
self
.
SIDES
:
self
.
assertEqual
(
self
.
_get_style
(
zone
,
'border{}Width'
.
format
(
side
),
True
),
'1px'
)
self
.
assertEqual
(
self
.
_get_style
(
zone
,
'border{}Style'
.
format
(
side
),
True
),
'dotted'
)
...
...
tests/unit/data/html/config_out.json
View file @
2ec7da2b
...
...
@@ -14,22 +14,20 @@
"zones"
:
[
{
"index"
:
1
,
"title"
:
"Zone <i>1</i>"
,
"x"
:
100
,
"y"
:
200
,
"width"
:
200
,
"height"
:
100
,
"
id"
:
"zone-1
"
"
uid"
:
"Zone <i>1</i>
"
},
{
"index"
:
2
,
"title"
:
"Zone <b>2</b>"
,
"x"
:
0
,
"y"
:
0
,
"width"
:
200
,
"height"
:
100
,
"
id"
:
"zone-2
"
"
uid"
:
"Zone <b>2</b>
"
}
],
...
...
tests/unit/data/old/config_out.json
View file @
2ec7da2b
...
...
@@ -14,22 +14,20 @@
"zones"
:
[
{
"index"
:
1
,
"title"
:
"Zone 1"
,
"x"
:
"100"
,
"y"
:
"200"
,
"width"
:
200
,
"height"
:
100
,
"
id"
:
"zone-
1"
"
uid"
:
"Zone
1"
},
{
"index"
:
2
,
"title"
:
"Zone 2"
,
"x"
:
0
,
"y"
:
0
,
"width"
:
200
,
"height"
:
100
,
"
id"
:
"zone-
2"
"
uid"
:
"Zone
2"
}
],
...
...
tests/unit/data/plain/config_out.json
View file @
2ec7da2b
...
...
@@ -14,22 +14,20 @@
"zones"
:
[
{
"index"
:
1
,
"title"
:
"Zone 1"
,
"y"
:
123
,
"x"
:
234
,
"width"
:
345
,
"height"
:
456
,
"id"
:
"zone-1"
"
u
id"
:
"zone-1"
},
{
"index"
:
2
,
"title"
:
"Zone 2"
,
"y"
:
20
,
"x"
:
10
,
"width"
:
30
,
"height"
:
40
,
"id"
:
"zone-2"
"
u
id"
:
"zone-2"
}
],
...
...
tests/unit/data/plain/data.json
View file @
2ec7da2b
{
"zones"
:
[
{
"index"
:
1
,
"title"
:
"Zone 1"
,
"y"
:
123
,
"x"
:
234
,
"width"
:
345
,
"height"
:
456
,
"id"
:
"zone-1"
"
u
id"
:
"zone-1"
},
{
"index"
:
2
,
"title"
:
"Zone 2"
,
"y"
:
20
,
"x"
:
10
,
"width"
:
30
,
"height"
:
40
,
"id"
:
"zone-2"
"
u
id"
:
"zone-2"
}
],
...
...
@@ -28,7 +26,7 @@
"incorrect"
:
"No 1"
,
"correct"
:
"Yes 1"
},
"zone"
:
"
Zone
1"
,
"zone"
:
"
zone-
1"
,
"imageURL"
:
""
,
"id"
:
0
},
...
...
@@ -38,7 +36,7 @@
"incorrect"
:
"No 2"
,
"correct"
:
"Yes 2"
},
"zone"
:
"
Zone
2"
,
"zone"
:
"
zone-
2"
,
"imageURL"
:
""
,
"id"
:
1
,
"inputOptions"
:
{
...
...
tests/unit/test_advanced.py
View file @
2ec7da2b
...
...
@@ -248,8 +248,8 @@ class TestDragAndDropHtmlData(BaseDragAndDropAjaxFixture, unittest.TestCase):
class
TestDragAndDropPlainData
(
BaseDragAndDropAjaxFixture
,
unittest
.
TestCase
):
FOLDER
=
"plain"
ZONE_1
=
"
Zone
1"
ZONE_2
=
"
Zone
2"
ZONE_1
=
"
zone-
1"
ZONE_2
=
"
zone-
2"
FEEDBACK
=
{
0
:
{
"correct"
:
"Yes 1"
,
"incorrect"
:
"No 1"
},
...
...
@@ -266,3 +266,6 @@ class TestOldDataFormat(TestDragAndDropPlainData):
"""
FOLDER
=
"old"
FINAL_FEEDBACK
=
"Final Feed"
ZONE_1
=
"Zone 1"
ZONE_2
=
"Zone 2"
tests/unit/test_basics.py
View file @
2ec7da2b
import
unittest
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
)
from
..utils
import
make_block
,
TestCaseMixin
...
...
@@ -65,25 +65,25 @@ class BasicTests(TestCaseMixin, unittest.TestCase):
assert_user_state_empty
()
# 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
)
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
)
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
)
# Check the result:
self
.
assertTrue
(
self
.
block
.
completed
)
self
.
assertEqual
(
self
.
block
.
item_state
,
{
'0'
:
{
'x_percent'
:
'33
%
'
,
'y_percent'
:
'11
%
'
,
'zone'
:
TOP_ZONE_
TITLE
},
'1'
:
{
'x_percent'
:
'67
%
'
,
'y_percent'
:
'80
%
'
,
'zone'
:
MIDDLE_ZONE_
TITLE
},
'2'
:
{
'x_percent'
:
'99
%
'
,
'y_percent'
:
'95
%
'
,
'zone'
:
BOTTOM_ZONE_
TITLE
},
'0'
:
{
'x_percent'
:
'33
%
'
,
'y_percent'
:
'11
%
'
,
'zone'
:
TOP_ZONE_
ID
},
'1'
:
{
'x_percent'
:
'67
%
'
,
'y_percent'
:
'80
%
'
,
'zone'
:
MIDDLE_ZONE_
ID
},
'2'
:
{
'x_percent'
:
'99
%
'
,
'y_percent'
:
'95
%
'
,
'zone'
:
BOTTOM_ZONE_
ID
},
})
self
.
assertEqual
(
self
.
call_handler
(
'get_user_state'
),
{
'items'
:
{
'0'
:
{
'x_percent'
:
'33
%
'
,
'y_percent'
:
'11
%
'
,
'correct_input'
:
True
,
'zone'
:
TOP_ZONE_
TITLE
},
'1'
:
{
'x_percent'
:
'67
%
'
,
'y_percent'
:
'80
%
'
,
'correct_input'
:
True
,
'zone'
:
MIDDLE_ZONE_
TITLE
},
'2'
:
{
'x_percent'
:
'99
%
'
,
'y_percent'
:
'95
%
'
,
'correct_input'
:
True
,
'zone'
:
BOTTOM_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_
ID
},
'2'
:
{
'x_percent'
:
'99
%
'
,
'y_percent'
:
'95
%
'
,
'correct_input'
:
True
,
'zone'
:
BOTTOM_ZONE_
ID
},
},
'finished'
:
True
,
'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