def click_duplicate_button(self, xblock_id): """ Click on the duplicate button for the given XBlock """ self._action_btn_for_xblock_id(xblock_id, "duplicate").click() sync_on_notification(self) self.wait_for_ajax()
def toggle_wiki_page_display(self): """ Toggles Wiki page display """ icon_visibility = self.q( css='.is-movable[data-tab-id="wiki"] .fa-eye' ).visible toggle_checkbox_css = '.is-movable[data-tab-id="wiki"] ' \ '.toggle-checkbox' checkbox_css_action = self.q(css=toggle_checkbox_css).results[0] self.wait_for_element_presence( toggle_checkbox_css, 'Toggle button presence' ) ActionChains(self.browser).move_to_element(checkbox_css_action).click( checkbox_css_action ).perform() sync_on_notification(self) if icon_visibility: self.wait_for_element_invisibility( '.is-movable[data-tab-id="wiki"] .fa-eye', 'Eye icon invisibility' ) else: self.wait_for_element_visibility( '.is-movable[data-tab-id="wiki"] .fa-eye', 'Icon visibility' ) return 'Wiki'
def toggle_wiki_page_display(self): """ Toggles Wiki page display """ icon_visibility = self.q( css='.is-movable[data-tab-id="wiki"] .fa-eye' ).visible toggle_checkbox_css = '.is-movable[data-tab-id="wiki"] ' \ '.toggle-checkbox' checkbox_css_action = self.q(css=toggle_checkbox_css).results[0] self.wait_for_element_presence( toggle_checkbox_css, 'Toggle button presence' ) ActionChains(self.browser).move_to_element(checkbox_css_action).click( checkbox_css_action ).perform() sync_on_notification(self) if icon_visibility: self.wait_for_element_invisibility( '.is-movable[data-tab-id="wiki"] .fa-eye', 'Eye icon invisibility' ) else: self.wait_for_element_visibility( '.is-movable[data-tab-id="wiki"] .fa-eye', 'Icon visibility' ) return 'Wiki'
def confirm_asset_deletion(self): """ Click to confirm deletion and sync on the notification.""" confirmation_title_selector = '.modal' self.q( css=confirmation_title_selector + ' button[data-identifier="asset-confirm-delete-button"]').click() # Click initiates an ajax call, waiting for it to complete self.wait_for_ajax() sync_on_notification(self)
def set_asset_lock(self, index=0, lock=True): """ Set the state of the asset in the row specified by index to locked or unlocked, depending on the 'lock' flag. Note: this will raise an IndexError if the row does not exist """ checkbox = self.q(css="li.action-lock input").execute()[index] selected = checkbox.is_selected() if (selected and not lock) or (lock and not selected): checkbox.click() # Click initiates an ajax call, waiting for it to complete self.wait_for_ajax() sync_on_notification(self, style='mini')
def delete_page(self, index=0): """ Deletes the page present at the index passed. Arguments: index (int): Index of page """ click_css(page=self, css='.delete-button.action-button', source_index=index, require_notification=False) self.q(css='.prompt.warning button.action-primary ').first.click() sync_on_notification(self)
def toggle_wiki_page_display(self): """ Toggles Wiki page display """ toggle_checkbox_css = '.is-movable[data-tab-id="wiki"] ' \ '.action-visible [type="checkbox"]' checkbox_css_action = self.q(css=toggle_checkbox_css).results[0] self.wait_for_element_presence(toggle_checkbox_css, 'Toggle button presence') ActionChains(self.browser).move_to_element(checkbox_css_action).click( checkbox_css_action).perform() sync_on_notification(self) return 'Wiki'
def set_asset_lock(self, index=0): """ Set the state of the asset in the row specified by index to locked or unlocked by clicking the button. Note: this will raise an IndexError if the row does not exist. """ lock_button = self.q( css=".table-responsive tbody tr td:nth-child(7) button").execute( )[index] lock_button.click() # Click initiates an ajax call, waiting for it to complete self.wait_for_ajax() sync_on_notification(self)
def delete_page(self, index=0): """ Deletes the page present at the index passed. Arguments: index (int): Index of page """ click_css( page=self, css='.delete-button.action-button', source_index=index, require_notification=False ) self.q(css='.prompt.warning button.action-primary ').first.click() sync_on_notification(self)
def add_component(page, item_type, specific_type, is_advanced_problem=False): """ Click one of the "Add New Component" buttons. item_type should be "advanced", "html", "problem", or "video" specific_type is required for some types and should be something like "Blank Common Problem". """ btn = page.q( css=u'.add-xblock-component .add-xblock-component-button[data-type={}]' .format(item_type)) multiple_templates = btn.filter( lambda el: 'multiple-templates' in el.get_attribute('class')).present btn.click() if multiple_templates: sub_template_menu_div_selector = u'.new-component-{}'.format(item_type) page.wait_for_element_visibility( sub_template_menu_div_selector, 'Wait for the templates sub-menu to appear') page.wait_for_element_invisibility( '.add-xblock-component .new-component', 'Wait for the add component menu to disappear') # "Common Problem Types" are shown by default. # For advanced problem types you must first select the "Advanced" tab. if is_advanced_problem: advanced_tab = page.q(css='.problem-type-tabs a').filter( text='Advanced').first advanced_tab.click() # Wait for the advanced tab to be active css = '.problem-type-tabs li.ui-tabs-active a' page.wait_for( lambda: len( page.q(css=css).filter(text=u'Advanced').execute()) > 0, 'Waiting for the Advanced problem tab to be active') all_options = page.q( css=u'.new-component-{} ul.new-component-template li button span'. format(item_type)) chosen_option = all_options.filter(text=specific_type).first chosen_option.click() sync_on_notification(page) page.wait_for_ajax()
def edit_page(self, new_content, index=0): """ Edits the page present at the index passed. Arguments: new_content (str): New content to set. index (int): Index of page """ click_css(page=self, css='.action-button-text', source_index=index, require_notification=False) self.browser.execute_script( 'tinyMCE.activeEditor.setContent("{}")'.format(new_content)) self.browser.execute_script( 'document.querySelectorAll(".button.action-primary' '.action-save")[0].click();') sync_on_notification(self)
def drag(page, source_index, target_index, placeholder_height=0): """ Gets the drag handle with index source_index (relative to the vertical layout of the page) and drags it to the location of the drag handle with target_index. This should drag the element with the source_index drag handle BEFORE the one with the target_index drag handle. """ draggables = page.q(css='.drag-handle') source = draggables[source_index] target = draggables[target_index] action = ActionChains(page.browser) action.click_and_hold(source).move_to_element_with_offset( target, 0, placeholder_height) if placeholder_height == 0: action.release(target).perform() else: action.release().perform() sync_on_notification(page)
def edit_page(self, new_content, index=0): """ Edits the page present at the index passed. Arguments: new_content (str): New content to set. index (int): Index of page """ click_css( page=self, css='.action-button-text', source_index=index, require_notification=False ) self.browser.execute_script( 'tinyMCE.activeEditor.setContent("{}")'.format(new_content) ) self.browser.execute_script( 'document.querySelectorAll(".button.action-primary' '.action-save")[0].click();' ) sync_on_notification(self)
def confirm_asset_deletion(self): """ Click to confirm deletion and sync on the notification""" self.q(css='button.action-primary').click() # Click initiates an ajax call, waiting for it to complete self.wait_for_ajax() sync_on_notification(self)