def call_handler(client, block_key, handler_name, method, data=None): """ Call an XBlock handler """ url_result = client.get( URL_BLOCK_GET_HANDLER_URL.format(block_key=block_key, handler_name=handler_name)) url = url_result.data["handler_url"] data_json = json.dumps(data) if data else None response = getattr(client, method)(url, data_json, content_type="application/json") self.assertEqual(response.status_code, 200) return response.json()
def test_mark_complete_via_handler(self): """ Test that a "complete on view" XBlock like the HTML block can be marked as complete using the LmsBlockMixin.publish_completion handler. """ block_id = library_api.create_library_block( self.library.key, "html", "completable_html").usage_key new_olx = """ <html display_name="Read this HTML"> <![CDATA[ <p>This is some <strong>HTML</strong>.</p> ]]> </html> """.strip() library_api.set_library_block_olx(block_id, new_olx) library_api.publish_changes(self.library.key) # We should get a REST API for retrieving completion data; for now use python def get_block_completion_status(): """ Get block completion status (0 to 1) """ block = xblock_api.load_block(block_id, self.student_a) assert hasattr(block, 'publish_completion') service = block.runtime.service(block, 'completion') return service.get_completions([block_id])[block_id] # At first the block is not completed assert get_block_completion_status() == 0 # Now call the 'publish_completion' handler: client = APIClient() client.login(username=self.student_a.username, password='******') result = client.get( URL_BLOCK_GET_HANDLER_URL.format( block_key=block_id, handler_name='publish_completion')) publish_completion_url = result.data["handler_url"] # This will test the 'completion' service and the completion event handler: result2 = client.post(publish_completion_url, {"completion": 1.0}, format='json') assert result2.status_code == 200 # Now the block is completed assert get_block_completion_status() == 1
def test_scores_persisted(self): """ Test that a block's emitted scores are cached in StudentModule In the future if there is a REST API to retrieve individual block's scores, that should be used instead of checking StudentModule directly. """ block_id = library_api.create_library_block(self.library.key, "problem", "scored_problem").usage_key new_olx = """ <problem display_name="New Multi Choice Question" max_attempts="5"> <multiplechoiceresponse> <p>This is a normal capa problem. It has "maximum attempts" set to **5**.</p> <label>Blockstore is designed to store.</label> <choicegroup type="MultipleChoice"> <choice correct="false">XBlock metadata only</choice> <choice correct="true">XBlock data/metadata and associated static asset files</choice> <choice correct="false">Static asset files for XBlocks and courseware</choice> <choice correct="false">XModule metadata only</choice> </choicegroup> </multiplechoiceresponse> </problem> """.strip() library_api.set_library_block_olx(block_id, new_olx) library_api.publish_changes(self.library.key) # Now view the problem as Alice: client = APIClient() client.login(username=self.student_a.username, password='******') student_view_result = client.get(URL_BLOCK_RENDER_VIEW.format(block_key=block_id, view_name='student_view')) problem_key = "input_{}_2_1".format(block_id) assert problem_key in student_view_result.data['content'] # And submit a wrong answer: result = client.get(URL_BLOCK_GET_HANDLER_URL.format(block_key=block_id, handler_name='xmodule_handler')) problem_check_url = result.data["handler_url"] + 'problem_check' submit_result = client.post(problem_check_url, data={problem_key: "choice_3"}) assert submit_result.status_code == 200 submit_data = json.loads(submit_result.content.decode('utf-8')) self.assertDictContainsSubset({ "current_score": 0, "total_possible": 1, "attempts_used": 1, }, submit_data) # Now test that the score is also persisted in StudentModule: # If we add a REST API to get an individual block's score, that should be checked instead of StudentModule. sm = get_score(self.student_a, block_id) assert sm.grade == 0 assert sm.max_grade == 1 # And submit a correct answer: submit_result = client.post(problem_check_url, data={problem_key: "choice_1"}) assert submit_result.status_code == 200 submit_data = json.loads(submit_result.content.decode('utf-8')) self.assertDictContainsSubset({ "current_score": 1, "total_possible": 1, "attempts_used": 2, }, submit_data) # Now test that the score is also updated in StudentModule: # If we add a REST API to get an individual block's score, that should be checked instead of StudentModule. sm = get_score(self.student_a, block_id) assert sm.grade == 1 assert sm.max_grade == 1