def onWindowActivated(self, event): """Called whenever one of gcalctool's toplevel windows is activated. Arguments: - event: the window activated Event """ if self._resultsDisplay and self._statusLine: gtk.Script.onWindowActivated(self, event) return obj = event.source role = obj.getRole() if role != pyatspi.ROLE_FRAME: gtk.Script.onWindowActivated(self, event) return isEditbar = lambda x: x and x.getRole() == pyatspi.ROLE_EDITBAR self._resultsDisplay = pyatspi.findDescendant(obj, isEditbar) if not self._resultsDisplay: self.presentMessage(messages.CALCULATOR_DISPLAY_NOT_FOUND) isStatusLine = lambda x: x and x.getRole() == pyatspi.ROLE_TEXT \ and not x.getState().contains(pyatspi.STATE_EDITABLE) self._statusLine = pyatspi.findDescendant(obj, isStatusLine) gtk.Script.onWindowActivated(self, event)
def setup(self, test): self._registry = pyatspi.Registry() print self._path self._desktop = self._registry.getDesktop(0) self._root = pyatspi.findDescendant( self._desktop, lambda x: x.name == "atspi-test-main" and x.getRole() == pyatspi.ROLE_WINDOW )
def setup(self, test): self._registry = pyatspi.Registry() print self._path self._desktop = self._registry.getDesktop(0) self._root = pyatspi.findDescendant( self._desktop, lambda x: x.name == "atspi-test-main" and x.getRole( ) == pyatspi.ROLE_WINDOW)
def selectedChildren(self, obj): if not obj: return [] role = obj.getRole() isSelection = lambda x: x and 'Selection' in pyatspi.listInterfaces(x) if not isSelection(obj) and role == pyatspi.ROLE_COMBO_BOX: child = pyatspi.findDescendant(obj, isSelection) if child: return super().selectedChildren(child) # Things only seem broken for certain tables, e.g. the Paths table. # TODO - JD: File the LibreOffice bugs and reference them here. if role != pyatspi.ROLE_TABLE or self.isSpreadSheetCell(obj): return super().selectedChildren(obj) try: selection = obj.querySelection() except: return [] children = [] for i, child in enumerate(obj): if selection.isChildSelected(i): children.append(obj[i]) return children
def doesrowexist(self, window_name, object_name, row_text): ''' Verify table cell value with given text @param window_name: Window name to type in, either full name, LDTP's name convention, or a Unix glob. @type window_name: string @param object_name: Object name to type in, either full name, LDTP's name convention, or a Unix glob. @type object_name: string @param row_text: Row text to match @type string @return: 1 on success 0 on failure. @rtype: integer ''' obj = self._get_object(window_name, object_name) def _searchString(acc): try: itext = acc.queryText() except NotImplementedError: return False return row_text == itext.getText(0,-1) results = pyatspi.findDescendant(obj, _searchString) return int(bool(results))
def selectedChildren(self, obj): if not obj: return [] role = obj.getRole() isSelection = lambda x: x and 'Selection' in pyatspi.listInterfaces(x) if not isSelection(obj) and role == pyatspi.ROLE_COMBO_BOX: child = pyatspi.findDescendant(obj, isSelection) if child: return super().selectedChildren(child) # Things only seem broken for certain tables, e.g. the Paths table. # TODO - JD: File the LibreOffice bugs and reference them here. if role != pyatspi.ROLE_TABLE or self.isSpreadSheetTable(obj): return super().selectedChildren(obj) try: selection = obj.querySelection() except: return [] children = [] for i, child in enumerate(obj): if selection.isChildSelected(i): children.append(obj[i]) return children
def selectedChildren(self, obj): if not obj: return [] role = obj.getRole() isSelection = lambda x: x and 'Selection' in pyatspi.listInterfaces(x) if not isSelection(obj) and role == pyatspi.ROLE_COMBO_BOX: child = pyatspi.findDescendant(obj, isSelection) if child: return super().selectedChildren(child) # Things only seem broken for certain tables, e.g. the Paths table. # TODO - JD: File the LibreOffice bugs and reference them here. if role != pyatspi.ROLE_TABLE: return super().selectedChildren(obj) # We will need to special case this due to the possibility of there # being lots of children (which may also prove to be zombie objects). # This is why we can't have nice things. if self.isSpreadSheetTable(obj): return [] try: selection = obj.querySelection() except: return [] children = [] for i, child in enumerate(obj): if selection.isChildSelected(i): children.append(obj[i]) return children
def findMessageBodyChild(self, root): roles = [pyatspi.ROLE_DOCUMENT_FRAME, pyatspi.ROLE_DOCUMENT_WEB] isDocument = lambda x: x and x.getRole() in roles candidate = pyatspi.findDescendant(root, isDocument) if self.isEmbeddedDocument(candidate): return self.findMessageBodyChild(candidate) return candidate
def _isCandidateWindow(self, window): if self._script.utilities.isDead(window): msg = "SOFFICE: %s is not candidate window because it's dead." % window debug.println(debug.LEVEL_INFO, msg, True) return False if window and window.childCount and window.getRole() == pyatspi.ROLE_FRAME: child = self._findChildDialog(window[0]) if child and child.getRole() == pyatspi.ROLE_DIALOG: isPageTabList = lambda x: x and x.getRole() == pyatspi.ROLE_PAGE_TAB_LIST if pyatspi.findDescendant(child, isPageTabList): return False isComboBox = lambda x: x and x.getRole() == pyatspi.ROLE_COMBO_BOX return pyatspi.findDescendant(child, isComboBox) return False
def _findErrorWidget(self, root): isPanel = lambda x: x and x.getRole() == pyatspi.ROLE_PANEL panel = pyatspi.findAncestor(self._changeToEntry, isPanel) if not panel: return None isError = lambda x: x and x.getRole() == pyatspi.ROLE_LABEL \ and not ":" in x.name and not x.getRelationSet() return pyatspi.findDescendant(panel, isError)
def _isCandidateWindow(self, window): if not (window and window.getRole() == pyatspi.ROLE_FRAME): return False isMenuBar = lambda x: x and x.getRole() == pyatspi.ROLE_MENU_BAR if pyatspi.findDescendant(window, isMenuBar): return False return True
def _isCandidateWindow(self, window): if window and window.childCount and window.getRole() == pyatspi.ROLE_FRAME: child = window[0] if child.getRole() == pyatspi.ROLE_DIALOG: isPageTabList = lambda x: x and x.getRole() == pyatspi.ROLE_PAGE_TAB_LIST if not pyatspi.findDescendant(child, isPageTabList): return True return False
def _isCandidateWindow(self, window): if not (window and window.getRole() == pyatspi.ROLE_DIALOG): return False roles = [pyatspi.ROLE_PAGE_TAB_LIST, pyatspi.ROLE_SPLIT_PANE] isNonSpellCheckChild = lambda x: x and x.getRole() in roles if pyatspi.findDescendant(window, isNonSpellCheckChild): return False return True
def searchObj(self, appname, ctrlname, elementname): reg = pyatspi.Registry desktop = reg.getDesktop(0) app = pyatspi.findDescendant(desktop, lambda x: x.name == self.appname) self.appname = app if self.ctrlname != None and self.ctrlname.startswith("application"): searchings = [] for i in desktop: if i is not None: searchings.append(i) elif self.ctrlname == None: searchings = pyatspi.findAllDescendants(self.appname, lambda x: x.name == self.elementname) elif self.ctrlname == None and self.findtype == "find": searchings = pyatspi.findDescendant(self.appname, lambda x: x.name == self.elementname) else: searchings = self.findFunc() return searchings
def setup(self, test): self._registry = pyatspi.Registry() self._desktop = self._registry.getDesktop(0) self._root = pyatspi.findDescendant( self._desktop, lambda x: x.name == "atspi-test-main" and x.getRole( ) == pyatspi.ROLE_APPLICATION) self._rset = self._root.getRelationSet() test.assertEqual( len(self._rset), 4, "Num relations expected %d, recieved %d" % (4, len(self._rset)))
def _isCandidateWindow(self, window): if window and window.childCount and window.getRole( ) == pyatspi.ROLE_FRAME: child = window[0] if child.getRole() == pyatspi.ROLE_DIALOG: isPageTabList = lambda x: x and x.getRole( ) == pyatspi.ROLE_PAGE_TAB_LIST if not pyatspi.findDescendant(child, isPageTabList): return True return False
def _isCandidateWindow(self, window): if self._script.utilities.isDead(window): msg = "SOFFICE: %s is not candidate window because it's dead." % window debug.println(debug.LEVEL_INFO, msg, True) return False if window and window.childCount and window.getRole( ) == pyatspi.ROLE_FRAME: child = self._findChildDialog(window[0]) if child and child.getRole() == pyatspi.ROLE_DIALOG: isPageTabList = lambda x: x and x.getRole( ) == pyatspi.ROLE_PAGE_TAB_LIST if pyatspi.findDescendant(child, isPageTabList): return False isComboBox = lambda x: x and x.getRole( ) == pyatspi.ROLE_COMBO_BOX return pyatspi.findDescendant(child, isComboBox) return False
def setup(self, test): self._registry = pyatspi.Registry() import time self._desktop = self._registry.getDesktop(0) print "--desktop len", len(self._desktop) for i in self._desktop: try: print "-- object",i,i.getRole() except: pass self._root = pyatspi.findDescendant (self._desktop, lambda x: x.name == "atspi-test-main" and x.getRole() == pyatspi.ROLE_APPLICATION) print "--root", self._root
def setup(self, test): self._registry = pyatspi.Registry() import time self._desktop = self._registry.getDesktop(0) print("--desktop len", len(self._desktop)) for i in self._desktop: try: print("-- object",i,i.getRole()) except: pass self._root = pyatspi.findDescendant (self._desktop, lambda x: x.name == "atspi-test-main" and x.getRole() == pyatspi.ROLE_APPLICATION) print("--root", self._root)
def findFunc(self): if self.findtype == 'find': try: searchings = [pyatspi.findDescendant(self.appname, lambda x: x.getRoleName() == self.ctrlname)] except TypeError: searchings = [] elif self.findtype == 'findAll': try: searchings = pyatspi.findAllDescendants(self.appname, lambda x: x.getRoleName() == self.ctrlname) except TypeError: searchings = [] return searchings
def _generateChildWidget(self, obj, **args): widgetRoles = [ pyatspi.ROLE_CHECK_BOX, pyatspi.ROLE_COMBO_BOX, pyatspi.ROLE_PUSH_BUTTON, pyatspi.ROLE_RADIO_BUTTON, pyatspi.ROLE_SLIDER, pyatspi.ROLE_TOGGLE_BUTTON ] isWidget = lambda x: x and x.getRole() in widgetRoles # For GtkListBox, such as those found in the control center if obj.parent and obj.parent.getRole() == pyatspi.ROLE_LIST_BOX: widget = pyatspi.findDescendant(obj, isWidget) if widget: return self.generate(widget, includeContext=False) return []
def _find_root_doc(self, window_acc): agent_id = self._get_agent() pred = lambda x: False if agent_id == self.AGENT_MOZILLA or agent_id ==self.AGENT_CHROME: # Firefox def pred(x): p = x.parent if p.getRole() == pyatspi.ROLE_INTERNAL_FRAME: attribs = \ dict([a.split(':',1) for a in p.getAttributes()]) if 'browser' in attribs.get('tag', '') and \ p.getState().contains(pyatspi.STATE_SHOWING): return True return False return pyatspi.findDescendant(window_acc, pred)
def _isCandidateWindow(self, window): if not window: return False role = window.getRole() if role == pyatspi.ROLE_DIALOG: return True if role != pyatspi.ROLE_FRAME: return False isSplitPane = lambda x: x and x.getRole() == pyatspi.ROLE_SPLIT_PANE if pyatspi.findDescendant(window, isSplitPane): return False return True
def popupMenuForFrame(self, obj): if not self.isFrameForPopupMenu(obj): return None try: menu = pyatspi.findDescendant( obj, lambda x: x and x.getRole() == pyatspi.ROLE_MENU) except: msg = "CHROMIUM: Exception finding descendant of %s" % obj debug.println(debug.LEVEL_INFO, msg, True) return None msg = "CHROMIUM: HACK: Popup menu for %s: %s" % (obj, menu) debug.println(debug.LEVEL_INFO, msg, True) return menu
def _generateChildWidget(self, obj, **args): widgetRoles = [pyatspi.ROLE_CHECK_BOX, pyatspi.ROLE_COMBO_BOX, pyatspi.ROLE_PUSH_BUTTON, pyatspi.ROLE_RADIO_BUTTON, pyatspi.ROLE_SLIDER, pyatspi.ROLE_TOGGLE_BUTTON] isWidget = lambda x: x and x.getRole() in widgetRoles # For GtkListBox, such as those found in the control center if obj.parent and obj.parent.getRole() == pyatspi.ROLE_LIST_BOX: widget = pyatspi.findDescendant(obj, isWidget) if widget: return self.generate(widget, includeContext=False) return []
def onFocusedChanged(self, event): """Callback for object:state-changed:focused accessibility events.""" if not event.detail1: return obj = event.source try: role = obj.getRole() name = obj.name except: return # The dialog will get presented when its first child gets focus. if role == pyatspi.ROLE_DIALOG: return # We're getting a spurious focus claim from the gnome-shell window after # the window switcher is used. if role == pyatspi.ROLE_WINDOW: return if role == pyatspi.ROLE_MENU_ITEM and not name \ and not self.utilities.labelsForObject(obj): isRealFocus = lambda x: x and x.getRole() == pyatspi.ROLE_SLIDER descendant = pyatspi.findDescendant(obj, isRealFocus) if descendant: orca.setLocusOfFocus(event, descendant) return # This is to present dialog boxes which are, to the user, newly # activated. And if something is claiming to be focused that is # not in a dialog, that's good to know as well, so update our # state regardless. activeDialog, timestamp = self._activeDialog if not activeDialog: isDialog = lambda x: x and x.getRole() == pyatspi.ROLE_DIALOG dialog = pyatspi.utils.findAncestor(obj, isDialog) self._activeDialog = (dialog, time.time()) if dialog: orca.setLocusOfFocus(None, dialog) labels = self.utilities.unrelatedLabels(dialog) for label in labels: self._activeDialogLabels[hash(label)] = label.name clutter.Script.onFocusedChanged(self, event)
def updateToPath(self, app_name, path): """ Update the node with a new accessible by providing a tree path in an application. @param app_name: Application name. @type app_name: string @param path: The accessible path in the application. @type path: list of integer """ acc = pyatspi.findDescendant(self.desktop, lambda x: x.name.lower() == app_name.lower(), breadth_first=True) if acc is None: return while path: child_index = path.pop(0) try: acc = acc[child_index] except IndexError: return self.update(acc)
def doesrowexist(self, window_name, object_name, row_text, partial_match=False): """ Verify table cell value with given text @param window_name: Window name to type in, either full name, LDTP's name convention, or a Unix glob. @type window_name: string @param object_name: Object name to type in, either full name, LDTP's name convention, or a Unix glob. @type object_name: string @param row_text: Row text to match @type string @param partial_match: Find partial match strings @type boolean @return: 1 on success 0 on failure. @rtype: integer """ try: obj = self._get_object(window_name, object_name) def _searchString(acc): try: itext = acc.queryText() except NotImplementedError: return False if partial_match: return bool( re.search(row_text, itext.getText(0, -1), re.M | re.U)) else: return row_text == itext.getText(0, -1) results = pyatspi.findDescendant(obj, _searchString) return int(bool(results)) except: return 0
def updateToPath(self, app_name, path): ''' Update the node with a new accessible by providing a tree path in an application. @param app_name: Application name. @type app_name: string @param path: The accessible path in the application. @type path: list of integer ''' acc = pyatspi.findDescendant( self.desktop, lambda x: x.name.lower()==app_name.lower(), breadth_first=True) if acc is None: return while path: child_index = path.pop(0) try: acc = acc[child_index] except IndexError: return self.update(acc)
def isComboBoxWithToggleDescendant(self, obj): if not (obj and obj.getRole() == pyatspi.ROLE_COMBO_BOX): return False rv = self._isComboBoxWithToggleDescendant.get(hash(obj)) if rv is not None: return rv isToggle = lambda x: x and x.getRole() == pyatspi.ROLE_TOGGLE_BUTTON for child in obj: if child.getRole() != pyatspi.ROLE_FILLER: continue toggle = pyatspi.findDescendant(child, isToggle) rv = toggle is not None if toggle: self._isToggleDescendantOfComboBox[hash(toggle)] = True break self._isComboBoxWithToggleDescendant[hash(obj)] = rv return rv
def doesrowexist(self, window_name, object_name, row_text, partial_match = False): """ Verify table cell value with given text @param window_name: Window name to type in, either full name, LDTP's name convention, or a Unix glob. @type window_name: string @param object_name: Object name to type in, either full name, LDTP's name convention, or a Unix glob. @type object_name: string @param row_text: Row text to match @type string @param partial_match: Find partial match strings @type boolean @return: 1 on success 0 on failure. @rtype: integer """ try: obj = self._get_object(window_name, object_name) def _searchString(acc): try: itext = acc.queryText() except NotImplementedError: return False if partial_match: return bool(re.search(row_text, itext.getText(0, -1), re.M | re.U)) else: return row_text == itext.getText(0, -1) results = pyatspi.findDescendant(obj, _searchString) return int(bool(results)) except: return 0
def _findErrorWidget(self, root): isError = lambda x: x and x.getRole() == pyatspi.ROLE_LABEL \ and not ":" in x.name and not x.getRelationSet() return pyatspi.findDescendant(root, isError)
def _findChangeToEntry(self, root): isEntry = lambda x: x and x.getRole() == pyatspi.ROLE_TEXT \ and x.getState().contains(pyatspi.STATE_SINGLE_LINE) return pyatspi.findDescendant(root, isEntry)
def drawingView(self, obj=orca_state.locusOfFocus): """Attempts to locate the Impress drawing view, which is the area in which slide editing occurs.""" return pyatspi.findDescendant(self.topLevelObject(obj), self.isDrawingView)
def findMessageBodyChild(self, root): candidate = pyatspi.findDescendant(root, self.isDocument) if self.isEmbeddedDocument(candidate): return self.findMessageBodyChild(candidate) return candidate
def infoBar(self, root): isInfoBar = lambda x: x and x.getRole() == pyatspi.ROLE_INFO_BAR return pyatspi.findDescendant(root, isInfoBar)
def openLink(self, accessible, app_name, linknum, uri, is_url, mouse_click=False): # get the action interface if we're not using a mouseClick iaction = None if not mouse_click: # get the accessible with the jump action ihypertext = accessible._accessible.queryHypertext() num_links = ihypertext.getNLinks() assert linknum < num_links, "Invalid linknum (%d), %s only have %d links" % (linknum, accessible, numlinks) link = ihypertext.getLink(linknum) obj = link.getObject(0) is_enabled = pyatspi.STATE_ENABLED in obj.getState().getStates() iaction = obj.queryAction() # make sure the action interface only has one action and that it is # jump procedurelogger.action("%s %s" % ("Check the number of actions associated with", accessible)) procedurelogger.expectedResult("%s has one associated action" % accessible) assert iaction.nActions == 1, "Only one action should exist for the LinkLabel" actionName = iaction.getName(0) procedurelogger.action("%s %s" % ("Check the name of the action associated with", accessible)) procedurelogger.expectedResult('Action name is "jump"') assert actionName == "jump", 'Action name for LinkLabel should be "jump"' # now we can just call iaction.doAction(0) to perform the jump action # if the link is a url: # make sure firefox opens to the link # if it's not a link: # make sure the proper application opens if is_url and is_enabled: # TODO: enhance this test so that it will handle the case # of a firefox app already being open firefox_app = pyatspi.findDescendant( self.desktop, lambda x: x.getRoleName() == "application" and x.name == "firefox" ) assert firefox_app is None, "Firefox should not be open" # execute the jump action, this should open firefox # application to the URL provided if mouse_click: accessible.mouseClick() else: iaction.doAction(0) # give firefox plenty of time to start sleep(20) firefox_app = cache._desktop.findApplication("firefox", checkShowing=False) assert firefox_app is not None, "Firefox should have opened" frames = firefox_app.findAllFrames(None) # only one new frame should have been opened assert len(frames) == 1, "Only one frame should have been opened" frame = frames[0] # find the urls after jumping # XXX FireFox is not fully accessible on OpenSuse 11.1 # url = self._getOpenURL(firefox_app) # now make sure Firefox opened to the correct link procedurelogger.action("%s" % "Ensure the correct link was opened in Firefox") procedurelogger.expectedResult("%s was opened" % uri) # assert uri == url, \ # '"%s" should have been opened instead of "%s"' % (uri, url) # now close firefox by finding one of the frames, finding its # extents, clicking on the title bar to select the firefox window # and then press Alt+F4 (what a pain!) # it looks like the the most recent frame is always found last icomponent = frame._accessible.queryComponent() bbox = icomponent.getExtents(pyatspi.DESKTOP_COORDS) x = bbox.x + (bbox.width / 2) y = bbox.y pyatspi.Registry.generateMouseEvent(x, y - 1, "b1c") self.altF4(assertClosed=False) procedurelogger.expectedResult("Firefox should be closed") sleep(config.SHORT_DELAY) elif is_url and not is_enabled: # if the URI is a URL but the link should be disabled we should # make sure we can still try to jump, but nothing should happen # execute the jump action, this should open another firefox # application to the URL provided firefox_app = pyatspi.findDescendant( self.desktop, lambda x: x.getRoleName() == "application" and x.name == "Firefox" ) assert firefox_app is None, "Firefox should not be open" if mouse_click: accessible.mouseClick() else: iaction.doAction(0) # give firefox plenty of time to start (in case it does try to # start) sleep(10) procedurelogger.action("%s" % "Ensure that Firefox was not opened") firefox_app = pyatspi.findDescendant( self.desktop, lambda x: x.getRoleName() == "application" and x.name == "Firefox" ) procedurelogger.expectedResult("Firefox was not opened") assert firefox_app is None, 'no "Firefox" application should have been found' elif not is_url: # TODO: enhance this test so that it will handle the case # of a gcalctool app already being open procedurelogger.action("Check if gcalctool is open") procedurelogger.expectedResult("gcalctool should not be open") calc_app = pyatspi.findDescendant( self.desktop, lambda x: x.getRoleName() == "application" and x.name == "gcalctool" ) assert calc_app is None, "No gcalctool should be open" # jump, this should open a gcalctool app if mouse_click: accessible.mouseClick() else: iaction.doAction(0) # give gcalctool plenty of time to open sleep(20) procedurelogger.action("Check if gcalctool is open") procedurelogger.expectedResult("gcalctool should be open") calc_app = pyatspi.findDescendant( self.desktop, lambda x: x.getRoleName() == "application" and x.name == "gcalctool" ) assert calc_app is not None, "One gcalctool should be open" # close the opened gcalctool (it becomes the active window, unlike # firefox, so this is a lot easier) self.altF4(assertClosed=False) procedurelogger.expectedResult("gcalctool should be closed") sleep(config.MEDIUM_DELAY) else: raise NotImplementedError, "Applcation wrapper does not support this call"
def _findSuggestionsList(self, root): isTable = lambda x: x and x.getRole() == pyatspi.ROLE_TABLE \ and 'Selection' in x.get_interfaces() return pyatspi.findDescendant(root, isTable)
def _findSuggestionsList(self, root): isList = lambda x: x and x.getRole() in [pyatspi.ROLE_LIST, pyatspi.ROLE_LIST_BOX] \ and 'Selection' in x.get_interfaces() return pyatspi.findDescendant(root, isList)
def _findSuggestionsList(self, root): isList = lambda x: x and x.getRole() == pyatspi.ROLE_LIST and x.name \ and 'Selection' in x.get_interfaces() \ and x.parent.getRole() != pyatspi.ROLE_COMBO_BOX return pyatspi.findDescendant(root, isList)
def _findErrorWidget(self, root): isError = lambda x: x and x.getRole() == pyatspi.ROLE_TEXT and x.name \ and x.parent.getRole() != pyatspi.ROLE_COMBO_BOX return pyatspi.findDescendant(root, isError)
def states(acc): stateSet = acc.getState() states = stateSet.getStates() state_strings = [] for state in states: state_strings.append(pyatspi.stateToString(state)) state_string = ' '.join(state_strings) return state_string def relations(acc): # create the relations string relations = acc.getRelationSet() if relations: relation_strings = [] for relation in relations: relation_strings.append( \ pyatspi.relationToString(relation.getRelationType())) rel_string = ' '.join(relation_strings) else: rel_string = '' reg = pyatspi.Registry desktop = reg.getDesktop(0) obj = pyatspi.findDescendant( desktop, lambda x: (x.name == 'ipy' or x.name == sys.argv[1].split('/')[-1] ) and x.getRole() == pyatspi.ROLE_APPLICATION) if (obj): printHierarchy(obj, 0)
def _findChangeToEntry(self, root): isEntry = lambda x: x and x.getRole() == pyatspi.ROLE_ENTRY \ and x.getState().contains(pyatspi.STATE_SINGLE_LINE) return pyatspi.findDescendant(root, isEntry)
def openLink(self, accessible, app_name, linknum, uri, is_url, mouse_click=False): # get the action interface if we're not using a mouseClick iaction = None if not mouse_click: # get the accessible with the jump action ihypertext = accessible._accessible.queryHypertext() num_links = ihypertext.getNLinks() assert linknum < num_links, \ 'Invalid linknum (%d), %s only have %d links' % \ (linknum, accessible, numlinks) link = ihypertext.getLink(linknum) obj = link.getObject(0) is_enabled = pyatspi.STATE_ENABLED in obj.getState().getStates() iaction = obj.queryAction() # make sure the action interface only has one action and that it is # jump procedurelogger.action("%s %s" %\ ("Check the number of actions associated with", accessible)) procedurelogger.expectedResult("%s has one associated action" % \ accessible) assert iaction.nActions == 1,\ "Only one action should exist for the LinkLabel" actionName = iaction.getName(0) procedurelogger.action("%s %s" % \ ("Check the name of the action associated with", accessible)) procedurelogger.expectedResult("Action name is \"jump\"") assert actionName == "jump", \ "Action name for LinkLabel should be \"jump\"" # now we can just call iaction.doAction(0) to perform the jump action # if the link is a url: # make sure firefox opens to the link # if it's not a link: # make sure the proper application opens if is_url and is_enabled: # TODO: enhance this test so that it will handle the case # of a firefox app already being open firefox_app = pyatspi.findDescendant(self.desktop, \ lambda x: x.getRoleName() == 'application' and \ x.name == 'firefox') assert firefox_app is None, "Firefox should not be open" # execute the jump action, this should open firefox # application to the URL provided if mouse_click: accessible.mouseClick() else: iaction.doAction(0) # give firefox plenty of time to start sleep(20) firefox_app = cache._desktop.findApplication("firefox", checkShowing=False) assert firefox_app is not None, "Firefox should have opened" frames = firefox_app.findAllFrames(None) # only one new frame should have been opened assert len(frames) == 1, "Only one frame should have been opened" frame = frames[0] # find the urls after jumping # XXX FireFox is not fully accessible on OpenSuse 11.1 #url = self._getOpenURL(firefox_app) # now make sure Firefox opened to the correct link procedurelogger.action("%s" % \ "Ensure the correct link was opened in Firefox") procedurelogger.expectedResult("%s was opened" % uri) #assert uri == url, \ # '"%s" should have been opened instead of "%s"' % (uri, url) # now close firefox by finding one of the frames, finding its # extents, clicking on the title bar to select the firefox window # and then press Alt+F4 (what a pain!) # it looks like the the most recent frame is always found last icomponent = frame._accessible.queryComponent() bbox = icomponent.getExtents(pyatspi.DESKTOP_COORDS) x = bbox.x + (bbox.width / 2) y = bbox.y pyatspi.Registry.generateMouseEvent(x, y - 1, 'b1c') self.altF4(assertClosed=False) procedurelogger.expectedResult("Firefox should be closed") sleep(config.SHORT_DELAY) elif is_url and not is_enabled: # if the URI is a URL but the link should be disabled we should # make sure we can still try to jump, but nothing should happen # execute the jump action, this should open another firefox # application to the URL provided firefox_app = pyatspi.findDescendant(self.desktop, \ lambda x: x.getRoleName() == 'application' and \ x.name == 'Firefox') assert firefox_app is None, "Firefox should not be open" if mouse_click: accessible.mouseClick() else: iaction.doAction(0) # give firefox plenty of time to start (in case it does try to # start) sleep(10) procedurelogger.action("%s" % \ "Ensure that Firefox was not opened") firefox_app = pyatspi.findDescendant(self.desktop, \ lambda x: x.getRoleName() == 'application' and \ x.name == 'Firefox') procedurelogger.expectedResult("Firefox was not opened") assert firefox_app is None, \ "no \"Firefox\" application should have been found" elif not is_url: # TODO: enhance this test so that it will handle the case # of a gcalctool app already being open procedurelogger.action("Check if gcalctool is open") procedurelogger.expectedResult("gcalctool should not be open") calc_app = pyatspi.findDescendant(self.desktop, \ lambda x: x.getRoleName() == 'application' and \ x.name == 'gcalctool') assert calc_app is None, "No gcalctool should be open" # jump, this should open a gcalctool app if mouse_click: accessible.mouseClick() else: iaction.doAction(0) # give gcalctool plenty of time to open sleep(20) procedurelogger.action("Check if gcalctool is open") procedurelogger.expectedResult("gcalctool should be open") calc_app = pyatspi.findDescendant(self.desktop, \ lambda x: x.getRoleName() == 'application' and \ x.name == 'gcalctool') assert calc_app is not None, "One gcalctool should be open" # close the opened gcalctool (it becomes the active window, unlike # firefox, so this is a lot easier) self.altF4(assertClosed=False) procedurelogger.expectedResult("gcalctool should be closed") sleep(config.MEDIUM_DELAY) else: raise NotImplementedError, \ "Applcation wrapper does not support this call"