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
if
not
data
.
name
:
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,
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
()
result
[
"answer_data"
]
=
{
"student_input"
:
answer_data
.
student_input
,
...
...
problem_builder/mixins.py
View file @
f79b231d
import
json
import
webob
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.fragment
import
Fragment
from
xblockutils.helpers
import
child_isinstance
...
...
@@ -185,7 +190,7 @@ class StudentViewUserStateMixin(object):
NESTED_BLOCKS_KEY
=
"components"
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,
retrievable from the Course Block API.
...
...
@@ -196,12 +201,23 @@ class StudentViewUserStateMixin(object):
result
[
field
.
name
]
=
field
.
read_from
(
self
)
if
getattr
(
self
,
"has_children"
,
False
):
components
=
[]
components
=
{}
for
child_id
in
self
.
children
:
child
=
self
.
runtime
.
get_block
(
child_id
)
if
hasattr
(
child
,
'
student_view_user_state
'
):
components
.
append
(
child
.
student_view_user_state
(
context
)
)
if
hasattr
(
child
,
'
build_user_state_data
'
):
components
[
str
(
child_id
)]
=
child
.
build_user_state_data
(
context
)
result
[
self
.
NESTED_BLOCKS_KEY
]
=
components
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.
"""
import
json
import
unittest
from
collections
import
namedtuple
from
datetime
import
datetime
...
...
@@ -62,7 +63,7 @@ class TestAnswerMixin(unittest.TestCase):
model
=
answer_mixin
.
get_model_object
()
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'
existing_model
=
Answer
(
name
=
name
,
...
...
@@ -74,7 +75,7 @@ class TestAnswerMixin(unittest.TestCase):
)
existing_model
.
save
()
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
=
{
"answer_data"
:
{
...
...
@@ -84,3 +85,28 @@ class TestAnswerMixin(unittest.TestCase):
}
}
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
from
datetime
import
datetime
import
pytz
from
mock
import
MagicMock
,
Mock
from
xblock.core
import
XBlock
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
...
...
@@ -22,7 +25,7 @@ class UserStateFieldsMixin(object):
preference_2
=
Integer
(
name
=
"pref2"
,
scope
=
Scope
.
preferences
)
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
):
...
...
@@ -76,7 +79,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
def
test_no_user_state_returns_empty
(
self
):
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
):
user_fields
=
{
...
...
@@ -85,19 +88,19 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
"preference_1"
:
"Yes"
,
"preference_2"
:
12
,
"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"
}
block_fields
=
self
.
_merge_dicts
(
user_fields
,
other_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
):
block
=
self
.
_build_block
(
XBlockChildrenNoUserState
,
{
"scope_settings"
:
"qwe"
,
"scope_content"
:
"ASD"
})
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
):
block
=
self
.
_build_block
(
XBlockChildrenNoUserState
,
{
"scope_settings"
:
"qwe"
,
"scope_content"
:
"ASD"
})
...
...
@@ -111,7 +114,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
self
.
assertEqual
(
self
.
_runtime
.
get_block
(
"child1"
),
no_user_state1
)
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"
:
[{},
{}]}
self
.
assertEqual
(
student_user_state
,
expected
)
...
...
@@ -126,7 +129,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
"preference_1"
:
"Yes"
,
"preference_2"
:
12
,
"user_info_1"
:
"John"
,
"user_info_2"
:
27
"user_info_2"
:
datetime
(
2017
,
1
,
2
,
3
,
4
,
5
,
tzinfo
=
pytz
.
UTC
)
}
user_fields2
=
{
"answer_1"
:
"BBBB"
,
...
...
@@ -134,7 +137,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
"preference_1"
:
"No"
,
"preference_2"
:
7
,
"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_state2
=
self
.
_build_block
(
XBlockNoChildrenWithUserState
,
self
.
_merge_dicts
(
user_fields2
,
other_fields
))
...
...
@@ -146,7 +149,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
self
.
assertEqual
(
self
.
_runtime
.
get_block
(
"child1"
),
user_state1
)
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
]}
self
.
assertEqual
(
student_user_state
,
expected
)
...
...
@@ -159,7 +162,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
"preference_1"
:
"IDN"
,
"preference_2"
:
42
,
"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
))
...
...
@@ -169,7 +172,7 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
"preference_1"
:
"Yes"
,
"preference_2"
:
12
,
"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
(
XBlockNoChildrenWithUserState
,
self
.
_merge_dicts
(
nested_user_fields
,
other_fields
)
...
...
@@ -181,8 +184,48 @@ class TestStudentViewUserStateMixin(unittest.TestCase):
self
.
assertEqual
(
block
.
children
,
nested
.
keys
())
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
[
"components"
]
=
[
nested_user_fields
]
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
"""
import
json
from
datetime
import
datetime
,
date
from
mock
import
MagicMock
,
Mock
,
patch
from
xblock.field_data
import
DictFieldData
...
...
@@ -87,3 +90,11 @@ def instantiate_block(cls, fields=None):
block
.
children
=
children
block
.
runtime
.
get_block
=
lambda
child_id
:
children
[
child_id
]
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