def see_a_single_step_component(step): for step_hash in step.hashes: component = step_hash['Component'] assert_in(component, ['Discussion', 'Video']) component_css = '.xmodule_{}Module'.format(component) assert_true(world.is_css_present(component_css), "{} couldn't be found".format(component))
def find_student_profile_table(step): # pylint: disable=unused-argument # Find the grading configuration display world.wait_for_visible('#data-student-profiles-table') # Wait for the data table to be populated world.wait_for(lambda _: world.css_text('#data-student-profiles-table') not in [u'', u'Loading']) if world.role == 'instructor': expected_data = [ world.instructor.username, world.instructor.email, world.instructor.profile.name, world.instructor.profile.gender, world.instructor.profile.goals ] elif world.role == 'staff': expected_data = [ world.staff.username, world.staff.email, world.staff.profile.name, world.staff.profile.gender, world.staff.profile.goals ] for datum in expected_data: assert_in(datum, world.css_text('#data-student-profiles-table'))
def see_a_single_step_component(step): for step_hash in step.hashes: component = step_hash['Component'] assert_in(component, ['Discussion', 'Video']) component_css = '.xmodule_{}Module'.format(component) assert_true(world.is_css_present(component_css), u"{} couldn't be found".format(component))
def see_a_multi_step_component(step, category): # Wait for all components to finish rendering if category == 'HTML': selector = 'li.studio-xblock-wrapper div.xblock-student_view' else: selector = 'li.studio-xblock-wrapper div.xblock-author_view' world.wait_for(lambda _: len(world.css_find(selector)) == len(step.hashes)) for idx, step_hash in enumerate(step.hashes): if category == 'HTML': html_matcher = { 'Text': '\n \n', 'Announcement': '<h3 class="hd hd-2">Announcement Date</h3>', 'Zooming Image Tool': '<h3 class="hd hd-2">Zooming Image Tool</h3>', 'E-text Written in LaTeX': '<h3 class="hd hd-2">Example: E-text page</h3>', 'Raw HTML': '<p>This template is similar to the Text template. The only difference is', } actual_html = world.css_html(selector, index=idx) assert_in(html_matcher[step_hash['Component']].strip(), actual_html.strip()) else: actual_text = world.css_text(selector, index=idx) assert_in(step_hash['Component'], actual_text)
def link_static_link_is_rewritten(_step, path): # Find the TinyMCE iframe within the main window with world.browser.get_iframe('mce_0_ifr') as tinymce: link = tinymce.find_by_tag('a').first assert_in( unicode(world.scenario_dict['COURSE'].id.make_asset_key( 'asset', path)), link['href'])
def log_into_studio(uname='robot', email='*****@*****.**', password='******', name='Robot Studio'): world.log_in(username=uname, password=password, email=email, name=name) # Navigate to the studio dashboard world.visit('/') assert_in(uname, world.css_text('span.account-username', timeout=10))
def add_a_single_step_component(step): for step_hash in step.hashes: component = step_hash['Component'] assert_in(component, ['Discussion', 'Video']) world.create_component_instance( step=step, category='{}'.format(component.lower()), )
def check_lti_component_no_elem(_step, text): selector_map = { 'a launch button': '.link_lti_new_window', 'an provider iframe': '.ltiLaunchFrame', 'feedback': '.problem-feedback', 'progress': '.problem-progress', } assert_in(text, selector_map) assert_true(world.is_css_not_present(selector_map[text]))
def see_elem_text(_step, elem, text): selector_map = { 'progress': '.problem-progress', 'feedback': '.problem-feedback', 'module title': '.problem-header', 'button': '.link_lti_new_window', 'description': '.lti-description' } assert_in(elem, selector_map) assert_true(world.css_has_text(selector_map[elem], text))
def log_into_studio( uname='robot', email='*****@*****.**', password='******', name='Robot Studio'): world.log_in(username=uname, password=password, email=email, name=name) # Navigate to the studio dashboard world.visit('/') assert_in(uname, world.css_text('span.account-username', timeout=10))
def click_grade(_step, version): version_map = { '1': {'selector': 'submit-button', 'expected_text': 'LTI consumer (edX) responded with XML content'}, '2': {'selector': 'submit-lti2-button', 'expected_text': 'LTI consumer (edX) responded with HTTP 200'}, } assert_in(version, version_map) location = world.scenario_dict['LTI'].location.html_id() iframe_name = 'ltiFrame-' + location with world.browser.get_iframe(iframe_name) as iframe: css_ele = version_map[version]['selector'] css_loc = '#' + css_ele world.wait_for_visible(css_loc) world.css_click(css_loc) assert iframe.is_text_present(version_map[version]['expected_text'])
def i_am_staff_or_instructor(step, role): # pylint: disable=unused-argument ## In summary: makes a test course, makes a new Staff or Instructor user ## (depending on `role`), and logs that user in to the course # Store the role assert_in(role, ['instructor', 'staff']) # Clear existing courses to avoid conflicts world.clear_courses() # Create a new course course = world.CourseFactory.create( org='edx', number='999', display_name='Test Course' ) world.course_key = course.id world.role = 'instructor' # Log in as the an instructor or staff for the course if role == 'instructor': # Make & register an instructor for the course world.instructor = InstructorFactory(course_key=world.course_key) world.enroll_user(world.instructor, world.course_key) world.log_in( username=world.instructor.username, password='******', email=world.instructor.email, name=world.instructor.profile.name ) else: world.role = 'staff' # Make & register a staff member world.staff = StaffFactory(course_key=world.course_key) world.enroll_user(world.staff, world.course_key) world.log_in( username=world.staff.username, password='******', email=world.staff.email, name=world.staff.profile.name )
def create_component_instance(step, category, component_type=None, is_advanced=False, advanced_component=None): """ Create a new component in a Unit. Parameters ---------- category: component type (discussion, html, problem, video, advanced) component_type: for components with multiple templates, the link text in the menu is_advanced: for problems, is the desired component under the advanced menu? advanced_component: for advanced components, the related value of policy key 'advanced_modules' """ assert_in(category, ['advanced', 'problem', 'html', 'video', 'discussion']) component_button_css = 'span.large-{}-icon'.format(category.lower()) if category == 'problem': module_css = 'div.xmodule_CapaModule' elif category == 'advanced': module_css = 'div.xmodule_{}Module'.format(advanced_component.title()) elif category == 'discussion': module_css = 'div.xblock-author_view-{}'.format(category.lower()) else: module_css = 'div.xmodule_{}Module'.format(category.title()) # Count how many of that module is on the page. Later we will # assert that one more was added. # We need to use world.browser.find_by_css instead of world.css_find # because it's ok if there are currently zero of them. module_count_before = len(world.browser.find_by_css(module_css)) # Disable the jquery animation for the transition to the menus. world.disable_jquery_animations() world.css_click(component_button_css) if category in ('problem', 'html', 'advanced'): world.wait_for_invisible(component_button_css) click_component_from_menu(category, component_type, is_advanced) expected_count = module_count_before + 1 world.wait_for(lambda _: len(world.css_find(module_css)) == expected_count, timeout=20)
def create_component_instance(step, category, component_type=None, is_advanced=False, advanced_component=None): """ Create a new component in a Unit. Parameters ---------- category: component type (discussion, html, problem, video, advanced) component_type: for components with multiple templates, the link text in the menu is_advanced: for problems, is the desired component under the advanced menu? advanced_component: for advanced components, the related value of policy key 'advanced_modules' """ assert_in(category, ['advanced', 'problem', 'html', 'video', 'discussion']) component_button_css = 'span.large-{}-icon'.format(category.lower()) if category == 'problem': module_css = 'div.xmodule_CapaModule' elif category == 'advanced': module_css = 'div.xmodule_{}Module'.format(advanced_component.title()) elif category == 'discussion': module_css = 'div.xblock-author_view-{}'.format(category.lower()) else: module_css = 'div.xmodule_{}Module'.format(category.title()) # Count how many of that module is on the page. Later we will # assert that one more was added. # We need to use world.browser.find_by_css instead of world.css_find # because it's ok if there are currently zero of them. module_count_before = len(world.browser.find_by_css(module_css)) # Disable the jquery animation for the transition to the menus. world.disable_jquery_animations() world.css_click(component_button_css) if category in ('problem', 'html', 'advanced'): world.wait_for_invisible(component_button_css) click_component_from_menu(category, component_type, is_advanced) expected_count = module_count_before + 1 world.wait_for( lambda _: len(world.css_find(module_css)) == expected_count, timeout=20 )
def click_grade(_step, version): version_map = { '1': { 'selector': 'submit-button', 'expected_text': 'LTI consumer (edX) responded with XML content' }, '2': { 'selector': 'submit-lti2-button', 'expected_text': 'LTI consumer (edX) responded with HTTP 200' }, } assert_in(version, version_map) location = world.scenario_dict['LTI'].location.html_id() iframe_name = 'ltiFrame-' + location with world.browser.get_iframe(iframe_name) as iframe: css_ele = version_map[version]['selector'] css_loc = '#' + css_ele world.wait_for_visible(css_loc) world.css_click(css_loc) assert iframe.is_text_present(version_map[version]['expected_text'])
def find_grading_config(step): # pylint: disable=unused-argument # Find the grading configuration display world.wait_for_visible('#data-grade-config-text') # expected config is the default grading configuration from common/lib/xmodule/xmodule/course_module.py expected_config = u"""----------------------------------------------------------------------------- Course grader: <class 'xmodule.graders.WeightedSubsectionsGrader'> Graded sections: subgrader=<class 'xmodule.graders.AssignmentFormatGrader'>, type=Homework, category=Homework, weight=0.15 subgrader=<class 'xmodule.graders.AssignmentFormatGrader'>, type=Lab, category=Lab, weight=0.15 subgrader=<class 'xmodule.graders.AssignmentFormatGrader'>, type=Midterm Exam, category=Midterm Exam, weight=0.3 subgrader=<class 'xmodule.graders.AssignmentFormatGrader'>, type=Final Exam, category=Final Exam, weight=0.4 ----------------------------------------------------------------------------- Listing grading context for course {} graded sections: [] all graded blocks: length=0""".format(world.course_key) assert_in(expected_config, world.css_text('#data-grade-config-text'))
def click_a_button(step, button): # pylint: disable=unused-argument if button == "Generate Grade Report": # Go to the data download section of the instructor dash go_to_section("data_download") # Click generate grade report button world.css_click('input[name="calculate-grades-csv"]') # Expect to see a message that grade report is being generated expected_msg = "The grade report is being created." \ " To view the status of the report, see" \ " Pending Tasks below." world.wait_for_visible('#report-request-response') assert_in( expected_msg, world.css_text('#report-request-response'), msg="Could not find grade report generation success message.") elif button == "Grading Configuration": # Go to the data download section of the instructor dash go_to_section("data_download") world.css_click('input[name="dump-gradeconf"]') elif button == "List enrolled students' profile information": # Go to the data download section of the instructor dash go_to_section("data_download") world.css_click('input[name="list-profiles"]') elif button == "Download profile information as a CSV": # Go to the data download section of the instructor dash go_to_section("data_download") world.css_click('input[name="list-profiles-csv"]') else: raise ValueError("Unrecognized button option " + button)
def click_a_button(step, button): # pylint: disable=unused-argument if button == "Generate Grade Report": # Go to the data download section of the instructor dash go_to_section("data_download") # Click generate grade report button world.css_click('input[name="calculate-grades-csv"]') # Expect to see a message that grade report is being generated expected_msg = "The grade report is being created." \ " To view the status of the report, see" \ " Pending Tasks below." world.wait_for_visible('#report-request-response') assert_in( expected_msg, world.css_text('#report-request-response'), msg="Could not find grade report generation success message." ) elif button == "Grading Configuration": # Go to the data download section of the instructor dash go_to_section("data_download") world.css_click('input[name="dump-gradeconf"]') elif button == "List enrolled students' profile information": # Go to the data download section of the instructor dash go_to_section("data_download") world.css_click('input[name="list-profiles"]') elif button == "Download profile information as a CSV": # Go to the data download section of the instructor dash go_to_section("data_download") world.css_click('input[name="list-profiles-csv"]') else: raise ValueError("Unrecognized button option " + button)
def i_am_staff_or_instructor(step, role): # pylint: disable=unused-argument ## In summary: makes a test course, makes a new Staff or Instructor user ## (depending on `role`), and logs that user in to the course # Store the role assert_in(role, ['instructor', 'staff']) # Clear existing courses to avoid conflicts world.clear_courses() # Create a new course course = world.CourseFactory.create(org='edx', number='999', display_name='Test Course') world.course_key = course.id world.role = 'instructor' # Log in as the an instructor or staff for the course if role == 'instructor': # Make & register an instructor for the course world.instructor = InstructorFactory(course_key=world.course_key) world.enroll_user(world.instructor, world.course_key) world.log_in(username=world.instructor.username, password='******', email=world.instructor.email, name=world.instructor.profile.name) else: world.role = 'staff' # Make & register a staff member world.staff = StaffFactory(course_key=world.course_key) world.enroll_user(world.staff, world.course_key) world.log_in(username=world.staff.username, password='******', email=world.staff.email, name=world.staff.profile.name)
def n_events_are_emitted(_step, count, event_type, event_source): # Ensure all events are written out to mongo before querying. world.mongo_client.fsync() # Note that splinter makes 2 requests when you call browser.visit('/foo') # the first just checks to see if the server responds with a status # code of 200, the next actually uses the browser to submit the request. # We filter out events associated with the status code checks by ignoring # events that come directly from splinter. criteria = { 'event_type': event_type, 'event_source': event_source, 'agent': { '$ne': 'python/splinter' } } cursor = world.event_collection.find(criteria) try: number_events = int(count) except ValueError: number_events = 1 assert_equals(cursor.count(), number_events) event = cursor.next() expected_field_values = { "username": world.scenario_dict['USER'].username, # pylint: disable=no-member "event_type": event_type, } for key, value in expected_field_values.iteritems(): assert_equals(event[key], value) for field in REQUIRED_EVENT_FIELDS: assert_in(field, event)
def default_options_sets_expected_font_family(step): # pylint: disable=unused-argument, redefined-outer-name fonts = get_available_fonts(get_fonts_list_panel(world)) fonts_found = fonts.get("Default", None) expected_font_family = CUSTOM_FONTS.get('Default') for expected_font in expected_font_family: assert_in(expected_font, fonts_found)
def check_page_text(step): assert_in(step.multiline, world.css_find('.xmodule_HtmlModule').html)
def check_standard_tinyMCE_fonts(_step): fonts = get_available_fonts(get_fonts_list_panel(world)) for label, expected_fonts in TINYMCE_FONTS.items(): for expected_font in expected_fonts: assert_in(expected_font, fonts.get(label, None))
def i_see_the_assignment_type(_step, name): assignment_css = '#course-grading-assignment-name' assignments = world.css_find(assignment_css) types = [ele['value'] for ele in assignments] assert_in(name, types)
def main_course_page(_step): main_page_link = reverse_course_url('course_handler', world.scenario_dict['COURSE'].id) world.visit(main_page_link) assert_in('Course Outline', world.css_text('h1.page-header'))
def see_pages_in_expected_order(page_names_in_expected_order): pages = world.css_find("li.course-tab") assert_equal(len(page_names_in_expected_order), len(pages)) for i, page_name in enumerate(page_names_in_expected_order): assert_in(page_name, pages[i].text)
def link_static_link_is_rewritten(_step, path): # Find the TinyMCE iframe within the main window with world.browser.get_iframe('mce_0_ifr') as tinymce: link = tinymce.find_by_tag('a').first assert_in(unicode(world.scenario_dict['COURSE'].id.make_asset_key('asset', path)), link['href'])