From 18ebc3bf3bc99570178d22078775cfd01a37b80e Mon Sep 17 00:00:00 2001 From: Jonathan Piacenti Date: Wed, 8 Apr 2015 14:04:42 -0500 Subject: [PATCH 01/11] Add Intellij project module filetype to .gitignore. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 767c1df8..1c37539a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ /workbench.* /dist /templates +*.iml \ No newline at end of file From 7a0f19be3ff15b0f9b6ca19e96818f58ad406a33 Mon Sep 17 00:00:00 2001 From: Jonathan Piacenti Date: Mon, 6 Apr 2015 20:53:30 +0000 Subject: [PATCH 02/11] Add support for 'assessment feedback' message. --- problem_builder/mentoring.py | 25 ++++++++++++++----- problem_builder/message.py | 3 +++ problem_builder/public/css/mentoring.css | 6 +++-- .../public/js/mentoring_assessment_view.js | 9 ++++++- problem_builder/templates/html/mentoring.html | 5 +++- .../templates/xml/mcq_with_html_choices.xml | 22 ++++++++++++++++ .../templates/xml/mentoring_assessment.xml | 3 +++ .../tests/integration/test_assessment.py | 14 +++++++++++ .../tests/integration/xml/assessment_1.xml | 4 +++ 9 files changed, 81 insertions(+), 10 deletions(-) create mode 100644 problem_builder/templates/xml/mcq_with_html_choices.xml diff --git a/problem_builder/mentoring.py b/problem_builder/mentoring.py index 8d8177bb..3e428a13 100644 --- a/problem_builder/mentoring.py +++ b/problem_builder/mentoring.py @@ -335,6 +335,21 @@ def publish_event(self, data, suffix=''): return {'result': 'ok'} + def get_message(self, completed): + if self.max_attempts_reached: + return self.get_message_html('max_attempts_reached') + elif completed: + return self.get_message_html('completed') + else: + return self.get_message_html('incomplete') + + @property + def assessment_message(self): + if not self.max_attempts_reached: + return self.get_message_html('on-assessment-review') + else: + return None + @XBlock.json_handler def submit(self, submissions, suffix=''): log.info(u'Received submissions: {}'.format(submissions)) @@ -354,12 +369,7 @@ def submit(self, submissions, suffix=''): child.save() completed = completed and (child_result['status'] == 'correct') - if self.max_attempts_reached: - message = self.get_message_html('max_attempts_reached') - elif completed: - message = self.get_message_html('completed') - else: - message = self.get_message_html('incomplete') + message = self.get_message(completed) # Once it has been completed once, keep completion even if user changes values if self.completed: @@ -416,6 +426,7 @@ def handle_assessment_submit(self, submissions, suffix): children = [self.runtime.get_block(child_id) for child_id in self.children] children = [child for child in children if not isinstance(child, MentoringMessageBlock)] steps = [child for child in children if isinstance(child, StepMixin)] # Faster than the self.steps property + assessment_message = None for child in children: if child.name and child.name in submissions: @@ -451,6 +462,7 @@ def handle_assessment_submit(self, submissions, suffix): 'score_type': 'proficiency', }) event_data['final_grade'] = score.raw + assessment_message = self.assessment_message self.num_attempts += 1 self.completed = True @@ -471,6 +483,7 @@ def handle_assessment_submit(self, submissions, suffix): 'correct_answer': score.correct, 'incorrect_answer': score.incorrect, 'partially_correct_answer': score.partially_correct, + 'assessment_message': assessment_message, } @XBlock.json_handler diff --git a/problem_builder/message.py b/problem_builder/message.py index d57d52d2..9d9775a1 100644 --- a/problem_builder/message.py +++ b/problem_builder/message.py @@ -56,6 +56,7 @@ class MentoringMessageBlock(XBlock, StudioEditableXBlockMixin): {"display_name": "Completed", "value": "completed"}, {"display_name": "Incompleted", "value": "incomplete"}, {"display_name": "Reached max. # of attemps", "value": "max_attempts_reached"}, + {"display_name": "Review with attempts left", "value": "on_assessment_review"} ), ) editable_fields = ("content", ) @@ -84,6 +85,8 @@ def display_name_with_default(self): return self._(u"Message shown when complete") if self.type == 'incomplete': return self._(u"Message shown when incomplete") + if self.type == 'on-assessment-review': + return self._(u"Message shown during review when attempts remain") return u"INVALID MESSAGE" @classmethod diff --git a/problem_builder/public/css/mentoring.css b/problem_builder/public/css/mentoring.css index c8a63bba..7688d113 100644 --- a/problem_builder/public/css/mentoring.css +++ b/problem_builder/public/css/mentoring.css @@ -2,14 +2,16 @@ margin: 1em 0em; } -.mentoring .messages { +.mentoring .messages, +.mentoring .assessment-messages { display: none; margin-top: 10px; border-top: 2px solid #eaeaea; padding: 12px 0px 20px; } -.mentoring .messages .title1 { +.mentoring .messages .title1, +.mentoring .assessment-messages .title1 { color: #333333; text-transform: uppercase; font-weight: bold; diff --git a/problem_builder/public/js/mentoring_assessment_view.js b/problem_builder/public/js/mentoring_assessment_view.js index dc060a94..871ea6e9 100644 --- a/problem_builder/public/js/mentoring_assessment_view.js +++ b/problem_builder/public/js/mentoring_assessment_view.js @@ -1,6 +1,6 @@ function MentoringAssessmentView(runtime, element, mentoring) { var gradeTemplate = _.template($('#xblock-grade-template').html()); - var submitDOM, nextDOM, reviewDOM, tryAgainDOM; + var submitDOM, nextDOM, reviewDOM, tryAgainDOM, messagesDOM; var submitXHR; var checkmark; var active_child; @@ -21,6 +21,7 @@ function MentoringAssessmentView(runtime, element, mentoring) { $('.grade').html(''); $('.attempts').html(''); + messagesDOM.empty().hide(); } function renderGrade() { @@ -42,6 +43,10 @@ function MentoringAssessmentView(runtime, element, mentoring) { } mentoring.renderAttempts(); + if (data.assessment_message && data.num_attempts < data.max_attempts) { + mentoring.setContent(messagesDOM, data.assessment_message); + messagesDOM.show(); + } } function handleTryAgain(result) { @@ -74,6 +79,7 @@ function MentoringAssessmentView(runtime, element, mentoring) { reviewDOM = $(element).find('.submit .input-review'); tryAgainDOM = $(element).find('.submit .input-try-again'); checkmark = $('.assessment-checkmark', element); + messagesDOM = $('.assessment-messages', element); submitDOM.show(); submitDOM.bind('click', submit); @@ -149,6 +155,7 @@ function MentoringAssessmentView(runtime, element, mentoring) { $('.grade', element).data('partially_correct_answer', result.partially_correct_answer); $('.grade', element).data('max_attempts', result.max_attempts); $('.grade', element).data('num_attempts', result.num_attempts); + $('.grade', element).data('assessment_message', result.assessment_message); $('.attempts', element).data('max_attempts', result.max_attempts); $('.attempts', element).data('num_attempts', result.num_attempts); diff --git a/problem_builder/templates/html/mentoring.html b/problem_builder/templates/html/mentoring.html index df04e2b1..c8ad29cf 100644 --- a/problem_builder/templates/html/mentoring.html +++ b/problem_builder/templates/html/mentoring.html @@ -25,9 +25,12 @@ data-incorrect_answer="{{ self.score.3 }}" data-partially_correct_answer="{{ self.score.4 }}" data-max_attempts="{{ self.max_attempts }}" - data-num_attempts="{{ self.num_attempts }}"> + data-num_attempts="{{ self.num_attempts }}" + data-assessment_message="{{ self.assessment_message }}"> +
+
{% if self.mode == 'assessment' %} diff --git a/problem_builder/templates/xml/mcq_with_html_choices.xml b/problem_builder/templates/xml/mcq_with_html_choices.xml new file mode 100644 index 00000000..2a0c6112 --- /dev/null +++ b/problem_builder/templates/xml/mcq_with_html_choices.xml @@ -0,0 +1,22 @@ + + + + Its elegance + Its beauty + Its gracefulness + Its bugs + + This MCQ is indeed very graceful + This is something everyone has to like about this MCQ + This is something everyone has to like about beauty + Nah, there isn\'t any! + + + +

Congratulations!

+
+ +

Still some work to do...

+
+
+
diff --git a/problem_builder/templates/xml/mentoring_assessment.xml b/problem_builder/templates/xml/mentoring_assessment.xml index e8d46dfd..e5a6cee3 100644 --- a/problem_builder/templates/xml/mentoring_assessment.xml +++ b/problem_builder/templates/xml/mentoring_assessment.xml @@ -36,4 +36,7 @@ This is something everyone has to like about this MRQ Nah, there isn't any! + + Assessment additional feedback message text + diff --git a/problem_builder/tests/integration/test_assessment.py b/problem_builder/tests/integration/test_assessment.py index 69816dac..3a860e41 100644 --- a/problem_builder/tests/integration/test_assessment.py +++ b/problem_builder/tests/integration/test_assessment.py @@ -256,6 +256,17 @@ def peek_at_review(self, mentoring, controls, expected): self.assert_hidden(controls.next_question) self.assert_hidden(controls.review) + def assert_messages_text(self, mentoring, text): + messages = mentoring.find_element_by_css_selector('.assessment-messages') + self.assertEqual(messages.text, text) + self.assertTrue(messages.is_displayed()) + + def assert_messages_empty(self, mentoring): + messages = mentoring.find_element_by_css_selector('.assessment-messages') + self.assertEqual(messages.text, '') + self.assertFalse(messages.find_elements_by_xpath('./*')) + self.assertFalse(messages.is_displayed()) + def test_assessment(self): mentoring, controls = self.go_to_assessment("Assessment 1") @@ -276,6 +287,7 @@ def test_assessment(self): } self.peek_at_review(mentoring, controls, expected_results) + self.assert_messages_text(mentoring, "Assessment additional feedback message text") self.assert_clickable(controls.try_again) controls.try_again.click() @@ -294,6 +306,7 @@ def test_assessment(self): } self.peek_at_review(mentoring, controls, expected_results) self.assert_disabled(controls.try_again) + self.assert_messages_empty(mentoring) def test_single_question_assessment(self): """ @@ -308,6 +321,7 @@ def test_single_question_assessment(self): } self.peek_at_review(mentoring, controls, expected_results) + self.assert_messages_empty(mentoring) controls.try_again.click() # this is a wait and assertion all together - it waits until expected text is in mentoring block diff --git a/problem_builder/tests/integration/xml/assessment_1.xml b/problem_builder/tests/integration/xml/assessment_1.xml index 77bb7ec3..5e1ad7a9 100644 --- a/problem_builder/tests/integration/xml/assessment_1.xml +++ b/problem_builder/tests/integration/xml/assessment_1.xml @@ -42,4 +42,8 @@ This is something everyone has to like about this MRQ Nah, there isn't any! + + + Assessment additional feedback message text + From 00b3d93f782b1aae9299beea548eb0e45c4976ce Mon Sep 17 00:00:00 2001 From: Jonathan Piacenti Date: Thu, 9 Apr 2015 10:27:41 -0500 Subject: [PATCH 03/11] Grammatical rigor --- doc/img/mrq-3.png | Bin 46683 -> 114239 bytes .../templates/xml/mentoring_assessment.xml | 2 +- problem_builder/tests/integration/test_mcq.py | 2 +- .../tests/integration/xml/assessment_1.xml | 2 +- .../integration/xml/mcq_with_comments_1.xml | 2 +- .../integration/xml/mcq_with_html_choices.xml | 2 +- .../v1/tests/xml/v1_upgrade_a_new.xml | 2 +- .../v1/tests/xml/v1_upgrade_a_old.xml | 2 +- 8 files changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/img/mrq-3.png b/doc/img/mrq-3.png index 5f5ece985b7bd50b22030e5aba22869fca51ea55..588c61294010bf345a058d62da3b94994ac7f5bd 100644 GIT binary patch literal 114239 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

^uvw*NOqS1{>l=!CnT=r=1 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 literal 46683 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 a)nEUno$b>0kThis MRQ is indeed very graceful This is something everyone has to like about this MRQ - Nah, there isn't any! + Nah, there aren't any! Assessment additional feedback message text diff --git a/problem_builder/tests/integration/test_mcq.py b/problem_builder/tests/integration/test_mcq.py index 34d7d3d3..dce589b4 100644 --- a/problem_builder/tests/integration/test_mcq.py +++ b/problem_builder/tests/integration/test_mcq.py @@ -194,7 +194,7 @@ def test_mcq_feedback_popups(self): "This is something everyone has to like about this MRQ", "This is something everyone has to like about beauty", "This MRQ is indeed very graceful", - "Nah, there isn\\'t any!" + "Nah, there aren\\'t any!" ] submit = mentoring.find_element_by_css_selector('.submit input.input-main') diff --git a/problem_builder/tests/integration/xml/assessment_1.xml b/problem_builder/tests/integration/xml/assessment_1.xml index 5e1ad7a9..0d1e1695 100644 --- a/problem_builder/tests/integration/xml/assessment_1.xml +++ b/problem_builder/tests/integration/xml/assessment_1.xml @@ -40,7 +40,7 @@ This MRQ is indeed very graceful This is something everyone has to like about this MRQ - Nah, there isn't any! + Nah, there aren't any! diff --git a/problem_builder/tests/integration/xml/mcq_with_comments_1.xml b/problem_builder/tests/integration/xml/mcq_with_comments_1.xml index 6f119c09..551df89d 100644 --- a/problem_builder/tests/integration/xml/mcq_with_comments_1.xml +++ b/problem_builder/tests/integration/xml/mcq_with_comments_1.xml @@ -9,7 +9,7 @@ This MRQ is indeed very graceful This is something everyone has to like about this MRQ This is something everyone has to like about beauty - Nah, there isn\'t any! + Nah, there aren\'t any! diff --git a/problem_builder/tests/integration/xml/mcq_with_html_choices.xml b/problem_builder/tests/integration/xml/mcq_with_html_choices.xml index f83de791..578dbb25 100644 --- a/problem_builder/tests/integration/xml/mcq_with_html_choices.xml +++ b/problem_builder/tests/integration/xml/mcq_with_html_choices.xml @@ -9,7 +9,7 @@ This MCQ is indeed very graceful This is something everyone has to like about this MCQ This is something everyone has to like about beauty - Nah, there isn\'t any! + Nah, there aren\'t any! diff --git a/problem_builder/v1/tests/xml/v1_upgrade_a_new.xml b/problem_builder/v1/tests/xml/v1_upgrade_a_new.xml index 7dd3e2bf..1a180814 100644 --- a/problem_builder/v1/tests/xml/v1_upgrade_a_new.xml +++ b/problem_builder/v1/tests/xml/v1_upgrade_a_new.xml @@ -29,7 +29,7 @@ Its bugs This MRQ is indeed very graceful This is something everyone has to like about this MRQ - Nah, there isn't any! + Nah, there aren't any!

Congratulations!

diff --git a/problem_builder/v1/tests/xml/v1_upgrade_a_old.xml b/problem_builder/v1/tests/xml/v1_upgrade_a_old.xml index 58188450..f4ed6ac8 100644 --- a/problem_builder/v1/tests/xml/v1_upgrade_a_old.xml +++ b/problem_builder/v1/tests/xml/v1_upgrade_a_old.xml @@ -51,7 +51,7 @@ Changes from the original: This MRQ is indeed very graceful This is something everyone has to like about this MRQ - Nah, there isn't any! + Nah, there aren't any! Thank you for answering! From 7f0d3def8138ad23304dc6293c8201ef75b5434a Mon Sep 17 00:00:00 2001 From: Jonathan Piacenti Date: Thu, 9 Apr 2015 11:00:45 -0500 Subject: [PATCH 04/11] Add 'get_results' method to all assessment block types --- problem_builder/answer.py | 15 +++++++++------ problem_builder/mcq.py | 16 +++++++++++----- problem_builder/mrq.py | 21 +++++++++++++-------- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/problem_builder/answer.py b/problem_builder/answer.py index f09016d5..ef877902 100644 --- a/problem_builder/answer.py +++ b/problem_builder/answer.py @@ -179,6 +179,14 @@ def student_view(self, context=None): """ Normal view of this XBlock, identical to mentoring_view """ return self.mentoring_view(context) + def get_results(self): + return { + 'student_input': self.student_input, + 'status': self.status, + 'weight': self.weight, + 'score': 1 if self.status == 'correct' else 0, + } + def submit(self, submission): """ The parent block is handling a student submission, including a new answer for this @@ -187,12 +195,7 @@ def submit(self, submission): self.student_input = submission[0]['value'].strip() self.save() log.info(u'Answer submitted for`{}`: "{}"'.format(self.name, self.student_input)) - return { - 'student_input': self.student_input, - 'status': self.status, - 'weight': self.weight, - 'score': 1 if self.status == 'correct' else 0, - } + return self.get_results() @property def status(self): diff --git a/problem_builder/mcq.py b/problem_builder/mcq.py index 8782744a..eb34773c 100644 --- a/problem_builder/mcq.py +++ b/problem_builder/mcq.py @@ -74,9 +74,7 @@ def describe_choice_correctness(self, choice_value): return self._(u"Wrong") return self._(u"Not Acceptable") - def submit(self, submission): - log.debug(u'Received MCQ submission: "%s"', submission) - + def calculate_results(self, submission): correct = submission in self.correct_choices tips_html = [] for tip in self.get_tips(): @@ -86,7 +84,7 @@ def submit(self, submission): if tips_html: formatted_tips = loader.render_template('templates/html/tip_choice_group.html', { 'tips_html': tips_html, - }) + }) self.student_choice = submission @@ -94,13 +92,21 @@ def submit(self, submission): # Also send to the submissions API: sub_api.create_submission(self.student_item_key, submission) - result = { + return { 'submission': submission, 'status': 'correct' if correct else 'incorrect', 'tips': formatted_tips if tips_html else None, 'weight': self.weight, 'score': 1 if correct else 0, } + + def get_results(self): + return self.calculate_results(self.student_choice) + + def submit(self, submission): + log.debug(u'Received MCQ submission: "%s"', submission) + result = self.calculate_results(submission) + self.student_choice = submission log.debug(u'MCQ submission result: %s', result) return result diff --git a/problem_builder/mrq.py b/problem_builder/mrq.py index 0fec59ca..e92e088a 100644 --- a/problem_builder/mrq.py +++ b/problem_builder/mrq.py @@ -81,9 +81,7 @@ def describe_choice_correctness(self, choice_value): return self._(u"Ignored") return self._(u"Not Acceptable") - def submit(self, submissions): - log.debug(u'Received MRQ submissions: "%s"', submissions) - + def calculate_results(self, submissions): score = 0 results = [] @@ -106,22 +104,20 @@ def submit(self, submissions): choice_result = { 'value': choice.value, 'selected': choice_selected, - } + } # Only include tips/results in returned response if we want to display them if not self.hide_results: loader = ResourceLoader(__name__) choice_result['completed'] = choice_completed choice_result['tips'] = loader.render_template('templates/html/tip_choice_group.html', { 'tips_html': choice_tips_html, - }) + }) results.append(choice_result) - self.student_choices = submissions - status = 'incorrect' if score <= 0 else 'correct' if score >= len(results) else 'partial' - result = { + return { 'submissions': submissions, 'status': status, 'choices': results, @@ -130,6 +126,15 @@ def submit(self, submissions): 'score': (float(score) / len(results)) if results else 0, } + def get_results(self): + return self.calculate_results(self.student_choices) + + def submit(self, submissions): + log.debug(u'Received MRQ submissions: "%s"', submissions) + + result = self.calculate_results(submissions) + self.student_choices = submissions + log.debug(u'MRQ submissions result: %s', result) return result From 990ba6280c9a2129cb60a7d4daf39fdc0a25e986 Mon Sep 17 00:00:00 2001 From: Jonathan Piacenti Date: Thu, 9 Apr 2015 13:10:25 -0500 Subject: [PATCH 05/11] Add scaffolding for displaying list of questions in extended feedback. --- problem_builder/mentoring.py | 112 ++++++++++++++++-- .../public/js/mentoring_assessment_view.js | 16 +++ problem_builder/templates/html/mentoring.html | 6 +- .../templates/html/mentoring_grade.html | 63 +++++----- .../html/mentoring_review_questions.html | 8 ++ 5 files changed, 168 insertions(+), 37 deletions(-) create mode 100644 problem_builder/templates/html/mentoring_review_questions.html diff --git a/problem_builder/mentoring.py b/problem_builder/mentoring.py index 3e428a13..5a28393c 100644 --- a/problem_builder/mentoring.py +++ b/problem_builder/mentoring.py @@ -61,6 +61,10 @@ def _(text): Score = namedtuple("Score", ["raw", "percentage", "correct", "incorrect", "partially_correct"]) +CORRECT = 'correct' +INCORRECT = 'incorrect' +PARTIAL = 'partial' + @XBlock.needs("i18n") @XBlock.wants('settings') @@ -160,6 +164,11 @@ class MentoringBlock(XBlock, StepParentMixin, StudioEditableXBlockMixin, StudioC default=[], scope=Scope.user_state ) + extended_feedback = Boolean( + help=_("Show extended feedback details when all attempts are used up."), + default=False, + Scope=Scope.content + ) # Global user state next_step = String( @@ -201,17 +210,39 @@ def get_theme(self): return xblock_settings[self.theme_key] return _default_theme_config + def get_question_number(self, question_id): + """ + Get the step number of the question id + """ + for child_id in self.children: + question = self.runtime.get_block(child_id) + if isinstance(question, StepMixin) and (question.name == question_id): + return question.step_number + raise ValueError("Question ID in answer set not a step of this Mentoring Block!") + + def answer_mapper(self, answer_status): + """ + Create a JSON-dumpable object with readable key names from a list of student answers. + """ + return [ + { + 'number': self.get_question_number(answer[0]), + 'id': answer[0], + 'details': answer[1], + } for answer in self.student_results if answer[1]['status'] == answer_status + ] + @property def score(self): """Compute the student score taking into account the weight of each step.""" weights = (float(self.runtime.get_block(step_id).weight) for step_id in self.steps) total_child_weight = sum(weights) if total_child_weight == 0: - return Score(0, 0, 0, 0, 0) + return Score(0, 0, [], [], []) score = sum(r[1]['score'] * r[1]['weight'] for r in self.student_results) / total_child_weight - correct = sum(1 for r in self.student_results if r[1]['status'] == 'correct') - incorrect = sum(1 for r in self.student_results if r[1]['status'] == 'incorrect') - partially_correct = sum(1 for r in self.student_results if r[1]['status'] == 'partial') + correct = self.answer_mapper(CORRECT) + incorrect = self.answer_mapper(INCORRECT) + partially_correct = self.answer_mapper(PARTIAL) return Score(score, int(round(score * 100)), correct, incorrect, partially_correct) @@ -259,6 +290,7 @@ def student_view(self, context): fragment.add_javascript_url(self.runtime.local_resource_url(self, 'public/js/mentoring.js')) fragment.add_resource(loader.load_unicode('templates/html/mentoring_attempts.html'), "text/html") fragment.add_resource(loader.load_unicode('templates/html/mentoring_grade.html'), "text/html") + fragment.add_resource(loader.load_unicode('templates/html/mentoring_review_questions.html'), "text/html") self.include_theme_files(fragment) # Workbench doesn't have font awesome, so add it: @@ -350,6 +382,72 @@ def assessment_message(self): else: return None + def show_extended_feedback(self): + return self.extended_feedback and self.max_attempts_reached + + def feedback_dispatch(self, target_data, stringify): + if self.show_extended_feedback(): + if stringify: + return json.dumps(target_data) + else: + return target_data + + def correct_json(self, stringify=True): + return self.feedback_dispatch(self.score.correct, stringify) + + def incorrect_json(self, stringify=True): + return self.feedback_dispatch(self.score.incorrect, stringify) + + def partial_json(self, stringify=True): + return self.feedback_dispatch(self.score.partially_correct, stringify) + + @XBlock.json_handler + def get_results(self, queries, suffix=''): + """ + Gets detailed results in the case of extended feedback. + + It may be a good idea to eventually have this function get results + in the general case instead of loading them in the template in the future, + and only using it for extended feedback situations. + + Right now there are two ways to get results-- through the template upon loading up + the mentoring block, or after submission of an AJAX request like in + submit or get_results here. + """ + results = [] + if not self.show_extended_feedback(): + return { + 'results': [], + 'error': 'Extended feedback results cannot be obtained.' + } + completed = True + choices = dict(self.student_results) + step = self.step + # Only one child should ever be of concern with this method. + for child_id in self.steps: + child = self.runtime.get_block(child_id) + if child.name and child.name in queries: + results = [child.name, child.get_results(choices[child.name])] + # Children may have their own definition of 'completed' which can vary from the general case + # of the whole mentoring block being completed. This is because in standard mode, all children + # must be correct to complete the block. In assessment mode with extended feedback, completion + # happens when you're out of attempts, no matter how you did. + completed = choices[child.name]['status'] == 'correct' + break + + # The 'completed' message should always be shown in this case, since no more attempts are available. + message = self.get_message(True) + + return { + 'results': results, + 'completed': completed, + 'attempted': self.attempted, + 'message': message, + 'step': step, + 'max_attempts': self.max_attempts, + 'num_attempts': self.num_attempts, + } + @XBlock.json_handler def submit(self, submissions, suffix=''): log.info(u'Received submissions: {}'.format(submissions)) @@ -480,9 +578,9 @@ def handle_assessment_submit(self, submissions, suffix): 'num_attempts': self.num_attempts, 'step': self.step, 'score': score.percentage, - 'correct_answer': score.correct, - 'incorrect_answer': score.incorrect, - 'partially_correct_answer': score.partially_correct, + 'correct_answer': len(score.correct), + 'incorrect_answer': len(score.incorrect), + 'partially_correct_answer': len(score.partially_correct), 'assessment_message': assessment_message, } diff --git a/problem_builder/public/js/mentoring_assessment_view.js b/problem_builder/public/js/mentoring_assessment_view.js index 871ea6e9..8fff9d5a 100644 --- a/problem_builder/public/js/mentoring_assessment_view.js +++ b/problem_builder/public/js/mentoring_assessment_view.js @@ -1,5 +1,6 @@ function MentoringAssessmentView(runtime, element, mentoring) { var gradeTemplate = _.template($('#xblock-grade-template').html()); + var reviewQuestionsTemplate = _.template($('#xblock-review-questions-template').html()); var submitDOM, nextDOM, reviewDOM, tryAgainDOM, messagesDOM; var submitXHR; var checkmark; @@ -24,9 +25,24 @@ function MentoringAssessmentView(runtime, element, mentoring) { messagesDOM.empty().hide(); } + function no_more_attempts() { + var attempts_data = $('.attempts', element).data(); + return attempts_data.num_attempts >= attempts_data.max_attempts; + } + function renderGrade() { notify('navigation', {state: 'unlock'}) var data = $('.grade', element).data(); + _.extend(data, { + 'enable_extended': (no_more_attempts() && data.extended_feedback), + 'runDetails': function(label) { + if (! this.enable_extended) { + return '.' + } + var self = this; + return reviewQuestionsTemplate({'questions': self[label], 'label': label}) + } + }); cleanAll(); $('.grade', element).html(gradeTemplate(data)); reviewDOM.hide(); diff --git a/problem_builder/templates/html/mentoring.html b/problem_builder/templates/html/mentoring.html index c8ad29cf..bd161943 100644 --- a/problem_builder/templates/html/mentoring.html +++ b/problem_builder/templates/html/mentoring.html @@ -21,9 +21,9 @@ {% if self.display_submit %}
diff --git a/problem_builder/templates/html/mentoring_grade.html b/problem_builder/templates/html/mentoring_grade.html index 8db0bedd..3541942b 100644 --- a/problem_builder/templates/html/mentoring_grade.html +++ b/problem_builder/templates/html/mentoring_grade.html @@ -10,33 +10,42 @@


-

- <%= _.template( - ngettext( - "You answered 1 question correctly.", - "You answered {number_correct} questions correctly.", - correct_answer - ), {number_correct: correct_answer}, {interpolate: /\{(.+?)\}/g}) - %> -

+
+

+ <%= _.template( + ngettext( + "You answered 1 question correctly.", + "You answered {number_correct} questions correctly.", + correct_answer + ), {number_correct: correct_answer}, {interpolate: /\{(.+?)\}/g}) + %> +

+ <%= runDetails('correct') %> +
-

- <%= _.template( - ngettext( - "You answered 1 question partially correctly.", - "You answered {number_partially_correct} questions partially correctly.", - partially_correct_answer - ), {number_partially_correct: partially_correct_answer}, {interpolate: /\{(.+?)\}/g}) - %> -

+
+

+ <%= _.template( + ngettext( + "You answered 1 question partially correctly.", + "You answered {number_partially_correct} questions partially correctly.", + partially_correct_answer + ), {number_partially_correct: partially_correct_answer}, {interpolate: /\{(.+?)\}/g}) + %> +

+ <%= runDetails('partial') %> +
-

- <%= _.template( - ngettext( - "You answered 1 question incorrectly.", - "You answered {number_incorrect} questions incorrectly.", - incorrect_answer - ), {number_incorrect: incorrect_answer}, {interpolate: /\{(.+?)\}/g}) - %> -

+
+

+ <%= _.template( + ngettext( + "You answered 1 question incorrectly.", + "You answered {number_incorrect} questions incorrectly.", + incorrect_answer + ), {number_incorrect: incorrect_answer}, {interpolate: /\{(.+?)\}/g}) + %> +

+ <%= runDetails('incorrect') %> +
diff --git a/problem_builder/templates/html/mentoring_review_questions.html b/problem_builder/templates/html/mentoring_review_questions.html new file mode 100644 index 00000000..bcb4b6ec --- /dev/null +++ b/problem_builder/templates/html/mentoring_review_questions.html @@ -0,0 +1,8 @@ + From 290030517d3fe1762b853f0c460cf66221ed07c5 Mon Sep 17 00:00:00 2001 From: Jonathan Piacenti Date: Thu, 9 Apr 2015 13:11:03 -0500 Subject: [PATCH 06/11] Fixup! Remove erroneously added workbench scenario --- .../templates/xml/mcq_with_html_choices.xml | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 problem_builder/templates/xml/mcq_with_html_choices.xml diff --git a/problem_builder/templates/xml/mcq_with_html_choices.xml b/problem_builder/templates/xml/mcq_with_html_choices.xml deleted file mode 100644 index 2a0c6112..00000000 --- a/problem_builder/templates/xml/mcq_with_html_choices.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - Its elegance - Its beauty - Its gracefulness - Its bugs - - This MCQ is indeed very graceful - This is something everyone has to like about this MCQ - This is something everyone has to like about beauty - Nah, there isn\'t any! - - - -

Congratulations!

-
- -

Still some work to do...

-
-
-
From 22e12f6dc84f731a0c95008ecf581e4c0bf4d36d Mon Sep 17 00:00:00 2001 From: Jonathan Piacenti Date: Fri, 10 Apr 2015 15:45:16 -0500 Subject: [PATCH 07/11] Implemented extended feedback. --- problem_builder/answer.py | 3 +- problem_builder/mcq.py | 10 +- problem_builder/mentoring.py | 12 +- problem_builder/mrq.py | 30 +-- problem_builder/public/css/mentoring.css | 25 +++ problem_builder/public/js/answer.js | 11 +- problem_builder/public/js/mentoring.js | 2 +- .../public/js/mentoring_assessment_view.js | 192 +++++++++++++----- .../public/js/mentoring_standard_view.js | 37 ++-- problem_builder/public/js/questionnaire.js | 25 ++- problem_builder/templates/html/mentoring.html | 7 +- .../templates/html/mentoring_grade.html | 3 + .../html/mentoring_review_questions.html | 2 +- .../templates/xml/mentoring_assessment.xml | 30 +-- 14 files changed, 274 insertions(+), 115 deletions(-) diff --git a/problem_builder/answer.py b/problem_builder/answer.py index ef877902..7054336a 100644 --- a/problem_builder/answer.py +++ b/problem_builder/answer.py @@ -179,7 +179,8 @@ def student_view(self, context=None): """ Normal view of this XBlock, identical to mentoring_view """ return self.mentoring_view(context) - def get_results(self): + def get_results(self, previous_response=None): + # Previous result is actually stored in database table-- ignore. return { 'student_input': self.student_input, 'status': self.status, diff --git a/problem_builder/mcq.py b/problem_builder/mcq.py index eb34773c..5647a72f 100644 --- a/problem_builder/mcq.py +++ b/problem_builder/mcq.py @@ -81,10 +81,12 @@ def calculate_results(self, submission): if submission in tip.values: tips_html.append(tip.render('mentoring_view').content) + formatted_tips = None + if tips_html: formatted_tips = loader.render_template('templates/html/tip_choice_group.html', { 'tips_html': tips_html, - }) + }) self.student_choice = submission @@ -95,13 +97,13 @@ def calculate_results(self, submission): return { 'submission': submission, 'status': 'correct' if correct else 'incorrect', - 'tips': formatted_tips if tips_html else None, + 'tips': formatted_tips, 'weight': self.weight, 'score': 1 if correct else 0, } - def get_results(self): - return self.calculate_results(self.student_choice) + def get_results(self, previous_result): + return self.calculate_results(previous_result['submission']) def submit(self, submission): log.debug(u'Received MCQ submission: "%s"', submission) diff --git a/problem_builder/mentoring.py b/problem_builder/mentoring.py index 5a28393c..dec6ffbf 100644 --- a/problem_builder/mentoring.py +++ b/problem_builder/mentoring.py @@ -21,6 +21,7 @@ # Imports ########################################################### import logging +import json from collections import namedtuple @@ -432,7 +433,7 @@ def get_results(self, queries, suffix=''): # of the whole mentoring block being completed. This is because in standard mode, all children # must be correct to complete the block. In assessment mode with extended feedback, completion # happens when you're out of attempts, no matter how you did. - completed = choices[child.name]['status'] == 'correct' + completed = choices[child.name]['status'] break # The 'completed' message should always be shown in this case, since no more attempts are available. @@ -510,7 +511,7 @@ def submit(self, submissions, suffix=''): }) return { - 'submitResults': submit_results, + 'results': submit_results, 'completed': self.completed, 'attempted': self.attempted, 'message': message, @@ -526,6 +527,8 @@ def handle_assessment_submit(self, submissions, suffix): steps = [child for child in children if isinstance(child, StepMixin)] # Faster than the self.steps property assessment_message = None + print children + print submissions for child in children: if child.name and child.name in submissions: submission = submissions[child.name] @@ -565,6 +568,7 @@ def handle_assessment_submit(self, submissions, suffix): self.num_attempts += 1 self.completed = True + print current_child event_data['exercise_id'] = current_child.name event_data['num_attempts'] = self.num_attempts event_data['submitted_answer'] = submissions @@ -581,6 +585,10 @@ def handle_assessment_submit(self, submissions, suffix): 'correct_answer': len(score.correct), 'incorrect_answer': len(score.incorrect), 'partially_correct_answer': len(score.partially_correct), + 'correct': self.correct_json(stringify=False), + 'incorrect': self.incorrect_json(stringify=False), + 'partial': self.partial_json(stringify=False), + 'extended_feedback': self.show_extended_feedback() or '', 'assessment_message': assessment_message, } diff --git a/problem_builder/mrq.py b/problem_builder/mrq.py index e92e088a..1d8fad59 100644 --- a/problem_builder/mrq.py +++ b/problem_builder/mrq.py @@ -81,9 +81,25 @@ def describe_choice_correctness(self, choice_value): return self._(u"Ignored") return self._(u"Not Acceptable") + def get_results(self, previous_result): + """ + Get the results a student has already submitted. + """ + result = self.calculate_results(previous_result['submissions']) + result['completed'] = True + return result + + def submit(self, submissions): + log.debug(u'Received MRQ submissions: "%s"', submissions) + + result = self.calculate_results(submissions) + self.student_choices = submissions + + log.debug(u'MRQ submissions result: %s', result) + return result + def calculate_results(self, submissions): score = 0 - results = [] for choice in self.custom_choices: choice_completed = True @@ -126,18 +142,6 @@ def calculate_results(self, submissions): 'score': (float(score) / len(results)) if results else 0, } - def get_results(self): - return self.calculate_results(self.student_choices) - - def submit(self, submissions): - log.debug(u'Received MRQ submissions: "%s"', submissions) - - result = self.calculate_results(submissions) - self.student_choices = submissions - - log.debug(u'MRQ submissions result: %s', result) - return result - def validate_field_data(self, validation, data): """ Validate this block's field data. diff --git a/problem_builder/public/css/mentoring.css b/problem_builder/public/css/mentoring.css index 7688d113..871ad97c 100644 --- a/problem_builder/public/css/mentoring.css +++ b/problem_builder/public/css/mentoring.css @@ -136,3 +136,28 @@ .mentoring input[type="radio"] { margin: 0; } + +.mentoring .review-list { + list-style: none; + padding-left: 0 !important; + margin-left: 0; +} +.mentoring .review-list li { + display: inline; +} + +.mentoring .review-list li a{ + font-weight: bold; +} + +.mentoring .results-section { + float: left; +} +.mentoring .clear { + display: block; + clear: both; +} + +.mentoring .review-link { + float: right; +} \ No newline at end of file diff --git a/problem_builder/public/js/answer.js b/problem_builder/public/js/answer.js index 8d6c48d9..4a50a255 100644 --- a/problem_builder/public/js/answer.js +++ b/problem_builder/public/js/answer.js @@ -17,15 +17,22 @@ function AnswerBlock(runtime, element) { return $(':input', element).serializeArray(); }, + handleReview: function(result) { + $('textarea', element).prop('disabled', true); + }, + handleSubmit: function(result) { - if (this.mode === 'assessment') - return; var checkmark = $('.answer-checkmark', element); $(element).find('.message').text((result || {}).error || ''); this.clearResult(); + if (this.mode === 'assessment') { + // Display of checkmark would be redundant. + return + } + if (result.status === "correct") { checkmark.addClass('checkmark-correct icon-ok fa-check'); } diff --git a/problem_builder/public/js/mentoring.js b/problem_builder/public/js/mentoring.js index 760beb32..f3ffe318 100644 --- a/problem_builder/public/js/mentoring.js +++ b/problem_builder/public/js/mentoring.js @@ -60,7 +60,7 @@ function MentoringBlock(runtime, element) { if (typeof obj !== 'undefined' && typeof obj[fn] == 'function') { return obj[fn].apply(obj, Array.prototype.slice.call(arguments, 2)); } else { - return undefined; + return null; } } diff --git a/problem_builder/public/js/mentoring_assessment_view.js b/problem_builder/public/js/mentoring_assessment_view.js index 8fff9d5a..0a094eff 100644 --- a/problem_builder/public/js/mentoring_assessment_view.js +++ b/problem_builder/public/js/mentoring_assessment_view.js @@ -1,7 +1,7 @@ function MentoringAssessmentView(runtime, element, mentoring) { var gradeTemplate = _.template($('#xblock-grade-template').html()); var reviewQuestionsTemplate = _.template($('#xblock-review-questions-template').html()); - var submitDOM, nextDOM, reviewDOM, tryAgainDOM, messagesDOM; + var submitDOM, nextDOM, reviewDOM, tryAgainDOM, messagesDOM, reviewLinkDOM; var submitXHR; var checkmark; var active_child; @@ -33,11 +33,11 @@ function MentoringAssessmentView(runtime, element, mentoring) { function renderGrade() { notify('navigation', {state: 'unlock'}) var data = $('.grade', element).data(); + data.enable_extended = (no_more_attempts() && data.extended_feedback); _.extend(data, { - 'enable_extended': (no_more_attempts() && data.extended_feedback), 'runDetails': function(label) { - if (! this.enable_extended) { - return '.' + if (! data.enable_extended) { + return '' } var self = this; return reviewQuestionsTemplate({'questions': self[label], 'label': label}) @@ -45,8 +45,13 @@ function MentoringAssessmentView(runtime, element, mentoring) { }); cleanAll(); $('.grade', element).html(gradeTemplate(data)); + reviewLinkDOM.hide(); reviewDOM.hide(); submitDOM.hide(); + if (data.enable_extended) { + nextDOM.unbind('click'); + nextDOM.bind('click', reviewNextChild) + } nextDOM.hide(); tryAgainDOM.show(); @@ -63,6 +68,7 @@ function MentoringAssessmentView(runtime, element, mentoring) { mentoring.setContent(messagesDOM, data.assessment_message); messagesDOM.show(); } + $('a.question-link', element).click(reviewJump); } function handleTryAgain(result) { @@ -80,7 +86,6 @@ function MentoringAssessmentView(runtime, element, mentoring) { } function tryAgain() { - var success = true; var handlerUrl = runtime.handlerUrl(element, 'try_again'); if (submitXHR) { submitXHR.abort(); @@ -94,18 +99,26 @@ function MentoringAssessmentView(runtime, element, mentoring) { nextDOM = $(element).find('.submit .input-next'); reviewDOM = $(element).find('.submit .input-review'); tryAgainDOM = $(element).find('.submit .input-try-again'); + reviewLinkDOM = $(element).find('.review-link'); checkmark = $('.assessment-checkmark', element); messagesDOM = $('.assessment-messages', element); + reviewLinkDOM.hide(); submitDOM.show(); submitDOM.bind('click', submit); nextDOM.bind('click', displayNextChild); nextDOM.show(); - reviewDOM.bind('click', renderGrade); tryAgainDOM.bind('click', tryAgain); active_child = mentoring.step; + function renderGradeEvent(event) { + event.preventDefault(); + renderGrade(); + } + reviewLinkDOM.bind('click', renderGradeEvent); + reviewDOM.bind('click', renderGradeEvent); + var options = { onChange: onChange }; @@ -135,24 +148,85 @@ function MentoringAssessmentView(runtime, element, mentoring) { } } - function displayNextChild() { - cleanAll(); + function reviewJump(event) { + // Used only during extended feedback. Assumes completion and attempts exhausted. + event.preventDefault(); - // find the next real child block to display. HTMLBlock are always displayed - active_child++; + var target = parseInt($(event.target).data('step')) - 1; + reviewDisplayChild(target); + } + + function reviewDisplayChild(child_index) { + active_child = child_index; + cleanAll(); var child = mentoring.steps[active_child]; $(child.element).show(); $(child.element).find("input, textarea").first().focus(); mentoring.publish_event({ - event_type: 'xblock.problem_builder.assessment.shown', - exercise_id: child.name + event_type: 'xblock.mentoring.assessment.review', + exercise_id: $(mentoring.steps[active_child]).attr('name') }); + post_display(true); + get_results(); + } - if (isDone()) + function reviewNextChild() { + nextDOM.attr('disabled', 'disabled'); + nextDOM.hide(); + findNextChild(); + reviewDisplayChild(active_child) + } + + function displayNextChild() { + cleanAll(); + findNextChild(true); + // find the next real child block to display. HTMLBlock are always displayed + if (isDone()) { renderGrade(); + } else { + post_display(); + } + } + + function findNextChild(fire_event) { + // find the next real child block to display. HTMLBlock are always displayed + ++active_child; + var child = mentoring.steps[active_child]; + $(child.element).show(); + $(child.element).find("input, textarea").first().focus(); + if (fire_event) { + mentoring.publish_event({ + event_type: 'xblock.problem_builder.assessment.shown', + exercise_id: child.name + }); + } + } + + function post_display(show_link) { nextDOM.attr('disabled', 'disabled'); - reviewDOM.attr('disabled', 'disabled'); - validateXBlock(); + if (no_more_attempts()) { + if (show_link) { + reviewLinkDOM.show(); + } else { + reviewDOM.show(); + reviewDOM.removeAttr('disabled') + } + } else { + reviewDOM.attr('disabled', 'disabled'); + } + validateXBlock(show_link); + if (show_link && ! isLastChild()) { + // User should also be able to browse forward if we're showing the review link. + nextDOM.show(); + nextDOM.removeAttr('disabled'); + } + if (show_link) { + // The user has no more tries, so the try again button is noise. A disabled submit button + // emphasizes that the user cannot change their answer. + tryAgainDOM.hide(); + submitDOM.show(); + submitDOM.attr('disabled', 'disabled') + } } function onChange() { @@ -164,20 +238,20 @@ function MentoringAssessmentView(runtime, element, mentoring) { } } - function handleSubmitResults(result) { - $('.grade', element).data('score', result.score); - $('.grade', element).data('correct_answer', result.correct_answer); - $('.grade', element).data('incorrect_answer', result.incorrect_answer); - $('.grade', element).data('partially_correct_answer', result.partially_correct_answer); - $('.grade', element).data('max_attempts', result.max_attempts); - $('.grade', element).data('num_attempts', result.num_attempts); - $('.grade', element).data('assessment_message', result.assessment_message); - $('.attempts', element).data('max_attempts', result.max_attempts); - $('.attempts', element).data('num_attempts', result.num_attempts); - - if (result.completed === 'partial') { + function handleResults(response) { + $('.grade', element).data('score', response.score); + $('.grade', element).data('correct_answer', response.correct_answer); + $('.grade', element).data('incorrect_answer', response.incorrect_answer); + $('.grade', element).data('partially_correct_answer', response.partially_correct_answer); + $('.grade', element).data('max_attempts', response.max_attempts); + $('.grade', element).data('num_attempts', response.num_attempts); + $('.grade', element).data('assessment_message', response.assessment_message); + $('.attempts', element).data('max_attempts', response.max_attempts); + $('.attempts', element).data('num_attempts', response.num_attempts); + + if (response.completed === 'partial') { checkmark.addClass('checkmark-partially-correct icon-ok fa-check'); - } else if (result.completed === 'correct') { + } else if (response.completed === 'correct') { checkmark.addClass('checkmark-correct icon-ok fa-check'); } else { checkmark.addClass('checkmark-incorrect icon-exclamation fa-exclamation'); @@ -185,40 +259,58 @@ function MentoringAssessmentView(runtime, element, mentoring) { submitDOM.attr('disabled', 'disabled'); - /* Something went wrong with student submission, denied next question */ - if (result.step != active_child+1) { - active_child = result.step-1; - displayNextChild(); - } else { - nextDOM.removeAttr("disabled"); - if (nextDOM.is(':visible')) { nextDOM.focus(); } - reviewDOM.removeAttr("disabled"); - if (reviewDOM.is(':visible')) { reviewDOM.focus(); } + /* We're not dealing with the current step */ + if (response.step != active_child+1) { + return } + nextDOM.removeAttr("disabled"); + reviewDOM.removeAttr("disabled"); + if (nextDOM.is(':visible')) { nextDOM.focus(); } + if (reviewDOM.is(':visible')) { reviewDOM.focus(); } } - function submit() { - var success = true; + function handleReviewResults(response) { + handleResults(response); + var options = { + max_attempts: response.max_attempts, + num_attempts: response.num_attempts + }; + var result = response.results[1]; + var child = mentoring.children[active_child]; + callIfExists(child, 'handleSubmit', result, options); + callIfExists(child, 'handleReview', result, options); + } + + function handleSubmitResults(response){ + handleResults(response); + // Update grade information + $('.grade').data(response); + } + + + function calculate_results(handler_name, callback) { var data = {}; var child = mentoring.steps[active_child]; if (child && child.name !== undefined) { - data[child.name] = callIfExists(child, 'submit'); + data[child.name] = callIfExists(child, handler_name); } - var handlerUrl = runtime.handlerUrl(element, 'submit'); + var handlerUrl = runtime.handlerUrl(element, handler_name); if (submitXHR) { submitXHR.abort(); } - submitXHR = $.post(handlerUrl, JSON.stringify(data)).success(handleSubmitResults); + submitXHR = $.post(handlerUrl, JSON.stringify(data)).success(callback); } - function validateXBlock() { - var is_valid = true; - var data = $('.attempts', element).data(); - var steps = mentoring.steps; + function submit() { + calculate_results('submit', handleSubmitResults) + } - // if ((data.max_attempts > 0) && (data.num_attempts >= data.max_attempts)) { - // is_valid = false; - // } + function get_results() { + calculate_results('get_results', handleReviewResults) + } + + function validateXBlock(hide_nav) { + var is_valid = true; var child = mentoring.steps[active_child]; if (child && child.name !== undefined) { var child_validation = callIfExists(child, 'validate'); @@ -235,7 +327,7 @@ function MentoringAssessmentView(runtime, element, mentoring) { submitDOM.removeAttr("disabled"); } - if (isLastChild()) { + if (isLastChild() && ! hide_nav) { nextDOM.hide(); reviewDOM.show(); } diff --git a/problem_builder/public/js/mentoring_standard_view.js b/problem_builder/public/js/mentoring_standard_view.js index ac45f0c2..a70d9ec7 100644 --- a/problem_builder/public/js/mentoring_standard_view.js +++ b/problem_builder/public/js/mentoring_standard_view.js @@ -4,26 +4,26 @@ function MentoringStandardView(runtime, element, mentoring) { var callIfExists = mentoring.callIfExists; - function handleSubmitResults(results) { + function handleSubmitResults(response) { messagesDOM.empty().hide(); - $.each(results.submitResults || [], function(index, submitResult) { - var input = submitResult[0]; - var result = submitResult[1]; + $.each(response.results || [], function(index, result_spec) { + var input = result_spec[0]; + var result = result_spec[1]; var child = mentoring.getChildByName(input); var options = { - max_attempts: results.max_attempts, - num_attempts: results.num_attempts + max_attempts: response.max_attempts, + num_attempts: response.num_attempts }; callIfExists(child, 'handleSubmit', result, options); }); - $('.attempts', element).data('max_attempts', results.max_attempts); - $('.attempts', element).data('num_attempts', results.num_attempts); + $('.attempts', element).data('max_attempts', response.max_attempts); + $('.attempts', element).data('num_attempts', response.num_attempts); mentoring.renderAttempts(); // Messages should only be displayed upon hitting 'submit', not on page reload - mentoring.setContent(messagesDOM, results.message); + mentoring.setContent(messagesDOM, response.message); if (messagesDOM.html().trim()) { messagesDOM.prepend('
' + gettext('Feedback') + '
'); messagesDOM.show(); @@ -32,23 +32,30 @@ function MentoringStandardView(runtime, element, mentoring) { submitDOM.attr('disabled', 'disabled'); } - function submit() { - var success = true; + function calculate_results(handler_name) { var data = {}; var children = mentoring.children; for (var i = 0; i < children.length; i++) { var child = children[i]; - if (child && child.name !== undefined && typeof(child.submit) !== "undefined") { - data[child.name] = child.submit(); + if (child && child.name !== undefined && typeof(child[handler_name]) !== "undefined") { + data[child.name] = child[handler_name](); } } - var handlerUrl = runtime.handlerUrl(element, 'submit'); + var handlerUrl = runtime.handlerUrl(element, handler_name); if (submitXHR) { submitXHR.abort(); } submitXHR = $.post(handlerUrl, JSON.stringify(data)).success(handleSubmitResults); } + function get_results() { + calculate_results('get_results'); + } + + function submit() { + calculate_results('submit') + } + function clearResults() { messagesDOM.empty().hide(); @@ -68,6 +75,8 @@ function MentoringStandardView(runtime, element, mentoring) { submitDOM = $(element).find('.submit .input-main'); submitDOM.bind('click', submit); submitDOM.show(); + // Not used in standard mode. + $(element).find('.review-link').hide(); var options = { onChange: onChange diff --git a/problem_builder/public/js/questionnaire.js b/problem_builder/public/js/questionnaire.js index a967c5b6..f6470959 100644 --- a/problem_builder/public/js/questionnaire.js +++ b/problem_builder/public/js/questionnaire.js @@ -97,23 +97,24 @@ function MCQBlock(runtime, element) { } }, - handleSubmit: function(result) { - if (this.mode === 'assessment') - return; + handleReview: function(result){ + $('.choice input[value="' + result.submission + '"]', element).prop('checked', true); + $('.choice input', element).prop('disabled', true); + }, + handleSubmit: function(result) { mentoring = this.mentoring; var messageView = MessageView(element, mentoring); messageView.clearResult(); - var choiceInputs = $('.choice input', element); + var choiceInputs = $('.choice-selector input', element); $.each(choiceInputs, function(index, choiceInput) { var choiceInputDOM = $(choiceInput); var choiceDOM = choiceInputDOM.closest('.choice'); var choiceResultDOM = $('.choice-result', choiceDOM); var choiceTipsDOM = $('.choice-tips', choiceDOM); - var choiceTipsCloseDOM; if (result.status === "correct" && choiceInputDOM.val() === result.submission) { choiceDOM.addClass('correct'); @@ -129,7 +130,6 @@ function MCQBlock(runtime, element) { messageView.showMessage(choiceTipsDOM); } - choiceTipsCloseDOM = $('.close', choiceTipsDOM); choiceResultDOM.off('click').on('click', function() { if (choiceTipsDOM.html() !== '') { messageView.showMessage(choiceTipsDOM); @@ -178,9 +178,14 @@ function MRQBlock(runtime, element) { return checkedValues; }, + handleReview: function(result) { + $.each(result.submissions, function (index, value) { + $('input[type="checkbox"][value="' + value + '"]').prop('checked', true) + }); + $('input', element).prop('disabled', true); + }, + handleSubmit: function(result, options) { - if (this.mode === 'assessment') - return; mentoring = this.mentoring; @@ -193,14 +198,13 @@ function MRQBlock(runtime, element) { var questionnaireDOM = $('fieldset.questionnaire', element); var data = questionnaireDOM.data(); - var hide_results = (data.hide_results === 'True') ? true : false; + var hide_results = (data.hide_results === 'True'); $.each(result.choices, function(index, choice) { var choiceInputDOM = $('.choice input[value='+choice.value+']', element); var choiceDOM = choiceInputDOM.closest('.choice'); var choiceResultDOM = $('.choice-result', choiceDOM); var choiceTipsDOM = $('.choice-tips', choiceDOM); - var choiceTipsCloseDOM; /* show hint if checked or max_attempts is disabled */ if (!hide_results && @@ -215,7 +219,6 @@ function MRQBlock(runtime, element) { mentoring.setContent(choiceTipsDOM, choice.tips); - choiceTipsCloseDOM = $('.close', choiceTipsDOM); choiceResultDOM.off('click').on('click', function() { messageView.showMessage(choiceTipsDOM); }); diff --git a/problem_builder/templates/html/mentoring.html b/problem_builder/templates/html/mentoring.html index bd161943..fa8d3da5 100644 --- a/problem_builder/templates/html/mentoring.html +++ b/problem_builder/templates/html/mentoring.html @@ -26,7 +26,11 @@ data-partially_correct_answer="{{ self.score.4|length }}" data-max_attempts="{{ self.max_attempts }}" data-num_attempts="{{ self.num_attempts }}" - data-assessment_message="{{ self.assessment_message }}"> + data-extended_feedback="{%if self.extended_feedback %}True{% endif %}" + data-assessment_message="{{ self.assessment_message }}" + data-correct="{{ self.correct_json }}" + data-incorrect="{{ self.incorrect_json }}" + data-partial="{{ self.partial_json }}">

@@ -49,4 +53,5 @@ {% endif %}
+ diff --git a/problem_builder/templates/html/mentoring_grade.html b/problem_builder/templates/html/mentoring_grade.html index 3541942b..f64ffb9f 100644 --- a/problem_builder/templates/html/mentoring_grade.html +++ b/problem_builder/templates/html/mentoring_grade.html @@ -22,6 +22,7 @@

<%= runDetails('correct') %> +

@@ -35,6 +36,7 @@

<%= runDetails('partial') %>

+

@@ -48,4 +50,5 @@

<%= runDetails('incorrect') %>

+
diff --git a/problem_builder/templates/html/mentoring_review_questions.html b/problem_builder/templates/html/mentoring_review_questions.html index bcb4b6ec..91069934 100644 --- a/problem_builder/templates/html/mentoring_review_questions.html +++ b/problem_builder/templates/html/mentoring_review_questions.html @@ -2,7 +2,7 @@ <% var q, last_question; %> diff --git a/problem_builder/templates/xml/mentoring_assessment.xml b/problem_builder/templates/xml/mentoring_assessment.xml index e1786c9b..2a69fd1e 100644 --- a/problem_builder/templates/xml/mentoring_assessment.xml +++ b/problem_builder/templates/xml/mentoring_assessment.xml @@ -1,41 +1,41 @@ - +

This paragraph is shared between all questions.

Please answer the questions below.

- - + - + Yes Maybe not I don't understand - Great! - Ah, damn. -
Really?
+ Great! + Ah, damn. +
Really?
- + I don't want to rate it - I love good grades. - Will do better next time... - Your loss! + I love good grades. + Will do better next time... + Your loss! - + Its elegance Its beauty Its gracefulness Its bugs - This MRQ is indeed very graceful - This is something everyone has to like about this MRQ - Nah, there aren't any! + This MRQ is indeed very graceful + This is something everyone has to like about this MRQ + Nah, there aren't any! + Assessment additional feedback message text From 98dd06794dc5196d7907c5be264ce9a28cdd5c58 Mon Sep 17 00:00:00 2001 From: Jonathan Piacenti Date: Fri, 10 Apr 2015 21:12:13 -0500 Subject: [PATCH 08/11] Tests almost working right. --- problem_builder/mentoring.py | 3 - .../public/js/mentoring_assessment_view.js | 2 +- .../xml/assessment_extended_feedback.xml | 49 ++++++++++++ .../templates/xml/mentoring_default.xml | 24 +++--- .../tests/integration/base_test.py | 25 ++++++ .../tests/integration/test_assessment.py | 79 +++++++++++++++---- .../{test_mcq.py => test_questionnaire.py} | 33 ++------ .../xml/assessment_extended_feedback.xml | 49 ++++++++++++ ...comments_1.xml => mrq_with_comments_1.xml} | 2 +- 9 files changed, 209 insertions(+), 57 deletions(-) create mode 100644 problem_builder/templates/xml/assessment_extended_feedback.xml rename problem_builder/tests/integration/{test_mcq.py => test_questionnaire.py} (89%) create mode 100644 problem_builder/tests/integration/xml/assessment_extended_feedback.xml rename problem_builder/tests/integration/xml/{mcq_with_comments_1.xml => mrq_with_comments_1.xml} (95%) diff --git a/problem_builder/mentoring.py b/problem_builder/mentoring.py index dec6ffbf..81707643 100644 --- a/problem_builder/mentoring.py +++ b/problem_builder/mentoring.py @@ -527,8 +527,6 @@ def handle_assessment_submit(self, submissions, suffix): steps = [child for child in children if isinstance(child, StepMixin)] # Faster than the self.steps property assessment_message = None - print children - print submissions for child in children: if child.name and child.name in submissions: submission = submissions[child.name] @@ -568,7 +566,6 @@ def handle_assessment_submit(self, submissions, suffix): self.num_attempts += 1 self.completed = True - print current_child event_data['exercise_id'] = current_child.name event_data['num_attempts'] = self.num_attempts event_data['submitted_answer'] = submissions diff --git a/problem_builder/public/js/mentoring_assessment_view.js b/problem_builder/public/js/mentoring_assessment_view.js index 0a094eff..b26329f1 100644 --- a/problem_builder/public/js/mentoring_assessment_view.js +++ b/problem_builder/public/js/mentoring_assessment_view.js @@ -276,7 +276,7 @@ function MentoringAssessmentView(runtime, element, mentoring) { num_attempts: response.num_attempts }; var result = response.results[1]; - var child = mentoring.children[active_child]; + var child = mentoring.steps[active_child]; callIfExists(child, 'handleSubmit', result, options); callIfExists(child, 'handleReview', result, options); } diff --git a/problem_builder/templates/xml/assessment_extended_feedback.xml b/problem_builder/templates/xml/assessment_extended_feedback.xml new file mode 100644 index 00000000..ca1cddf4 --- /dev/null +++ b/problem_builder/templates/xml/assessment_extended_feedback.xml @@ -0,0 +1,49 @@ + + +

This paragraph is shared between all questions.

+ +

Please answer the questions below.

+
+ + + We need an XBlock with JavaScript here to test that it doesn't interfere + with the assessment, since it will show up in runtime(element).children, + but it is not a "step" element: + + + + + + + Yes + Maybe not + I don't understand + + Great! + Ah, damn. +
Really?
+
+ + + I don't want to rate it + + I love good grades. + Will do better next time... + Your loss! + + + + Its elegance + Its beauty + Its gracefulness + Its bugs + + This MRQ is indeed very graceful + This is something everyone has to like about this MRQ + Nah, there aren't any! + + + + Assessment additional feedback message text + +
diff --git a/problem_builder/templates/xml/mentoring_default.xml b/problem_builder/templates/xml/mentoring_default.xml index ce10d5b2..927677bb 100644 --- a/problem_builder/templates/xml/mentoring_default.xml +++ b/problem_builder/templates/xml/mentoring_default.xml @@ -6,32 +6,32 @@ - + Yes Maybe not I don't understand - Great! - Ah, damn. -
Really?
+ Great! + Ah, damn. +
Really?
- + I don't want to rate it - I love good grades. - Will do better next time... - Your loss! + I love good grades. + Will do better next time... + Your loss! - + Its elegance Its beauty Its gracefulness Its bugs - This MRQ is indeed very graceful - This is something everyone has to like about this MRQ - Nah, there aren't any! + This MRQ is indeed very graceful + This is something everyone has to like about this MRQ + Nah, there aren't any! diff --git a/problem_builder/tests/integration/base_test.py b/problem_builder/tests/integration/base_test.py index 4b90884f..9ed18e83 100644 --- a/problem_builder/tests/integration/base_test.py +++ b/problem_builder/tests/integration/base_test.py @@ -32,6 +32,30 @@ class MentoringBaseTest(SeleniumBaseTest): module_name = __name__ default_css_selector = 'div.mentoring' + def popup_check(self, mentoring, item_feedbacks, prefix='', do_submit=True): + + submit = mentoring.find_element_by_css_selector('.submit input.input-main') + + for index, expected_feedback in enumerate(item_feedbacks): + choice_wrapper = mentoring.find_elements_by_css_selector(prefix + " .choice")[index] + if do_submit: + # clicking on actual radio button + choice_wrapper.find_element_by_css_selector(".choice-selector input").click() + submit.click() + self.wait_until_disabled(submit) + item_feedback_icon = choice_wrapper.find_element_by_css_selector(".choice-result") + choice_wrapper.click() + item_feedback_icon.click() # clicking on item feedback icon + item_feedback_popup = choice_wrapper.find_element_by_css_selector(".choice-tips") + self.assertTrue(item_feedback_popup.is_displayed()) + self.assertEqual(item_feedback_popup.text, expected_feedback) + + item_feedback_popup.click() + self.assertTrue(item_feedback_popup.is_displayed()) + + mentoring.click() + self.assertFalse(item_feedback_popup.is_displayed()) + class MentoringAssessmentBaseTest(MentoringBaseTest): @staticmethod @@ -54,6 +78,7 @@ class Namespace(object): controls.next_question = mentoring.find_element_by_css_selector("input.input-next") controls.review = mentoring.find_element_by_css_selector("input.input-review") controls.try_again = mentoring.find_element_by_css_selector("input.input-try-again") + controls.review_link = mentoring.find_element_by_css_selector(".review-link a") return mentoring, controls diff --git a/problem_builder/tests/integration/test_assessment.py b/problem_builder/tests/integration/test_assessment.py index 3a860e41..1948359c 100644 --- a/problem_builder/tests/integration/test_assessment.py +++ b/problem_builder/tests/integration/test_assessment.py @@ -17,11 +17,13 @@ # along with this program in a file in the toplevel directory called # "AGPLv3". If not, see . # +from ddt import ddt, unpack, data from .base_test import MentoringAssessmentBaseTest, GetChoices CORRECT, INCORRECT, PARTIAL = "correct", "incorrect", "partially-correct" +@ddt class MentoringAssessmentTest(MentoringAssessmentBaseTest): def _selenium_bug_workaround_scroll_to(self, mentoring, question): """Workaround for selenium bug: @@ -190,19 +192,29 @@ def rating_question(self, number, mentoring, controls, choice_name, result, last self._assert_checkmark(mentoring, result) self.do_post(controls, last) - def peek_at_multiple_choice_question(self, number, mentoring, controls, last=False): + def peek_at_multiple_response_question( + self, number, mentoring, controls, last=False, extended_feedback=False, alternative_review=False + ): question = self.expect_question_visible(number, mentoring) self.assert_persistent_elements_present(mentoring) self._selenium_bug_workaround_scroll_to(mentoring, question) self.assertIn("What do you like in this MRQ?", mentoring.text) - self.assert_disabled(controls.submit) - self.ending_controls(controls, last) + if extended_feedback: + self.assert_disabled(controls.submit) + if alternative_review: + self.assert_clickable(controls.review_link) + self.assert_hidden(controls.try_again) + else: + self.assert_clickable(controls.review) + else: + self.assert_disabled(controls.submit) + self.ending_controls(controls, last) return question - def multiple_choice_question(self, number, mentoring, controls, choice_names, result, last=False): - question = self.peek_at_multiple_choice_question(number, mentoring, controls, last=last) + def multiple_response_question(self, number, mentoring, controls, choice_names, result, last=False): + question = self.peek_at_multiple_response_question(number, mentoring, controls, last=last) choices = GetChoices(question) expected_choices = { @@ -227,11 +239,17 @@ def multiple_choice_question(self, number, mentoring, controls, choice_names, re self._assert_checkmark(mentoring, result) controls.review.click() - def peek_at_review(self, mentoring, controls, expected): + def peek_at_review(self, mentoring, controls, expected, extended_feedback=False): self.wait_until_text_in("You scored {percentage}% on this assessment.".format(**expected), mentoring) self.assert_persistent_elements_present(mentoring) if expected["num_attempts"] < expected["max_attempts"]: self.assertIn("Note: if you retake this assessment, only your final score counts.", mentoring.text) + self.assertFalse(mentoring.find_elements_by_css_selector('.review-list')) + elif extended_feedback: + for q_type in ['correct', 'incorrect', 'partial']: + self.assertEqual(len(mentoring.find_elements_by_css_selector('.%s-list li' % q_type)), expected[q_type]) + else: + self.assertFalse(mentoring.find_elements_by_css_selector('.review-list')) if expected["correct"] == 1: self.assertIn("You answered 1 questions correctly.".format(**expected), mentoring.text) else: @@ -255,6 +273,7 @@ def peek_at_review(self, mentoring, controls, expected): self.assert_hidden(controls.submit) self.assert_hidden(controls.next_question) self.assert_hidden(controls.review) + self.assert_hidden(controls.review_link) def assert_messages_text(self, mentoring, text): messages = mentoring.find_element_by_css_selector('.assessment-messages') @@ -267,25 +286,55 @@ def assert_messages_empty(self, mentoring): self.assertFalse(messages.find_elements_by_xpath('./*')) self.assertFalse(messages.is_displayed()) - def test_assessment(self): - mentoring, controls = self.go_to_assessment("Assessment 1") + def extended_feedback_checks(self, mentoring, controls, expected_results): + # Multiple choice is third correctly answered question + self.assert_hidden(controls.review_link) + mentoring.find_elements_by_css_selector('.correct-list li a')[2].click() + self.peek_at_multiple_response_question(4, mentoring, controls, extended_feedback=True, alternative_review=True) + # Four correct items, plus the overall correct indicator. + correct_marks = mentoring.find_elements_by_css_selector('.checkmark-correct') + incorrect_marks = mentoring.find_elements_by_css_selector('.checkmark-incorrect') + self.assertEqual(len(correct_marks), 5) + self.assertEqual(len(incorrect_marks), 0) + item_feedbacks = [ + "This is something everyone has to like about this MRQ", + "This is something everyone has to like about this MRQ", + "This MRQ is indeed very graceful", + "Nah, there aren't any!" + ] + self.popup_check(mentoring, item_feedbacks, prefix='div[data-name="mrq_1_1"]', do_submit=False) + self.assert_hidden(controls.review) + self.assert_disabled(controls.submit) + controls.review_link.click() + self.peek_at_review(mentoring, controls, expected_results, extended_feedback=True) + # Rating question, right before MRQ. + mentoring.find_elements_by_css_selector('.incorrect-list li a')[0].click() + # Should be possible to visit the MRQ from there. + self.wait_until_clickable(controls.next_question) + controls.next_question.click() + self.peek_at_multiple_response_question(4, mentoring, controls, extended_feedback=True, alternative_review=True) + + @data((1, False), ('Extended Feedback', True)) + @unpack + def test_assessment(self, assessment, extended_feedback): + mentoring, controls = self.go_to_assessment("Assessment %s" % assessment) self.freeform_answer(1, mentoring, controls, 'This is the answer', CORRECT) self.single_choice_question(2, mentoring, controls, 'Maybe not', INCORRECT) self.rating_question(3, mentoring, controls, "5 - Extremely good", CORRECT) - self.peek_at_multiple_choice_question(4, mentoring, controls, last=True) + self.peek_at_multiple_response_question(4, mentoring, controls, last=True) # see if assessment remembers the current step self.go_to_workbench_main_page() - mentoring, controls = self.go_to_assessment("Assessment 1") + mentoring, controls = self.go_to_assessment("Assessment %s" % assessment) - self.multiple_choice_question(4, mentoring, controls, ("Its beauty",), PARTIAL, last=True) + self.multiple_response_question(4, mentoring, controls, ("Its beauty",), PARTIAL, last=True) expected_results = { "correct": 2, "partial": 1, "incorrect": 1, "percentage": 63, "num_attempts": 1, "max_attempts": 2 } - self.peek_at_review(mentoring, controls, expected_results) + self.peek_at_review(mentoring, controls, expected_results, extended_feedback=extended_feedback) self.assert_messages_text(mentoring, "Assessment additional feedback message text") self.assert_clickable(controls.try_again) @@ -298,15 +347,17 @@ def test_assessment(self): self.rating_question(3, mentoring, controls, "1 - Not good at all", INCORRECT) user_selection = ("Its elegance", "Its beauty", "Its gracefulness") - self.multiple_choice_question(4, mentoring, controls, user_selection, CORRECT, last=True) + self.multiple_response_question(4, mentoring, controls, user_selection, CORRECT, last=True) expected_results = { "correct": 3, "partial": 0, "incorrect": 1, "percentage": 75, "num_attempts": 2, "max_attempts": 2 } - self.peek_at_review(mentoring, controls, expected_results) + self.peek_at_review(mentoring, controls, expected_results, extended_feedback=extended_feedback) self.assert_disabled(controls.try_again) self.assert_messages_empty(mentoring) + if extended_feedback: + self.extended_feedback_checks(mentoring, controls, expected_results) def test_single_question_assessment(self): """ diff --git a/problem_builder/tests/integration/test_mcq.py b/problem_builder/tests/integration/test_questionnaire.py similarity index 89% rename from problem_builder/tests/integration/test_mcq.py rename to problem_builder/tests/integration/test_questionnaire.py index dce589b4..adf2f494 100644 --- a/problem_builder/tests/integration/test_mcq.py +++ b/problem_builder/tests/integration/test_questionnaire.py @@ -31,7 +31,7 @@ @ddt.ddt -class MCQBlockTest(MentoringBaseTest): +class QuestionnaireBlockTest(MentoringBaseTest): def _selenium_bug_workaround_scroll_to(self, mcq_legend): """Workaround for selenium bug: @@ -159,8 +159,8 @@ def test_mcq_choices_rating(self): self.assertFalse(mcq1_tips.is_displayed()) self.assertFalse(mcq2_tips.is_displayed()) - def test_mcq_with_comments(self): - mentoring = self.go_to_page('Mcq With Comments 1') + def test_mrq_with_comments(self): + mentoring = self.go_to_page('Mrq With Comments 1') mcq = mentoring.find_element_by_css_selector('fieldset.choices') messages = mentoring.find_element_by_css_selector('.messages') submit = mentoring.find_element_by_css_selector('.submit input.input-main') @@ -186,9 +186,8 @@ def test_mcq_with_comments(self): self.assertEqual(mcq_choices_input[2].get_attribute('value'), 'gracefulness') self.assertEqual(mcq_choices_input[3].get_attribute('value'), 'bugs') - def test_mcq_feedback_popups(self): - mentoring = self.go_to_page('Mcq With Comments 1') - choices_list = mentoring.find_element_by_css_selector(".choices-list") + def test_mrq_feedback_popups(self): + mentoring = self.go_to_page('Mrq With Comments 1') item_feedbacks = [ "This is something everyone has to like about this MRQ", @@ -196,25 +195,7 @@ def test_mcq_feedback_popups(self): "This MRQ is indeed very graceful", "Nah, there aren\\'t any!" ] - submit = mentoring.find_element_by_css_selector('.submit input.input-main') - - for index, expected_feedback in enumerate(item_feedbacks): - choice_wrapper = choices_list.find_elements_by_css_selector(".choice")[index] - choice_wrapper.find_element_by_css_selector(".choice-selector input").click() # click actual radio button - submit.click() - self.wait_until_disabled(submit) - item_feedback_icon = choice_wrapper.find_element_by_css_selector(".choice-result") - choice_wrapper.click() - item_feedback_icon.click() # clicking on item feedback icon - item_feedback_popup = choice_wrapper.find_element_by_css_selector(".choice-tips") - self.assertTrue(item_feedback_popup.is_displayed()) - self.assertEqual(item_feedback_popup.text, expected_feedback) - - item_feedback_popup.click() - self.assertTrue(item_feedback_popup.is_displayed()) - - mentoring.click() - self.assertFalse(item_feedback_popup.is_displayed()) + self.popup_check(mentoring, item_feedbacks, prefix='div[data-name="mrq_1_1_7"]') def _get_questionnaire_options(self, questionnaire): result = [] @@ -299,7 +280,7 @@ def test_tip_height(self, choice_value, expected_height): @patch.object(MentoringBlock, 'get_theme', Mock(return_value={'package': 'problem_builder', 'locations': ['public/themes/lms.css']})) -class MCQBlockAprosThemeTest(MCQBlockTest): +class QuestionnaireBlockAprosThemeTest(QuestionnaireBlockTest): """ Test MRQ/MCQ questions without the LMS theme which is on by default. """ diff --git a/problem_builder/tests/integration/xml/assessment_extended_feedback.xml b/problem_builder/tests/integration/xml/assessment_extended_feedback.xml new file mode 100644 index 00000000..ca1cddf4 --- /dev/null +++ b/problem_builder/tests/integration/xml/assessment_extended_feedback.xml @@ -0,0 +1,49 @@ + + +

This paragraph is shared between all questions.

+ +

Please answer the questions below.

+
+ + + We need an XBlock with JavaScript here to test that it doesn't interfere + with the assessment, since it will show up in runtime(element).children, + but it is not a "step" element: + + + + + + + Yes + Maybe not + I don't understand + + Great! + Ah, damn. +
Really?
+
+ + + I don't want to rate it + + I love good grades. + Will do better next time... + Your loss! + + + + Its elegance + Its beauty + Its gracefulness + Its bugs + + This MRQ is indeed very graceful + This is something everyone has to like about this MRQ + Nah, there aren't any! + + + + Assessment additional feedback message text + +
diff --git a/problem_builder/tests/integration/xml/mcq_with_comments_1.xml b/problem_builder/tests/integration/xml/mrq_with_comments_1.xml similarity index 95% rename from problem_builder/tests/integration/xml/mcq_with_comments_1.xml rename to problem_builder/tests/integration/xml/mrq_with_comments_1.xml index 551df89d..2f4d980c 100644 --- a/problem_builder/tests/integration/xml/mcq_with_comments_1.xml +++ b/problem_builder/tests/integration/xml/mrq_with_comments_1.xml @@ -1,5 +1,5 @@ - + Its elegance Its beauty From c972cc8d35a7b0555906d2b6d7753ced13647ae4 Mon Sep 17 00:00:00 2001 From: Braden MacDonald Date: Mon, 13 Apr 2015 13:40:22 -0700 Subject: [PATCH 09/11] Fix flaky dashboard test --- problem_builder/questionnaire.py | 10 +++++----- problem_builder/tests/integration/test_dashboard.py | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/problem_builder/questionnaire.py b/problem_builder/questionnaire.py index b2a352fd..d57e3e41 100644 --- a/problem_builder/questionnaire.py +++ b/problem_builder/questionnaire.py @@ -21,10 +21,10 @@ # Imports ########################################################### from django.utils.safestring import mark_safe -import logging -from lxml import etree +from lazy import lazy +import uuid from xblock.core import XBlock -from xblock.fields import Scope, String, Float, List, UNIQUE_ID +from xblock.fields import Scope, String, Float, UNIQUE_ID from xblock.fragment import Fragment from xblock.validation import ValidationMessage from xblockutils.helpers import child_isinstance @@ -90,14 +90,14 @@ def _(self, text): """ translate text """ return self.runtime.service(self, "i18n").ugettext(text) - @property + @lazy def html_id(self): """ A short, simple ID string used to uniquely identify this question. This is only used by templates for matching and