Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
problem-builder
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
problem-builder
Commits
f79b231d
Commit
f79b231d
authored
Aug 07, 2017
by
E. Kolpakov
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
student_view_user_state -> XBlock.handler
parent
ef6d54ad
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
117 additions
and
21 deletions
+117
-21
problem_builder/answer.py
+2
-2
problem_builder/mixins.py
+20
-4
problem_builder/tests/unit/test_answer_mixin.py
+28
-2
problem_builder/tests/unit/test_mixins.py
+56
-13
problem_builder/tests/unit/utils.py
+11
-0
No files found.
problem_builder/answer.py
View file @
f79b231d
...
@@ -115,12 +115,12 @@ class AnswerMixin(XBlockWithPreviewMixin, XBlockWithTranslationServiceMixin, Stu
...
@@ -115,12 +115,12 @@ class AnswerMixin(XBlockWithPreviewMixin, XBlockWithTranslationServiceMixin, Stu
if
not
data
.
name
:
if
not
data
.
name
:
add_error
(
u"A Question ID is required."
)
add_error
(
u"A Question ID is required."
)
def
student_view_user_state
(
self
,
context
=
None
):
def
build_user_state_data
(
self
,
context
=
None
):
"""
"""
Returns a JSON representation of the student data of this XBlock,
Returns a JSON representation of the student data of this XBlock,
retrievable from the Course Block API.
retrievable from the Course Block API.
"""
"""
result
=
super
(
AnswerMixin
,
self
)
.
student_view_user_state
(
context
)
result
=
super
(
AnswerMixin
,
self
)
.
build_user_state_data
(
context
)
answer_data
=
self
.
get_model_object
()
answer_data
=
self
.
get_model_object
()
result
[
"answer_data"
]
=
{
result
[
"answer_data"
]
=
{
"student_input"
:
answer_data
.
student_input
,
"student_input"
:
answer_data
.
student_input
,
...
...
problem_builder/mixins.py
View file @
f79b231d
import
json
import
webob
from
lazy
import
lazy
from
lazy
import
lazy
from
problem_builder.tests.unit.utils
import
DateTimeEncoder
from
xblock.core
import
XBlock
from
xblock.fields
import
String
,
Boolean
,
Float
,
Scope
,
UNIQUE_ID
from
xblock.fields
import
String
,
Boolean
,
Float
,
Scope
,
UNIQUE_ID
from
xblock.fragment
import
Fragment
from
xblock.fragment
import
Fragment
from
xblockutils.helpers
import
child_isinstance
from
xblockutils.helpers
import
child_isinstance
...
@@ -185,7 +190,7 @@ class StudentViewUserStateMixin(object):
...
@@ -185,7 +190,7 @@ class StudentViewUserStateMixin(object):
NESTED_BLOCKS_KEY
=
"components"
NESTED_BLOCKS_KEY
=
"components"
INCLUDE_SCOPES
=
(
Scope
.
user_state
,
Scope
.
user_info
,
Scope
.
preferences
)
INCLUDE_SCOPES
=
(
Scope
.
user_state
,
Scope
.
user_info
,
Scope
.
preferences
)
def
student_view_user_state
(
self
,
context
=
None
):
def
build_user_state_data
(
self
,
context
=
None
):
"""
"""
Returns a JSON representation of the student data of this XBlock,
Returns a JSON representation of the student data of this XBlock,
retrievable from the Course Block API.
retrievable from the Course Block API.
...
@@ -196,12 +201,23 @@ class StudentViewUserStateMixin(object):
...
@@ -196,12 +201,23 @@ class StudentViewUserStateMixin(object):
result
[
field
.
name
]
=
field
.
read_from
(
self
)
result
[
field
.
name
]
=
field
.
read_from
(
self
)
if
getattr
(
self
,
"has_children"
,
False
):
if
getattr
(
self
,
"has_children"
,
False
):
components
=
[]
components
=
{}
for
child_id
in
self
.
children
:
for
child_id
in
self
.
children
:
child
=
self
.
runtime
.
get_block
(
child_id
)
child
=
self
.
runtime
.
get_block
(
child_id
)
if
hasattr
(
child
,
'
student_view_user_state
'
):
if
hasattr
(
child
,
'
build_user_state_data
'
):
components
.
append
(
child
.
student_view_user_state
(
context
)
)
components
[
str
(
child_id
)]
=
child
.
build_user_state_data
(
context
)
result
[
self
.
NESTED_BLOCKS_KEY
]
=
components
result
[
self
.
NESTED_BLOCKS_KEY
]
=
components
return
result
return
result
@XBlock.handler
def
student_view_user_state
(
self
,
context
=
None
,
suffix
=
''
):
"""
Returns a JSON representation of the student data of this XBlock,
retrievable from the Course Block API.
"""
result
=
self
.
build_user_state_data
(
context
)
json_result
=
json
.
dumps
(
result
,
cls
=
DateTimeEncoder
)
return
webob
.
response
.
Response
(
body
=
json_result
,
content_type
=
'application/json'
)
problem_builder/tests/unit/test_answer_mixin.py
View file @
f79b231d
"""
"""
Unit tests for AnswerMixin.
Unit tests for AnswerMixin.
"""
"""
import
json
import
unittest
import
unittest
from
collections
import
namedtuple
from
collections
import
namedtuple
from
datetime
import
datetime
from
datetime
import
datetime
...
@@ -62,7 +63,7 @@ class TestAnswerMixin(unittest.TestCase):
...
@@ -62,7 +63,7 @@ class TestAnswerMixin(unittest.TestCase):
model
=
answer_mixin
.
get_model_object
()
model
=
answer_mixin
.
get_model_object
()
self
.
assertEqual
(
model
.
course_key
,
course_id
)
self
.
assertEqual
(
model
.
course_key
,
course_id
)
def
test_
student_view_user_state
(
self
):
def
test_
build_user_state_data
(
self
):
name
=
'test-course-key-2'
name
=
'test-course-key-2'
existing_model
=
Answer
(
existing_model
=
Answer
(
name
=
name
,
name
=
name
,
...
@@ -74,7 +75,7 @@ class TestAnswerMixin(unittest.TestCase):
...
@@ -74,7 +75,7 @@ class TestAnswerMixin(unittest.TestCase):
)
)
existing_model
.
save
()
existing_model
.
save
()
answer_mixin
=
self
.
make_answer_mixin
(
name
=
name
)
answer_mixin
=
self
.
make_answer_mixin
(
name
=
name
)
student_view_user_state
=
answer_mixin
.
student_view_user_state
()
student_view_user_state
=
answer_mixin
.
build_user_state_data
()
expected_user_state_data
=
{
expected_user_state_data
=
{
"answer_data"
:
{
"answer_data"
:
{
...
@@ -84,3 +85,28 @@ class TestAnswerMixin(unittest.TestCase):
...
@@ -84,3 +85,28 @@ class TestAnswerMixin(unittest.TestCase):
}
}
}
}
self
.
assertEqual
(
student_view_user_state
,
expected_user_state_data
)
self
.
assertEqual
(
student_view_user_state
,
expected_user_state_data
)
def
test_student_view_user_state
(
self
):
name
=
'test-course-key-3'
existing_model
=
Answer
(
name
=
name
,
student_id
=
self
.
anonymous_student_id
,
course_key
=
self
.
course_id
,
student_input
=
"Test"
,
created_on
=
datetime
(
2017
,
1
,
2
,
3
,
4
,
5
),
modified_on
=
datetime
(
2017
,
7
,
8
,
9
,
10
,
11
),
)
existing_model
.
save
()
answer_mixin
=
self
.
make_answer_mixin
(
name
=
name
)
student_view_user_state
=
answer_mixin
.
student_view_user_state
()
parsed_student_state
=
json
.
loads
(
student_view_user_state
.
body
)
expected_user_state_data
=
{
"answer_data"
:
{
"student_input"
:
existing_model
.
student_input
,
"created_on"
:
existing_model
.
created_on
.
isoformat
(),
"modified_on"
:
existing_model
.
modified_on
.
isoformat
(),
}
}
self
.
assertEqual
(
parsed_student_state
,
expected_user_state_data
)
problem_builder/tests/unit/test_mixins.py
View file @
f79b231d
import
json
import
unittest
import
unittest
from
datetime
import
datetime
import
pytz
from
mock
import
MagicMock
,
Mock
from
mock
import
MagicMock
,
Mock
from
xblock.core
import
XBlock
from
xblock.core
import
XBlock
from
xblock.field_data
import
DictFieldData
from
xblock.field_data
import
DictFieldData
from
xblock.fields
import
String
,
Scope
,
Boolean
,
Integer
from
xblock.fields
import
String
,
Scope
,
Boolean
,
Integer
,
DateTime
from
problem_builder.mixins
import
StudentViewUserStateMixin
from
problem_builder.mixins
import
StudentViewUserStateMixin
...
@@ -22,7 +25,7 @@ class UserStateFieldsMixin(object):
...
@@ -22,7 +25,7 @@ class UserStateFieldsMixin(object):
preference_2
=
Integer
(
name
=
"pref2"
,
scope
=
Scope
.
preferences
)
preference_2
=
Integer
(
name
=
"pref2"
,
scope
=
Scope
.
preferences
)
user_info_1
=
String
(
name
=
"info1"
,
scope
=
Scope
.
user_info
)
user_info_1
=
String
(
name
=
"info1"
,
scope
=
Scope
.
user_info
)
user_info_2
=
Integer
(
name
=
"info2"
,
scope
=
Scope
.
user_info
)
user_info_2
=
DateTime
(
name
=
"info2"
,
scope
=
Scope
.
user_info
)
class
ChildrenMixin
(
object
):
class
ChildrenMixin
(
object
):
...
@@ -76,7 +79,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
...
@@ -76,7 +79,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
def
test_no_user_state_returns_empty
(
self
):
def
test_no_user_state_returns_empty
(
self
):
block
=
self
.
_build_block
(
XBlockWithNoUserState
,
{
"scope_settings"
:
"qwe"
,
"scope_content"
:
"ASD"
})
block
=
self
.
_build_block
(
XBlockWithNoUserState
,
{
"scope_settings"
:
"qwe"
,
"scope_content"
:
"ASD"
})
self
.
assertEqual
(
block
.
student_view_user_state
(),
{})
self
.
assertEqual
(
block
.
build_user_state_data
(),
{})
def
test_no_child_blocks_with_user_state
(
self
):
def
test_no_child_blocks_with_user_state
(
self
):
user_fields
=
{
user_fields
=
{
...
@@ -85,19 +88,19 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
...
@@ -85,19 +88,19 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
"preference_1"
:
"Yes"
,
"preference_1"
:
"Yes"
,
"preference_2"
:
12
,
"preference_2"
:
12
,
"user_info_1"
:
"John"
,
"user_info_1"
:
"John"
,
"user_info_2"
:
27
"user_info_2"
:
datetime
(
2017
,
1
,
2
,
3
,
4
,
5
,
tzinfo
=
pytz
.
UTC
)
}
}
other_fields
=
{
"setting"
:
"setting"
,
"content"
:
"content"
,
"user_state_summary"
:
"Something"
}
other_fields
=
{
"setting"
:
"setting"
,
"content"
:
"content"
,
"user_state_summary"
:
"Something"
}
block_fields
=
self
.
_merge_dicts
(
user_fields
,
other_fields
)
block_fields
=
self
.
_merge_dicts
(
user_fields
,
other_fields
)
block
=
self
.
_build_block
(
XBlockNoChildrenWithUserState
,
block_fields
)
block
=
self
.
_build_block
(
XBlockNoChildrenWithUserState
,
block_fields
)
self
.
assertEqual
(
block
.
student_view_user_state
(),
user_fields
)
self
.
assertEqual
(
block
.
build_user_state_data
(),
user_fields
)
def
test_children_empty_no_user_state
(
self
):
def
test_children_empty_no_user_state
(
self
):
block
=
self
.
_build_block
(
XBlockChildrenNoUserState
,
{
"scope_settings"
:
"qwe"
,
"scope_content"
:
"ASD"
})
block
=
self
.
_build_block
(
XBlockChildrenNoUserState
,
{
"scope_settings"
:
"qwe"
,
"scope_content"
:
"ASD"
})
self
.
assertEqual
(
block
.
children
,
[])
# precondition
self
.
assertEqual
(
block
.
children
,
[])
# precondition
self
.
assertEqual
(
block
.
student_view_user_state
(),
{
"components"
:
[]})
self
.
assertEqual
(
block
.
build_user_state_data
(),
{
"components"
:
[]})
def
test_children_no_user_state
(
self
):
def
test_children_no_user_state
(
self
):
block
=
self
.
_build_block
(
XBlockChildrenNoUserState
,
{
"scope_settings"
:
"qwe"
,
"scope_content"
:
"ASD"
})
block
=
self
.
_build_block
(
XBlockChildrenNoUserState
,
{
"scope_settings"
:
"qwe"
,
"scope_content"
:
"ASD"
})
...
@@ -111,7 +114,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
...
@@ -111,7 +114,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
self
.
assertEqual
(
self
.
_runtime
.
get_block
(
"child1"
),
no_user_state1
)
self
.
assertEqual
(
self
.
_runtime
.
get_block
(
"child1"
),
no_user_state1
)
self
.
assertEqual
(
self
.
_runtime
.
get_block
(
"child2"
),
no_user_state2
)
self
.
assertEqual
(
self
.
_runtime
.
get_block
(
"child2"
),
no_user_state2
)
student_user_state
=
block
.
student_view_user_state
()
student_user_state
=
block
.
build_user_state_data
()
expected
=
{
"components"
:
[{},
{}]}
expected
=
{
"components"
:
[{},
{}]}
self
.
assertEqual
(
student_user_state
,
expected
)
self
.
assertEqual
(
student_user_state
,
expected
)
...
@@ -126,7 +129,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
...
@@ -126,7 +129,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
"preference_1"
:
"Yes"
,
"preference_1"
:
"Yes"
,
"preference_2"
:
12
,
"preference_2"
:
12
,
"user_info_1"
:
"John"
,
"user_info_1"
:
"John"
,
"user_info_2"
:
27
"user_info_2"
:
datetime
(
2017
,
1
,
2
,
3
,
4
,
5
,
tzinfo
=
pytz
.
UTC
)
}
}
user_fields2
=
{
user_fields2
=
{
"answer_1"
:
"BBBB"
,
"answer_1"
:
"BBBB"
,
...
@@ -134,7 +137,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
...
@@ -134,7 +137,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
"preference_1"
:
"No"
,
"preference_1"
:
"No"
,
"preference_2"
:
7
,
"preference_2"
:
7
,
"user_info_1"
:
"jane"
,
"user_info_1"
:
"jane"
,
"user_info_2"
:
19
"user_info_2"
:
datetime
(
2017
,
1
,
2
,
3
,
4
,
5
,
tzinfo
=
pytz
.
UTC
)
}
}
user_state1
=
self
.
_build_block
(
XBlockNoChildrenWithUserState
,
self
.
_merge_dicts
(
user_fields1
,
other_fields
))
user_state1
=
self
.
_build_block
(
XBlockNoChildrenWithUserState
,
self
.
_merge_dicts
(
user_fields1
,
other_fields
))
user_state2
=
self
.
_build_block
(
XBlockNoChildrenWithUserState
,
self
.
_merge_dicts
(
user_fields2
,
other_fields
))
user_state2
=
self
.
_build_block
(
XBlockNoChildrenWithUserState
,
self
.
_merge_dicts
(
user_fields2
,
other_fields
))
...
@@ -146,7 +149,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
...
@@ -146,7 +149,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
self
.
assertEqual
(
self
.
_runtime
.
get_block
(
"child1"
),
user_state1
)
self
.
assertEqual
(
self
.
_runtime
.
get_block
(
"child1"
),
user_state1
)
self
.
assertEqual
(
self
.
_runtime
.
get_block
(
"child2"
),
user_state2
)
self
.
assertEqual
(
self
.
_runtime
.
get_block
(
"child2"
),
user_state2
)
student_user_state
=
block
.
student_view_user_state
()
student_user_state
=
block
.
build_user_state_data
()
expected
=
{
"components"
:
[
user_fields1
,
user_fields2
]}
expected
=
{
"components"
:
[
user_fields1
,
user_fields2
]}
self
.
assertEqual
(
student_user_state
,
expected
)
self
.
assertEqual
(
student_user_state
,
expected
)
...
@@ -159,7 +162,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
...
@@ -159,7 +162,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
"preference_1"
:
"IDN"
,
"preference_1"
:
"IDN"
,
"preference_2"
:
42
,
"preference_2"
:
42
,
"user_info_1"
:
"Douglas"
,
"user_info_1"
:
"Douglas"
,
"user_info_2"
:
9
"user_info_2"
:
datetime
(
2017
,
1
,
2
,
3
,
4
,
5
,
tzinfo
=
pytz
.
UTC
)
}
}
block
=
self
.
_build_block
(
XBlockChildrenUserState
,
self
.
_merge_dicts
(
user_fields
,
other_fields
))
block
=
self
.
_build_block
(
XBlockChildrenUserState
,
self
.
_merge_dicts
(
user_fields
,
other_fields
))
...
@@ -169,7 +172,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
...
@@ -169,7 +172,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
"preference_1"
:
"Yes"
,
"preference_1"
:
"Yes"
,
"preference_2"
:
12
,
"preference_2"
:
12
,
"user_info_1"
:
"John"
,
"user_info_1"
:
"John"
,
"user_info_2"
:
27
"user_info_2"
:
datetime
(
2017
,
1
,
2
,
3
,
4
,
5
,
tzinfo
=
pytz
.
UTC
)
}
}
user_state
=
self
.
_build_block
(
user_state
=
self
.
_build_block
(
XBlockNoChildrenWithUserState
,
self
.
_merge_dicts
(
nested_user_fields
,
other_fields
)
XBlockNoChildrenWithUserState
,
self
.
_merge_dicts
(
nested_user_fields
,
other_fields
)
...
@@ -181,8 +184,48 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
...
@@ -181,8 +184,48 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
self
.
assertEqual
(
block
.
children
,
nested
.
keys
())
self
.
assertEqual
(
block
.
children
,
nested
.
keys
())
self
.
assertEqual
(
self
.
_runtime
.
get_block
(
"child1"
),
user_state
)
self
.
assertEqual
(
self
.
_runtime
.
get_block
(
"child1"
),
user_state
)
student_user_state
=
block
.
student_view_user_state
()
student_user_state
=
block
.
build_user_state_data
()
expected
=
user_fields
.
copy
()
expected
=
user_fields
.
copy
()
expected
[
"components"
]
=
[
nested_user_fields
]
expected
[
"components"
]
=
[
nested_user_fields
]
self
.
assertEqual
(
student_user_state
,
expected
)
self
.
assertEqual
(
student_user_state
,
expected
)
def
test_user_state_handler
(
self
):
other_fields
=
{
"setting"
:
"setting"
,
"content"
:
"content"
,
"user_state_summary"
:
"Something"
}
user_fields
=
{
"answer_1"
:
"OOOO"
,
"answer_2"
:
True
,
"preference_1"
:
"IDN"
,
"preference_2"
:
42
,
"user_info_1"
:
"Douglas"
,
"user_info_2"
:
datetime
(
2017
,
1
,
2
,
3
,
4
,
5
,
tzinfo
=
pytz
.
UTC
)
}
block
=
self
.
_build_block
(
XBlockChildrenUserState
,
self
.
_merge_dicts
(
user_fields
,
other_fields
))
nested_user_fields
=
{
"answer_1"
:
"AAAA"
,
"answer_2"
:
False
,
"preference_1"
:
"Yes"
,
"preference_2"
:
12
,
"user_info_1"
:
"John"
,
"user_info_2"
:
datetime
(
2017
,
1
,
2
,
3
,
4
,
5
,
tzinfo
=
pytz
.
UTC
)
}
user_state
=
self
.
_build_block
(
XBlockNoChildrenWithUserState
,
self
.
_merge_dicts
(
nested_user_fields
,
other_fields
)
)
nested
=
{
"child1"
:
user_state
}
self
.
_set_children
(
block
,
nested
)
# preconditions
self
.
assertEqual
(
block
.
children
,
nested
.
keys
())
self
.
assertEqual
(
self
.
_runtime
.
get_block
(
"child1"
),
user_state
)
student_user_state_response
=
block
.
student_view_user_state
()
student_user_state
=
json
.
loads
(
student_user_state_response
.
body
)
expected
=
user_fields
.
copy
()
expected
[
"user_info_2"
]
=
expected
[
"user_info_2"
]
.
isoformat
()
nested_copy
=
nested_user_fields
.
copy
()
nested_copy
[
"user_info_2"
]
=
nested_copy
[
"user_info_2"
]
.
isoformat
()
expected
[
"components"
]
=
[
nested_copy
]
self
.
assertEqual
(
student_user_state
,
expected
)
problem_builder/tests/unit/utils.py
View file @
f79b231d
"""
"""
Helper methods for testing Problem Builder / Step Builder blocks
Helper methods for testing Problem Builder / Step Builder blocks
"""
"""
import
json
from
datetime
import
datetime
,
date
from
mock
import
MagicMock
,
Mock
,
patch
from
mock
import
MagicMock
,
Mock
,
patch
from
xblock.field_data
import
DictFieldData
from
xblock.field_data
import
DictFieldData
...
@@ -87,3 +90,11 @@ def instantiate_block(cls, fields=None):
...
@@ -87,3 +90,11 @@ def instantiate_block(cls, fields=None):
block
.
children
=
children
block
.
children
=
children
block
.
runtime
.
get_block
=
lambda
child_id
:
children
[
child_id
]
block
.
runtime
.
get_block
=
lambda
child_id
:
children
[
child_id
]
return
block
return
block
class
DateTimeEncoder
(
json
.
JSONEncoder
):
def
default
(
self
,
o
):
if
isinstance
(
o
,
(
datetime
,
date
)):
return
o
.
isoformat
()
return
json
.
JSONEncoder
.
default
(
self
,
o
)
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