def test_xblockcompletion_get_resumen(self): """ test to generate course survey report and then test the report authenticity. """ from lms.djangoapps.courseware.models import StudentModule data = {'format': True, 'course': str(self.course.id), 'base_url':'this_is_a_url'} task_input = {'data': data } module = StudentModule( module_state_key=self.items[0].location, student=self.student, course_id=self.course.id, module_type='problem', state='{"score": {"raw_earned": 0, "raw_possible": 3}, "seed": 1, "attempts":1}') module.save() with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'): result = generate( None, None, self.course.id, task_input, 'EOL_Xblock_Completion' ) report_store = ReportStore.from_config(config_name='GRADES_DOWNLOAD') header_row = ",".join(['Titulo', 'Username', 'Email', 'Run', 'Seccion', 'SubSeccion', 'Unidad', 'Intentos', 'Pts Ganados', 'Pts Posibles', 'Url', 'block_id']) student1_row = ",".join([ self.items[0].display_name, self.student.username, self.student.email, '', '1.' + self.chapter.display_name, '1.1.' + self.section.display_name, '1.1.1.' + self.subsection.display_name, '1','0','3' ]) expected_data = [header_row, student1_row] self._verify_csv_file_report(report_store, expected_data)
def test_student_user_view_with_false_past_due_form_completed( self, get, post): """ Test student view when section is finished """ from lms.djangoapps.courseware.models import StudentModule get.side_effect = [namedtuple("Request", ["status_code", "text"])( 200, json.dumps({"session": {"api_token": "test_token"}}))] post.side_effect = [ namedtuple( "Request", [ "status_code", "headers"])( 200, { 'Set-Cookie': 'Domain=quilgo.com; Path=/, connect.sid=test;'}), namedtuple( "Request", [ "status_code", "text"])( 200, json.dumps( { "links": [ { "id": 1, "hash": "testhash", "label": "test"}]}))] self.xblock.xmodule_runtime.user_is_staff = False self.xblock.scope_ids.user_id = self.student.id module = StudentModule( module_state_key=self.xblock.location, student_id=self.student.id, course_id=self.course.id, state='{"id_link": "1", "score": "2", "link": "testhash", "name_link": "test", "id_form": "11223344", "expired": "2020-05-11T15:37:55.000Z"}') module.save() with mock.patch('eoltimify.eoltimify.EolTimifyXBlock.is_past_due', return_value=True): response = self.xblock.student_view() self.assertTrue('id="expired"' in response.content) self.assertTrue('<label>Puntaje: 2</label>' in response.content)
def test_student_user_view_get_1_400(self, get, post): """ Test student view when get api-key fail """ from lms.djangoapps.courseware.models import StudentModule get.side_effect = [namedtuple("Request", ["status_code", "text", "content"])( 400, json.dumps({"session": {"api_token": "test_token"}}), 'error')] post.side_effect = [ namedtuple( "Request", [ "status_code", "headers"])( 200, { 'Set-Cookie': 'Domain=quilgo.com; Path=/, connect.sid=test;'}), namedtuple( "Request", [ "status_code", "text"])( 200, json.dumps( { "links": [ { "id": 1, "hash": "testhash", "label": "test"}]}))] self.xblock.idform = "11223344" self.xblock.xmodule_runtime.user_is_staff = False self.xblock.scope_ids.user_id = self.student.id module = StudentModule( module_state_key=self.xblock.location, student_id=self.student.id, course_id=self.course.id, state='{}') module.save() response = self.xblock.student_view() self.assertTrue('Sin Datos' in response.content)
def make_student(self, block, name, make_state=True, **state): """ Create a student along with submission state. """ answer = {} module = None for key in ('sha1', 'mimetype', 'filename', 'finalized'): if key in state: answer[key] = state.pop(key) score = state.pop('score', None) with transaction.atomic(): user = User(username=name, email='{}@example.com'.format(name)) user.save() profile = UserProfile(user=user, name=name) profile.save() if make_state: module = StudentModule(module_state_key=block.location, student=user, course_id=self.course_id, state=json.dumps(state)) module.save() anonymous_id = anonymous_id_for_user(user, self.course_id) item = StudentItem(student_id=anonymous_id, course_id=self.course_id, item_id=block.block_id, item_type='sga') item.save() if answer: student_id = block.get_student_item_dict(anonymous_id) submission = submissions_api.create_submission( student_id, answer) if score is not None: submissions_api.set_score(submission['uuid'], score, block.max_score()) else: submission = None self.addCleanup(item.delete) self.addCleanup(profile.delete) self.addCleanup(user.delete) if make_state: self.addCleanup(module.delete) return { 'module': module, 'item': item, 'submission': submission } return {'item': item, 'submission': submission}
def test_xblockcompletion_get_all_data(self, report): """ Test xblockcompletion view all data """ state_1 = {_("Answer ID"): 'answer_id', _("Question"): 'question_text', _("Answer"): 'answer_text', _("Correct Answer") : 'correct_answer_text' } state_2 = {_("Answer ID"): 'answer_id', _("Question"): 'question_text', _("Answer"): 'correct_answer_text', _("Correct Answer") : 'correct_answer_text' } generated_report_data = {self.student.username : [state_1,state_2,state_1]} report.return_value = generated_report_data from lms.djangoapps.courseware.models import StudentModule data = {'format': False, 'course': str(self.course.id), 'base_url':'this_is_a_url'} task_input = {'data': data } module = StudentModule( module_state_key=self.items[0].location, student=self.student, course_id=self.course.id, module_type='problem', state='{"score": {"raw_earned": 1, "raw_possible": 3}, "seed": 1, "attempts": 1}') module.save() with patch('lms.djangoapps.instructor_task.tasks_helper.runner._get_current_task'): result = generate( None, None, self.course.id, task_input, 'EOL_Xblock_Completion' ) report_store = ReportStore.from_config(config_name='GRADES_DOWNLOAD') header_row = ",".join(['Titulo', 'Username', 'Email', 'Run', 'Seccion', 'SubSeccion', 'Unidad', 'Pregunta', 'Respuesta Estudiante', 'Resp. Correcta', 'Intentos', 'Pts Ganados', 'Pts Posibles', 'Pts Total Componente', 'Url', 'block_id']) base_student_row = ",".join([ self.items[0].display_name, self.student.username, self.student.email, '', '1.' + self.chapter.display_name, '1.1.' + self.section.display_name, '1.1.1.' + self.subsection.display_name ]) student_row = base_student_row + ',question_text,answer_text,correct_answer_text,1,0,1.0,3' student_row2 = base_student_row + ',question_text,correct_answer_text,correct_answer_text,1,1.0,1.0,3' expected_data = [header_row, student_row, student_row2, student_row] self._verify_csv_file_report(report_store, expected_data)
def test_student_user_view_no_setting(self): """ Verify student view if the xblock dont have user/password in settings """ from lms.djangoapps.courseware.models import StudentModule self.xblock.idform = "11223344" self.xblock.xmodule_runtime.user_is_staff = False self.xblock.scope_ids.user_id = self.student.id module = StudentModule( module_state_key=self.xblock.location, student_id=self.student.id, course_id=self.course.id, state='{}') module.save() response = self.xblock.student_view() self.assertTrue('Sin Datos' in response.content)
def test_student_user_view_with_different_id_form(self, get, post): """ Test student view when student already have student_module and if form is different """ from lms.djangoapps.courseware.models import StudentModule get.side_effect = [namedtuple("Request", ["status_code", "text"])(200, json.dumps({"session": {"api_token": "test_token"}})), namedtuple("Request", ["status_code", "text"])(200, json.dumps({"links": [{"id": 1, "hash": "testhash", "label": "test", "finishedAt": None}]}))] post.side_effect = [ namedtuple( "Request", [ "status_code", "headers"])( 200, { 'Set-Cookie': 'Domain=quilgo.com; Path=/, connect.sid=test;'}), namedtuple( "Request", [ "status_code", "text"])( 200, json.dumps( { "links": [ { "id": 1, "hash": "testhash", "label": "test"}]}))] self.xblock.idform = "55667788" self.xblock.xmodule_runtime.user_is_staff = False self.xblock.scope_ids.user_id = self.student.id module = StudentModule( module_state_key=self.xblock.location, student_id=self.student.id, course_id=self.course.id, state='{"id_link": "1", "score": "Sin Registros", "link": "testhash", "name_link": "test", "id_form": "11223344", "expired": null}') module.save() response = self.xblock.student_view() self.assertTrue( 'href=https://quilgo.com/link/testhash ' in response.content)
def _get_modules_to_update(course_id, usage_keys, student_identifier, filter_fcn, override_score_task=False): """ Fetches a StudentModule instances for a given `course_id`, `student` object, and `usage_keys`. StudentModule instances are those that match the specified `course_id` and `module_state_key`. If `student_identifier` is not None, it is used as an additional filter to limit the modules to those belonging to that student. If `student_identifier` is None, performs update on modules for all students on the specified problem. The matched instances are then applied `filter_fcn` if not None. It filters out the matched instances. It takes one argument, which is the query being filtered, and returns the filtered version of the query. If `override_score_task` is True and we there were not matching instances of StudentModule, try to create those instances. This is only for override scores and the use case is for learners that have missed the deadline. Arguments: course_id(str): The unique identifier for the course. usage_keys(list): List of UsageKey objects student_identifier(str): Identifier for a student or None. The identifier can be either username or email filter_fcn: If it is not None, it is applied to the query that has been constructed. override_score_task (bool): Optional argument which indicates if it is an override score or not. """ def get_student(): """ Fetches student instance if an identifier is provided, else return None """ return None if not student_identifier else get_user_by_username_or_email( student_identifier) module_query_params = { 'course_id': course_id, 'module_state_keys': usage_keys } # give the option of updating an individual student. If not specified, # then updates all students who have responded to a problem so far student = get_student() if student: module_query_params['student_id'] = student.id student_modules = StudentModule.get_state_by_params(**module_query_params) if filter_fcn is not None: student_modules = filter_fcn(student_modules) can_create_student_modules = (override_score_task and (student_modules.count() == 0) and student is not None) if can_create_student_modules: student_modules = [ StudentModule.objects.get_or_create(course_id=course_id, student=student, module_state_key=key)[0] for key in usage_keys ] return student_modules
def test_student_user_view(self, get, post): """ Test student view normal process """ from lms.djangoapps.courseware.models import StudentModule get.side_effect = [namedtuple("Request", ["status_code", "text"])( 200, json.dumps({"session": {"api_token": "test_token"}}))] post.side_effect = [ namedtuple( "Request", [ "status_code", "headers"])( 200, { 'Set-Cookie': 'Domain=quilgo.com; Path=/, connect.sid=test;'}), namedtuple( "Request", [ "status_code", "text"])( 200, json.dumps( { "links": [ { "id": 1, "hash": "testhash", "label": "test"}]}))] self.xblock.idform = "11223344" self.xblock.xmodule_runtime.user_is_staff = False self.xblock.scope_ids.user_id = self.student.id module = StudentModule( module_state_key=self.xblock.location, student_id=self.student.id, course_id=self.course.id, state='{}') module.save() response = self.xblock.student_view() state = StudentModule.objects.get(pk=module.id) self.assertEqual( json.loads(state.state), json.loads('{"name_link": "test", "id_link": "1", "score": "Sin Registros", "link": "testhash", "id_form": "11223344", "expired": null}')) self.assertTrue( 'href=https://quilgo.com/link/testhash ' in response.content)
def generate_dummy_submission(student, block, course_key): """ Generates a random answers for a specified user and block The currently supported blocks are poll and survey """ location = block.location answer = {} if block.category == 'poll': # Possible answers come in this format: # ('G', {'img': None, 'img_alt': None, 'label': 'Green'}) # and we only need the 'G' bit for saving the answer possible_answers = [answer for answer, _ in block.answers] # Answer format for StudentModule model: # {"submissions_count": 1, "choice": "R"} choice = random.choice(possible_answers) answer = { "submissions_count": 1, "choice": choice, } elif block.category == 'survey': # Questions come in this format: # ('enjoy', {'img': None, 'img_alt': None, 'label': 'Are you enjoying the course?'}) # and we only need the 'enjoy' part questions = [question for question, _ in block.questions] # This happens similarly with answers possible_answers = [answer for answer, _ in block.answers] # Answer format for StudentModule model: # {"submissions_count": 1, "choices": {"enjoy": "Y", "learn": "Y", "recommend": "N"}} choices = { key: random.choice(possible_answers) for key in questions } answer = { "submissions_count": 1, "choices": choices, } return StudentModule( module_type='problem', module_state_key=location, student=student, course_id=course_key, state=json.dumps(answer), )
def create_course_reference_data(course): """ Populates DB with test data """ course_key = course.id user = UserFactory() group = GroupFactory() CourseGroupRelationship(course_id=course_key, group=group).save() StudentGradebook( user=user, course_id=course_key, grade=0.9, proforma_grade=0.91, progress_summary='test', grade_summary='test', grading_policy='test', ).save() CourseEnrollment.get_or_create_enrollment(user, course_key) CourseAccessRole(user=user, course_id=course_key, org='test', role='TA').save() handouts_usage_key = course_key.make_usage_key('course_info', 'handouts') StudentModule(student=user, course_id=course_key, module_state_key=handouts_usage_key).save() CourseAggregatedMetaData(id=course_key, total_assessments=10, total_modules=20).save() structure_json = '{"test": true}' course_structure, created = CourseStructure.objects.get_or_create( course_id=course_key, defaults={'structure_json': structure_json}) if not created: course_structure.structure_json = structure_json course_structure.save() CourseOverview.get_from_id(course_key)
def transform_block_filters(self, usage_info, block_structure): all_library_children = set() all_selected_children = set() for block_key in block_structure: if block_key.block_type != 'library_content': continue library_children = block_structure.get_children(block_key) if library_children: all_library_children.update(library_children) selected = [] mode = block_structure.get_xblock_field(block_key, 'mode') max_count = block_structure.get_xblock_field( block_key, 'max_count') # Retrieve "selected" json from LMS MySQL database. state_dict = get_student_module_as_dict( usage_info.user, usage_info.course_key, block_key) for selected_block in state_dict.get('selected', []): # Add all selected entries for this user for this # library module to the selected list. block_type, block_id = selected_block usage_key = usage_info.course_key.make_usage_key( block_type, block_id) if usage_key in library_children: selected.append(selected_block) # Update selected previous_count = len(selected) block_keys = LibraryContentModule.make_selection( selected, library_children, max_count, mode) selected = block_keys['selected'] # Save back any changes if any(block_keys[changed] for changed in ('invalid', 'overlimit', 'added')): state_dict['selected'] = list(selected) StudentModule.save_state( student=usage_info.user, course_id=usage_info.course_key, module_state_key=block_key, defaults={ 'state': json.dumps(state_dict), }, ) # publish events for analytics self._publish_events( block_structure, block_key, previous_count, max_count, block_keys, usage_info.user.id, ) all_selected_children.update( usage_info.course_key.make_usage_key(s[0], s[1]) for s in selected) def check_child_removal(block_key): """ Return True if selected block should be removed. Block is removed if it is part of library_content, but has not been selected for current user. """ if block_key not in all_library_children: return False if block_key in all_selected_children: return False return True return [block_structure.create_removal_filter(check_child_removal)]
def test_staff_user_view_with_datetime_late(self, get, post): """ Test staff view when finished datetime section is already finished """ from lms.djangoapps.courseware.models import StudentModule request = TestRequest() request.method = 'POST' get.side_effect = [namedtuple("Request", ["status_code", "text"])(200, json.dumps({"session": {"api_token": "test_token"}})), namedtuple("Request", ["status_code", "text"])(200, json.dumps({"links": [{"id": 1, "score": "1", "finishedAt": "2020-05-11T15:37:55.000Z"}, {"id": 2, "score": None, "finishedAt": None}]}))] post.side_effect = [ namedtuple( "Request", [ "status_code", "headers"])( 200, { 'Set-Cookie': 'Domain=quilgo.com; Path=/, connect.sid=test;'}), namedtuple( "Request", [ "status_code", "text"])( 200, json.dumps( { "links": [ { "id": 1, "hash": "testhash", "label": "test"}]}))] self.xblock.idform = "11223344" self.xblock.xmodule_runtime.user_is_staff = True self.xblock.scope_ids.user_id = self.staff_user.id data = b'{}' request.body = data module = StudentModule( module_state_key=self.xblock.location, student_id=self.student.id, course_id=self.course.id, state='{"id_link": "1", "score": "Sin Registros", "link": "testhash", "name_link": "test", "id_form": "11223344", "expired": "2020-05-11T15:37:55.000Z"}') module.save() module2 = StudentModule( module_state_key=self.xblock.location, student_id=self.staff_user.id, course_id=self.course.id, state='{"id_link": "2", "score": "Sin Registros", "link": "testhash", "name_link": "test", "id_form": "11223344", "expired": null}') module2.save() from dateutil.parser import parse with mock.patch('eoltimify.eoltimify.EolTimifyXBlock.expired_date', return_value=parse("2020-05-11T15:36:55.000Z")): response = self.xblock.show_score(request) data = json.loads(response._app_iter[0].decode()) list_student = [[self.staff_user.id, 'staff_user', '*****@*****.**', 'test', 'Sin Registros', 'Sin Registros'], [self.student.id, 'student', '*****@*****.**', 'test', '1', 'Si']] self.assertEqual(data["list_student"], list_student) self.assertEqual(data["result"], "success")