Commit f79b231d by E. Kolpakov

student_view_user_state -> XBlock.handler

parent ef6d54ad
......@@ -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,
......
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')
"""
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)
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)
"""
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)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment