def discard_changes(self): """ Discards draft changes (which will then re-render the page). """ click_css(self, 'a.action-discard', 0, require_notification=False) confirm_prompt(self) self.wait_for_ajax()
def add_html_component(page, menu_index, boilerplate=None): """ Adds an instance of the HTML component with the specified name. menu_index specifies which instance of the menus should be used (based on vertical placement within the page). """ # Click on the HTML icon. page.wait_for_component_menu() click_css(page, 'button>span.large-html-icon', menu_index, require_notification=False) # Make sure that the menu of HTML components is visible before clicking page.wait_for_element_visibility('.new-component-html', 'HTML component menu is visible') # Now click on the component to add it. component_css = 'button[data-category=html]' if boilerplate: component_css += '[data-boilerplate={}]'.format(boilerplate) else: component_css += ':not([data-boilerplate])' page.wait_for_element_visibility(component_css, 'HTML component {} is visible'.format(boilerplate)) # Adding some components will make an ajax call but we should be OK because # the click_css method is written to handle that. click_css(page, component_css, 0)
def open_move_modal(self): """ Opens the move modal. """ click_css(self, '.move-button', require_notification=False) self.wait_for(lambda: self.q(css='.modal-window.move-modal').visible, description='move modal is visible')
def view_live(self): """ Clicks the "View Live" link and switches to the new tab """ click_css(self, '.view-live-button', require_notification=False) self.wait_for_page() self.browser.switch_to_window(self.browser.window_handles[-1])
def click_review_in_notification(self, notification_type): """ Click on the "Review" button within the visible notification. """ css_string = '.notification.notification-{notification_type} .review-btn'.format( notification_type=notification_type ) # The review button cannot be clicked on until it is tabbed to, so first tab to it. # Multiple tabs may be required depending on the content (for instance, hints with links). def tab_until_review_focused(): """ Tab until the review button is focused """ self.browser.switch_to_active_element().send_keys(Keys.TAB) if self.q(css=css_string).focused: self.scroll_to_element(css_string) return self.q(css=css_string).focused self.wait_for( tab_until_review_focused, 'Waiting for the Review button to become focused' ) self.wait_for_element_visibility( css_string, 'Waiting for the button to be visible' ) click_css(self, css_string, require_notification=False)
def add_advanced_component(page, menu_index, name): """ Adds an instance of the advanced component with the specified name. menu_index specifies which instance of the menus should be used (based on vertical placement within the page). """ # Click on the Advanced icon. page.wait_for_component_menu() click_css(page, 'button>span.large-advanced-icon', menu_index, require_notification=False) # This does an animation to hide the first level of buttons # and instead show the Advanced buttons that are available. # We should be OK though because click_css turns off jQuery animations # Make sure that the menu of advanced components is visible before clicking (the HTML is always on the # page, but will have display none until the large-advanced-icon is clicked). page.wait_for_element_visibility('.new-component-advanced', 'Advanced component menu is visible') # Now click on the component to add it. component_css = 'button[data-category={}]'.format(name) page.wait_for_element_visibility(component_css, 'Advanced component {} is visible'.format(name)) # Adding some components, e.g. the Discussion component, will make an ajax call # but we should be OK because the click_css method is written to handle that. click_css(page, component_css, 0)
def click_review_in_notification(self, notification_type): """ Click on the "Review" button within the visible notification. """ css_string = u'.notification.notification-{notification_type} .review-btn'.format( notification_type=notification_type ) # The review button cannot be clicked on until it is tabbed to, so first tab to it. # Multiple tabs may be required depending on the content (for instance, hints with links). def tab_until_review_focused(): """ Tab until the review button is focused """ self.browser.switch_to_active_element().send_keys(Keys.TAB) if self.q(css=css_string).focused: self.scroll_to_element(css_string) return self.q(css=css_string).focused self.wait_for( tab_until_review_focused, 'Waiting for the Review button to become focused' ) self.wait_for_element_visibility( css_string, 'Waiting for the button to be visible' ) click_css(self, css_string, require_notification=False)
def click_undo_move_link(self): """ Click undo move link. """ click_css( self, '#page-alert .alert.confirmation .nav-actions .action-primary')
def open_move_modal(self): """ Opens the move modal. """ click_css(self, '.move-button', require_notification=False) # lint-amnesty, pylint: disable=unexpected-keyword-arg self.wait_for(lambda: self.q(css='.modal-window.move-modal').visible, description='move modal is visible')
def click_take_me_there_link(self): """ Click take me there link. """ click_css( self, '#page-alert .alert.confirmation .nav-actions .action-secondary', require_notification=False)
def publish(self): """ Publish the unit. """ click_css(self, self._bounded_selector(".action-publish"), require_notification=False) modal = CourseOutlineModal(self) EmptyPromise(lambda: modal.is_shown(), "Modal is shown.") # pylint: disable=unnecessary-lambda modal.publish()
def click_delete_update_button(self): """ Clicks the delete update post button and confirms the delete notification. """ click_css(self, '.post-preview .delete-button', require_notification=False) confirm_prompt(self)
def publish(self): """ Publish the unit. """ click_css(self, self._bounded_selector('.action-publish'), require_notification=False) modal = CourseOutlineModal(self) EmptyPromise(lambda: modal.is_shown(), 'Modal is shown.') # pylint: disable=unnecessary-lambda modal.publish()
def click_take_me_there_link(self): """ Click take me there link. """ click_css( self, '#page-alert .alert.confirmation .nav-actions .action-secondary', require_notification=False) # lint-amnesty, pylint: disable=unexpected-keyword-arg
def discard_changes(self): """ Discards draft changes (which will then re-render the page). """ self.scroll_to_element('a.action-discard') click_css(self, 'a.action-discard', 0, require_notification=False) # lint-amnesty, pylint: disable=unexpected-keyword-arg confirm_prompt(self) self.wait_for_ajax()
def delete(self, cancel=False): """ Clicks the delete button, then cancels at the confirmation prompt if cancel is True. """ click_css(self, self._bounded_selector('.delete-button'), require_notification=False) confirm_prompt(self, cancel)
def delete_static_tab(self): """ Deletes a static page """ click_css(self, '.btn-default.delete-button.action-button', require_notification=False) confirm_prompt(self)
def open_move_modal(self): """ Opens the move modal. """ click_css(self, '.move-button', require_notification=False) self.wait_for( lambda: self.q(css='.modal-window.move-modal').visible, description='move modal is visible' )
def add_section_from_bottom_button(self, click_child_icon=False): """ Clicks the button for adding a section which resides at the bottom of the screen. """ element_css = self.BOTTOM_ADD_SECTION_BUTTON if click_child_icon: element_css += " .fa-plus" click_css(self, element_css)
def add_child(self, require_notification=True): """ Adds a child to this xblock, waiting for notifications. """ click_css( self, self._bounded_selector(self.ADD_BUTTON_SELECTOR), require_notification=require_notification, )
def add_discussion(page, menu_index=0): """ Add a new instance of the discussion category. menu_index specifies which instance of the menus should be used (based on vertical placement within the page). """ page.wait_for_component_menu() click_css(page, 'button>span.large-discussion-icon', menu_index)
def click_hint(self, hint_index=0): """ Click the Hint button. Arguments: hint_index (int): Index of a displayed hint """ click_css(self, '.problem .hint-button', require_notification=False) self.wait_for_focus_on_hint_notification(hint_index)
def click_edit_update_button(self): """ Clicks the edit update post button. """ click_css(self, '.post-preview .edit-button', require_notification=False) self.wait_for_element_visibility('.CodeMirror', 'Waiting for .CodeMirror')
def delete(self, source_index): """ Delete the item with index source_index (based on vertical placement in page). Only visible items are counted in the source_index. The index of the first item is 0. """ # Click the delete button click_css(self, '.delete-button', source_index, require_notification=False) # Click the confirmation dialog button confirm_prompt(self)
def delete(self, source_index): """ Delete the item with index source_index (based on vertical placement in page). Only visible items are counted in the source_index. The index of the first item is 0. """ # Click the delete button click_css(self, 'a.delete-button', source_index, require_notification=False) # Click the confirmation dialog button confirm_prompt(self)
def sign_up_user(self, registration_dictionary): """ Register the user. """ for css, value in registration_dictionary.iteritems(): set_input_value(self, css, value) click_css(page=self, css='#tos', require_notification=False) click_css(page=self, css='#submit', require_notification=False) self.wait_for_element_absence('#submit', 'Submit button is gone.')
def add_static_page(self): """ Adds a static page """ total_tabs = len(self.q(css='.course-nav-list>li')) click_css(self, '.add-pages .new-tab', require_notification=False) self.wait_for( lambda: len(self.q(css='.course-nav-list>li')) == total_tabs + 1, description="Static tab is added") self.wait_for_element_visibility( u'.tab-list :nth-child({}) .xblock-student_view'.format( total_tabs), 'Static tab is visible')
def click_leave_team_link(self, remaining_members=0, cancel=False): """ Click on Leave Team link""" leave_team_css = '.leave-team-link' self.wait_for_element_visibility(leave_team_css, 'Leave Team link is visible.') click_css(self, leave_team_css, require_notification=False) confirm_prompt(self, cancel, require_notification=False) if cancel is False: self.wait_for( lambda: self.join_team_button_present, description="Join Team button did not become present" ) self.wait_for_capacity_text(remaining_members)
def click_new_update_button(self): """ Clicks the new-update button. """ def is_update_button_enabled(): """ Checks if the New Update button is enabled """ return self.q(css='.new-update-button').attrs('disabled')[0] is None self.wait_for(promise_check_func=is_update_button_enabled, description='Waiting for the New update button to be enabled.') click_css(self, '.new-update-button', require_notification=False) self.wait_for_element_visibility('.CodeMirror', 'Waiting for .CodeMirror')
def click_review_in_notification(self): """ Click on the "Review" button within the visible notification. """ # The review button cannot be clicked on until it is tabbed to, so first tab to it. # Multiple tabs may be required depending on the content (for instance, hints with links). def tab_until_review_focused(): """ Tab until the review button is focused """ self.browser.switch_to_active_element().send_keys(Keys.TAB) return self.q(css='.notification .review-btn').focused self.wait_for(tab_until_review_focused, 'Waiting for the Review button to become focused') click_css(self, '.notification .review-btn', require_notification=False)
def upload_pdf_file(self, file_name): """ Uploads a pdf textbook. """ # If the pdf upload section has not yet been toggled on, click on the upload pdf button test_dir = path(__file__).abspath().dirname().dirname().dirname().dirname() # pylint:disable=no-value-for-parameter file_path = test_dir + '/data/uploads/' + file_name click_css(self, ".edit-textbook .action-upload", require_notification=False) self.wait_for_element_visibility(".upload-dialog input", "Upload modal opened") file_input = self.q(css=".upload-dialog input").results[0] file_input.send_keys(file_path) click_css(self, ".wrapper-modal-window-assetupload .action-upload", require_notification=False) self.wait_for_element_absence(".modal-window-overlay", "Upload modal closed")
def toggle_staff_lock(self, inherits_staff_lock=False): """ Toggles "hide from students" which enables or disables a staff-only lock. Returns True if the lock is now enabled, else False. """ was_locked_initially = self.is_staff_locked if not was_locked_initially: self.q(css='a.action-staff-lock').first.click() else: click_css(self, 'a.action-staff-lock', 0, require_notification=False) if not inherits_staff_lock: confirm_prompt(self) self.wait_for_ajax() return not was_locked_initially
def upload_image(self, file_name): """ Upload image and add description and click save to upload image via TinyMCE editor. """ file_input_css = "[type='file']" # select file input element and change visibility to add file. self.browser.execute_script( '$("{}").css("display","block");'.format(file_input_css)) self.wait_for_element_visibility(file_input_css, "Input is visible") self.q(css=file_input_css).results[0].send_keys(file_name) self.wait_for_element_visibility('#imageDescription', 'Upload form is visible.') self.q(css='#imageDescription').results[0].send_keys('test image') click_css(self, '.modal-footer .btn-primary')
def upload_tarball(self, tarball_filename): """ Upload a tarball to be imported. """ asset_file_path = self.file_path(tarball_filename) # Make the upload elements visible to the WebDriver. self.browser.execute_script('$(".file-name-block").show();$(".file-input").show()') # Upload the file. self.q(css='input[type="file"]')[0].send_keys(asset_file_path) # Upload the same file again. Reason behind this is to decrease the # probability or fraction of times the failure occur. Please be # noted this doesn't eradicate the root cause of the error, it # just decreases to failure rate to minimal. # Jira ticket reference: TNL-4191. self.q(css='input[type="file"]')[0].send_keys(asset_file_path) # Some of the tests need these lines to pass so don't remove them. self._wait_for_button() click_css(self, '.submit-button', require_notification=True)
def _studio_add_content(self, studio_course_outline, html_content): """ Add content to first section on studio course page. """ # create a unit in course outline studio_course_outline.visit() subsection = studio_course_outline.section_at(0).subsection_at(0) subsection.expand_subsection() subsection.add_unit() # got to unit and create an HTML component and save (not publish) unit_page = ContainerPage(self.browser, None) unit_page.wait_for_page() add_html_component(unit_page, 0) unit_page.wait_for_element_presence('.edit-button', 'Edit button is visible') click_css(unit_page, '.edit-button', 0, require_notification=False) unit_page.wait_for_element_visibility('.modal-editor', 'Modal editor is visible') type_in_codemirror(unit_page, 0, html_content) click_css(unit_page, '.action-save', 0)
def _studio_add_content(self, section_index): """ Add content on studio course page under specified section """ self._auto_auth(self.STAFF_USERNAME, self.STAFF_EMAIL, True) # create a unit in course outline self.studio_course_outline.visit() subsection = self.studio_course_outline.section_at(section_index).subsection_at(0) subsection.expand_subsection() subsection.add_unit() # got to unit and create an HTML component and save (not publish) unit_page = ContainerPage(self.browser, None) unit_page.wait_for_page() add_html_component(unit_page, 0) unit_page.wait_for_element_presence('.edit-button', 'Edit button is visible') click_css(unit_page, '.edit-button', 0, require_notification=False) unit_page.wait_for_element_visibility('.modal-editor', 'Modal editor is visible') type_in_codemirror(unit_page, 0, self.HTML_CONTENT) click_css(unit_page, '.action-save', 0)
def click_take_me_there_link(self): """ Click take me there link. """ click_css(self, '#page-alert .alert.confirmation .nav-actions .action-secondary', require_notification=False)
def duplicate(self, source_index): """ Duplicate the item with index source_index (based on vertical placement in page). """ click_css(self, 'a.duplicate-button', source_index)
def cancel(self): """ Clicks cancel button. """ click_css(self, 'a.action-cancel', require_notification=False)
def save(self): """ Clicks save button. """ click_css(self, 'a.action-save')
def save(self): """ Clicks save button. """ click_css(self, '.save-button')
def click_submit(self): """ Click the Submit button. """ click_css(self, '.problem .submit', require_notification=False)
def click_save(self): """ Click the Save button. """ click_css(self, '.problem .save', require_notification=False)
def click_add_grade(self): """ Clicks to add a grade """ click_css(self, '.new-grade-button', require_notification=False)
def click_reset(self): """ Click the Reset button. """ click_css(self, '.problem .reset', require_notification=False) self.wait_for_ajax()