def get_element_by_name(contact_editor, name, section=None): """Get a field object by name in section (if specified)""" element = None if section: panel = contact_editor.findChild( GenericPredicate(roleName='panel', name=section), retry=False, requireResult=False) if not panel: # Other section is not a panel, but a toggle button panel = contact_editor.child(roleName='toggle button', name=section) element = panel.childLabelled(name) else: label = contact_editor.findChild( GenericPredicate(label=name), retry=False, requireResult=False) if not label: # In case childLabelled is missing # Find a filler with this name and get its text child element = contact_editor.child( roleName='filler', name=name).child(roleName='text') else: element = contact_editor.childLabelled(name) if element: return element else: raise RuntimeError("Cannot find element named '%s' in section '%s'" % ( name, section))
def install_enigmail_web_search(tb, search): '''Handle new addons manager search result which is just embedded addons.thunderbird.net website''' # search term search.children[0].text = 'enigmail' # search button search.children[1].doActionNamed('press') results = tb.child(name='enigmail :: Search :: Add-ons for Thunderbird', roleName='document web') # navigation on the website is fragile and ugly, but what we can do, the # old addons manager is gone # find "Enigmail" link, then navigate through the table to a column to its # right with "Add to Thunderbird link" enigmail_link = results.child(name='Enigmail', roleName='link') # Enigmail (link) -> Enigmail FEATURED (heading) -> '' (section) -> '' (section) # TODO: how to find next sibling? right now it relies on first result being the right one install_link = enigmail_link.parent.parent.parent.\ children[1].child(name='Add to Thunderbird', roleName='link') install_link.doActionNamed('jump') # now confirmation dialog, it needs to have focus for 3 sec until "Install" # button will be active config.searchCutoffCount = 20 install_dialog = tb.findChild( orPredicate( GenericPredicate(name='Software Installation', roleName='frame'), GenericPredicate(name='Software Installation', roleName='dialog'), )) install_dialog.button('Install Now').doActionNamed('press') config.searchCutoffCount = 10
def send_email(tb, sign=False, encrypt=False, inline=False, attachment=None): tb.findChild(GenericPredicate( roleName='page tab list')).children[0].doActionNamed('switch') write = tb.button('Write') write.doActionNamed('press') # write.menuItem('Message').doActionNamed('click') tb.button('Write').menuItem('Message').doActionNamed('click') compose = tb.findChild(GenericPredicate(name='Write: .*', roleName='frame')) to = compose.findChild( GenericPredicate(name='To:', roleName='autocomplete')) to.findChild(GenericPredicate(roleName='entry')).text = 'user@localhost' compose.findChild(TBEntry('Subject:')).text = subject compose.findChild(GenericPredicate( roleName='document frame')).text = 'This is test message' # lets thunderbird settle down on default values (after filling recipients) time.sleep(1) compose.button('Enigmail Encryption Info').doActionNamed('press') sign_encrypt = tb.dialog('Enigmail Encryption & Signing Settings') encrypt_checkbox = sign_encrypt.childNamed('Encrypt Message') if encrypt_checkbox.checked != encrypt: encrypt_checkbox.doActionNamed(encrypt_checkbox.actions.keys()[0]) sign_checkbox = sign_encrypt.childNamed('Sign Message') if sign_checkbox.checked != sign: sign_checkbox.doActionNamed(sign_checkbox.actions.keys()[0]) if inline: sign_encrypt.childNamed('Use Inline PGP').doActionNamed('select') else: sign_encrypt.childNamed('Use PGP/MIME').doActionNamed('select') sign_encrypt.button('OK').doActionNamed('press') if attachment: attach(tb, compose, attachment) compose.button('Send').doActionNamed('press') if inline and attachment: tb.dialog('Enigmail Prompt').button('OK').doActionNamed('press')
def configure_enigmail_global(tb): # disable p≡p Junior before creating an account, see # https://sourceforge.net/p/enigmail/bugs/904/ menu = tb.menu('Edit') menu.doActionNamed('click') menu.menuItem('Preferences').doActionNamed('click') config.searchCutoffCount = 20 preferences = tb.findChild( orPredicate( GenericPredicate(name='Thunderbird Preferences', roleName='frame'), GenericPredicate(name='Thunderbird Preferences', roleName='dialog'), )) try: preferences.child(name='Privacy', roleName='radio button'). \ doActionNamed('select') except tree.SearchError: preferences.child(name='Privacy', roleName='list item').\ doActionNamed('') config.searchCutoffCount = 10 preferences.child( name='Force using S/MIME and Enigmail', roleName='radio button').\ doActionNamed('select') preferences.button('Close').doActionNamed('press') menu = tb.menu('Enigmail') menu.doActionNamed('click') menu.menuItem('Preferences').doActionNamed('click') enigmail_prefs = tb.dialog('Enigmail Preferences') # wait for dialog to really initialize, otherwise it may load defaults # over just set values time.sleep(1) try: enigmail_prefs.child(name='Override with', roleName='check box').doActionNamed('check') enigmail_prefs.child( name='Override with', roleName='section').children[0].text = \ '/usr/bin/qubes-gpg-client-wrapper' except tree.ActionNotSupported: pass enigmail_prefs.button('OK').doActionNamed('press') config.searchCutoffCount = 5 try: agent_alert = tb.dialog('Enigmail Alert') if 'Cannot connect to gpg-agent' in agent_alert.description: agent_alert.childNamed('Do not show.*').doActionNamed('check') agent_alert.button('OK').doActionNamed('press') else: raise Exception('Unknown alert: {}'.format( agent_alert.description)) except tree.SearchError: pass finally: config.searchCutoffCount = 10
def show_menu_bar(tb): config.searchCutoffCount = 20 app = tb.findChild( GenericPredicate(name='Application', roleName='menu bar')) app.findChild(GenericPredicate(name='View', roleName='menu')).doActionNamed('click') app.findChild(GenericPredicate(name='Toolbars', roleName='menu')).doActionNamed('click') app.findChild(GenericPredicate( name='Menu Bar', roleName='check menu item')).doActionNamed('click') config.searchCutoffCount = defaultCutoffCount
def test_load_save(self): self.goToEnd_button = self.viewer.child(name="goToEnd_button") seektime = self.viewer.child(name="timecode_entry").child( roleName="text") infobar_media = self.medialibrary.child(name="Information", roleName="alert") filename1 = "/tmp/test_project-%i.xptv" % time() filename2 = "/tmp/test_project-%i.xptv" % time() #Create project self.assertTrue(infobar_media.showing) sample = self.import_media() self.insert_clip(sample) self.saveProject(filename1) self.assertFalse(infobar_media.showing) #Create new, check if cleaned sleep(0.5) self.menubar.menu("Project").click() self.menubar.menu("Project").menuItem("New").click() self.pitivi.child(name="Project Settings", roleName="dialog", recursive=False).button("OK").click() icons = self.medialibrary.findChildren( GenericPredicate(roleName="icon")) self.goToEnd_button.click() self.assertEqual(len(icons), 0) self.assertTrue(infobar_media.showing) #Create bigger project sample = self.import_media() self.import_media("flat_colour1_640x480.png") self.insert_clip(sample, 2) self.saveProject(filename2) self.assertFalse(infobar_media.showing) #Load first, check if populated self.load_project(filename1) icons = self.medialibrary.findChildren( GenericPredicate(roleName="icon")) self.goToEnd_button.click() self.assertEqual(len(icons), 1) self.assertEqual(seektime.text, DURATION_OF_ONE_CLIP) self.assertFalse(infobar_media.showing) #Load second, check if populated self.load_project(filename2) icons = self.medialibrary.findChildren( GenericPredicate(roleName="icon")) self.goToEnd_button.click() self.assertEqual(len(icons), 2) self.assertEqual(seektime.text, DURATION_OF_TWO_CLIPS) self.assertFalse(infobar_media.showing)
def handle_authentication_window(context, password='******'): # Get a list of applications app_names = [] for attempt in range(0, 15): try: app_names = map(lambda x: x.name, root.applications()) break except GLib.GError: sleep(1) continue if 'gcr-prompter' in app_names: # Non gnome shell stuf passprompt = root.application('gcr-prompter') continue_button = passprompt.findChild( GenericPredicate(name='Continue'), retry=False, requireResult=False) if continue_button: passprompt.findChildren( GenericPredicate(roleName='password text'))[-1].grab_focus() sleep(0.5) typeText(password) # Don't save passwords to keyring keyCombo('<Tab>') # Click Continue keyCombo('<Tab>') keyCombo('<Tab>') keyCombo('<Enter>') elif 'gnome-shell' in app_names: shell = root.application('gnome-shell') # if wait_until(lambda x: x.findChildren( # lambda x: x.roleName == 'password text' and x.showing) != [], shell): # pswrd = shell.child(roleName='password text') # pswrd.text = password # st = shell.child('Add this password to your keyring') # if not st.parent.parent.checked: # st.click() # continue_button = shell.button('Continue') # shell.button('Continue').click() # sleep(3) if wait_until( lambda x: x.findChildren(lambda x: x.roleName == 'password text' and x.showing) != [], shell): st = shell.child('Add this password to your keyring') if not st.parent.parent.checked: st.click() pswrd = shell.child(roleName='password text') pswrd.click() typeText(password) keyCombo('<Enter>') wait_until(st.dead) sleep(1)
def select_contact_with_name(context, contact_name): # heading shows the name of currently selected contact # We have to keep on pressing Tab to select the next contact # Until we meet the first contact # WARNING - what if we will have two identical contacts? fail = False selected_contact = None # HACK # To make the contact table appear # we need to focus on search window # and send Tabs to have the first contact focused context.app.search_bar.grab_focus() sleep(0.1) # Switch to 'Any field contains' (not reachable in 3.6) icons = context.app.search_bar.findChildren(GenericPredicate(roleName='icon')) if icons != []: icons[0].click() wait_until(lambda x: x.findChildren( GenericPredicate(roleName='check menu item', name='Any field contains')) != [], context.app) context.app.menuItem('Any field contains').click() for attempts in range(0, 10): try: context.app.search_bar.text = contact_name break except (GLib.GError, AttributeError): sleep(0.1) continue keyCombo("<Enter>") context.app.search_bar.grab_focus() keyCombo("<Tab>") first_contact_name = context.app.child(roleName='heading').text while True: selected_contact = context.app.child(roleName='heading') if selected_contact.text == contact_name: fail = False break keyCombo("<Tab>") # Wait until contact data is being rendered sleep(1) if first_contact_name == selected_contact.text: fail = True break context.assertion.assertFalse( fail, "Can't find contact named '%s'" % contact_name) context.selected_contact_text = selected_contact.text
def add_windows_live_account(context, user, password): dialog = context.app.instance.dialog('Windows Live account') # Input credentials # assert wait_until( # lambda x: x.findChildren( # GenericPredicate(roleName='entry')) != [], dialog, # timeout=90), "Windows Live auth window didn't appear" entry = dialog.child(roleName='entry', description="Email or phone") if entry.text != user: entry.click() typeText(user) pressKey('Tab') typeText(password) doDelay(2) dialog.button('Sign in').click() doDelay(5) # Wait for GNOME icon to appear third_party_icon_pred = GenericPredicate( roleName='document web', name='Let this app access your info?') for attempts in range(0, 10): # pylint: disable=W0612 if dialog.findChild(third_party_icon_pred, retry=False, requireResult=False) is not None: break else: doDelay(2) doDelay(1) allow_button = dialog.child("Yes", roleName='push button') if not allow_button.showing: # Scroll to confirmation button scrolls = dialog.findChildren(GenericPredicate(roleName='scroll bar')) scrolls[-1].value = scrolls[-1].maxValue pressKey('space') pressKey('space') # Wait for button to become enabled for attempts in range(0, 10): if pyatspi.STATE_SENSITIVE in \ allow_button.getState().getStates(): break else: doDelay(1) allow_button.click() assert wait_until(lambda x: x.dead, dialog), \ "Dialog was not closed"
def attach(tb, compose_window, path): compose_window.button('Attach').button('Attach').doActionNamed('press') compose_window.button('Attach').menuItem('File.*').doActionNamed('click') select_file = tb.dialog('Attach File.*') places = select_file.findChild( GenericPredicate(roleName='table', name='Places')) places.findChild(GenericPredicate(name='Desktop')).click() location_toggle = select_file.findChild( GenericPredicate(roleName='toggle button', name='Type a file name')) if not location_toggle.checked: location_toggle.doActionNamed('click') location_label = select_file.child(name='Location:', roleName='label') location = location_label.parent.children[location_label.indexInParent + 1] location.text = path select_file.button('Open').doActionNamed('click')
def search_by_text(self, text, parent, name=None, roleName=None, exactMatchOnly=True): """ Search a parent widget for the first child whose text matches exactly. If you want to search for a widget "containing" the text, set the "exactMatchOnly" parameter to False (it will also be case-insensitive). """ children = parent.findChildren( GenericPredicate(roleName=roleName, name=name)) for child in children: if hasattr(child, "text"): # This is cute and all, but we're not just searching inside # text entry widgets or labels... we can also be in a table cell # and that means we can't assume that it's a text cell. Many # listviews/treeviews/etc have cells for icons (text is None) if child.text is not None: print("Searching for", text, "in", child.text) if exactMatchOnly: if text == child.text: return child elif text.lower() in child.text.lower(): return child
def check_select_disks(self, spoke): # FIXME: This is a really roundabout way of determining whether a disk is # selected or not. For some reason when a DiskOverview is selected, its icon # loses the name "Hard Disk". For now, we can use this to check. def _selected(do): return len(do.findChildren(GenericPredicate(name="Hard Disk"))) == 0 # A real disk is any disk attached to the VM that's not the special 10 MB # one used for communicating in and out of the VM. Therefore, scan all # children of the DiskOverview looking for one whose name contains that # size. def _real_disk(do): for child in do.findChildren(GenericPredicate()): if child.name == "10 MiB": return False return True # There should be some disks displayed on the screen. overviews = spoke.findChildren(GenericPredicate(roleName="disk overview")) self.assertGreater(len(overviews), 0, msg="No disks are displayed") if len(overviews) == 1: # Only one disk was given to this test case, so anaconda selected it # by default. Verify. Not sure how this would happen with how # testing is currently done, but it's good to be prepared. self.assertTrue(_selected(overviews[0])) else: # More than one disk was provided, so anaconda did not select any. # Let's select all disks and proceed. for overview in filter(_real_disk, overviews): self.assertFalse(_selected(overview)) overview.click() self.assertTrue(_selected(overview))
def import_media(self, filename="tears of steel.webm"): dogtail.rawinput.pressKey("Esc") # Ensure the welcome dialog is closed self.import_button.click() # Force dogtail to look only one level deep, which is much faster # as it doesn't have to analyze the whole mainwindow. import_dialog = self.pitivi.child(name="Select One or More Files", roleName="file chooser", recursive=False) # Instead of checking for the presence of the path text field and then # searching for the toggle button to enable it, use the fact that GTK's # file chooser allows typing the path directly if it starts with "/". dogtail.rawinput.pressKey("/") # This text will be replaced later filepath = os.path.realpath(__file__).split("dogtail_scripts/")[0] filepath += "samples/" + filename import_dialog.child(roleName='text').text = filepath dogtail.rawinput.pressKey("Enter") # Don't search for the Add button sleep(0.6) # Check if the item is now visible in the media library. for i in range(5): # The time it takes for the icon to appear is unpredictable, # therefore we try up to 5 times to look for it icons = self.medialibrary.findChildren(GenericPredicate(roleName="icon")) for icon in icons: if icon.text == filename: return icon sleep(0.5) # Failure to find an icon might be because it is hidden due to a search current_search_text = self.medialibrary.child(name="media_search_entry", roleName="text").text.lower() self.assertNotEqual(current_search_text, "") self.assertNotIn(filename.lower(), current_search_text) return None
def check_shown_spoke_selectors(self, hub): # FIXME: This forces English. validSelectors = ["ROOT PASSWORD", "USER CREATION"] selectors = hub.findChildren( GenericPredicate(roleName="spoke selector")) self.assertEqual(len(selectors), len(validSelectors), msg="Incorrect number of spoke selectors shown") # Validate that only the spoke selectors we expect are shown. At the same time, # we can also validate the status of each selector. This only validates the # initial state of everything. Once we start clicking on spokes, things are # going to change. # FIXME: This encodes default information. for selector in selectors: if selector.name == "ROOT PASSWORD": self.assertEqual(selector.description, "Root password is not set") elif selector.name == "USER CREATION": self.assertEqual(selector.description, "No user will be created") else: self.fail("Invalid spoke selector shown on livecd: %s" % selector.name)
def startViaMenu(self, throughCategories=False): # pylint: disable=W0613 """ Start the app via Gnome Shell menu """ desktopConfig = self.parseDesktopFile() if self.forceKill and self.isRunning(): self.kill() assert wait_until(lambda x: not x.isRunning(), self, timeout=30),\ "Application cannot be stopped" # panel button Activities gnomeShell = root.application('gnome-shell') os.system("dbus-send --session --type=method_call " + "--dest='org.gnome.Shell' " + "'/org/gnome/Shell' " + "org.gnome.Shell.FocusSearch") textEntry = gnomeShell.textentry('') assert wait_until(lambda x: x.showing, textEntry), \ "Can't find gnome shell search textbar" app_name = self.getName(desktopConfig) typeText(app_name) sleep(1) icons = gnomeShell.findChildren( GenericPredicate(roleName='label', name=app_name)) visible_icons = [x for x in icons if x.showing] assert wait_until(lambda x: len(x) > 0, visible_icons), \ "Can't find gnome shell icon for '%s'" % app_name visible_icons[0].click() assert wait_until(lambda x: x.isRunning(), self, timeout=30),\ "Application failed to start"
def install_enigmail(tb): tools = tb.menu('Tools') tools.doActionNamed('click') tools.menuItem('Add-ons').doActionNamed('click') addons = tb.child(name='Add-ons Manager', roleName='embedded') # check if already installed addons.child(name='Extensions', roleName='list item').\ doActionNamed('') time.sleep(1) config.searchCutoffCount = 1 try: addons_list = addons.findChildren(GenericPredicate(name='', roleName='list box'), recursive=False)[1] addons_list.childNamed('Enigmail.*') except tree.SearchError: pass else: # already installed return finally: config.searchCutoffCount = 10 search = addons.child( name='Search all add-ons|Search on addons.thunderbird.net|Find more extensions', roleName='section') if 'addons.thunderbird.net' in search.name or 'Find more' in search.name: install_enigmail_web_search(tb, search) else: install_enigmail_builtin(tb, search)
def add_google_account(context, user, password): dialog = get_showing_node_name('Google account', context.app.instance) #idialog = context.app.instance.dialog('Google account') # Input credentials entry = get_showing_node_name('Enter your email', dialog) if entry.text != user: entry.click() typeText(user) if dialog.findChildren(lambda x: x.roleName == 'password text') == []: dialog.child('Next').click() get_showing_node_name('Password', dialog).click() typeText(password) keyCombo('<Enter>') #get_showing_node_name('Sign in', dialog).click() # Wait for Allow to appear third_party_icon_pred = GenericPredicate(roleName='push button', name='Allow') for attempts in range(0, 40): # pylint: disable=W0612 if dialog.findChild(third_party_icon_pred, retry=False, requireResult=False) is not None: break else: doDelay(0.5) allow_button = dialog.child("Allow", roleName='push button') if not allow_button.showing: # Scroll to confirmation button scrolls = dialog.findChildren(GenericPredicate(roleName='scroll bar')) scrolls[-1].value = scrolls[-1].maxValue pressKey('space') pressKey('space') # Wait for button to become enabled for attempts in range(0, 10): if pyatspi.STATE_SENSITIVE in \ allow_button.getState().getStates(): break else: doDelay(0.5) sleep(1) allow_button.click() assert wait_until(lambda x: x.dead, dialog), \ "Dialog was not closed"
def add_account_via_goa(context, acc_type): account_cfg = context.app.get_account_configuration(acc_type, 'GOA') def get_account_string(acc_type): if acc_type in ['Google', 'Facebook', 'Windows Live']: return '%s\n%s' % (account_cfg['provider'], account_cfg['id']) elif acc_type in ['Exchange 2010', 'Exchange 2013']: return '%s\n%s' % (account_cfg['provider'], account_cfg['email']) elif acc_type == 'Owncloud': return '%s\n%s@%s' % (account_cfg['provider'], account_cfg['id'], account_cfg['server']) else: raise Exception("Cannot form account string for '%s' type" % acc_type) account_string = get_account_string(acc_type) get_showing_node_name("Online Accounts", context.app.instance, 'frame') sleep(5) account_exists = context.app.instance.findChild( GenericPredicate(account_string), retry=False, requireResult=False) if not account_exists: if context.app.instance.findChild( GenericPredicate('No online accounts configured'), retry=False, requireResult=False).showing: get_showing_node_name("Add an online account", context.app.instance, 'push button').click() sleep(2) else: btn = context.app.instance.child('Add Account', roleName='push button') if not btn.sensitive: btn = get_showing_node_name("Add an online account", context.app.instance, 'push button') btn.grabFocus() btn.click() sleep(2) dialog = get_showing_node_name('Add Account', context.app.instance, rolename="dialog") get_showing_node_name(account_cfg['provider'], dialog).click() sleep(2) fill_in_credentials(context, account_cfg) assert get_showing_node_name(account_string,context.app.instance) is not None,\ "GOA account was not added"
def import_media_multiple(self, files): dogtail.rawinput.pressKey("Esc") # Ensure the welcome dialog is closed self.import_button.click() import_dialog = self.pitivi.child(name="Select One or More Files", roleName="file chooser", recursive=False) path_toggle = import_dialog.child(name="Type a file name", roleName="toggle button") if not path_toggle.checked: path_toggle.click() dir_path = os.path.realpath(__file__).split( "dogtail_scripts/")[0] + "samples/" import_dialog.child(roleName='text').text = dir_path time.sleep(0.2) dogtail.rawinput.pressKey("Enter") # We are now in the samples directory, select various items. # We use Ctrl click to select multiple items. However, since the first # row of the filechooser is always selected by default, we must not use # ctrl when selecting the first item of our list, in order to deselect. ctrl_code = dogtail.rawinput.keyNameToKeyCode("Control_L") file_list = import_dialog.child(name="Files", roleName="table") first = True for f in files: time.sleep(0.5) file_list.child(name=f).click() if first: registry.generateKeyboardEvent(ctrl_code, None, KEY_PRESS) first = False registry.generateKeyboardEvent(ctrl_code, None, KEY_RELEASE) import_dialog.button('Add').click() current_search_text = self.medialibrary.child( name="media_search_entry", roleName="text").text.lower() if current_search_text != "": # Failure to find some icons might be because of search filtering. # The following avoids searching for files that can't be found. for f in files: if current_search_text not in f.lower(): files.remove(f) # Check if non-filtered items are now visible in the media library. samples = [] for i in range(5): # The time it takes for icons to appear is unpredictable, # therefore we try up to 5 times to look for them icons = self.medialibrary.findChildren( GenericPredicate(roleName="icon")) for icon in icons: for f in files: if icon.text == f: samples.append(icon) files.remove(f) if len(files) == 0: break time.sleep(0.5) return samples
def search_by_regex(self, regex, parent, name=None, roleName=None, regex_flags=0): """ Search a parent widget for childs containing the given regular expression """ children = parent.findChildren(GenericPredicate(roleName=roleName, name=name)) r = re.compile(regex, regex_flags) for child in children: if child.text is not None and r.match(child.text): return child
def get_combobox_textbox_object(contact_editor, section, scroll_to_bottom=True): """Get a list of paired 'combobox-textbox' objects in contact editor""" section_names = { 'Ims': 'Instant Messaging', 'Phones': 'Telephone', 'Emails': 'Email'} section = section_names[section.capitalize()] lbl = contact_editor.child(roleName='toggle button', name=section) panel = lbl.findAncestor(GenericPredicate(roleName='filler')) textboxes = panel.findChildren(GenericPredicate(roleName='text')) # Scroll to the bottom of the page if needed pagetab = panel.findAncestor(GenericPredicate(roleName='page tab')) for scroll in pagetab.findChildren(lambda x: x.roleName == 'scroll bar'): if scroll_to_bottom: scroll.value = scroll.maxValue else: scroll.value = 0 # Expand section if button exists button = panel.findChild( GenericPredicate(roleName='push button', name=section), retry=False, requireResult=False) # Expand button if any of textboxes is not visible if button and (False in [x.showing for x in textboxes]): button.click() comboboxes = panel.findChildren(GenericPredicate(roleName='combo box')) # Rearrange comboboxes and textboxes according to their position result = [] for combo in comboboxes: combo_row = combo.position[1] matching_textboxes = [ x for x in textboxes if ((x.position[1] - combo_row) == 0) and (x.position[0] > combo.position[0])] if (matching_textboxes != []): correct_textbox = min(matching_textboxes, key=lambda x: x.position[0]) result.append((combo, correct_textbox)) comboboxes = [x[0] for x in result][::-1] textboxes = [x[1] for x in result][::-1] return (textboxes, comboboxes, button)
def select_addressbook(context, name, password=None): cells = context.app.findChildren( GenericPredicate(name=name, roleName='table cell')) visible_cells = filter(lambda x: x.showing, cells) if visible_cells == []: raise RuntimeError("Cannot find addressbook '%s'" % name) visible_cells[0].click() # Wait for addressbook to load try: spinner = context.app.findChild( GenericPredicate(name='Spinner'), retry=False, requireResult=False) if spinner: start_time = time() while spinner.showing: sleep(1) if (time() - start_time) > 180: raise RuntimeError("Contacts take too long to synchronize") except (GLib.GError, TypeError): pass
def configure_enigmail_global(tb): tools = tb.menu('Tools') tools.doActionNamed('click') tools.menuItem('Add-ons').doActionNamed('click') addons = tb.findChild( GenericPredicate(name='Add-ons Manager', roleName='embedded')) addons.findChild( GenericPredicate(name='Extensions', roleName='list item')).\ doActionNamed('') enigmail = addons.findChild( GenericPredicate(name='Enigmail .*', roleName='list item')) enigmail.button('Preferences').doActionNamed('press') enigmail_prefs = tb.dialog('Enigmail Preferences') # wait for dialog to really initialize, otherwise it may load defaults # over just set values time.sleep(1) try: enigmail_prefs.findChild( GenericPredicate(name='Override with', roleName='check box')).doActionNamed('check') enigmail_prefs.findChild( GenericPredicate(name='Override with', roleName='section') ).children[0].text = '/usr/bin/qubes-gpg-client-wrapper' except tree.ActionNotSupported: pass enigmail_prefs.button('OK').doActionNamed('press') config.searchCutoffCount = 5 try: agent_alert = tb.dialog('Enigmail Alert') if 'Cannot connect to gpg-agent' in agent_alert.description: agent_alert.childNamed('Do not show.*').doActionNamed('check') agent_alert.button('OK').doActionNamed('press') else: raise Exception('Unknown alert: {}'.format( agent_alert.description)) except tree.SearchError: pass finally: config.searchCutoffCount = 10
def configure_openpgp_global(tb): menu = tb.menu('Edit') menu.doActionNamed('click') menu.menuItem('Preferences').doActionNamed('click') preferences = tb.findChild( GenericPredicate(name='Preferences.*', roleName='frame')) config_editor = preferences.findChild( GenericPredicate(name='Config Editor.*', roleName='push button')) config_editor.doActionNamed('press') preferences.findChild( GenericPredicate(name='I accept the risk!', roleName='push button')).doActionNamed('press') about_config = preferences.findChild( GenericPredicate(name='about:config', roleName='embedded')) search = about_config.findChild( GenericPredicate(name='Search:', roleName='unknown')) search.children[0].text = 'mail.openpgp.allow_external_gnupg' allow_external_gnupg = preferences.findChild( GenericPredicate( name='mail.openpgp.allow_external_gnupg default boolean false', roleName='table row')) doubleClick(*allow_external_gnupg.position) search.children[0].text = 'mail.openpgp.alternative_gpg_path' alternative_gpg_path = preferences.findChild( GenericPredicate( name='mail.openpgp.alternative_gpg_path default string.*', roleName='table row')) doubleClick(*alternative_gpg_path.position) gpg_entry_value = tb.findChild( GenericPredicate(name='Enter string value', roleName='frame')) gpg_entry_value.findChild(GenericPredicate( roleName='entry')).text = '/usr/bin/qubes-gpg-client-wrapper' gpg_entry_value.findChild( GenericPredicate(name='OK', roleName='push button')).doActionNamed('press') file = preferences.menu('File') file.doActionNamed('click') file.child('Close').doActionNamed('click')
def check_shown_spoke_selectors(self, spoke): # FIXME: This forces English. validSelectors = [ "KEYBOARD", "LANGUAGE SUPPORT", "TIME & DATE", "INSTALLATION SOURCE", "SOFTWARE SELECTION", "INSTALLATION DESTINATION", "NETWORK & HOST NAME" ] selectors = spoke.findChildren( GenericPredicate(roleName="spoke selector")) self.assertEqual(len(selectors), len(validSelectors), msg="Incorrect number of spoke selectors shown") # Validate that only the spoke selectors we expect are shown. At the same time, # we can also validate the status of each selector. This only validates the # initial state of everything. Once we start clicking on spokes, things are # going to change. # FIXME: This encodes default information. for selector in selectors: if selector.name == "TIME & DATE": self.assertEqual(selector.description, "Americas/New York timezone") elif selector.name == "KEYBOARD": self.assertEqual(selector.description, "English (US)") elif selector.name == "LANGUAGE SUPPORT": self.assertEqual(selector.description, "English (United States)") elif selector.name == "INSTALLATION DESTINATION": # We don't know how many disks are going to be involved - if there's # just one, anaconda selects it by default. If there's more than # one, it selects none. self.assertIn( selector.description, ["Automatic partitioning selected", "No disks selected"]) elif selector.name == "NETWORK & HOST NAME": self.assertTrue( selector.description.startswith("Connected:") or re.match("Wired (.*) connected", selector.description) or selector.description.startswith("Wireless connected to")) elif selector.name == "INSTALLATION SOURCE": self.assertIn( selector.description, ["Closest mirror", "Downloading group metadata..."]) elif selector.name == "SOFTWARE SELECTION": self.assertIn( selector.description, ["Minimal Install", "Downloading group metadata..."]) else: self.fail("Invalid spoke selector shown: %s" % selector.name)
def install_enigmail(tb): tools = tb.menu('Tools') tools.doActionNamed('click') tools.menuItem('Add-ons').doActionNamed('click') addons = tb.findChild( GenericPredicate(name='Add-ons Manager', roleName='embedded')) # check if already installed addons.findChild( GenericPredicate(name='Extensions', roleName='list item')).\ doActionNamed('') config.searchCutoffCount = 1 try: addons.childNamed('Enigmail.*') except tree.SearchError: pass else: # already installed return finally: config.searchCutoffCount = 10 search = addons.findChild( GenericPredicate(name='Search all add-ons', roleName='section')) # search term search.children[0].text = 'enigmail' # saerch button search.children[1].doActionNamed('press') enigmail = addons.findChild( GenericPredicate(name='Enigmail .*', roleName='list item')) enigmail.button('Install').doActionNamed('press') addons.button('Restart now').doActionNamed('press') tree.doDelay(5) tb = get_app() skip_system_integration(tb) tb.dialog('Enigmail Setup Wizard').button('Cancel').doActionNamed('press') tb.dialog('Enigmail Alert').button('Close').doActionNamed('press')
def disable_html(tb, version): open_account_setup(tb) settings = tb.findChild( orPredicate( GenericPredicate(name='Account Settings.*', roleName='frame'), GenericPredicate(name='Account Settings', roleName='dialog'), )) # assume only one account... settings.childNamed('Composition & Addressing').doActionNamed('activate') config.searchCutoffCount = 5 try: settings.childNamed('Compose messages in HTML format').doActionNamed( 'uncheck') except tree.ActionNotSupported: pass if version >= 78: file = settings.menu('File') file.doActionNamed('click') file.child('Close').doActionNamed('click') else: try: settings.button('OK').doActionNamed('press') except tree.SearchError: pass
def import_media(self, filename="tears_of_steel.webm"): """ @return: The icon widget. """ dogtail.rawinput.pressKey("Esc") # Ensure the welcome dialog is closed self.import_button.click() # Force dogtail to look only one level deep, which is much faster # as it doesn't have to analyze the whole mainwindow. import_dialog = self.pitivi.child(name="Select One or More Files", roleName="file chooser", recursive=False) path_toggle = import_dialog.child(name="Type a file name", roleName="toggle button") if not path_toggle.checked: path_toggle.click() filepath = os.path.realpath(__file__).split("dogtail_scripts/")[0] filepath += "samples/" + filename import_dialog.child(roleName='text').text = filepath time.sleep(0.2) dogtail.rawinput.pressKey("Enter") # Don't search for the Add button time.sleep(0.6) # Check if the item is now visible in the media library. for i in range(5): # The time it takes for the icon to appear is unpredictable, # therefore we try up to 5 times to look for it try: icons = self.medialibrary.findChildren( GenericPredicate(roleName="icon")) except TypeError: # If no icon can be seen due to restrictive search results, # don't try to loop over "icons" (which will be a None type). # See further below for further checks that verify this. continue for icon in icons: if icon.text == filename: return icon time.sleep(0.5) # Failure to find an icon might be because it is hidden due to a search current_search_text = self.medialibrary.child( name="media_search_entry", roleName="text").text.lower() self.assertNotEqual(current_search_text, "") self.assertNotIn(filename.lower(), current_search_text) return None
def add_facebook_account(context, user, password): dialog = context.app.instance.dialog('Facebook account') # Input credentials assert wait_until(lambda x: x.findChildren( GenericPredicate(roleName='entry')) != [], dialog, timeout=90), \ "Facebook auth window didn't appear" entry = dialog.child(roleName='entry') if entry.text != user: entry.text = user dialog.child(roleName='password text').text = password doDelay(1) dialog.child(roleName='password text').grabFocus() pressKey('Enter') assert wait_until(lambda x: x.dead, dialog), \ "Dialog was not closed"
def wait_for_configuration_to_settle(self, spoke): """ Wait for some of the configuration to settle down before continuing further. """ selectors = spoke.findChildren( GenericPredicate(roleName="spoke selector")) for wait_for in [ "INSTALLATION SOURCE", "SOFTWARE SELECTION", "INSTALLATION DESTINATION" ]: retry = 0 while retry < 5: for selector in selectors: if (selector.name == wait_for): if not selector.sensitive: retry += 1 doDelay(10) else: retry = 5 # break while break