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 css_has_text(css_selector, text, index=0, strip=False, allow_blank=True): """ Return a boolean indicating whether the element with `css_selector` has `text`. If `strip` is True, strip whitespace at beginning/end of both strings before comparing. If `allow_blank` is False, wait for the element to have non-empty text before making the assertion. This is useful for elements that are populated by JavaScript after the page loads. If there are multiple elements matching the css selector, use `index` to indicate which one. """ if not allow_blank: world.wait_for(lambda _: world.css_text(css_selector, index=index)) actual_text = world.css_text(css_selector, index=index) if strip: actual_text = actual_text.strip() text = text.strip() return actual_text == text
def check_textbook_chapters(_step, textbook_name, num_chapters_str): num_chapters = int(num_chapters_str) title = world.css_text(".textbook .view-textbook h3.textbook-title", index=0) toggle_text = world.css_text(".textbook .view-textbook .chapter-toggle", index=0) assert_equal(title, textbook_name) assert_equal( toggle_text, "{num} PDF Chapters".format(num=num_chapters), "Expected {num} chapters, found {real}".format(num=num_chapters, real=toggle_text) )
def then_i_see_a_tables_of_modules_progress(step): world.wait_for_visible('.progress-report-list') if world.role == 'instructor': summary_text = "Test Course\nenrollments 1\nactive_students 1" elif world.role == 'staff': summary_text = "Test Course\nenrollments 2\nactive_students 2" modules_text = "i4x://edx/999/problem/Problem_1\ncorrect_map {u'i4x-org-cn-problem-unitid_2_1': 1}\ncount 2\ncourse_id edx/999/Test_Course\n" assert_true(world.browser.status_code.is_success()) assert_in(summary_text, world.css_text("table.summary-table")) assert_in(modules_text, world.css_text("table.modules-table"))
def see_a_multi_step_component(step, category): # Wait for all components to finish rendering selector = 'li.studio-xblock-wrapper div.xblock-student_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': '<p> Words of encouragement! This is a short note that most students will read. </p>', 'Zooming Image': '<h2>ZOOMING DIAGRAMS</h2>', 'E-text Written in LaTeX': '<h2>Example: E-text page</h2>', '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']], actual_html) else: actual_text = world.css_text(selector, index=idx) assert_in(step_hash['Component'].upper(), actual_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 = "Your grade report is being generated! You can view the status of the generation task in the 'Pending Instructor Tasks' section." world.wait_for_visible('#grade-request-response') assert_in( expected_msg, world.css_text('#grade-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"]') else: raise ValueError("Unrecognized button option " + button)
def see_a_problem_component(step, category): component_css = "section.xmodule_CapaModule" assert_true(world.is_css_present(component_css), "No problem was added to the unit.") problem_css = "li.component section.xblock-student_view" actual_text = world.css_text(problem_css) assert_in(category.upper(), actual_text)
def see_result(_step): """ Uppercasing since CSS capitalizes the headings """ strong_css = '.your_words strong' target_text = set([world.css_text(strong_css, i) for i in range(2)]) assert set(['text1', 'text2']) == target_text
def verify_action_link_text(driver): actualText = world.css_text('#course-checklist' + str(checklist) + ' a', index=task) if actualText == actionText: return True else: # toggle checklist item to make sure that the link button is showing toggleTask(checklist, task) return False
def see_a_problem_component(step, category): component_css = 'div.xmodule_CapaModule' assert_true(world.is_css_present(component_css), 'No problem was added to the unit.') problem_css = 'li.studio-xblock-wrapper div.xblock-student_view' actual_text = world.css_text(problem_css) assert_in(category.upper(), actual_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 the_total_number_of_courses_is_foo(step, count): div_css = 'div.view-header' # should return something like: 'Showing 1 - 15 of 62' div_text = world.css_text(div_css) pattern = re.compile(r'Courses: Showing (?P<first>\d+) - (?P<last>\d+) of (?P<total>\d+)') matched_text = re.match(pattern, div_text) assert matched_text assert_equals(matched_text.group('total'), count)
def main_course_page(step): course_name = world.scenario_dict['COURSE'].display_name.replace(' ', '_') main_page_link = '/course/{org}.{number}.{name}/branch/draft/block/{name}'.format( org=world.scenario_dict['COURSE'].org, number=world.scenario_dict['COURSE'].number, name=course_name ) world.visit(main_page_link) assert_in('Course Outline', world.css_text('h1.page-header'))
def view_asset(_step, status): url = django_url('/c4x/MITx/999/asset/asset.html') if status == 'viewable': expected_text = 'test file' else: expected_text = 'Unauthorized' # Note that world.visit would trigger a 403 error instead of displaying "Unauthorized" # Instead, we can drop back into the selenium driver get command. world.browser.driver.get(url) assert_equal(world.css_text('body'), expected_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 uname in world.css_text('h2.title', max_attempts=15)
def main_course_page(step): course_name = world.scenario_dict['COURSE'].display_name.replace(' ', '_') course_key = SlashSeparatedCourseKey( world.scenario_dict['COURSE'].org, world.scenario_dict['COURSE'].number, course_name ) main_page_link = reverse_course_url('course_handler', course_key) world.visit(main_page_link) assert_in('Course Outline', world.css_text('h1.page-header'))
def video_time(): """ Return a tuple `(elapsed_time, duration)`, each in seconds. """ # The full time has the form "0:32 / 3:14" full_time = world.css_text('div.vidtime') # Split the time at the " / ", to get ["0:32", "3:14"] elapsed_str, duration_str = full_time.split(' / ') # Convert each string to seconds return (parse_time_str(elapsed_str), parse_time_str(duration_str))
def css_has_text(css_selector, text, index=0, strip=False): """ Return a boolean indicating whether the element with `css_selector` has `text`. If `strip` is True, strip whitespace at beginning/end of both strings before comparing. If there are multiple elements matching the css selector, use `index` to indicate which one. """ # If we're expecting a non-empty string, give the page # a chance to fill in text fields. if text: world.wait_for(lambda _: world.css_text(css_selector, index=index)) actual_text = world.css_text(css_selector, index=index) if strip: actual_text = actual_text.strip() text = text.strip() return actual_text == text
def view_asset(_step, status): asset_loc = world.scenario_dict['COURSE'].id.make_asset_key(asset_type='asset', path='asset.html') svr_loc = django_url() asset_url = unicode(asset_loc) divider = '/' if asset_url[0] == '/': divider = '' url = '{}{}{}'.format(svr_loc, divider, asset_url) if status == 'viewable': expected_text = 'test file' else: expected_text = 'Unauthorized' # Note that world.visit would trigger a 403 error instead of displaying "Unauthorized" # Instead, we can drop back into the selenium driver get command. world.browser.driver.get(url) assert_equal(world.css_text('body'), expected_text)
def when_i_send_an_email(step, recipient): # Check that the recipient is valid assert_in( recipient, SEND_TO_OPTIONS, msg="Invalid recipient: {}".format(recipient) ) # Clear the queue of existing emails while not mail.queue.empty(): # pylint: disable=E1101 mail.queue.get() # pylint: disable=E1101 # Because we flush the database before each run, # we need to ensure that the email template fixture # is re-loaded into the database call_command('loaddata', 'course_email_template.json') # Go to the email section of the instructor dash world.visit('/courses/edx/999/Test_Course') world.css_click('a[href="/courses/edx/999/Test_Course/instructor"]') world.css_click('div.beta-button-wrapper>a') world.css_click('a[data-section="send_email"]') # Select the recipient world.select_option('send_to', SEND_TO_OPTIONS[recipient]) # Enter subject and message world.css_fill('input#id_subject', 'Hello') with world.browser.get_iframe('mce_0_ifr') as iframe: editor = iframe.find_by_id('tinymce')[0] editor.fill('test message') # Click send world.css_click('input[name="send"]') # Confirm the alert world.browser.get_alert().accept() # Expect to see a message that the email was sent expected_msg = "Your email was successfully queued for sending." world.wait_for_visible('#request-response') assert_in( expected_msg, world.css_text('#request-response'), msg="Could not find email success message." )
def see_a_multi_step_component(step, category): # Wait for all components to finish rendering selector = "li.component section.xblock-student_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": "<p> Words of encouragement! This is a short note that most students will read. </p>", "E-text Written in LaTeX": "<h2>Example: E-text page</h2>", } actual_html = world.css_html(selector, index=idx) assert_in(html_matcher[step_hash["Component"]], actual_html) else: actual_text = world.css_text(selector, index=idx) assert_in(step_hash["Component"].upper(), actual_text)
def i_see_a_release_date_for_my_section(_step): import re css = 'span.published-status' assert world.is_css_present(css) status_text = world.css_text(css) # e.g. 11/06/2012 at 16:25 msg = 'Will Release:' date_regex = r'(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) \d\d?, \d{4}' if not re.search(date_regex, status_text): print status_text, date_regex time_regex = r'[0-2]\d:[0-5]\d( \w{3})?' if not re.search(time_regex, status_text): print status_text, time_regex match_string = r'%s\s+%s at %s' % (msg, date_regex, time_regex) if not re.match(match_string, status_text): print status_text, match_string assert re.match(match_string, status_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 descriptors: length=0""".format(world.course_key) assert_in(expected_config, world.css_text('#data-grade-config-text'))
def see_a_multi_step_component(step, category): # Wait for all components to finish rendering selector = 'li.studio-xblock-wrapper div.xblock-student_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 see_a_multi_step_component(step, category): # Wait for all components to finish rendering selector = 'li.component section.xmodule_display' 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': '<p> Words of encouragement! This is a short note that most students will read. </p>', 'E-text Written in LaTeX': '<h2>Example: E-text page</h2>', } actual_html = world.css_html(selector, index=idx) assert_in(html_matcher[step_hash['Component']], actual_html) else: actual_text = world.css_text(selector, index=idx) assert_in(step_hash['Component'].upper(), actual_text)
def upload_transcript(step): input_hidden = '.metadata-video-translations .input' # Number of previously added translations initial_index = len(world.css_find(TRANSLATION_BUTTONS['download'])) if step.hashes: for i, item in enumerate(step.hashes): lang_code = item['lang_code'] filename = item['filename'] index = initial_index + i choose_new_lang(lang_code) expected_text = world.css_text(TRANSLATION_BUTTONS['upload'], index=index) assert_equal(expected_text, "Upload") assert_equal(world.css_find(input_hidden).last.value, "") world.css_click(TRANSLATION_BUTTONS['upload'], index=index) success_upload_file(filename) world.wait_for_visible(TRANSLATION_BUTTONS['download'], index=index) assert_equal(world.css_find(TRANSLATION_BUTTONS['upload']).last.text, "Replace") assert_equal(world.css_find(input_hidden).last.value, filename)
def when_i_send_an_email(step, recipient): # pylint: disable=unused-argument # Check that the recipient is valid assert_in(recipient, SEND_TO_OPTIONS, msg="Invalid recipient: {}".format(recipient)) # Clear the queue of existing emails while not mail.queue.empty(): # pylint: disable=no-member mail.queue.get() # pylint: disable=no-member # Because we flush the database before each run, # we need to ensure that the email template fixture # is re-loaded into the database call_command("loaddata", "course_email_template.json") # Go to the email section of the instructor dash url = "/courses/{}".format(world.bulk_email_course_key) world.visit(url) world.css_click('a[href="{}/instructor"]'.format(url)) world.css_click('a[data-section="send_email"]') # Select the recipient world.select_option("send_to", SEND_TO_OPTIONS[recipient]) # Enter subject and message world.css_fill("input#id_subject", "Hello") with world.browser.get_iframe("mce_0_ifr") as iframe: editor = iframe.find_by_id("tinymce")[0] editor.fill("test message") # Click send world.css_click('input[name="send"]', dismiss_alert=True) # Expect to see a message that the email was sent expected_msg = "Your email was successfully queued for sending." world.wait_for_visible("#request-response") assert_in(expected_msg, world.css_text("#request-response"), msg="Could not find email success message.")
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 = "Your grade report is being generated! You can view the status of the generation task in the 'Pending Instructor Tasks' section." world.wait_for_visible('#grade-request-response') assert_in( expected_msg, world.css_text('#grade-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") # Don't do anything else, next step will handle clicking & downloading else: raise ValueError("Unrecognized button option " + button)
def see_a_multi_step_component(step, category): # Wait for all components to finish rendering selector = 'li.component div.xblock-student_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': '<p> Words of encouragement! This is a short note that most students will read. </p>', 'Zooming Image': '<h2>ZOOMING DIAGRAMS</h2>', 'E-text Written in LaTeX': '<h2>Example: E-text page</h2>', } actual_html = world.css_html(selector, index=idx) assert_in(html_matcher[step_hash['Component']], actual_html) else: actual_text = world.css_text(selector, index=idx) assert_in(step_hash['Component'].upper(), actual_text)
def verify_text(driver): return world.css_text('.problem') == 'hi'
def check_value(self, step, value): r'the displayed value should be (?P<value>\d+)$' assert_equals(world.css_text('.gst-value'), value)
def see_spelling_msg(step, msg): spelling_msg = world.css_text('div.spelling') assert_equals('Spelling: %s' % msg, spelling_msg)
def then_i_see_that_i_was_most_recently_in_the_subsection(step): message = world.css_text('section.course-content > p') assert_in("You were most recently in Test Subsection 2", message)
def check_text_in_the_captions(_step, text): world.wait_for_present('.video.is-captions-rendered') world.wait_for(lambda _: world.css_text('.subtitles'), timeout=30) actual_text = world.css_text('.subtitles') assert (text in actual_text)
def see_the_grader_status(step, status): status_css = 'div.grader-status' assert_equals(status, world.css_text(status_css))
def find_problem(_driver): return world.css_text(component_css, int(index)).startswith(display_name.upper())
def the_section_release_date_is_updated(step): css = 'span.published-status' status_text = world.css_text(css) assert_equal(status_text, 'Will Release: 12/25/2013 at 00:00 UTC')
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 check_component_display_name(step, display_name): label = world.css_text(".component-header") assert display_name == label
def see_result(_step): strong_css = '.your_words strong' target_text = set([world.css_text(strong_css, i) for i in range(2)]) assert set(['text1', 'text2']) == target_text
def i_should_see_text_in_the_dashboard_banner_section(step, text): css_selector = "section.dashboard-banner h2" assert (text in world.css_text(css_selector))
def error_on_save(step): assert_regexp_matches(world.css_text('#notification-error-description'), 'Incorrect setting format')
def check_captions(_step): world.wait_for_present('.video.is-captions-rendered') for index, video in enumerate(_step.hashes): assert (video.get('text') in world.css_text('.subtitles', index=index))
def verify_text(driver): css_sel = '.problem div>span' return world.css_text(css_sel) == 'hi'
def verify_validation_error_message(step, error_message): assert_equal(world.css_text('#upload_error'), error_message)
def i_am_brought_to_course_outline(step): assert_in('Course Outline', world.css_text('.outline .page-header')) assert_equal(1, len(world.browser.windows))
def verify_action_link_text(driver): return world.css_text('#course-checklist' + str(checklist) + ' a', index=task) == actionText
def click_on_the_caption(_step, index): world.wait_for_present('.video.is-captions-rendered') world.wait_for(lambda _: world.css_text('.subtitles'), timeout=30) find_caption_line_by_data_index(int(index.strip()))._element.send_keys( Keys.ENTER)
def check_text_in_the_captions(_step, text): world.wait_for(lambda _: world.css_text('.subtitles')) actual_text = world.css_text('.subtitles') assert (text in actual_text)
def see_empty_result(_step): assert world.css_text('.your_words', 0) == ''
def see_grader_message(step, msg): message_css = 'div.external-grader-message' assert_in(msg, world.css_text(message_css))
def error_on_save(step): assert_regexp_matches(world.css_text('.error-item-message'), "Value stored in a .* must be .*, found .*")
def see_the_grader_score(step, score): score_css = 'div.result-output > p' score_text = world.css_text(score_css) assert_equals(score_text, 'Score: %s' % score)
def the_tab_is_active(step, tab_text): assert world.css_text('.course-tabs a.active') == tab_text
def answer_is_queued_for_instructor_grading(step): list_css = 'ul.problem-list > li > a' actual_msg = world.css_text(list_css) expected_msg = "(0 graded, 1 pending)" assert_in(expected_msg, actual_msg)
def css_has_text(css_selector, text): return world.css_text(css_selector) == text
def check_textbook(_step, textbook_name, chapter_name): title = world.css_text(".textbook h3.textbook-title", index=0) chapter = world.css_text(".textbook .wrap-textbook p", index=0) assert_equal(title, textbook_name) assert_equal(chapter, chapter_name)